X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Ftracktype.cpp;h=3c6876b0cc8b5bd72a7e0f476f45b6d631f2aa6a;hb=2875ea548e0567ad2ce1b8f9bda58e6452813204;hp=29bf47be5409d42eb79fbd9644fbf1a62e08e1bc;hpb=64340dad429ba4040538fc06b6882aabdb489925;p=r2c2.git diff --git a/source/libr2c2/tracktype.cpp b/source/libr2c2/tracktype.cpp index 29bf47b..3c6876b 100644 --- a/source/libr2c2/tracktype.cpp +++ b/source/libr2c2/tracktype.cpp @@ -1,4 +1,6 @@ #include +#include +#include "trackappearance.h" #include "tracktype.h" using namespace std; @@ -6,12 +8,18 @@ using namespace Msp; namespace R2C2 { -TrackType::TrackType(const ArticleNumber &an): - art_nr(an), +TrackType::TrackType(const ArticleNumber &an, const TrackAppearance &ta): + ObjectType(an), + appearance(ta), state_bits(0), autofit_preference(1) { } +float TrackType::get_gauge() const +{ + return appearance.get_gauge(); +} + float TrackType::get_total_length() const { return get_path_length(-1); @@ -42,6 +50,36 @@ unsigned TrackType::get_n_paths() const return n; } +unsigned TrackType::coerce_path(unsigned entry, unsigned path) const +{ + const Endpoint &ep = get_endpoint(entry); + if(ep.has_path(path)) + return path; + + unsigned paths = get_paths(); + if(paths>>(1<>p; p+=step) + if(ep.has_path(p)) + return p; + } + + // Find an endpoint that's connected to the entry and has the requested path + for(vector::const_iterator i=endpoints.begin(); i!=endpoints.end(); ++i) + if(i->has_path(path) && i->has_common_paths(ep)) + { + unsigned p = 1; + for(unsigned m=i->paths&ep.paths; m>>p; ++p) ; + return p-1; + } + + // TODO crossings fall here + throw logic_error("TrackType::coerce_path"); +} + bool TrackType::is_turnout() const { return endpoints.size()>2; @@ -60,7 +98,7 @@ const TrackType::Endpoint &TrackType::get_endpoint(unsigned i) const return endpoints[i]; } -TrackPoint TrackType::get_point(unsigned epi, unsigned path, float d) const +OrientedPoint TrackType::get_point(unsigned epi, unsigned path, float d) const { if(epi>=endpoints.size()) throw out_of_range("TrackType::get_point"); @@ -69,16 +107,15 @@ TrackPoint TrackType::get_point(unsigned epi, unsigned path, float d) const unsigned part_ep = 0; for(vector::const_iterator i=parts.begin(); i!=parts.end(); ++i) { - if((endpoints[epi].paths&(1<get_path()!=path) + if(endpoints[epi].has_path(path) && i->get_path()!=path) continue; unsigned n_part_eps = (i->is_dead_end() ? 1 : 2); for(unsigned j=0; jget_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) + OrientedPoint p = i->get_point(j ? i->get_length() : 0); + Vector span = p.position-endpoints[epi].pos; + if(dot(span, span)<1e-6) { part = &*i; part_ep = j; @@ -96,9 +133,9 @@ TrackPoint TrackType::get_point(unsigned epi, unsigned path, float d) const { if(part_ep==1) d = plen-d; - TrackPoint p = part->get_point(d); + OrientedPoint p = part->get_point(d); if(part_ep==1) - p.dir += M_PI; + p.rotation += Angle::half_turn(); return p; } else @@ -113,13 +150,23 @@ TrackPoint TrackType::get_point(unsigned epi, unsigned path, float d) const } } -bool TrackType::collide_ray(const Vector &start, const Vector &dir, float width) const +OrientedPoint TrackType::get_nearest_point(const Vector &p) const { + OrientedPoint result; + float dist = -1; + for(vector::const_iterator i=parts.begin(); i!=parts.end(); ++i) - if(i->collide_ray(start, dir, width)) - return true; + { + OrientedPoint n = i->get_nearest_point(p); + float d = distance(n.position, p); + if(dget_link(j)) { - TrackPoint p = i->get_point(j ? i->get_length() : 0); + OrientedPoint p = i->get_point(j ? i->get_length() : 0); if(j==0) - p.dir += M_PI; + p.rotation += Angle::half_turn(); 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; + Vector d = k->pos-p.position; - float da = k->dir-p.dir; - while(da>M_PI) - da -= M_PI*2; - while(da<-M_PI) - da += M_PI*2; + Angle da = wrap_balanced(k->dir-p.rotation); - if(dx*dx+dy*dy<1e-6 && da>-0.01 && da<0.01) + if(dot(d, d)<1e-6 && abs(da).radians()<0.01) { k->paths |= 1<get_path(); found = true; @@ -160,24 +202,23 @@ void TrackType::collect_endpoints() } if(!found) - endpoints.push_back(Endpoint(p.pos.x, p.pos.y, p.dir, 1<get_path())); + endpoints.push_back(Endpoint(p.position.x, p.position.y, p.rotation, 1<get_path())); } } } -TrackType::Endpoint::Endpoint(float x, float y, float d, unsigned p): - pos(x, y), +TrackType::Endpoint::Endpoint(float x, float y, const Angle &d, unsigned p): + pos(x, y, 0), dir(d), paths(p) { } TrackType::Loader::Loader(TrackType &t): - Msp::DataFile::ObjectLoader(t), + DataFile::DerivedObjectLoader(t), state_bits_set(false) { add("autofit_preference", &TrackType::autofit_preference); - add("description", &TrackType::description); add("object", &TrackType::object); add("state_bits", &Loader::state_bits); add("part", &Loader::part); @@ -186,6 +227,13 @@ TrackType::Loader::Loader(TrackType &t): void TrackType::Loader::finish() { obj.collect_endpoints(); + vector shapes; + for(vector::iterator i=obj.parts.begin(); i!=obj.parts.end(); ++i) + { + i->create_shape(); + shapes.push_back(&i->get_shape()); + } + obj.shape = Geometry::Union::from_iterator_range(shapes.begin(), shapes.end()).clone(); } void TrackType::Loader::part()