]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/trackattachment.cpp
Add an abstraction for things that are attached to tracks
[r2c2.git] / source / libr2c2 / trackattachment.cpp
1 #include "catalogue.h"
2 #include "layout.h"
3 #include "track.h"
4 #include "trackattachment.h"
5
6 using namespace std;
7
8 namespace R2C2 {
9
10 TrackAttachment::TrackAttachment(Layout &l):
11         Object(l),
12         offset(0)
13 { }
14
15 TrackAttachment::~TrackAttachment()
16 {
17         if(track)
18                 track->remove_attachment(*this);
19 }
20
21 void TrackAttachment::attach_to(const TrackIter &t, float o)
22 {
23         if(track)
24                 track->remove_attachment(*this);
25
26         track = t;
27         offset = o;
28
29         if(track)
30                 track->add_attachment(*this);
31 }
32
33 void TrackAttachment::attach_to_closest(float limit)
34 {
35         const set<Track *> &tracks = layout.get_all<Track>();
36         float dist = -1;
37         Track *trk = 0;
38         Vector closest;
39         for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
40                 if(!(*i)->get_type().is_turnout())
41                 {
42                         Snap sn;
43                         sn.position = position;
44                         sn.rotation = rotation;
45                         if((*i)->snap(sn, limit, SNAP_SEGMENT))
46                         {
47                                 float d = distance(position, sn.position);
48                                 if(d<dist || dist<0)
49                                 {
50                                         trk = *i;
51                                         closest = sn.position;
52                                         dist = d;
53                                 }
54                         }
55                 }
56
57         if(trk)
58         {
59                 unsigned nsn = trk->get_n_snap_nodes();
60                 for(unsigned i=0; i<nsn; ++i)
61                 {
62                         Snap sn = trk->get_snap_node(i);
63                         Angle adiff = abs(wrap_balanced(sn.rotation-rotation));
64                         if(adiff<Angle::quarter_turn())
65                         {
66                                 TrackIter iter(trk, i);
67                                 attach_to(iter, find_offset(iter, closest));
68                                 break;
69                         }
70                 }
71         }
72         else
73                 attach_to(TrackIter(), 0);
74 }
75
76 float TrackAttachment::find_offset(const TrackIter &trk, const Vector &point)
77 {
78         float margin = 0.01*layout.get_catalogue().get_scale();
79         Vector epp = trk->get_snap_node(trk.entry()).position;
80
81         float dist = distance(epp, point);
82         float offs = dist;
83         while(1)
84         {
85                 TrackPoint tp = trk->get_point(trk.entry(), offs);
86                 float diff = dist-distance(epp, tp.pos);
87                 if(abs(diff)<margin)
88                         break;
89                 offs += diff;
90         }
91
92         return offs;
93 }
94
95 } // namespace R2C"