]> git.tdb.fi Git - r2c2.git/commitdiff
Add a generic snapping interface in Object
authorMikko Rasa <tdb@tdb.fi>
Sun, 12 May 2013 16:08:30 +0000 (19:08 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 13 May 2013 19:40:53 +0000 (22:40 +0300)
13 files changed:
source/3d/endpoint.cpp
source/designer/manipulator.cpp
source/designer/measure.cpp
source/designer/measure.h
source/designer/svgexporter.cpp
source/engineer/engineer.cpp
source/libr2c2/object.cpp [new file with mode: 0644]
source/libr2c2/object.h
source/libr2c2/signal.cpp
source/libr2c2/signal.h
source/libr2c2/snap.h [new file with mode: 0644]
source/libr2c2/track.cpp
source/libr2c2/track.h

index e851007b2ba0736546f27b6d81ae5bac2518a1c5..5d7ebb511e9838dfc4febf34e740399bfd6c7467 100644 (file)
@@ -27,13 +27,12 @@ void Endpoint3D::render(GL::Renderer &renderer, const GL::Tag &tag) const
 {
        if(tag=="unlit")
        {
-               Vector p = track.get_track().get_endpoint_position(index);
-               float a = track.get_track().get_endpoint_direction(index)+M_PI;
+               Snap sn = track.get_track().get_snap_node(index);
 
                GL::MatrixStack::Push push_mtx(renderer.matrix_stack());
                GL::Matrix matrix;
-               matrix.translate(p.x, p.y, p.z);
-               matrix.rotate(a, 0, 0, 1);
+               matrix.translate(sn.position.x, sn.position.y, sn.position.z);
+               matrix.rotate(sn.rotation+M_PI, 0, 0, 1);
                renderer.matrix_stack() *= matrix;
 
                if(track.get_track().get_link(index))
index 5b95d5c4bddab072fbdce0c4d3b0588aa1925e70..6aca114aa5538ecfbceebf5ab328009c4b5a675b 100644 (file)
@@ -174,10 +174,10 @@ void Manipulator::even_slope(bool smooth)
 
        set<Track *>::iterator nb = neighbors.begin();
        int epi = (*nb)->get_endpoint_by_link(*order.front().track);
-       float start_z = (*nb)->get_endpoint_position(epi).z;
+       float start_z = (*nb)->get_snap_node(epi).position.z;
        ++nb;
        epi = (*nb)->get_endpoint_by_link(*order.back().track);
-       float end_z = (*nb)->get_endpoint_position(epi).z;
+       float end_z = (*nb)->get_snap_node(epi).position.z;
 
        if(smooth)
        {
@@ -233,8 +233,7 @@ void Manipulator::connect()
 
        float limit = designer.get_layout().get_catalogue().get_gauge()/10;
 
-       Vector pos1;
-       float dir1;
+       Snap sn1;
        bool ok = false;
        float gap = 0;
        for(unsigned i=0; i<track1->get_type().get_endpoints().size(); ++i)
@@ -242,22 +241,20 @@ void Manipulator::connect()
                if(track1->get_link(i))
                        continue;
 
-               pos1 = track1->get_endpoint_position(i);
-               dir1 = track1->get_endpoint_direction(i);
+               sn1 = track1->get_snap_node(i);
 
                for(unsigned j=0; j<track2->get_type().get_endpoints().size(); ++j)
                {
                        if(track2->get_link(j))
                                continue;
 
-                       Vector pos2 = track2->get_endpoint_position(j);
-                       float dir2 = track2->get_endpoint_direction(j);
+                       Snap sn2 = track2->get_snap_node(j);
 
-                       float dz = pos2.z-pos1.z;
+                       float dz = sn2.position.z-sn1.position.z;
                        if(abs(dz)>0.02)
                                continue;
 
-                       float adiff = dir1+M_PI-dir2;
+                       float adiff = sn1.rotation+M_PI-sn2.rotation;
                        while(adiff<-M_PI)
                                adiff += M_PI*2;
                        while(adiff>M_PI)
@@ -265,10 +262,10 @@ void Manipulator::connect()
                        if(abs(adiff)>0.01)
                                continue;
 
-                       float c = cos(dir1);
-                       float s = sin(dir1);
-                       float dx = pos2.x-pos1.x;
-                       float dy = pos2.y-pos1.y;
+                       float c = cos(sn1.rotation);
+                       float s = sin(sn1.rotation);
+                       float dx = sn2.position.x-sn1.position.x;
+                       float dy = sn2.position.y-sn1.position.y;
                        if(abs(dx*s-dy*c)>limit)
                                continue;
 
@@ -289,7 +286,7 @@ void Manipulator::connect()
                return;
        }
 
-       vector<Track *> trks = create_straight(pos1, dir1, gap, limit);
+       vector<Track *> trks = create_straight(sn1.position, sn1.rotation, gap, limit);
 
        if(trks.empty())
        {
@@ -472,19 +469,18 @@ void Manipulator::axis_motion(unsigned axis, float value, float)
                                if(track->get_link(j))
                                        continue;
 
-                               Vector ep_pos = track->get_endpoint_position(j);
-                               float ep_dir = track->get_endpoint_direction(j);
-                               float c = cos(ep_dir);
-                               float s = sin(ep_dir);
-                               float dx = gpointer.x-ep_pos.x;
-                               float dy = gpointer.y-ep_pos.y;
+                               Snap sn = track->get_snap_node(j);
+                               float c = cos(sn.rotation);
+                               float s = sin(sn.rotation);
+                               float dx = gpointer.x-sn.position.x;
+                               float dy = gpointer.y-sn.position.y;
 
                                float len = dx*c+dy*s;
                                if(len<length)
                                        continue;
 
-                               pos = ep_pos;
-                               dir = ep_dir;
+                               pos = sn.position;
+                               dir = sn.rotation;
                                length = len;
                        }
                }
@@ -557,7 +553,7 @@ void Manipulator::update_objects()
                        unsigned n_endpoints = track->get_type().get_endpoints().size();
                        for(unsigned j=0; j<n_endpoints; ++j)
                        {
-                               Vector p = track->get_endpoint_position(j);
+                               Vector p = track->get_snap_node(j).position;
                                if(i==objects.begin() && j==0)
                                        minp = maxp = p;
                                else
index f115f9ddd5a287f9f7a14df8f170fc8ef1e346f4..69ada814e110ff53935e8151e70462762cf8e059 100644 (file)
@@ -28,9 +28,9 @@ void Measure::button_press(float gx, float gy, unsigned btn)
 
        if(btn==1)
        {
-               spoint = Vector(gx, gy, 0);
-               sdir = 0;
-               snap_to_tracks(spoint, sdir);
+               ssnap.position = Vector(gx, gy, 0);
+               ssnap.rotation = 0;
+               snap_to_tracks(ssnap);
 
                state = ACTIVE;
        }
@@ -54,20 +54,21 @@ void Measure::pointer_motion(float gx, float gy)
        if(!state)
                return;
 
-       pointer = Vector(gx, gy, 0);
-       float dir = sdir;
-       snap_to_tracks(pointer, dir);
+       Snap sn = ssnap;
+       sn.position = Vector(gx, gy, 0);
+       snap_to_tracks(sn);
+       pointer = sn.position;
 
        if(state!=STARTING)
        {
-               Vector delta(pointer.x-spoint.x, pointer.y-spoint.y, 0);
-               float c = cos(sdir);
-               float s = sin(sdir);
+               Vector delta(pointer.x-ssnap.position.x, pointer.y-ssnap.position.y, 0);
+               float c = cos(ssnap.rotation);
+               float s = sin(ssnap.rotation);
 
                par_dist = delta.x*c+delta.y*s;
                perp_dist = delta.x*s-delta.y*c;
 
-               adiff = dir-sdir+M_PI;
+               adiff = sn.rotation-ssnap.rotation+M_PI;
                while(adiff<-M_PI)
                        adiff += M_PI*2;
                while(adiff>M_PI)
@@ -85,7 +86,7 @@ void Measure::render(GL::Renderer &renderer, const GL::Tag &) const
                return;
 
        GL::Renderer::Push push(renderer);
-       const Vector &pos = (state==ACTIVE ? spoint : pointer);
+       const Vector &pos = (state==ACTIVE ? ssnap.position : pointer);
        renderer.matrix_stack() *= GL::Matrix::translation(pos.x, pos.y, pos.z);
 
        mesh.draw(renderer);
@@ -108,25 +109,25 @@ void Measure::update_mesh()
 
        if(state==ACTIVE)
        {
-               float c = cos(sdir);
-               float s = sin(sdir);
+               float c = cos(ssnap.rotation);
+               float s = sin(ssnap.rotation);
                bld.begin(GL::QUAD_STRIP);
                bld.vertex(0, 0, 0);
                bld.vertex(0, 0, 0.01);
                bld.vertex(c*par_dist, s*par_dist, 0);
                bld.vertex(c*par_dist, s*par_dist, 0.01);
-               bld.vertex(pointer.x-spoint.x, pointer.y-spoint.y, 0);
-               bld.vertex(pointer.x-spoint.x, pointer.y-spoint.y, 0.01);
+               bld.vertex(pointer.x-ssnap.position.x, pointer.y-ssnap.position.y, 0);
+               bld.vertex(pointer.x-ssnap.position.x, pointer.y-ssnap.position.y, 0.01);
                bld.vertex(0, 0, 0);
                bld.vertex(0, 0, 0.01);
                bld.end();
        }
 }
 
-void Measure::snap_to_tracks(Vector &pt, float &dir)
+void Measure::snap_to_tracks(Snap &sn)
 {
        const set<Track *> &ltracks = designer.get_layout().get_tracks();
        for(set<Track *>::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i)
-               if((*i)->snap(pt, dir))
+               if((*i)->snap(sn, 0.01, SNAP_NODE))
                        return;
 }
index 84b1c832ea21a646052b05c432e07cdeb0c3da5f..022c3140639427367b6c4d1d86b42655f1aacfa1 100644 (file)
@@ -23,8 +23,7 @@ public:
 private:
        Designer &designer;
        R2C2::Vector pointer;
-       R2C2::Vector spoint;
-       float sdir;
+       R2C2::Snap ssnap;
        float par_dist;
        float perp_dist;
        float adiff;
@@ -42,7 +41,7 @@ public:
        virtual void render(Msp::GL::Renderer &, const Msp::GL::Tag &) const;
 private:
        void update_mesh();
-       void snap_to_tracks(R2C2::Vector &, float &);
+       void snap_to_tracks(R2C2::Snap &);
 };
 
 #endif
index 11edf645ad7cff6cf2571e383a102e58f4ade6f3..62e869c368215ae7b1c590f02c7f227a0caed589 100644 (file)
@@ -45,7 +45,7 @@ void SvgExporter::save(const string &fn)
                unsigned n_endpoints = (*i)->get_type().get_endpoints().size();
                for(unsigned j=0; j<n_endpoints; ++j)
                {
-                       Vector pos = (*i)->get_endpoint_position(j);
+                       Vector pos = (*i)->get_snap_node(j).position;
                        if(i==tracks.begin() && j==0)
                                minp = maxp = pos;
                        else
index e19c11e063707a8e7e91383a51044e9ce100f8df..b0296a192d6cbb175b9fd8c3c03e078c14425201 100644 (file)
@@ -230,11 +230,10 @@ void Engineer::tick()
                camera.apply();
                GL::MatrixStack::Push push_mat(GL::MatrixStack::modelview());
 
-               float rot = picking_track->get_endpoint_direction(picking_entry);
-               Vector pos = picking_track->get_endpoint_position(picking_entry);
+               Snap sn = picking_track->get_snap_node(picking_entry);
 
-               GL::MatrixStack::modelview() *= GL::Matrix::translation(pos.x, pos.y, pos.z+0.03);
-               GL::MatrixStack::modelview() *= GL::Matrix::rotation(rot+M_PI, 0, 0, 1);
+               GL::MatrixStack::modelview() *= GL::Matrix::translation(sn.position.x, sn.position.y, sn.position.z+0.03);
+               GL::MatrixStack::modelview() *= GL::Matrix::rotation(sn.rotation+M_PI, 0, 0, 1);
 
                arrow_mesh.draw();
        }
diff --git a/source/libr2c2/object.cpp b/source/libr2c2/object.cpp
new file mode 100644 (file)
index 0000000..1b48a86
--- /dev/null
@@ -0,0 +1,60 @@
+#include <stdexcept>
+#include "object.h"
+
+using namespace std;
+
+namespace R2C2 {
+
+Snap Object::get_snap_node(unsigned) const
+{
+       throw out_of_range("Object::get_snap_node");
+}
+
+bool Object::snap(Snap &sn, float limit, SnapType what) const
+{
+       if(what&SNAP_NODE)
+       {
+               unsigned nsn = get_n_snap_nodes();
+               for(unsigned i=0; i<nsn; ++i)
+               {
+                       Snap node = get_snap_node(i);
+                       Vector d(sn.position.x-node.position.x, sn.position.y-node.position.y, sn.position.z-node.position.z);
+                       if(d.x*d.x+d.y*d.y<limit*limit)
+                       {
+                               sn = node;
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
+bool Object::snap_to(const Object &other, float limit, SnapType what)
+{
+       if(what==SNAP_DEFAULT)
+               what = get_default_snap_type_to(other);
+
+       if(!what)
+               return false;
+
+       unsigned nsn = get_n_snap_nodes();
+       for(unsigned i=0; i<nsn; ++i)
+       {
+               Snap sn = get_snap_node(i);
+               Snap ssn = sn;
+               if(other.snap(ssn, limit, what))
+               {
+                       set_rotation(rotation+ssn.rotation-sn.rotation-M_PI);
+                       sn = get_snap_node(i);
+                       position.x += ssn.position.x-sn.position.x;
+                       position.y += ssn.position.y-sn.position.y;
+                       position.z += ssn.position.z-sn.position.z;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+} // namespace R2C2
index 206ec336d8e1cb99b1dd26f9dad09ea9bd3907a3..8ce521ab5366df54375973e3db4715e11cc0c81e 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "geometry.h"
 #include "objecttype.h"
+#include "snap.h"
 
 namespace R2C2 {
 
@@ -27,6 +28,15 @@ public:
        const Vector &get_position() const { return position; }
        float get_rotation() const { return rotation; }
        virtual Object *get_parent() const { return 0; }
+
+       virtual unsigned get_n_snap_nodes() const { return 0; }
+       virtual Snap get_snap_node(unsigned) const;
+       virtual bool snap(Snap &, float, SnapType = SNAP_DEFAULT) const;
+       virtual bool snap_to(const Object &, float, SnapType = SNAP_DEFAULT);
+protected:
+       virtual SnapType get_default_snap_type_to(const Object &) const { return NO_SNAP; }
+
+public:
        virtual bool collide_ray(const Vector &, const Vector &) const = 0;
 };
 
index 72cf235193e6a9c537e67a003ede7a221b8c7673..650c36232e87d82559fc36cfbb6aba2bc160ab55 100644 (file)
@@ -56,12 +56,15 @@ void Signal::set_position(const Vector &p)
        for(set<Track *>::const_iterator i=tracks.begin(); i!=tracks.end(); ++i)
                if(!(*i)->get_type().is_turnout())
                {
-                       TrackPoint n = (*i)->get_nearest_point(p);
-                       float d = distance(p, n.pos);
+                       Snap sn;
+                       sn.position = p;
+                       sn.rotation = rotation;
+                       (*i)->snap(sn, 1000, SNAP_SEGMENT);
+                       float d = distance(p, sn.position);
                        if(d<dist || dist<0)
                        {
-                               position = n.pos;
-                               rotation = n.dir;
+                               position = sn.position;
+                               rotation = sn.rotation;
                                track = *i;
                                dist = d;
                        }
@@ -77,7 +80,7 @@ void Signal::normalize_location()
        unsigned n_endpoints = track->get_type().get_endpoints().size();
        for(unsigned j=0; j<n_endpoints; ++j)
        {
-               float a = track->get_endpoint_direction(j)-rotation;
+               float a = track->get_snap_node(j).rotation-rotation;
                while(a<-M_PI/2)
                        a += M_PI*2;
                while(a>M_PI*3/2)
@@ -107,6 +110,30 @@ void Signal::set_rotation(float r)
        normalize_location();
 }
 
+unsigned Signal::get_n_snap_nodes() const
+{
+       return 1;
+}
+
+Snap Signal::get_snap_node(unsigned i) const
+{
+       if(i>=1)
+               throw out_of_range("Signal::get_snap_node");
+
+       Snap sn;
+       sn.position = position;
+       sn.rotation = rotation;
+       return sn;
+}
+
+SnapType Signal::get_default_snap_type_to(const Object &other) const
+{
+       if(dynamic_cast<const Track *>(&other))
+               return SNAP_SEGMENT;
+
+       return NO_SNAP;
+}
+
 bool Signal::collide_ray(const Vector &start, const Vector &ray) const
 {
        // XXX Totally hardcoded stuff, should be replaced with a geometry system
index 92e197744ba975f257198cb4984d559963b08e7e..b6049516c45b6ffa18db0c664cdfccbfdf984a6b 100644 (file)
@@ -54,6 +54,12 @@ private:
 public:
        virtual Track *get_parent() const { return track; }
 
+       virtual unsigned get_n_snap_nodes() const;
+       virtual Snap get_snap_node(unsigned) const;
+private:
+       virtual SnapType get_default_snap_type_to(const Object &) const;
+
+public:
        virtual bool collide_ray(const Vector &, const Vector &) const;
 
        void tick(const Msp::Time::TimeDelta &);
diff --git a/source/libr2c2/snap.h b/source/libr2c2/snap.h
new file mode 100644 (file)
index 0000000..844af3d
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef LIBR2C2_SNAP_H_
+#define LIBR2C2_SNAP_H_
+
+namespace R2C2 {
+
+enum SnapType
+{
+       SNAP_DEFAULT = 0,
+       NO_SNAP = 0,
+       SNAP_NODE = 1,
+       SNAP_SEGMENT = 2
+};
+
+struct Snap
+{
+       Vector position;
+       float rotation;
+};
+
+inline SnapType operator|(SnapType s1, SnapType s2)
+{ return static_cast<SnapType>(static_cast<int>(s1)|static_cast<int>(s2)); }
+
+} // namespace R2C2
+
+#endif
index b679af783867f72746793f205179f004a9e02baa..e4d7badfb9f9e053d2dc7fa7650b039bf890cf90 100644 (file)
@@ -100,8 +100,8 @@ void Track::check_slope()
 
        if(links[0] && links[1])
        {
-               Vector epp0 = links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this));
-               Vector epp1 = links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this));
+               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;
                position.z = epp0.z;
                slope = epp1.z-position.z;
        }
@@ -110,12 +110,12 @@ void Track::check_slope()
                slope = 0;
                if(links[0])
                {
-                       Vector epp = links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this));
+                       Vector epp = links[0]->get_snap_node(links[0]->get_endpoint_by_link(*this)).position;
                        position.z = epp.z;
                }
                else if(links[1])
                {
-                       Vector epp = links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this));
+                       Vector epp = links[1]->get_snap_node(links[1]->get_endpoint_by_link(*this)).position;
                        position.z = epp.z;
                }
        }
@@ -164,34 +164,6 @@ int Track::get_endpoint_by_link(Track &other) const
        return -1;
 }
 
-Vector Track::get_endpoint_position(unsigned epi) const
-{
-       const vector<TrackType::Endpoint> &eps = type.get_endpoints();
-       if(epi>=eps.size())
-               throw out_of_range("Track::get_endpoint_position");
-
-       const TrackType::Endpoint &ep = eps[epi];
-
-       float c = cos(rotation);
-       float s = sin(rotation);
-
-       Vector p(position.x+c*ep.pos.x-s*ep.pos.y, position.y+s*ep.pos.x+c*ep.pos.y, position.z);
-       if(eps.size()==2 && epi==1)
-               p.z += slope;
-       return p;
-}
-
-float Track::get_endpoint_direction(unsigned epi) const
-{
-       const vector<TrackType::Endpoint> &eps = type.get_endpoints();
-       if(epi>=eps.size())
-               throw out_of_range("Track::get_endpoint_direction");
-
-       const TrackType::Endpoint &ep = eps[epi];
-
-       return rotation+ep.dir;
-}
-
 bool Track::snap_to(Track &other, bool link, float limit)
 {
        if(!limit || link)
@@ -207,14 +179,14 @@ bool Track::snap_to(Track &other, bool link, float limit)
 
        for(unsigned i=0; i<eps.size(); ++i)
        {
-               Vector epp = get_endpoint_position(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_endpoint_position(j);
+                       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;
@@ -251,26 +223,6 @@ bool Track::snap_to(Track &other, bool link, float limit)
        return false;
 }
 
-bool Track::snap(Vector &pt, float &d) const
-{
-       const vector<TrackType::Endpoint> &eps = type.get_endpoints();
-
-       for(unsigned i=0; i<eps.size(); ++i)
-       {
-               Vector epp = get_endpoint_position(i);
-               float dx = pt.x-epp.x;
-               float dy = pt.y-epp.y;
-               if(dx*dx+dy*dy<1e-4)
-               {
-                       pt = epp;
-                       d = rotation+eps[i].dir;
-                       return true;
-               }
-       }
-
-       return false;
-}
-
 void Track::break_link(Track &trk)
 {
        for(vector<Track *>::iterator i=links.begin(); i!=links.end(); ++i)
@@ -335,17 +287,63 @@ TrackPoint Track::get_point(unsigned epi, float d) const
        return get_point(epi, active_path, d);
 }
 
-TrackPoint Track::get_nearest_point(const Vector &p) const
+unsigned Track::get_n_snap_nodes() const
 {
-       Vector local(p.x-position.x, p.y-position.y, p.z-position.z);
+       return type.get_endpoints().size();
+}
+
+Snap Track::get_snap_node(unsigned i) const
+{
+       const vector<TrackType::Endpoint> &eps = type.get_endpoints();
+       if(i>=eps.size())
+               throw out_of_range("Track::get_snap_node");
+
+       Snap result;
+       const TrackType::Endpoint &ep = eps[i];
+
        float c = cos(rotation);
        float s = sin(rotation);
-       local = Vector(c*local.x+s*local.y, c*local.y-s*local.x, local.z);
 
-       TrackPoint tp = type.get_nearest_point(local);
-       tp.pos = Vector(position.x+tp.pos.x*c-tp.pos.y*s, position.y+tp.pos.y*c+tp.pos.x*s, position.z+tp.pos.z);
-       tp.dir += rotation;
-       return tp;
+       result.position = Vector(position.x+c*ep.pos.x-s*ep.pos.y, position.y+s*ep.pos.x+c*ep.pos.y, position.z);
+       if(eps.size()==2 && i==1)
+               result.position.z += slope;
+
+       result.rotation = rotation+ep.dir;
+
+       return result;
+}
+
+bool Track::snap(Snap &sn, float limit, SnapType what) const
+{
+       if(Object::snap(sn, limit, what))
+               return true;
+
+       if(what&SNAP_SEGMENT)
+       {
+               Vector local(sn.position.x-position.x, sn.position.y-position.y, sn.position.z-position.z);
+               float c = cos(rotation);
+               float s = sin(rotation);
+               local = Vector(c*local.x+s*local.y, c*local.y-s*local.x, local.z);
+
+               TrackPoint tp = type.get_nearest_point(local);
+               Vector d(local.x-tp.pos.x, local.y-tp.pos.y, local.z-tp.pos.z);
+               if(d.x*d.x+d.y*d.y+d.z*d.z<=limit*limit)
+               {
+                       sn.position = Vector(position.x+tp.pos.x*c-tp.pos.y*s, position.y+tp.pos.y*c+tp.pos.x*s, position.z+tp.pos.z);
+                       sn.rotation = tp.dir+rotation;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+SnapType Track::get_default_snap_type_to(const Object &other) const
+{
+       if(dynamic_cast<const Track *>(&other))
+               return SNAP_NODE;
+
+       return NO_SNAP;
 }
 
 bool Track::collide_ray(const Vector &start, const Vector &ray) const
index 883fb5eda506ab04a0614bbbebf1333560bbe41f..b8a9a3d330bc6f472818f24a006266e111c9552b 100644 (file)
@@ -70,18 +70,21 @@ public:
        bool is_path_changing() const { return path_changing; }
 
        int get_endpoint_by_link(Track &) const;
-       Vector get_endpoint_position(unsigned) const;
-       float get_endpoint_direction(unsigned) const;
        bool snap_to(Track &, bool, float = 0);
-       bool snap(Vector &, float &) const;
        void break_link(Track &);
        void break_links();
        const std::vector<Track *> &get_links() const { return links; }
        Track *get_link(unsigned) const;
        TrackPoint get_point(unsigned, unsigned, float) const;
        TrackPoint get_point(unsigned, float) const;
-       TrackPoint get_nearest_point(const Vector &) const;
 
+       virtual unsigned get_n_snap_nodes() const;
+       virtual Snap get_snap_node(unsigned) const;
+       virtual bool snap(Snap &, float, SnapType = SNAP_DEFAULT) const;
+private:
+       virtual SnapType get_default_snap_type_to(const Object &) const;
+
+public:
        virtual bool collide_ray(const Vector &, const Vector &) const;
 
        void save(std::list<Msp::DataFile::Statement> &) const;