X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibmarklin%2Ftracktype.cpp;h=9f2979bebff80ca4112eb2c3013d6a4209da1ddf;hb=9b05c573a38639827697fe393d55b7c76f5bde45;hp=c6757cb221b12b9a206bdf6b0295f13fb835c789;hpb=6dc18b0e518407bd2a86602bae1e9bbae05da7c8;p=r2c2.git diff --git a/source/libmarklin/tracktype.cpp b/source/libmarklin/tracktype.cpp index c6757cb..9f2979b 100644 --- a/source/libmarklin/tracktype.cpp +++ b/source/libmarklin/tracktype.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of the MSP Märklin suite -Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa +Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa Distributed under the GPL */ @@ -9,11 +9,14 @@ Distributed under the GPL #include "tracktype.h" using namespace std; +using namespace Msp; namespace Marklin { -TrackType::TrackType(unsigned a): - art_nr(a) +TrackType::TrackType(const ArticleNumber &an): + art_nr(an), + double_address(false), + autofit_preference(1) { } float TrackType::get_total_length() const @@ -25,67 +28,154 @@ float TrackType::get_path_length(int p) const { float len = 0; for(vector::const_iterator i=parts.begin(); i!=parts.end(); ++i) - if(p<0 || i->path==static_cast(p)) - { - float l = i->length; - if(i->radius) - l *= abs(i->radius); - len += l; - } + if(p<0 || i->get_path()==static_cast(p)) + len += i->get_length(); return len; } -unsigned TrackType::get_n_paths() const +unsigned TrackType::get_paths() const { - unsigned n = 1; + unsigned mask = 0; for(vector::const_iterator i=parts.begin(); i!=parts.end(); ++i) - if(i->path>=n) - n = i->path+1; + mask |= 1<get_path(); + return mask; +} + +unsigned TrackType::get_n_paths() const +{ + unsigned n = 0; + for(unsigned mask = get_paths(); mask; ++n) + mask &= mask-1; return n; } -void TrackType::collect_endpoints() +bool TrackType::is_turnout() const { - endpoints.clear(); + return endpoints.size()>2; +} - for(vector::iterator i=parts.begin(); i!=parts.end(); ++i) - i->collect_endpoints(endpoints); +bool TrackType::is_dead_end() const +{ + return endpoints.size()<2; +} + +const TrackType::Endpoint &TrackType::get_endpoint(unsigned i) const +{ + if(i>=endpoints.size()) + throw InvalidParameterValue("Endpoint index out of range"); + + return endpoints[i]; +} + +TrackPoint TrackType::get_point(unsigned epi, unsigned path, float d) const +{ + if(epi>=endpoints.size()) + throw InvalidParameterValue("Endpoint index out of range"); - for(vector::iterator i=endpoints.begin(); i!=endpoints.end();) + const TrackPart *part = 0; + unsigned part_ep = 0; + for(vector::const_iterator i=parts.begin(); i!=parts.end(); ++i) { - bool rm = false; - for(vector::iterator j=i+1; j!=endpoints.end();) + if((endpoints[epi].paths&(1<get_path()!=path) + continue; + + unsigned n_part_eps = (i->is_dead_end() ? 1 : 2); + for(unsigned j=0; jpos.x-j->pos.x; - float dy = i->pos.y-j->pos.y; - if(dx*dx+dy*dy<0.0001) + TrackPoint p = i->get_point(j ? i->get_length() : 0); + float dx = p.pos.x-endpoints[epi].pos.x; + float dy = p.pos.y-endpoints[epi].pos.y; + if(dx*dx+dy*dy<1e-6) { - float da = i->dir-j->dir; - if(da<-M_PI) - da += M_PI*2; - if(da>M_PI) - da -= M_PI*2; - if(da<-3.1 || da>3.1) - rm = true; - i->paths |= j->paths; - j = endpoints.erase(j); + part = &*i; + part_ep = j; } - else - ++j; } + } + + if(!part) + throw Exception("Internal error (endpoint does not match any part)"); - if(rm) - i = endpoints.erase(i); + while(1) + { + float plen = part->get_length(); + if(d<=plen) + { + if(part_ep==1) + d = plen-d; + TrackPoint p = part->get_point(d); + if(part_ep==1) + p.dir += M_PI; + return p; + } else - ++i; + { + d -= plen; + TrackPart *next = part->get_link(1-part_ep); + if(!next) + throw InvalidParameterValue("Distance out of range"); + part_ep = (next->get_link(0)==part ? 0 : 1); + part = next; + } } } +void TrackType::collect_endpoints() +{ + endpoints.clear(); + + for(vector::iterator i=parts.begin(); i!=parts.end(); ++i) + { + for(vector::iterator j=i; ++j!=parts.end();) + i->check_link(*j); + + unsigned n_part_eps = (i->is_dead_end() ? 1 : 2); + for(unsigned j=0; jget_link(j)) + { + TrackPoint p = i->get_point(j ? i->get_length() : 0); + if(j==0) + p.dir += M_PI; + + bool found = false; + for(vector::iterator k=endpoints.begin(); k!=endpoints.end(); ++k) + { + float dx = k->pos.x-p.pos.x; + float dy = k->pos.y-p.pos.y; + + float da = k->dir-p.dir; + while(da>M_PI) + da -= M_PI*2; + while(da<-M_PI) + da += M_PI*2; + + if(dx*dx+dy*dy<1e-6 && da>-0.01 && da<0.01) + { + k->paths |= 1<get_path(); + found = true; + break; + } + } + + if(!found) + endpoints.push_back(Endpoint(p.pos.x, p.pos.y, p.dir, 1<get_path())); + } + } +} + +TrackType::Endpoint::Endpoint(float x, float y, float d, unsigned p): + pos(x, y), + dir(d), + paths(p) +{ } + TrackType::Loader::Loader(TrackType &t): Msp::DataFile::BasicLoader(t) { + add("autofit_preference", &TrackType::autofit_preference); add("description", &TrackType::description); + add("double_address", &TrackType::double_address); add("part", &Loader::part); }