X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibmarklin%2Flayout.cpp;h=f8ad397f183992507ea2eb0140d1d2ae20bccf2c;hb=2029c5e4220e0809a39744a28ca9e2ff22e8ad28;hp=c0930352fb7d2b171f7279a55c0dd1fddffc454b;hpb=651698847d5293cfb15b6fb23a394701388c0151;p=r2c2.git diff --git a/source/libmarklin/layout.cpp b/source/libmarklin/layout.cpp index c093035..f8ad397 100644 --- a/source/libmarklin/layout.cpp +++ b/source/libmarklin/layout.cpp @@ -9,16 +9,17 @@ Distributed under the GPL #include #include #include +#include #include #include "block.h" #include "catalogue.h" #include "driver.h" #include "layout.h" -#include "locotype.h" #include "route.h" #include "track.h" #include "tracktype.h" #include "train.h" +#include "vehicletype.h" using namespace std; using namespace Msp; @@ -27,8 +28,12 @@ namespace Marklin { Layout::Layout(Catalogue &c, Driver *d): catalogue(c), - driver(d) -{ } + driver(d), + next_turnout_id(0x800) +{ + if(driver) + driver->signal_sensor.connect(sigc::mem_fun(this, &Layout::sensor_event)); +} Layout::~Layout() { @@ -36,7 +41,7 @@ Layout::~Layout() while(!trains.empty()) delete trains.begin()->second; while(!routes.empty()) - delete routes.begin()->second; + delete *routes.begin(); while(!tracks.empty()) delete *tracks.begin(); while(!blocks.empty()) @@ -68,6 +73,14 @@ void Layout::remove_track(Track &t) } } +unsigned Layout::allocate_turnout_id(bool dbl) +{ + unsigned result = next_turnout_id++; + if(dbl) + ++next_turnout_id; + return result; +} + void Layout::add_block(Block &b) { blocks.insert(&b); @@ -82,10 +95,10 @@ Block &Layout::get_block(unsigned id) const throw KeyError("Unknown block", lexical_cast(id)); } -Block &Layout::get_block_by_track(const Track &t) const +Block &Layout::get_block_by_track(Track &t) const { for(set::const_iterator i=blocks.begin(); i!=blocks.end(); ++i) - if((*i)->get_tracks().count(const_cast(&t))) + if((*i)->has_track(t)) return **i; throw InvalidParameterValue("No block found for track"); @@ -113,14 +126,14 @@ void Layout::create_blocks() (*i)->check_link(**j); } -void Layout::create_blocks(const Track &track) +void Layout::create_blocks(Track &track) { const vector &links = track.get_links(); for(set::iterator i=blocks.begin(); i!=blocks.end();) { - bool del = (*i)->get_tracks().count(const_cast(&track)); + bool del = (*i)->has_track(track); for(vector::const_iterator j=links.begin(); (!del && j!=links.end()); ++j) - del = (*i)->get_tracks().count(*j); + del = (*i)->has_track(**j); if(del) delete *i++; @@ -138,24 +151,27 @@ void Layout::remove_block(Block &b) void Layout::add_route(Route &r) { - if(routes.count(r.get_name())) - throw KeyError("Duplicate route name", r.get_name()); - - routes[r.get_name()] = &r; - signal_route_added.emit(r); + if(routes.insert(&r).second) + signal_route_added.emit(r); } Route &Layout::get_route(const string &name) const { - map::const_iterator i = routes.find(name); - if(i==routes.end()) - throw KeyError("Unknown route", name); - return *i->second; + for(set::const_iterator i=routes.begin(); i!=routes.end(); ++i) + if((*i)->get_name()==name) + return **i; + throw KeyError("Unknown route", name); +} + +void Layout::update_routes() +{ + for(set::iterator i=routes.begin(); i!=routes.end(); ++i) + (*i)->update_turnouts(); } void Layout::remove_route(Route &r) { - if(routes.erase(r.get_name())) + if(routes.erase(&r)) signal_route_removed.emit(r); } @@ -182,6 +198,18 @@ void Layout::remove_train(Train &t) signal_train_removed.emit(t); } +void Layout::add_vehicle(Vehicle &v) +{ + if(vehicles.insert(&v).second) + signal_vehicle_added.emit(v); +} + +void Layout::remove_vehicle(Vehicle &v) +{ + if(vehicles.erase(&v)) + signal_vehicle_removed.emit(v); +} + void Layout::tick() { if(driver) @@ -197,6 +225,14 @@ void Layout::tick() i->second->tick(t, dt); } +void Layout::emergency(const string &msg) +{ + if(driver) + driver->halt(true); + IO::print("Emergency: %s\n", msg); + signal_emergency.emit(msg); +} + void Layout::save(const string &fn) { IO::BufferedFile out(fn, IO::M_WRITE); @@ -213,11 +249,13 @@ void Layout::save(const string &fn) writer.write(st); } - for(map::iterator i=routes.begin(); i!=routes.end(); ++i) + for(set::iterator i=routes.begin(); i!=routes.end(); ++i) { + if((*i)->is_temporary()) + continue; + DataFile::Statement st("route"); - st.append(i->first); - i->second->save(st.sub); + (*i)->save(st.sub); writer.write(st); } } @@ -237,98 +275,17 @@ void Layout::save_trains(const string &fn) } } -void Layout::check_links() -{ - for(set::iterator i=tracks.begin(); i!=tracks.end(); ++i) - (*i)->break_links(); - - list flext; - for(set::iterator i=tracks.begin(); i!=tracks.end(); ++i) - { - if((*i)->get_flex()) - flext.push_back(*i); - else - { - for(set::iterator j=i; j!=tracks.end(); ++j) - if(j!=i) - (*i)->snap_to(**j, true); - } - } - - for(list::iterator i=flext.begin(); i!=flext.end(); ++i) - for(set::iterator j=tracks.begin(); j!=tracks.end(); ++j) - if(*j!=*i) - (*i)->snap_to(**j, true); -} - -void Layout::check_routes() +void Layout::sensor_event(unsigned addr, bool state) { - for(map::iterator i=routes.begin(); i!=routes.end(); ++i) + if(state) { - /* We must copy the turnout map, since adding tracks to the route will - (temporarily) mess it up */ - const map turnouts = i->second->get_turnouts(); - - // Find any turnout in the route - Track *track = 0; - unsigned trk_path = 0; - for(set::const_iterator j=tracks.begin(); j!=tracks.end(); ++j) - { - map::const_iterator k = turnouts.find((*j)->get_turnout_id()); - if(k!=turnouts.end()) - { - track = *j; - trk_path = k->second; - break; - } - } - - if(!track) - continue; - - // Find an applicable endpoint - const vector &eps = track->get_type().get_endpoints(); - unsigned ep = 0; - for(unsigned j=0; j::iterator i=blocks.begin(); i!=blocks.end(); ++i) + if((*i)->get_sensor_id()==addr) { - ep = j; - break; - } - - Track *start = 0; - while(1) - { - // Traverse the track and get the next one - unsigned out_ep = track->traverse(ep, trk_path); - Track *next = track->get_links()[out_ep]; - if(!next || next == start) + if(!(*i)->get_train()) + emergency(format("Unreserved sensor %d triggered", addr)); break; - - ep = next->get_endpoint_by_link(*track); - if(next->get_type().is_turnout()) - { - // Select correct path across the turnout, or break if we hit an unknown turnout - map::const_iterator j = turnouts.find(next->get_turnout_id()); - if(j==turnouts.end()) - break; - trk_path = j->second; } - else - { - trk_path = 0; - - /* Start adding tracks when we find the first non-turnout. This - prevents the occurrence of ambiguities while adding the tracks */ - if(!start) - start = next; - } - - if(start) - i->second->add_track(*next); - - track = next; - } } } @@ -338,24 +295,28 @@ Layout::Loader::Loader(Layout &l): new_tracks(false) { add("base", &Layout::base); - add("route", &Loader::route); + add("route", static_cast(&Loader::route)); + add("route", static_cast(&Loader::route)); add("track", &Loader::track); add("train", &Loader::train); } void Layout::Loader::finish() { - if(new_tracks) - obj.check_links(); - obj.check_routes(); - for(set::iterator i=obj.tracks.begin(); i!=obj.tracks.end(); ++i) (*i)->check_slope(); } +void Layout::Loader::route() +{ + Route *rte = new Route(obj); + load_sub(*rte); +} + void Layout::Loader::route(const string &n) { - Route *rte = new Route(obj, n); + Route *rte = new Route(obj); + rte->set_name(n); load_sub(*rte); } @@ -364,11 +325,14 @@ void Layout::Loader::track(unsigned art_nr) Track *trk = new Track(obj, obj.catalogue.get_track(art_nr)); load_sub(*trk); new_tracks = true; + for(set::iterator i=obj.tracks.begin(); i!=obj.tracks.end(); ++i) + if(*i!=trk) + trk->snap_to(**i, true); } void Layout::Loader::train(unsigned art_nr, unsigned addr) { - Train *trn = new Train(obj, obj.catalogue.get_locomotive(art_nr), addr); + Train *trn = new Train(obj, obj.catalogue.get_vehicle(art_nr), addr); load_sub(*trn); }