X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibmarklin%2Fblock.cpp;h=ec07947d7e1cbffa500f05b29661ba7178b99fa8;hb=f74ce147edde73319e55475433adb8e1d87b7201;hp=f96e295a13a75f1962bfd149ccd59dbac41a3796;hpb=78bc40c2d1a5fcc5715143bd2326716fbb143730;p=r2c2.git diff --git a/source/libmarklin/block.cpp b/source/libmarklin/block.cpp index f96e295..ec07947 100644 --- a/source/libmarklin/block.cpp +++ b/source/libmarklin/block.cpp @@ -1,183 +1,239 @@ -#include "control.h" -#include "block.h" -#include "trafficmanager.h" -#include "turnout.h" +/* $Id$ -using namespace Msp; +This file is part of the MSP Märklin suite +Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa +Distributed under the GPL +*/ + +#include +#include "block.h" +#include "layout.h" +#include "route.h" +#include "tracktype.h" -#include using namespace std; +using namespace Msp; namespace Marklin { -Block::Block(TrafficManager &tm, Track *start): - trfc_mgr(tm), - id(next_id++), - sensor_id(0), +Block::Block(Layout &l, Track &start): + layout(l), + id(0), + sensor_id(start.get_sensor_id()), + turnout_id(start.get_turnout_id()), train(0) { - tracks.insert(start); + tracks.insert(&start); + start.set_block(this); - if(start->get_sensor_id()) - { - sensor_id=start->get_sensor_id(); - const Track::EndpointSeq &eps=start->get_endpoints(); - for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i) - endpoints.push_back(Endpoint(start, &*i)); - } - else - { - TrackSeq queue; - queue.push_back(start); + list queue; + queue.push_back(&start); - while(!queue.empty()) - { - Track *track=queue.front(); - queue.erase(queue.begin()); + while(!queue.empty()) + { + Track *track = queue.front(); + queue.erase(queue.begin()); - const Track::EndpointSeq &eps=track->get_endpoints(); - for(Track::EndpointSeq::const_iterator i=eps.begin(); i!=eps.end(); ++i) - if(i->link && tracks.count(i->link)==0) + const vector &links = track->get_links(); + for(unsigned i=0; iget_sensor_id()==sensor_id && links[i]->get_turnout_id()==turnout_id) { - if(!i->link->get_sensor_id()) - { - queue.push_back(i->link); - tracks.insert(i->link); - } - else - endpoints.push_back(Endpoint(track, &*i)); + queue.push_back(links[i]); + tracks.insert(links[i]); + links[i]->set_block(this); } - } + else + endpoints.push_back(Endpoint(track, i)); + } } - unsigned n=0; - for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i, ++n) + determine_id(); + + for(unsigned i=0; iroutes|=route; + unsigned path = 1< visited; - find_routes(i->track, i->track_ep, route, visited); + find_paths(*endpoints[i].track, endpoints[i].track_ep, path, visited); } + + layout.add_block(*this); } -const Block::Endpoint *Block::get_endpoint_by_link(const Block *other) const +Block::~Block() { - for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i) - if(i->link==other) - return &*i; + set trks = tracks; + tracks.clear(); + for(set::iterator i=trks.begin(); i!=trks.end(); ++i) + (*i)->set_block(0); - return 0; + for(vector::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + if(Block *blk = i->link) + { + i->link = 0; + blk->break_link(*this); + } + + layout.remove_block(*this); } -const Block::Endpoint *Block::traverse(const Endpoint *ep) const +bool Block::has_track(Track &t) const { - Track *track=ep->track; - const Track::Endpoint *track_ep=ep->track_ep; + return tracks.count(&t); +} - while(1) - { - unsigned cur_route=0; - unsigned tid=track->get_turnout_id(); - if(tid) - { - Turnout *turnout=trfc_mgr.get_control().get_turnout(tid); - if(turnout) - cur_route=turnout->get_route(); - } +int Block::get_endpoint_by_link(Block &other) const +{ + for(unsigned i=0; itraverse(track_ep, cur_route); - if(!other_ep) - return 0; + return -1; +} - for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i) - if(i->track==track && i->track_ep==other_ep) - return &*i; +unsigned Block::traverse(unsigned epi, float *len) const +{ + return traverse(epi, 0, len); +} - track_ep=track->get_endpoint_by_link(other_ep->link); - track=other_ep->link; +unsigned Block::traverse(unsigned epi, const Route *route, float *len) const +{ + if(epi>=endpoints.size()) + throw InvalidParameterValue("Endpoint index out of range"); + + const Endpoint &ep = endpoints[epi]; + Track *track = ep.track; + unsigned track_ep = ep.track_ep; - if(tracks.count(track)==0) - return 0; + if(len) + *len = 0; + + while(1) + { + int cur_path = -1; + if(track->get_turnout_id() && route) + cur_path = route->get_turnout(track->get_turnout_id()); + if(cur_path==-1) + cur_path = track->get_active_path(); + + if(len) + *len += track->get_type().get_path_length(cur_path); + + unsigned other_ep = track->traverse(track_ep, cur_path); + for(unsigned i=0; i(other_ep)) + return i; + + Track *next = track->get_link(other_ep); + if(!tracks.count(next)) + throw LogicError("Block traversal strayed out of the block"); + track_ep = next->get_endpoint_by_link(*track); + track = next; } } void Block::check_link(Block &other) { - for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + for(vector::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) { if(i->link) continue; - for(EndpointSeq::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j) - if(j->track==i->track_ep->link && j->track_ep->link==i->track && !j->link) + for(vector::iterator j=other.endpoints.begin(); j!=other.endpoints.end(); ++j) + if(j->track==i->track->get_link(i->track_ep) && j->track->get_link(j->track_ep)==i->track && !j->link) { - i->link=&other; - j->link=this; + i->link = &other; + j->link = this; + + determine_id(); + other.determine_id(); } } } -bool Block::reserve(const Train *t) +void Block::break_link(Block &other) +{ + for(vector::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + if(i->link==&other) + { + i->link = 0; + other.break_link(*this); + determine_id(); + } +} + +Block *Block::get_link(unsigned epi) const +{ + if(epi>=endpoints.size()) + throw InvalidParameterValue("Endpoint index out of range"); + return endpoints[epi].link; +} + +bool Block::reserve(Train *t) { if(!t || !train) { - train=t; + train = t; + layout.signal_block_reserved.emit(*this, train); return true; } else return false; } -void Block::print_debug() +void Block::find_paths(Track &track, unsigned track_ep, unsigned path, set &visited) { - cout<<"Block "<get_sensor_id()) - cout<<", sensor="<<(*tracks.begin())->get_sensor_id(); - cout<<'\n'; - for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + visited.insert(&track); + + const vector &eps = track.get_type().get_endpoints(); + for(unsigned i=0; i