/* $Id$
This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
Distributed under the GPL
*/
#include "trackpart.h"
using namespace std;
+using namespace Msp;
namespace Marklin {
TrackPart::TrackPart():
- x(0),
- y(0),
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)
+TrackPoint TrackPart::get_point(float d) const
{
- eps.push_back(Endpoint(x, y, dir+M_PI, 1<<route));
+ TrackPoint result;
- if(dead_end)
- ;
- else if(radius)
+ if(radius)
{
- float a=((radius<0) ? -length : length);
- float c=cos(a);
- float s=sin(a);
- float rx=radius*sin(dir);
- float ry=-radius*cos(dir);
- eps.push_back(Endpoint(x+c*rx-s*ry-rx, y+c*ry+s*rx-ry, 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(x+cos(dir)*length, 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;
+}
+
+void TrackPart::check_link(TrackPart &other)
+{
+ 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)
+ {
+ 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;
+ }
+ }
+ }
+}
+
+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.x/=1000;
- part.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.x=x;
- part.y=y;
- part.dir=d;
+ obj.pos = Point(x, y);
+ obj.dir = d;
}
} // namespace Marklin