if(links[0] && links[1])
{
- Vector epp0 = links[0]->get_snap_node(links[0]->get_endpoint_by_link(*this)).position;
- Vector epp1 = links[1]->get_snap_node(links[1]->get_endpoint_by_link(*this)).position;
+ Vector epp0 = links[0]->get_snap_node(links[0]->get_link_slot(*this)).position;
+ Vector epp1 = links[1]->get_snap_node(links[1]->get_link_slot(*this)).position;
position.z = epp0.z;
slope = epp1.z-position.z;
}
slope = 0;
if(links[0])
{
- Vector epp = links[0]->get_snap_node(links[0]->get_endpoint_by_link(*this)).position;
+ Vector epp = links[0]->get_snap_node(links[0]->get_link_slot(*this)).position;
position.z = epp.z;
}
else if(links[1])
{
- Vector epp = links[1]->get_snap_node(links[1]->get_endpoint_by_link(*this)).position;
+ Vector epp = links[1]->get_snap_node(links[1]->get_link_slot(*this)).position;
position.z = epp.z;
}
}
layout.get_driver().set_turnout(turnout_id, p);
}
-int Track::get_endpoint_by_link(Track &other) const
-{
- for(unsigned i=0; i<links.size(); ++i)
- if(links[i]==&other)
- return i;
-
- return -1;
-}
-
-bool Track::snap_to(Track &other, bool link, float limit)
-{
- if(!limit || link)
- {
- limit = layout.get_catalogue().get_gauge();
- if(link && !flex && !other.get_flex())
- limit /= 10;
- }
- limit *= limit;
-
- const vector<TrackType::Endpoint> &eps = type.get_endpoints();
- const vector<TrackType::Endpoint> &other_eps = other.get_type().get_endpoints();
-
- for(unsigned i=0; i<eps.size(); ++i)
- {
- Vector epp = get_snap_node(i).position;
-
- for(unsigned j=0; j<other_eps.size(); ++j)
- {
- if(other.get_link(j))
- continue;
-
- Vector epp2 = other.get_snap_node(j).position;
- float dx = epp2.x-epp.x;
- float dy = epp2.y-epp.y;
- float dz = epp2.z-epp.z;
- if(dx*dx+dy*dy<limit && dz*dz<limit)
- {
- if(!link || (!flex && !other.get_flex()))
- {
- set_rotation(other.rotation+other_eps[j].dir-eps[i].dir+M_PI);
- Vector p(epp2.x-(eps[i].pos.x*cos(rotation)-eps[i].pos.y*sin(rotation)),
- epp2.y-(eps[i].pos.y*cos(rotation)+eps[i].pos.x*sin(rotation)),
- epp2.z);
- if(eps.size()==2 && i==1)
- p.z -= slope;
- set_position(p);
- }
-
- if(link)
- {
- if(links[i])
- break_link(*links[i]);
- links[i] = &other;
- other.links[j] = this;
- layout.create_blocks(*this);
-
- signal_link_changed.emit(i, &other);
- other.signal_link_changed.emit(j, this);
- }
-
- return true;
- }
- }
- }
-
- return false;
-}
-
-void Track::break_link(Track &trk)
-{
- for(vector<Track *>::iterator i=links.begin(); i!=links.end(); ++i)
- if(*i==&trk)
- {
- *i = 0;
- trk.break_link(*this);
- // XXX Creates the blocks twice
- layout.create_blocks(*this);
- signal_link_changed.emit(i-links.begin(), 0);
- return;
- }
-}
-
-void Track::break_links()
-{
- for(vector<Track *>::iterator i=links.begin(); i!=links.end(); ++i)
- if(Track *trk=*i)
- {
- *i = 0;
- trk->break_link(*this);
- }
-}
-
-Track *Track::get_link(unsigned i) const
-{
- if(i>=links.size())
- throw out_of_range("Track::get_link");
-
- return links[i];
-}
-
TrackPoint Track::get_point(unsigned epi, unsigned path, float d) const
{
TrackPoint p = type.get_point(epi, path, d);
return NO_SNAP;
}
+unsigned Track::get_n_link_slots() const
+{
+ return links.size();
+}
+
+Track *Track::get_link(unsigned i) const
+{
+ if(i>=links.size())
+ throw out_of_range("Track::get_link");
+
+ return links[i];
+}
+
+int Track::get_link_slot(const Object &other) const
+{
+ for(unsigned i=0; i<links.size(); ++i)
+ if(links[i]==&other)
+ return i;
+
+ return -1;
+}
+
+bool Track::link_to(Object &other)
+{
+ Track *otrack = dynamic_cast<Track *>(&other);
+ if(!otrack)
+ return false;
+
+ float limit = layout.get_catalogue().get_gauge();
+ if(!flex && !otrack->get_flex())
+ limit /= 10;
+ limit *= limit;
+
+ unsigned nsn = get_n_snap_nodes();
+ unsigned other_nsn = other.get_n_snap_nodes();
+ for(unsigned i=0; i<nsn; ++i)
+ {
+ Snap sn = get_snap_node(i);
+ for(unsigned j=0; j<other_nsn; ++j)
+ {
+ Snap osn = other.get_snap_node(j);
+ Vector d(osn.position.x-sn.position.x, osn.position.y-sn.position.y, osn.position.z-sn.position.z);
+ float da = osn.rotation-sn.rotation-M_PI;
+ while(da<-M_PI)
+ da += M_PI*2;
+ while(da>M_PI)
+ da -= M_PI*2;
+
+ if(d.x*d.x+d.y*d.y<limit && d.z*d.z<limit && da>-0.01 && da<0.01)
+ {
+ break_link(i);
+ links[i] = otrack;
+ otrack->links[j] = this;
+ layout.create_blocks(*this);
+
+ signal_link_changed.emit(i, otrack);
+ otrack->signal_link_changed.emit(j, this);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Track::break_link(unsigned i)
+{
+ if(i>=links.size())
+ throw out_of_range("Track::break_link");
+
+ Track *other = links[i];
+ if(!other)
+ return false;
+
+ links[i] = 0;
+ other->break_link(*this);
+ // XXX Creates the blocks twice, because the other track calls this too
+ layout.create_blocks(*this);
+ signal_link_changed.emit(i, 0);
+
+ return true;
+}
+
bool Track::collide_ray(const Vector &start, const Vector &ray) const
{
Vector local_start(start.x-position.x, start.y-position.y, start.z-position.z);