]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/trackattachment.cpp
Add a function to retrieve track attachments in order
[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         layout.signal_object_removed.connect(sigc::mem_fun(this, &TrackAttachment::object_removed));
15 }
16
17 TrackAttachment::~TrackAttachment()
18 {
19         if(track)
20                 track->remove_attachment(*this);
21 }
22
23 float TrackAttachment::get_offset_from_endpoint(unsigned epi) const
24 {
25         if(epi==track.entry())
26                 return offset;
27         else
28                 return track->get_type().get_path_length(0)-offset;
29 }
30
31 void TrackAttachment::attach_to(const TrackIter &t, float o)
32 {
33         if(track)
34                 track->remove_attachment(*this);
35
36         track = t;
37         offset = o;
38
39         if(track)
40                 track->add_attachment(*this);
41 }
42
43 void TrackAttachment::attach_to_closest(float limit)
44 {
45         const set<Track *> &tracks = layout.get_all<Track>();
46         float dist = -1;
47         Track *trk = 0;
48         Vector closest;
49         for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
50                 if(!(*i)->get_type().is_turnout())
51                 {
52                         Snap sn;
53                         sn.position = position;
54                         sn.rotation = rotation;
55                         if((*i)->snap(sn, limit, SNAP_SEGMENT))
56                         {
57                                 float d = distance(position, sn.position);
58                                 if(d<dist || dist<0)
59                                 {
60                                         trk = *i;
61                                         closest = sn.position;
62                                         dist = d;
63                                 }
64                         }
65                 }
66
67         if(trk)
68         {
69                 unsigned nsn = trk->get_n_snap_nodes();
70                 for(unsigned i=0; i<nsn; ++i)
71                 {
72                         Snap sn = trk->get_snap_node(i);
73                         Angle adiff = abs(wrap_balanced(sn.rotation-rotation));
74                         if(adiff<Angle::quarter_turn())
75                         {
76                                 TrackIter iter(trk, i);
77                                 attach_to(iter, find_offset(iter, closest));
78                                 break;
79                         }
80                 }
81         }
82         else
83                 attach_to(TrackIter(), 0);
84 }
85
86 float TrackAttachment::find_offset(const TrackIter &trk, const Vector &point)
87 {
88         float margin = 0.01*layout.get_catalogue().get_scale();
89         Vector epp = trk->get_snap_node(trk.entry()).position;
90
91         float dist = distance(epp, point);
92         float offs = min(dist, trk->get_type().get_path_length(0));
93         while(1)
94         {
95                 TrackPoint tp = trk->get_point(trk.entry(), offs);
96                 float diff = dist-distance(epp, tp.pos);
97                 if(abs(diff)<margin)
98                         break;
99                 offs += diff;
100         }
101
102         return offs;
103 }
104
105 void TrackAttachment::object_removed(Object &o)
106 {
107         if(&o==track.track())
108                 track = TrackIter();
109 }
110
111 } // namespace R2C"