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