1 #include <msp/strings/format.h>
2 #include "libr2c2/articlenumber.h"
4 #include "extendtool.h"
10 ExtendTool::ExtendTool(Designer &d, Input::Keyboard &k, Input::Mouse &m, const set<Object *> &objects):
14 for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
15 if(Track *t = dynamic_cast<Track *>(*i))
17 unsigned nls = t->get_n_link_slots();
18 for(unsigned j=0; j<nls; ++j)
20 unlinked_endpoints.push_back(TrackIter(t, j));
23 if(unlinked_endpoints.empty())
25 set_status("No free endpoints");
29 const Catalogue::ObjectMap &object_types = designer.get_catalogue().get_all();
30 for(Catalogue::ObjectMap::const_iterator i=object_types.begin(); i!=object_types.end(); ++i)
31 if(const TrackType *tt = dynamic_cast<const TrackType *>(i->second))
33 const vector<TrackPart> &parts = tt->get_parts();
36 if(parts.front().is_curved() || parts.front().is_dead_end())
39 types_by_length[parts.front().get_length()] = tt;
40 max_preference = max(max_preference, tt->get_autofit_preference());
44 ExtendTool::~ExtendTool()
48 for(vector<R2C2::Track *>::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i)
53 void ExtendTool::connect()
57 Track *start_track = 0;
62 for(vector<TrackIter>::const_iterator i=unlinked_endpoints.begin(); i!=unlinked_endpoints.end(); ++i)
64 start_sn = (*i)->get_snap_node(i->entry());
65 limit = (*i)->get_type().get_appearance().get_gauge()/10;
67 for(vector<TrackIter>::const_iterator j=i; ++j!=unlinked_endpoints.end(); )
69 Snap end_sn = (*j)->get_snap_node(j->entry());
71 float dz = end_sn.position.z-start_sn.position.z;
75 Angle adiff = wrap_balanced(start_sn.rotation+Angle::half_turn()-end_sn.rotation);
76 if(abs(adiff).radians()>0.01)
79 Vector delta = rotated_vector(end_sn.position-start_sn.position, -start_sn.rotation);
80 if(abs(delta.y)>limit)
87 start_track = i->track();
88 end_track = j->track();
98 set_status("No aligned endpoints found");
103 extend_tracks = create_straight(start_sn.position, start_sn.rotation, gap, limit);
105 if(extend_tracks.empty())
107 set_status("No connection possible");
112 extend_tracks.front()->link_to(*start_track);
113 extend_tracks.back()->link_to(*end_track);
118 void ExtendTool::pointer_motion()
124 for(vector<TrackIter>::const_iterator i=unlinked_endpoints.begin(); i!=unlinked_endpoints.end(); ++i)
126 Snap sn = (*i)->get_snap_node(i->entry());
127 Vector delta = rotated_vector(ground_pointer-sn.position, -sn.rotation);
139 vector<Track *> trks = create_straight(pos, dir, length, max(length/500, 0.001f));
143 for(vector<Track *>::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i)
145 extend_tracks = trks;
147 map<ArticleNumber, unsigned> counts;
149 for(vector<Track *>::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i)
151 length += (*i)->get_type().get_total_length();
152 ++counts[(*i)->get_type().get_article_number()];
156 for(map<ArticleNumber, unsigned>::const_iterator i=counts.begin(); i!=counts.end(); ++i)
160 detail += format("%dx %s", i->second, i->first);
163 signal_status.emit(format("Extend: %.0fmm (%s)", length*1000, detail));
168 void ExtendTool::finish()
170 if(!extend_tracks.empty())
172 for(vector<TrackIter>::const_iterator i=unlinked_endpoints.begin(); i!=unlinked_endpoints.end(); ++i)
173 if(extend_tracks.front()->link_to(**i))
178 vector<Track *> ExtendTool::create_straight(const Vector &start, const Angle &dir, float length, float limit)
180 vector<float> lengths;
181 unsigned preference = max_preference;
186 for(map<float, const TrackType *>::iterator i=types_by_length.end(); i!=types_by_length.begin(); )
189 if(i->second->get_autofit_preference()<preference)
191 if((!removed || i->first<removed) && i->first<length+limit)
193 unsigned n = static_cast<unsigned>((length+limit)/i->first);
194 lengths.insert(lengths.end(), n, i->first);
195 length -= n*i->first;
215 length += lengths.back();
216 removed = lengths.back();
220 vector<Track *> trks;
225 Transform trans = Transform::rotation(dir, Vector(0, 0, 1));
226 for(vector<float>::iterator i=lengths.begin(); i!=lengths.end(); ++i)
228 Track *track = new Track(designer.get_layout(), *get_item(types_by_length, *i));
229 track->set_position(pos);
230 track->set_rotation(dir);
233 track->link_to(*trks.back());
234 trks.push_back(track);
236 pos += trans.transform(Vector(*i, 0, 0));
243 void ExtendTool::update_selection(Selection &sel) const
246 sel.replace(extend_tracks.begin(), extend_tracks.end());