X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibmarklin%2Froute.cpp;h=79886d28c371c793ed223909ef343b79edc0b726;hb=9b05c573a38639827697fe393d55b7c76f5bde45;hp=6dc7ae51e13350efe01269c06c199fde829675f8;hpb=2bb6ce8ada216c0b2caa48f4639d03f2c581098e;p=r2c2.git diff --git a/source/libmarklin/route.cpp b/source/libmarklin/route.cpp index 6dc7ae5..79886d2 100644 --- a/source/libmarklin/route.cpp +++ b/source/libmarklin/route.cpp @@ -24,21 +24,20 @@ typedef std::pair Key; struct Node { - Track *track; - unsigned ep; + TrackIter track; Node *prev; float dist; Node(): - track(0), ep(0), prev(0), dist(0) + prev(0), dist(0) { } - Node(Track &t, unsigned e): - track(&t), ep(e), prev(0), dist(0) + Node(const TrackIter &t): + track(t), prev(0), dist(0) { } - Node(Track &t, unsigned e, Node &r, float d): - track(&t), ep(e), prev(&r), dist(prev->dist+d) + Node(const TrackIter &t, Node &r, float d): + track(t), prev(&r), dist(prev->dist+d) { } bool operator<(const Node &other) const @@ -64,20 +63,20 @@ struct TrackInSet }; template -list dijkstra(Track &from, unsigned ep, const Pred &goal) +list dijkstra(const TrackIter &from, const Pred &goal) { map track_nodes; priority_queue nodes; Node *final = 0; - nodes.push(Node(from, ep)); + nodes.push(from); while(!nodes.empty()) { Node lowest = nodes.top(); nodes.pop(); - Key key(lowest.track, lowest.ep); + Key key(lowest.track.track(), lowest.track.entry()); if(track_nodes.count(key)) continue; @@ -88,44 +87,37 @@ list dijkstra(Track &from, unsigned ep, const Pred &goal) break; } - const TrackType &type = lowest.track->get_type(); - const vector &eps = type.get_endpoints(); - const vector &links = lowest.track->get_links(); - for(unsigned i=0; iget_endpoint_by_link(*lowest.track); - if(track_nodes.count(Key(links[i], link_ep))) - continue; + unsigned paths = lowest.track.endpoint().paths; + for(unsigned i=0; paths>>i; ++i) + if(paths&(1<>=1) ; - nodes.push(Node(*links[i], links[i]->get_endpoint_by_link(*lowest.track), ref, type.get_path_length(path))); - } + nodes.push(Node(next, ref, lowest.track->get_type().get_path_length(i))); + } } - if(!final) - throw InvalidParameterValue("Could not find a route"); - list result; for(Node *node=final; node; node=node->prev) - result.push_front(node->track); + result.push_front(&*node->track); return result; } template -Route *create_route(Track &from, unsigned ep, const Pred &goal) +Route *create_route(const TrackIter &from, const Pred &goal) { - list tracks = dijkstra(from, ep, goal); + list tracks = dijkstra(from, goal); + + if(tracks.empty()) + return 0; - Route *route = new Route(from.get_layout()); + Route *route = new Route(from->get_layout()); for(list::iterator i=tracks.begin(); i!=tracks.end(); ++i) route->add_track(**i); @@ -184,11 +176,11 @@ void Route::update_turnouts() { found.insert(tid); - const vector &endpoints = (*i)->get_type().get_endpoints(); + const vector &endpoints = (*i)->get_type().get_endpoints(); const vector &links = (*i)->get_links(); // Build a combined path mask from linked endpoints - unsigned mask = 15; + unsigned mask = (*i)->get_type().get_paths(); for(unsigned j=0; jget_turnout_id()) { - const Endpoint &ep = links[j]->get_type().get_endpoints()[links[j]->get_endpoint_by_link(**i)]; + const TrackType::Endpoint &ep = links[j]->get_type().get_endpoint(links[j]->get_endpoint_by_link(**i)); int p = get_turnout(tid2); if(p>=0 && !(ep.paths&(1<::const_iterator i = turnouts.find(tid); + if(i!=turnouts.end()) + return i->second; + } + return trk.get_active_path(); +} + void Route::add_track(Track &trk) { if(tracks.count(&trk)) @@ -326,50 +329,61 @@ void Route::save(list &st) const unsigned Route::check_validity(Track &trk) const { unsigned result = 4; - for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + const vector &links = trk.get_links(); + for(vector::const_iterator i=links.begin(); i!=links.end(); ++i) { - int epi=(*i)->get_endpoint_by_link(trk); - if(epi>=0) + if(!*i) + continue; + if(!tracks.count(*i)) + continue; + + // Linked to an existing track - good + result |= 1; + + if(unsigned tid = (*i)->get_turnout_id()) { - // Linked to an existing track - good - result |= 1; - const vector &endpoints = (*i)->get_type().get_endpoints(); - if(unsigned tid=(*i)->get_turnout_id()) + const TrackType::Endpoint &ep = (*i)->get_type().get_endpoint((*i)->get_endpoint_by_link(trk)); + int path = get_turnout(tid); + if(path>=0) { - int r = get_turnout(tid); - if(r>=0) - { - // Linking to a turnout with path set is only good if we're continuing that path - if(endpoints[epi].paths&(1< &links = (*i)->get_links(); - int epj = -1; - for(unsigned k=0; k &tlinks = (*i)->get_links(); + unsigned count = 0; + for(unsigned j=0; jget_turnout_id(); + if(tid2) { - ++count; - epj = k; + const TrackType::Endpoint &ep2 = tlinks[j]->get_type().get_endpoint(tlinks[j]->get_endpoint_by_link(**i)); + path = get_turnout(tid2); + // Ignore a linked turnout with some other path set + if(path>0 && !(ep2.paths&(1<=0 && !(endpoints[epi].paths&endpoints[epj].paths)) + ++count; + + const TrackType::Endpoint &ep2 = (*i)->get_type().get_endpoint(j); + if(!(ep.paths&ep2.paths)) // Impossible path through the turnout - not good result &= 3; } - } + + // Only good if at most one other track is linked to the turnout + if(count<=1) + result |= 2; } - else - // Linked to something linear - good - result |= 2; } + else + // Linked to something linear - good + result |= 2; } return result; @@ -380,19 +394,19 @@ void Route::track_removed(Track &t) tracks.erase(&t); } -Route *Route::find(Track &from, unsigned ep, Track &to) +Route *Route::find(const TrackIter &from, Track &to) { - return create_route(from, ep, TrackMatch(to)); + return create_route(from, TrackMatch(to)); } -Route *Route::find(Track &from, unsigned ep, const Route &to) +Route *Route::find(const TrackIter &from, const Route &to) { - return create_route(from, ep, TrackInSet(to.get_tracks())); + return create_route(from, TrackInSet(to.get_tracks())); } -Route *Route::find(Track &from, unsigned ep, const set &to) +Route *Route::find(const TrackIter &from, const set &to) { - return create_route(from, ep, TrackInSet(to)); + return create_route(from, TrackInSet(to)); } @@ -417,7 +431,7 @@ void Route::Loader::finish() continue; unsigned path_mask = 1<second; - const vector &eps = (*i)->get_type().get_endpoints(); + const vector &eps = (*i)->get_type().get_endpoints(); for(unsigned k=0; k