+ {
+ 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];