X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibmarklin%2Ftrack.cpp;h=230b268fc22576bb3fdea0dbcb7c03c94ac1b515;hb=52cbe8d99669f843f8f75c51128e2748584dd03a;hp=6f83e5b05238080c63a95fdbcd9d5182661f86f7;hpb=36beacc579d3132642ed4d98ce5a6d99842b5812;p=r2c2.git diff --git a/source/libmarklin/track.cpp b/source/libmarklin/track.cpp index 6f83e5b..230b268 100644 --- a/source/libmarklin/track.cpp +++ b/source/libmarklin/track.cpp @@ -1,5 +1,6 @@ #include #include "track.h" +#include "tracktype.h" using namespace std; using namespace Msp; @@ -8,24 +9,19 @@ using namespace Msp; namespace Marklin { -Track::Track(unsigned a): - art_nr(a), +Track::Track(const TrackType &t): + type(t), rot(0), slope(0), flex(false), turnout_id(0), - sensor_id(0) + sensor_id(0), + links(t.get_endpoints().size()) { } Track::~Track() { - for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) - if(i->link) - { - Track *trk=i->link; - i->link=0; - trk->break_link(*this); - } + break_links(); } void Track::set_position(const Point &p) @@ -44,83 +40,94 @@ void Track::set_rotation(float r) void Track::set_slope(float s) { - if(endpoints.size()!=2) return; + if(links.size()!=2) return; slope=s; - endpoints.back().pos.z=slope; } -const Track::Endpoint *Track::get_endpoint_by_link(Track *other) const +void Track::set_flex(bool f) { - for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i) - if(i->link==other) - return &*i; + flex=f; +} - return 0; +void Track::set_turnout_id(unsigned i) +{ + turnout_id=i; } -Point Track::get_endpoint_position(const Endpoint &ep) const +void Track::set_sensor_id(unsigned i) { - float c=cos(rot); - float s=sin(rot); - return Point(pos.x+c*ep.pos.x-s*ep.pos.y, pos.y+s*ep.pos.x+c*ep.pos.y, pos.z+ep.pos.z); + sensor_id=i; } -float Track::get_length() const +int Track::get_endpoint_by_link(const Track &other) const { - float len=parts.front().length; - if(parts.front().radius) - len*=parts.front().radius; - return len; + for(unsigned i=0; ilength; - if(i->radius) - l*=i->radius; - len+=l; - } - return len; + const vector &eps=type.get_endpoints(); + if(epi>=eps.size()) + throw InvalidParameterValue("Endpoint index out of range"); + + const Endpoint &ep=eps[epi]; + + float c=cos(rot); + float s=sin(rot); + + Point p(pos.x+c*ep.x-s*ep.y, pos.y+s*ep.x+c*ep.y, pos.z); + if(eps.size()==2 && epi==1) + p.z+=slope; + return p; } -unsigned Track::get_n_routes() const +float Track::get_endpoint_direction(unsigned epi) const { - unsigned n=1; - for(PartSeq::const_iterator i=parts.begin(); i!=parts.end(); ++i) - if(i->route>=n) - n=i->route+1; - return n; + const vector &eps=type.get_endpoints(); + if(epi>=eps.size()) + throw InvalidParameterValue("Endpoint index out of range"); + + const Endpoint &ep=eps[epi]; + + return rot+ep.dir; } bool Track::snap_to(Track &other, bool link) { float limit=(link && !flex) ? 1e-6 : 1e-4; - for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + const vector &eps=type.get_endpoints(); + const vector &other_eps=other.get_type().get_endpoints(); + + for(unsigned i=0; ilink) + if(other.get_link(j)) continue; - Point epp2=other.get_endpoint_position(*j); + Point epp2=other.get_endpoint_position(j); float dx=epp2.x-epp.x; float dy=epp2.y-epp.y; if(dx*dx+dy*dyrot-i->rot+M_PI); - set_position(Point(epp2.x-(i->pos.x*cos(rot)-i->pos.y*sin(rot)), epp2.y-(i->pos.y*cos(rot)+i->pos.x*sin(rot)), other.pos.z+j->pos.z-i->pos.z)); + set_rotation(other.rot+other_eps[j].dir-eps[i].dir+M_PI); + set_position(Point(epp2.x-(eps[i].x*cos(rot)-eps[i].y*sin(rot)), epp2.y-(eps[i].y*cos(rot)+eps[i].x*sin(rot)), epp2.z)); + if(link) { - if(i->link) - break_link(*i->link); - i->link=&other; - j->link=this; + if(links[i]) + break_link(*links[i]); + links[i]=&other; + other.links[j]=this; } + return true; } } @@ -131,15 +138,17 @@ bool Track::snap_to(Track &other, bool link) bool Track::snap(Point &pt, float &d) const { - for(EndpointSeq::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + const vector &eps=type.get_endpoints(); + + for(unsigned i=0; irot; + d=rot+eps[i].dir; return true; } } @@ -149,10 +158,10 @@ bool Track::snap(Point &pt, float &d) const void Track::break_link(Track &trk) { - for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) - if(i->link==&trk) + for(vector::iterator i=links.begin(); i!=links.end(); ++i) + if(*i==&trk) { - i->link=0; + *i=0; trk.break_link(*this); return; } @@ -160,122 +169,87 @@ void Track::break_link(Track &trk) void Track::break_links() { - for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end(); ++i) - if(i->link) + for(vector::iterator i=links.begin(); i!=links.end(); ++i) + if(Track *trk=*i) { - Track *trk=i->link; - i->link=0; + *i=0; trk->break_link(*this); } } +Track *Track::get_link(unsigned i) const +{ + if(i>links.size()) + throw InvalidParameterValue("Link index out of range"); + + return links[i]; +} + void Track::check_slope() { - if(endpoints.size()!=2) + if(links.size()!=2) return; - Track *link1=endpoints.front().link; - Track *link2=endpoints.back().link; - if(link1 && link2) + if(links[0] && links[1]) { - const Endpoint *ep1=link1->get_endpoint_by_link(this); - const Endpoint *ep2=link2->get_endpoint_by_link(this); - pos.z=link1->pos.z+ep1->pos.z; - slope=(link2->pos.z+ep2->pos.z)-pos.z; + Point epp0=links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this)); + Point epp1=links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this)); + pos.z=epp0.z; + slope=epp1.z-pos.z; } else { slope=0; - if(link1) + if(links[0]) { - const Endpoint *ep=link1->get_endpoint_by_link(this); - pos.z=link1->pos.z+ep->pos.z; + Point epp=links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this)); + pos.z=epp.z; } - else if(link2) + else if(links[1]) { - const Endpoint *ep=link2->get_endpoint_by_link(this); - pos.z=link2->pos.z+ep->pos.z; + Point epp=links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this)); + pos.z=epp.z; } } - - endpoints.back().pos.z=slope; } -const Track::Endpoint *Track::traverse(const Endpoint *ep, unsigned route) const +int Track::traverse(unsigned i, unsigned route) const { - if(ep->routes&(1< &eps=type.get_endpoints(); + if(i>=eps.size()) + throw InvalidParameterValue("Endpoint index out of range"); + + const Endpoint &ep=eps[i]; + + if(ep.routes&(1<routes&(1<routes&(1<routes&ep->routes)) - return &*i; + for(unsigned j=0; jendpoints.begin(); i!=trk->endpoints.end(); ++i) - i->link=0; - trk->turnout_id=0; - trk->sensor_id=0; + Track *trk=new Track(type); + trk->set_position(pos); + trk->set_rotation(rot); + trk->set_slope(slope); + trk->set_flex(flex); return trk; } -/*** private ***/ - -void Track::collect_endpoints() -{ - endpoints.clear(); - - for(PartSeq::iterator i=parts.begin(); i!=parts.end(); ++i) - i->collect_endpoints(endpoints); - endpoints.back().pos.z=slope; - - for(EndpointSeq::iterator i=endpoints.begin(); i!=endpoints.end();) - { - bool rm=false; - for(EndpointSeq::iterator j=i; j!=endpoints.end();) - { - if(j==i) - { - ++j; - continue; - } - float dx=i->pos.x-j->pos.x; - float dy=i->pos.y-j->pos.y; - if(dx*dx+dy*dy<0.0001) - { - float da=i->rot-j->rot; - if(da<-M_PI) - da+=M_PI*2; - if(da>M_PI) - da-=M_PI*2; - if(da<-3 || da>3) - rm=true; - i->routes|=j->routes; - j=endpoints.erase(j); - } - else - ++j; - } - if(rm) - i=endpoints.erase(i); - else - ++i; - } -} - /******************* ** Track::Loader */ @@ -283,8 +257,6 @@ void Track::collect_endpoints() Track::Loader::Loader(Track &t): track(t) { - add("description", &Track::description); - add("part", &Loader::part); add("position", &Loader::position); add("rotation", &Track::rot); add("slope", &Track::slope); @@ -293,85 +265,9 @@ Track::Loader::Loader(Track &t): add("flex", &Track::flex); } -Track::Loader::~Loader() -{ - track.collect_endpoints(); -} - -void Track::Loader::part() -{ - Part p; - load_sub(p); - track.parts.push_back(p); -} - void Track::Loader::position(float x, float y, float z) { track.pos=Point(x, y, z); } -/******************* -** Track::Part -*/ - -Track::Part::Part(): - x(0), - y(0), - dir(0), - length(0), - radius(0), - route(0), - dead_end(false) -{ } - -void Track::Part::collect_endpoints(EndpointSeq &epl) -{ - epl.push_back(Endpoint(Point(x, y, 0), dir+M_PI, 1<