From: Mikko Rasa Date: Thu, 14 Oct 2010 19:25:50 +0000 (+0000) Subject: Generate IDs for new turnouts X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=f409cd39a687900724d987c9db629cbff0dd49be;p=r2c2.git Generate IDs for new turnouts Update routes when a turnout ID is changed Properly support non-loop routes Link tracks as they are loaded Don't move tracks when linking if one of them is flexible Move route rebuilding to the Route class --- diff --git a/source/designer/designer.cpp b/source/designer/designer.cpp index c6d253e..396cb07 100644 --- a/source/designer/designer.cpp +++ b/source/designer/designer.cpp @@ -489,8 +489,11 @@ void Designer::update_track_icon(Track3D &track) } else if(unsigned tid = track.get_track().get_turnout_id()) { - overlay->add_graphic(track, "turnout"); - overlay->set_label(track, lexical_cast(tid)); + if(tid<0x800) + { + overlay->add_graphic(track, "turnout"); + overlay->set_label(track, lexical_cast(tid)); + } } } diff --git a/source/libmarklin/layout.cpp b/source/libmarklin/layout.cpp index 1448a1d..a495a21 100644 --- a/source/libmarklin/layout.cpp +++ b/source/libmarklin/layout.cpp @@ -28,7 +28,8 @@ 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)); @@ -72,6 +73,11 @@ void Layout::remove_track(Track &t) } } +unsigned Layout::allocate_turnout_id() +{ + return next_turnout_id++; +} + void Layout::add_block(Block &b) { blocks.insert(&b); @@ -157,6 +163,12 @@ Route &Layout::get_route(const string &name) const return *i->second; } +void Layout::update_routes() +{ + for(map::iterator i=routes.begin(); i!=routes.end(); ++i) + i->second->update_turnouts(); +} + void Layout::remove_route(Route &r) { if(routes.erase(r.get_name())) @@ -264,106 +276,6 @@ 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() -{ - for(map::iterator i=routes.begin(); i!=routes.end(); ++i) - { - if(i->second->is_temporary()) - continue; - - /* 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; jget_type().get_endpoints().size()<2) - break; - unsigned out_ep = track->traverse(ep, trk_path); - Track *next = track->get_links()[out_ep]; - if(!next || next == start) - 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; - } - } -} - void Layout::sensor_event(unsigned addr, bool state) { if(state) @@ -391,10 +303,6 @@ Layout::Loader::Loader(Layout &l): 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(); } @@ -410,6 +318,9 @@ 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) diff --git a/source/libmarklin/layout.h b/source/libmarklin/layout.h index 6683e2d..f820cb5 100644 --- a/source/libmarklin/layout.h +++ b/source/libmarklin/layout.h @@ -62,6 +62,7 @@ private: std::map trains; std::set vehicles; Msp::Time::TimeStamp last_tick; + unsigned next_turnout_id; public: Layout(Catalogue &, Driver * = 0); @@ -75,6 +76,7 @@ public: void add_track(Track &); const std::set &get_tracks() const { return tracks; } void remove_track(Track &); + unsigned allocate_turnout_id(); void add_block(Block &); Block &get_block(unsigned) const; @@ -87,6 +89,7 @@ public: void add_route(Route &); const std::map &get_routes() const { return routes; } Route &get_route(const std::string &) const; + void update_routes(); void remove_route(Route &); void add_train(Train &); @@ -103,8 +106,6 @@ public: void save(const std::string &); void save_trains(const std::string &); private: - void check_links(); - void check_routes(); void sensor_event(unsigned, bool); }; diff --git a/source/libmarklin/route.cpp b/source/libmarklin/route.cpp index 7ecd473..cdbcf1d 100644 --- a/source/libmarklin/route.cpp +++ b/source/libmarklin/route.cpp @@ -213,17 +213,44 @@ void Route::add_tracks(const set &trks) update_turnouts(); } -void Route::save(list &st) const +void Route::add_track_chain(const Track &start, unsigned ep, const TurnoutMap &trnts) { - for(map::const_iterator i=turnouts.begin(); i!=turnouts.end(); ++i) - st.push_back((DataFile::Statement("turnout"), i->first, i->second)); + const Track *track = &start; + while(1) + { + if(track->get_type().is_dead_end()) + break; + + if(tracks.count(track)) + break; + + int path = 0; + if(track->get_turnout_id()) + { + TurnoutMap::const_iterator i = trnts.find(track->get_turnout_id()); + if(i==trnts.end()) + break; + + path = i->second; + } + + add_track(*track); + + unsigned out_ep = track->traverse(ep, path); + Track *next = track->get_links()[out_ep]; + if(!next) + break; + + ep = next->get_endpoint_by_link(*track); + track = next; + } } void Route::update_turnouts() { set found; for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) - if(unsigned tid=(*i)->get_turnout_id()) + if(unsigned tid = (*i)->get_turnout_id()) { found.insert(tid); @@ -237,7 +264,7 @@ void Route::update_turnouts() if(!tracks.count(links[j])) continue; - if(unsigned tid2=links[j]->get_turnout_id()) + if(unsigned tid2 = links[j]->get_turnout_id()) { const Endpoint &ep = links[j]->get_type().get_endpoints()[links[j]->get_endpoint_by_link(**i)]; int p = get_turnout(tid2); @@ -273,6 +300,12 @@ void Route::update_turnouts() } } +void Route::save(list &st) const +{ + for(map::const_iterator i=turnouts.begin(); i!=turnouts.end(); ++i) + st.push_back((DataFile::Statement("turnout"), i->first, i->second)); +} + unsigned Route::check_validity(const Track &trk) const { unsigned result = 4; @@ -347,9 +380,37 @@ Route::Loader::Loader(Route &r): add("turnout", &Loader::turnout); } +void Route::Loader::finish() +{ + const set <racks = obj.layout.get_tracks(); + for(set::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i) + { + unsigned tid = (*i)->get_turnout_id(); + if(!tid) + continue; + + TurnoutMap::iterator j = turnouts.find(tid); + if(j==turnouts.end()) + continue; + + unsigned path_mask = 1<second; + const vector &eps = (*i)->get_type().get_endpoints(); + for(unsigned k=0; kget_link(k); + if(!obj.tracks.count(link)) + obj.add_track_chain(*link, link->get_endpoint_by_link(**i), turnouts); + if(!obj.tracks.count(*i)) + obj.add_track_chain(**i, k, turnouts); + break; + } + } +} + void Route::Loader::turnout(unsigned id, unsigned path) { - obj.turnouts[id] = path; + turnouts[id] = path; } } // namespace Marklin diff --git a/source/libmarklin/route.h b/source/libmarklin/route.h index 010bb87..6b36f46 100644 --- a/source/libmarklin/route.h +++ b/source/libmarklin/route.h @@ -22,11 +22,17 @@ class Track; class Route: public sigc::trackable { public: + typedef std::map TurnoutMap; + class Loader: public Msp::DataFile::BasicLoader { + private: + TurnoutMap turnouts; + public: Loader(Route &); private: + virtual void finish(); void turnout(unsigned, unsigned); }; @@ -35,7 +41,7 @@ private: std::string name; bool temporary; std::set tracks; - std::map turnouts; + TurnoutMap turnouts; public: Route(Layout &, const std::string &); @@ -44,14 +50,15 @@ public: const std::string &get_name() const { return name; } void set_temporary(bool); bool is_temporary() const { return temporary; } + void update_turnouts(); int get_turnout(unsigned) const; const std::map &get_turnouts() const { return turnouts; } void add_track(const Track &); void add_tracks(const std::set &); + void add_track_chain(const Track &, unsigned, const TurnoutMap &); const std::set &get_tracks() const { return tracks; } void save(std::list &) const; private: - void update_turnouts(); unsigned check_validity(const Track &) const; void track_removed(Track &); diff --git a/source/libmarklin/track.cpp b/source/libmarklin/track.cpp index 05f9f2f..74e51ac 100644 --- a/source/libmarklin/track.cpp +++ b/source/libmarklin/track.cpp @@ -22,9 +22,9 @@ Track::Track(Layout &l, const TrackType &t): rot(0), slope(0), flex(false), - turnout_id(0), + turnout_id(type.is_turnout() ? layout.allocate_turnout_id() : 0), sensor_id(0), - links(t.get_endpoints().size()), + links(type.get_endpoints().size()), active_path(0) { layout.add_track(*this); @@ -103,6 +103,7 @@ void Track::set_turnout_id(unsigned i) turnout_id = i; layout.create_blocks(*this); + layout.update_routes(); if(layout.has_driver() && turnout_id) { layout.get_driver().add_turnout(turnout_id); @@ -175,7 +176,7 @@ float Track::get_endpoint_direction(unsigned epi) const bool Track::snap_to(Track &other, bool link) { - float limit = (link && !flex) ? 1e-6 : 1e-4; + float limit = (link && !flex && !other.get_flex()) ? 1e-6 : 1e-4; const vector &eps = type.get_endpoints(); const vector &other_eps = other.get_type().get_endpoints(); @@ -193,13 +194,16 @@ bool Track::snap_to(Track &other, bool link) float dy = epp2.y-epp.y; if(dx*dx+dy*dy2; } +bool TrackType::is_dead_end() const +{ + return endpoints.size()<2; +} + TrackPoint TrackType::get_point(unsigned epi, unsigned path, float d) const { if(epi>=endpoints.size()) diff --git a/source/libmarklin/tracktype.h b/source/libmarklin/tracktype.h index 582f77a..99989be 100644 --- a/source/libmarklin/tracktype.h +++ b/source/libmarklin/tracktype.h @@ -44,6 +44,7 @@ public: unsigned get_paths() const; unsigned get_n_paths() const; bool is_turnout() const; + bool is_dead_end() const; bool is_double_address() const { return double_address; } const std::vector &get_parts() const { return parts; } const std::vector &get_endpoints() const { return endpoints; }