]> git.tdb.fi Git - r2c2.git/blob - source/designer/slopetool.cpp
Split the Manipulator class into several Tools
[r2c2.git] / source / designer / slopetool.cpp
1 #include "slopetool.h"
2
3 using namespace std;
4 using namespace Msp;
5 using namespace R2C2;
6
7 SlopeTool::SlopeTool(Designer &d, Input::Mouse &m, const set<Object *> &objects):
8         Tool(d, m),
9         total_length(0)
10 {
11         for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
12         {
13                 unsigned nls = (*i)->get_n_link_slots();
14                 if(nls!=2 || !dynamic_cast<Track *>(*i))
15                 {
16                         set_status("Must have linear tracks only");
17                         return;
18                 }
19         }
20
21         for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
22         {
23                 unsigned nls = (*i)->get_n_link_slots();
24                 for(unsigned j=0; j<nls; ++j)
25                         if(Track *link = dynamic_cast<Track *>((*i)->get_link(j)))
26                                 if(!objects.count(link))
27                                         neighbors.push_back(link);
28         }
29
30         list<Track *> tmp_tracks;
31         for(set<Object *>::iterator i=objects.begin(); i!=objects.end(); ++i)
32                 if(Track *track = dynamic_cast<Track *>(*i))
33                         tmp_tracks.push_back(track);
34
35         Track *cur = neighbors.front();
36         while(!tmp_tracks.empty())
37         {
38                 bool rev = false;
39                 for(list<Track *>::iterator i=tmp_tracks.begin(); i!=tmp_tracks.end(); ++i)
40                 {
41                         const vector<Track *> &links = (*i)->get_links();
42                         if(links[0]==cur)
43                         {
44                                 cur = *i;
45                                 tmp_tracks.erase(i);
46                                 break;
47                         }
48                         else if(links[1]==cur)
49                         {
50                                 cur = *i;
51                                 rev = true;
52                                 tmp_tracks.erase(i);
53                                 break;
54                         }
55                 }
56                 tracks.push_back(TrackOrder(cur, rev));
57                 total_length += cur->get_type().get_total_length();
58         }
59 }
60
61 void SlopeTool::even_slope(bool smooth)
62 {
63         list<Track *>::iterator nb = neighbors.begin();
64         int epi = (*nb)->get_link_slot(*tracks.front().track);
65         float start_z = (*nb)->get_snap_node(epi).position.z;
66         ++nb;
67         epi = (*nb)->get_link_slot(*tracks.back().track);
68         float end_z = (*nb)->get_snap_node(epi).position.z;
69
70         float length = total_length;
71         if(smooth)
72         {
73                 float dir = (end_z>start_z)?1:-1;
74                 float cur_slope = 0;
75                 while((end_z-start_z)*dir/length>cur_slope+0.025 && tracks.size()>2)
76                 {
77                         cur_slope += 0.025;
78                         Angle tilt = Geometry::atan(cur_slope);
79
80                         set_slope(tracks.front(), start_z, tilt);
81                         start_z += tracks.front().track->get_type().get_path_length(0)*dir*cur_slope;
82                         length -= tracks.front().track->get_type().get_path_length(0);
83                         tracks.pop_front();
84
85                         end_z -= tracks.back().track->get_type().get_path_length(0)*dir*cur_slope;
86                         set_slope(tracks.back(), end_z, tilt);
87                         length -= tracks.back().track->get_type().get_path_length(0);
88                         tracks.pop_back();
89                 }
90         }
91
92         float cur_z = start_z;
93         Angle tilt = Geometry::atan((end_z-start_z)/length);
94         for(list<TrackOrder>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
95         {
96                 set_slope(*i, cur_z, tilt);
97                 cur_z += i->track->get_type().get_path_length(0)*(end_z-start_z)/length;
98         }
99 }
100
101 void SlopeTool::flatten()
102 {
103         float z = 0;
104         for(list<TrackOrder>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
105         {
106                 unsigned nsn = i->track->get_n_snap_nodes();
107                 for(unsigned j=0; j<nsn; ++j)
108                         z += i->track->get_snap_node(j).position.z/nsn;
109         }
110         z /= static_cast<int>(tracks.size());
111
112         for(list<TrackOrder>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
113         {
114                 Vector p = i->track->get_position();
115                 i->track->set_position(Vector(p.x, p.y, z));
116                 i->track->set_tilt(Angle::zero());
117         }
118 }
119
120 void SlopeTool::set_slope(TrackOrder &track, float z, const Angle &tilt)
121 {
122         const Vector &p = track.track->get_position();
123         float dz = tan(tilt)*track.track->get_type().get_path_length(0);
124         if(track.rev)
125         {
126                 track.track->set_position(Vector(p.x, p.y, z+dz));
127                 track.track->set_tilt(-tilt);
128         }
129         else
130         {
131                 track.track->set_position(Vector(p.x, p.y, z));
132                 track.track->set_tilt(tilt);
133         }
134 }