]> git.tdb.fi Git - r2c2.git/commitdiff
Improve algorithms in several editing tools
authorMikko Rasa <tdb@tdb.fi>
Mon, 19 Aug 2013 16:21:51 +0000 (19:21 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 19 Aug 2013 16:23:46 +0000 (19:23 +0300)
source/designer/extendtool.cpp
source/designer/extendtool.h
source/designer/movetool.cpp
source/designer/movetool.h
source/designer/slopetool.cpp
source/designer/slopetool.h

index ec4e7f685e9cb037d2b22182df965f68f8bd956d..aa0f72384e2543ec0c73e9abf32de82b4afef168 100644 (file)
@@ -7,21 +7,20 @@ using namespace std;
 using namespace Msp;
 using namespace R2C2;
 
-ExtendTool::ExtendTool(Designer &d, Input::Mouse &m, const set<Object *> &o):
+ExtendTool::ExtendTool(Designer &d, Input::Mouse &m, const set<Object *> &objects):
        Tool(d, m),
-       objects(o),
        accepted(false)
 {
-       bool ok = false;
-       for(set<Object *>::const_iterator i=objects.begin(); (!ok && i!=objects.end()); ++i)
-               if(Track *track = dynamic_cast<Track *>(*i))
+       for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+               if(Track *t = dynamic_cast<Track *>(*i))
                {
-                       const vector<Track *> &links = track->get_links();
-                       for(vector<Track *>::const_iterator j=links.begin(); (!ok && j!=links.end()); ++j)
-                               ok = !*j;
+                       unsigned nls = t->get_n_link_slots();
+                       for(unsigned j=0; j<nls; ++j)
+                               if(!t->get_link(j))
+                                       unlinked_endpoints.push_back(TrackIter(t, j));
                }
 
-       if(!ok)
+       if(unlinked_endpoints.empty())
        {
                done = true;
                set_status("No free endpoints");
@@ -39,50 +38,30 @@ ExtendTool::~ExtendTool()
 
 void ExtendTool::connect()
 {
-       if(objects.size()!=2)
-       {
-               signal_status.emit("Exactly two tracks must be selected");
-               return;
-       }
-
-       Track *track1 = dynamic_cast<Track *>(*objects.begin());
-       Track *track2 = dynamic_cast<Track *>(*--objects.end());
-       if(!track1 || !track2)
-       {
-               signal_status.emit("Exactly two tracks must be selected");
-               return;
-       }
-
        float limit = designer.get_layout().get_catalogue().get_gauge()/10;
 
-       Snap sn1;
+       Track *start_track = 0;
+       Track *end_track = 0;
+       Snap start_sn;
        bool ok = false;
        float gap = 0;
-       unsigned nls1 = track1->get_n_link_slots();
-       unsigned nls2 = track2->get_n_link_slots();
-       for(unsigned i=0; i<nls1; ++i)
+       for(vector<TrackIter>::const_iterator i=unlinked_endpoints.begin(); i!=unlinked_endpoints.end(); ++i)
        {
-               if(track1->get_link(i))
-                       continue;
-
-               sn1 = track1->get_snap_node(i);
+               start_sn = (*i)->get_snap_node(i->entry());
                
-               for(unsigned j=0; j<nls2; ++j)
+               for(vector<TrackIter>::const_iterator j=i; ++j!=unlinked_endpoints.end(); )
                {
-                       if(track2->get_link(j))
-                               continue;
+                       Snap end_sn = (*j)->get_snap_node(j->entry());
 
-                       Snap sn2 = track2->get_snap_node(j);
-
-                       float dz = sn2.position.z-sn1.position.z;
+                       float dz = end_sn.position.z-start_sn.position.z;
                        if(abs(dz)>0.02)
                                continue;
 
-                       Angle adiff = wrap_balanced(sn1.rotation+Angle::half_turn()-sn2.rotation);
+                       Angle adiff = wrap_balanced(start_sn.rotation+Angle::half_turn()-end_sn.rotation);
                        if(abs(adiff).radians()>0.01)
                                continue;
 
-                       Vector delta = rotated_vector(sn2.position-sn1.position, -sn1.rotation);
+                       Vector delta = rotated_vector(end_sn.position-start_sn.position, -start_sn.rotation);
                        if(abs(delta.y)>limit)
                                continue;
 
@@ -103,7 +82,7 @@ void ExtendTool::connect()
                return;
        }
 
-       extend_tracks = create_straight(sn1.position, sn1.rotation, gap, limit);
+       extend_tracks = create_straight(start_sn.position, start_sn.rotation, gap, limit);
 
        if(extend_tracks.empty())
        {
@@ -111,8 +90,8 @@ void ExtendTool::connect()
                return;
        }
 
-       extend_tracks.front()->link_to(*track1);
-       extend_tracks.back()->link_to(*track2);
+       extend_tracks.front()->link_to(*start_track);
+       extend_tracks.back()->link_to(*end_track);
 
        accepted = true;
        set_done();
@@ -122,7 +101,7 @@ void ExtendTool::button_press(unsigned btn)
 {
        if(btn==1)
        {
-               for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+               for(vector<TrackIter>::const_iterator i=unlinked_endpoints.begin(); i!=unlinked_endpoints.end(); ++i)
                        if(extend_tracks.front()->link_to(**i))
                                break;
                accepted = true;
@@ -140,24 +119,17 @@ void ExtendTool::axis_motion(unsigned axis, float value, float rel)
        Angle dir;
        float length = 0;
 
-       for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+       for(vector<TrackIter>::const_iterator i=unlinked_endpoints.begin(); i!=unlinked_endpoints.end(); ++i)
        {
-               unsigned nls = (*i)->get_n_link_slots();
-               for(unsigned j=0; j<nls; ++j)
-               {
-                       if((*i)->get_link(j))
-                               continue;
-
-                       Snap sn = (*i)->get_snap_node(j);
-                       Vector delta = rotated_vector(ground_pointer-sn.position, -sn.rotation);
+               Snap sn = (*i)->get_snap_node(i->entry());
+               Vector delta = rotated_vector(ground_pointer-sn.position, -sn.rotation);
 
-                       if(delta.x<length)
-                               continue;
+               if(delta.x<length)
+                       continue;
 
-                       pos = sn.position;
-                       dir = sn.rotation;
-                       length = delta.x;
-               }
+               pos = sn.position;
+               dir = sn.rotation;
+               length = delta.x;
        }
 
        if(length)
index 979c9205ef7038ba907ef60498c74000b5700de1..8e14fcf89a0cf07ea8bdd8b9bb9e064da5a39602 100644 (file)
@@ -3,13 +3,14 @@
 
 #include <set>
 #include <vector>
-#include "libr2c2/track.h"
+#include "libr2c2/object.h"
+#include "libr2c2/trackiter.h"
 #include "tool.h"
 
 class ExtendTool: public Tool
 {
 private:
-       std::set<R2C2::Object *> objects;
+       std::vector<R2C2::TrackIter> unlinked_endpoints;
        std::vector<R2C2::Track *> extend_tracks;
        bool accepted;
 
index c7bae59cd9a8f010d324d908b5f45699bcfd8d8e..57d72928612e95792e4c5801c349ac97deb70b17 100644 (file)
@@ -9,7 +9,19 @@ using namespace R2C2;
 MoveTool::MoveTool(Designer &d, Input::Mouse &m, const set<Object *> &o):
        Manipulator(d, m, o),
        origin(ground_pointer)
-{ }
+{
+       for(ObjectArray::iterator i=objects.begin(); i!=objects.end(); ++i)
+       {
+               unsigned nls = i->object->get_n_link_slots();
+               for(unsigned j=0; j<nls; ++j)
+                       if(!o.count(i->object->get_link(j)))
+                               boundaries.push_back(Boundary(&*i, j));
+       }
+
+       snap_targets = designer.get_layout().get_all<Object>();
+       for(ObjectArray::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+               snap_targets.erase(i->object);
+}
 
 void MoveTool::axis_motion(unsigned axis, float value, float rel)
 {
@@ -22,21 +34,14 @@ void MoveTool::axis_motion(unsigned axis, float value, float rel)
                i->object->set_rotation(i->original_rotation);
        }
 
-       const set<Track *> &ltracks = designer.get_layout().get_all<Track>();
        float limit = max(designer.get_layout().get_catalogue().get_gauge(),
                designer.get_camera_controller().get_view_scale()/100.0f);
        MObject *snapped = 0;
-       for(set<Track *>::const_iterator i=ltracks.begin(); (i!=ltracks.end() && !snapped); ++i)
+       for(list<Boundary>::iterator i=boundaries.begin(); (!snapped && i!=boundaries.end()); ++i)
        {
-               bool ok = true;
-               for(ObjectArray::iterator j=objects.begin(); (j!=objects.end() && ok); ++j)
-                       ok = (j->object!=*i);
-               if(!ok)
-                       continue;
-
-               for(ObjectArray::iterator j=objects.begin(); (j!=objects.end() && !snapped); ++j)
-                       if(j->object->snap_to(**i, limit))
-                               snapped = &*j;
+               for(set<Object *>::const_iterator j=snap_targets.begin(); (!snapped && j!=snap_targets.end()); ++j)
+                       if((*i)->snap_to(**j, limit))
+                               snapped = i->object;
        }
 
        if(snapped)
@@ -54,3 +59,9 @@ void MoveTool::axis_motion(unsigned axis, float value, float rel)
                }
        }
 }
+
+
+MoveTool::Boundary::Boundary(MObject *o, unsigned i):
+       object(o),
+       index(i)
+{ }
index 5eb1c8599ef1ec9952a89468eb9ba0922da7077d..2f243fefdd5228b3b2a630a610c0f7a751565a54 100644 (file)
@@ -6,6 +6,18 @@
 class MoveTool: public Manipulator
 {
 private:
+       struct Boundary
+       {
+               MObject *object;
+               unsigned index;
+
+               Boundary(MObject *, unsigned);
+
+               R2C2::Object *operator->() const { return object->object; }
+       };
+
+       std::list<Boundary> boundaries;
+       std::set<R2C2::Object *> snap_targets;
        R2C2::Vector origin;
 
 public:
index c38269f050886bdc9778d87685972928caf3978a..0f6990eeec50abda37799186b19d1dcae8c57c31 100644 (file)
@@ -1,3 +1,4 @@
+#include "libr2c2/track.h"
 #include "slopetool.h"
 
 using namespace std;
@@ -9,63 +10,35 @@ SlopeTool::SlopeTool(Designer &d, Input::Mouse &m, const set<Object *> &objects)
        total_length(0)
 {
        for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
-       {
-               unsigned nls = (*i)->get_n_link_slots();
-               if(nls!=2 || !dynamic_cast<Track *>(*i))
+               if(!dynamic_cast<Track *>(*i) || (*i)->get_n_link_slots()!=2)
                {
                        set_status("Must have linear tracks only");
                        return;
                }
-       }
-
-       for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
-       {
-               unsigned nls = (*i)->get_n_link_slots();
-               for(unsigned j=0; j<nls; ++j)
-                       if(Track *link = dynamic_cast<Track *>((*i)->get_link(j)))
-                               if(!objects.count(link))
-                                       neighbors.push_back(link);
-       }
-
-       list<Track *> tmp_tracks;
-       for(set<Object *>::iterator i=objects.begin(); i!=objects.end(); ++i)
-               if(Track *track = dynamic_cast<Track *>(*i))
-                       tmp_tracks.push_back(track);
 
-       Track *cur = neighbors.front();
-       while(!tmp_tracks.empty())
-       {
-               bool rev = false;
-               for(list<Track *>::iterator i=tmp_tracks.begin(); i!=tmp_tracks.end(); ++i)
+       TrackIter track;
+       for(set<Object *>::const_iterator i=objects.begin(); (!track && i!=objects.end()); ++i)
+               if(Track *t = dynamic_cast<Track *>(*i))
                {
-                       const vector<Track *> &links = (*i)->get_links();
-                       if(links[0]==cur)
-                       {
-                               cur = *i;
-                               tmp_tracks.erase(i);
-                               break;
-                       }
-                       else if(links[1]==cur)
-                       {
-                               cur = *i;
-                               rev = true;
-                               tmp_tracks.erase(i);
-                               break;
-                       }
+                       unsigned nls = t->get_n_link_slots();
+                       for(unsigned j=0; (!track && j<nls); ++j)
+                               if(!objects.count((*i)->get_link(j)))
+                                       track = TrackIter(t, j);
                }
-               tracks.push_back(TrackOrder(cur, rev));
-               total_length += cur->get_type().get_total_length();
+
+       total_length = 0;
+       while(track && objects.count(track.track()))
+       {
+               tracks.push_back(track);
+               total_length += track->get_type().get_path_length(0);
+               track = track.next();
        }
 }
 
 void SlopeTool::even_slope(bool smooth)
 {
-       list<Track *>::iterator nb = neighbors.begin();
-       int epi = (*nb)->get_link_slot(*tracks.front().track);
-       float start_z = (*nb)->get_snap_node(epi).position.z;
-       ++nb;
-       epi = (*nb)->get_link_slot(*tracks.back().track);
-       float end_z = (*nb)->get_snap_node(epi).position.z;
+       float start_z = tracks.front()->get_snap_node(tracks.front().entry()).position.z;
+       float end_z = tracks.back()->get_snap_node(tracks.back().reverse().entry()).position.z;
 
        float length = total_length;
        if(smooth)
@@ -78,57 +51,57 @@ void SlopeTool::even_slope(bool smooth)
                        Angle tilt = Geometry::atan(cur_slope);
 
                        set_slope(tracks.front(), start_z, tilt);
-                       start_z += tracks.front().track->get_type().get_path_length(0)*dir*cur_slope;
-                       length -= tracks.front().track->get_type().get_path_length(0);
+                       start_z += tracks.front()->get_type().get_path_length(0)*dir*cur_slope;
+                       length -= tracks.front()->get_type().get_path_length(0);
                        tracks.pop_front();
 
-                       end_z -= tracks.back().track->get_type().get_path_length(0)*dir*cur_slope;
+                       end_z -= tracks.back()->get_type().get_path_length(0)*dir*cur_slope;
                        set_slope(tracks.back(), end_z, tilt);
-                       length -= tracks.back().track->get_type().get_path_length(0);
+                       length -= tracks.back()->get_type().get_path_length(0);
                        tracks.pop_back();
                }
        }
 
        float cur_z = start_z;
        Angle tilt = Geometry::atan((end_z-start_z)/length);
-       for(list<TrackOrder>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+       for(list<TrackIter>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
        {
                set_slope(*i, cur_z, tilt);
-               cur_z += i->track->get_type().get_path_length(0)*(end_z-start_z)/length;
+               cur_z += (*i)->get_type().get_path_length(0)*(end_z-start_z)/length;
        }
 }
 
 void SlopeTool::flatten()
 {
        float z = 0;
-       for(list<TrackOrder>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+       for(list<TrackIter>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
        {
-               unsigned nsn = i->track->get_n_snap_nodes();
+               unsigned nsn = (*i)->get_n_snap_nodes();
                for(unsigned j=0; j<nsn; ++j)
-                       z += i->track->get_snap_node(j).position.z/nsn;
+                       z += (*i)->get_snap_node(j).position.z/nsn;
        }
        z /= static_cast<int>(tracks.size());
 
-       for(list<TrackOrder>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+       for(list<TrackIter>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
        {
-               Vector p = i->track->get_position();
-               i->track->set_position(Vector(p.x, p.y, z));
-               i->track->set_tilt(Angle::zero());
+               Vector p = (*i)->get_position();
+               (*i)->set_position(Vector(p.x, p.y, z));
+               (*i)->set_tilt(Angle::zero());
        }
 }
 
-void SlopeTool::set_slope(TrackOrder &track, float z, const Angle &tilt)
+void SlopeTool::set_slope(const TrackIter &track, float z, const Angle &tilt)
 {
-       const Vector &p = track.track->get_position();
-       float dz = tan(tilt)*track.track->get_type().get_path_length(0);
-       if(track.rev)
+       const Vector &p = track->get_position();
+       float dz = tan(tilt)*track->get_type().get_path_length(0);
+       if(track.entry()==1)
        {
-               track.track->set_position(Vector(p.x, p.y, z+dz));
-               track.track->set_tilt(-tilt);
+               track->set_position(Vector(p.x, p.y, z+dz));
+               track->set_tilt(-tilt);
        }
        else
        {
-               track.track->set_position(Vector(p.x, p.y, z));
-               track.track->set_tilt(tilt);
+               track->set_position(Vector(p.x, p.y, z));
+               track->set_tilt(tilt);
        }
 }
index b3b5e2b461e22d38e9a0689bd54c749d9e03e9b6..9edc1d8c817c3fdf8167fd19f57ca925006f4279 100644 (file)
@@ -1,22 +1,14 @@
 #ifndef SLOPETOOL_H_
 #define SLOPETOOL_H_
 
+#include "libr2c2/object.h"
+#include "libr2c2/trackiter.h"
 #include "tool.h"
-#include "libr2c2/track.h"
 
 class SlopeTool: public Tool
 {
 private:
-       struct TrackOrder
-       {
-               R2C2::Track *track;
-               bool rev;
-
-               TrackOrder(R2C2::Track *t, bool r): track(t), rev(r) { }
-       };
-
-       std::list<R2C2::Track *> neighbors;
-       std::list<TrackOrder> tracks;
+       std::list<R2C2::TrackIter> tracks;
        float total_length;
 
 public:
@@ -25,7 +17,7 @@ public:
        void even_slope(bool =false);
        void flatten();
 private:
-       void set_slope(TrackOrder &, float, const R2C2::Angle &);
+       void set_slope(const R2C2::TrackIter &, float, const R2C2::Angle &);
 };
 
 #endif