]> git.tdb.fi Git - r2c2.git/blobdiff - source/designer/slopetool.cpp
Split the Manipulator class into several Tools
[r2c2.git] / source / designer / slopetool.cpp
diff --git a/source/designer/slopetool.cpp b/source/designer/slopetool.cpp
new file mode 100644 (file)
index 0000000..c38269f
--- /dev/null
@@ -0,0 +1,134 @@
+#include "slopetool.h"
+
+using namespace std;
+using namespace Msp;
+using namespace R2C2;
+
+SlopeTool::SlopeTool(Designer &d, Input::Mouse &m, const set<Object *> &objects):
+       Tool(d, m),
+       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))
+               {
+                       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)
+               {
+                       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;
+                       }
+               }
+               tracks.push_back(TrackOrder(cur, rev));
+               total_length += cur->get_type().get_total_length();
+       }
+}
+
+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 length = total_length;
+       if(smooth)
+       {
+               float dir = (end_z>start_z)?1:-1;
+               float cur_slope = 0;
+               while((end_z-start_z)*dir/length>cur_slope+0.025 && tracks.size()>2)
+               {
+                       cur_slope += 0.025;
+                       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);
+                       tracks.pop_front();
+
+                       end_z -= tracks.back().track->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);
+                       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)
+       {
+               set_slope(*i, cur_z, tilt);
+               cur_z += i->track->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)
+       {
+               unsigned nsn = i->track->get_n_snap_nodes();
+               for(unsigned j=0; j<nsn; ++j)
+                       z += i->track->get_snap_node(j).position.z/nsn;
+       }
+       z /= static_cast<int>(tracks.size());
+
+       for(list<TrackOrder>::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());
+       }
+}
+
+void SlopeTool::set_slope(TrackOrder &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)
+       {
+               track.track->set_position(Vector(p.x, p.y, z+dz));
+               track.track->set_tilt(-tilt);
+       }
+       else
+       {
+               track.track->set_position(Vector(p.x, p.y, z));
+               track.track->set_tilt(tilt);
+       }
+}