]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/trackpart.cpp
Turn TrackPart into a proper class
[r2c2.git] / source / libmarklin / trackpart.cpp
1 /* $Id$
2
3 This file is part of the MSP Märklin suite
4 Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
6 */
7
8 #include <cmath>
9 #include "trackpart.h"
10
11 using namespace std;
12 using namespace Msp;
13
14 #include <msp/io/print.h>
15
16 namespace Marklin {
17
18 TrackPart::TrackPart():
19         dir(0),
20         length(0),
21         radius(0),
22         path(0),
23         dead_end(false)
24 {
25         links[0] = 0;
26         links[1] = 0;
27 }
28
29 float TrackPart::get_length() const
30 {
31         if(radius)
32                 return abs(radius)*length;
33         else
34                 return length;
35 }
36
37 TrackPoint TrackPart::get_point(float d) const
38 {
39         TrackPoint result;
40
41         if(radius)
42         {
43                 float a = d/radius;
44                 float c = cos(a);
45                 float s = sin(a);
46                 float rx = radius*sin(dir);
47                 float ry = -radius*cos(dir);
48                 result.pos = Point(pos.x+c*rx-s*ry-rx, pos.y+c*ry+s*rx-ry);
49                 result.dir = dir+a;
50         }
51         else
52         {
53                 result.pos = Point(pos.x+cos(dir)*d, pos.y+sin(dir)*d);
54                 result.dir = dir;
55         }
56
57         return result;
58 }
59
60 void TrackPart::check_link(TrackPart &other)
61 {
62         unsigned n_eps = (dead_end ? 1 : 2);
63         unsigned n_other_eps = (other.is_dead_end() ? 1 : 2);
64         for(unsigned i=0; i<n_eps; ++i)
65         {
66                 TrackPoint p1 = get_point(i ? get_length() : 0);
67                 for(unsigned j=0; j<n_other_eps; ++j)
68                 {
69                         TrackPoint p2 = other.get_point(j ? other.get_length() : 0);
70
71                         float dx = p2.pos.x-p1.pos.x;
72                         float dy = p2.pos.y-p1.pos.y;
73
74                         float da = p2.dir-p1.dir+M_PI*((i+j+1)%2);
75                         while(da>M_PI)
76                                 da -= M_PI*2;
77                         while(da<-M_PI)
78                                 da += M_PI*2;
79
80                         if(dx*dx+dy*dy<1e-6 && da>=-0.01 && da<=0.01)
81                         {
82                                 IO::print("TrackParts linked!\n");
83                                 links[i] = &other;
84                                 other.links[j] = this;
85                                 return;
86                         }
87                 }
88         }
89 }
90
91 TrackPart *TrackPart::get_link(unsigned i) const
92 {
93         if(i>=2)
94                 throw InvalidParameterValue("Index out of range");
95         return links[i];
96 }
97
98
99 TrackPart::Loader::Loader(TrackPart &p):
100         Msp::DataFile::BasicLoader<TrackPart>(p)
101 {
102         add("start",    &Loader::start);
103         add("length",   &TrackPart::length);
104         add("radius",   &TrackPart::radius);
105         add("path",     &TrackPart::path);
106         add("dead_end", &TrackPart::dead_end);
107 }
108
109 void TrackPart::Loader::finish()
110 {
111         if(obj.radius)
112         {
113                 obj.length *= M_PI/180;
114                 obj.radius /= 1000;
115         }
116         else
117                 obj.length /= 1000;
118
119         obj.pos.x /= 1000;
120         obj.pos.y /= 1000;
121         obj.dir *= M_PI/180;
122 }
123
124 void TrackPart::Loader::start(float x, float y, float d)
125 {
126         obj.pos = Point(x, y);
127         obj.dir = d;
128 }
129
130 } // namespace Marklin