]> git.tdb.fi Git - r2c2.git/blobdiff - source/libmarklin/trackpart.cpp
Make LCD output selectable at runtime through an extra I/O pin
[r2c2.git] / source / libmarklin / trackpart.cpp
index 046b9276ac23025a34ac586ef2509d74ca2b1d7f..37c5f97a90b0fc81cae5eb150bb2cbd8a654e8d5 100644 (file)
@@ -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,6 +9,7 @@ Distributed under the GPL
 #include "trackpart.h"
 
 using namespace std;
+using namespace Msp;
 
 namespace Marklin {
 
@@ -16,71 +17,111 @@ TrackPart::TrackPart():
        dir(0),
        length(0),
        radius(0),
-       route(0),
+       path(0),
        dead_end(false)
-{ }
+{
+       links[0] = 0;
+       links[1] = 0;
+}
+
+float TrackPart::get_length() const
+{
+       if(radius)
+               return abs(radius)*length;
+       else
+               return length;
+}
 
-void TrackPart::collect_endpoints(vector<Endpoint> &eps) const
+TrackPoint TrackPart::get_point(float d) const
 {
-       eps.push_back(Endpoint(pos.x, pos.y, dir+M_PI, 1<<route));
+       TrackPoint result;
 
-       if(dead_end)
-               ;
-       else if(radius)
+       if(radius)
        {
-               float a=((radius<0) ? -length : length);
-               Point p=get_point(length*abs(radius));
-               eps.push_back(Endpoint(p.x, p.y, dir+a, 1<<route));
+               float a = d/radius;
+               float c = cos(a);
+               float s = sin(a);
+               float rx = radius*sin(dir);
+               float ry = -radius*cos(dir);
+               result.pos = Point(pos.x+c*rx-s*ry-rx, pos.y+c*ry+s*rx-ry);
+               result.dir = dir+a;
        }
        else
-               eps.push_back(Endpoint(pos.x+cos(dir)*length, pos.y+sin(dir)*length, dir, 1<<route));
+       {
+               result.pos = Point(pos.x+cos(dir)*d, pos.y+sin(dir)*d);
+               result.dir = dir;
+       }
+
+       return result;
 }
 
-Point TrackPart::get_point(float d) const
+void TrackPart::check_link(TrackPart &other)
 {
-       if(radius)
+       unsigned n_eps = (dead_end ? 1 : 2);
+       unsigned n_other_eps = (other.is_dead_end() ? 1 : 2);
+       for(unsigned i=0; i<n_eps; ++i)
        {
-               float a=d/radius;
-               float c=cos(a);
-               float s=sin(a);
-               float rx=radius*sin(dir);
-               float ry=-radius*cos(dir);
-               return Point(pos.x+c*rx-s*ry-rx, pos.y+c*ry+s*rx-ry);
+               TrackPoint p1 = get_point(i ? get_length() : 0);
+               for(unsigned j=0; j<n_other_eps; ++j)
+               {
+                       TrackPoint p2 = other.get_point(j ? other.get_length() : 0);
+
+                       float dx = p2.pos.x-p1.pos.x;
+                       float dy = p2.pos.y-p1.pos.y;
+
+                       float da = p2.dir-p1.dir+M_PI*((i+j+1)%2);
+                       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)
+                       {
+                               links[i] = &other;
+                               other.links[j] = this;
+                               return;
+                       }
+               }
        }
-       else
-               return Point(pos.x+cos(dir)*d, pos.y+sin(dir)*d);
+}
+
+TrackPart *TrackPart::get_link(unsigned i) const
+{
+       if(i>=2)
+               throw InvalidParameterValue("Index out of range");
+       return links[i];
 }
 
 
 TrackPart::Loader::Loader(TrackPart &p):
-       part(p)
+       Msp::DataFile::BasicLoader<TrackPart>(p)
 {
        add("start",    &Loader::start);
        add("length",   &TrackPart::length);
        add("radius",   &TrackPart::radius);
-       add("route",    &TrackPart::route);
+       add("path",     &TrackPart::path);
        add("dead_end", &TrackPart::dead_end);
 }
 
 void TrackPart::Loader::finish()
 {
-       if(part.radius)
+       if(obj.radius)
        {
-               part.length*=M_PI/180;
-               part.radius/=1000;
+               obj.length *= M_PI/180;
+               obj.radius /= 1000;
        }
        else
-               part.length/=1000;
+               obj.length /= 1000;
 
-       part.pos.x/=1000;
-       part.pos.y/=1000;
-       part.dir*=M_PI/180;
+       obj.pos.x /= 1000;
+       obj.pos.y /= 1000;
+       obj.dir *= M_PI/180;
 }
 
 void TrackPart::Loader::start(float x, float y, float d)
 {
-       part.pos=Point(x, y);
-       part.dir=d;
+       obj.pos = Point(x, y);
+       obj.dir = d;
 }
 
 } // namespace Marklin