1 #include <msp/strings/format.h>
2 #include "libr2c2/articlenumber.h"
4 #include "extendtool.h"
10 ExtendTool::ExtendTool(Designer &d, Input::Mouse &m, const set<Object *> &o):
16 for(set<Object *>::const_iterator i=objects.begin(); (!ok && i!=objects.end()); ++i)
17 if(Track *track = dynamic_cast<Track *>(*i))
19 const vector<Track *> &links = track->get_links();
20 for(vector<Track *>::const_iterator j=links.begin(); (!ok && j!=links.end()); ++j)
27 set_status("No free endpoints");
31 ExtendTool::~ExtendTool()
35 for(vector<R2C2::Track *>::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i)
40 void ExtendTool::connect()
44 signal_status.emit("Exactly two tracks must be selected");
48 Track *track1 = dynamic_cast<Track *>(*objects.begin());
49 Track *track2 = dynamic_cast<Track *>(*--objects.end());
50 if(!track1 || !track2)
52 signal_status.emit("Exactly two tracks must be selected");
56 float limit = designer.get_layout().get_catalogue().get_gauge()/10;
61 unsigned nls1 = track1->get_n_link_slots();
62 unsigned nls2 = track2->get_n_link_slots();
63 for(unsigned i=0; i<nls1; ++i)
65 if(track1->get_link(i))
68 sn1 = track1->get_snap_node(i);
70 for(unsigned j=0; j<nls2; ++j)
72 if(track2->get_link(j))
75 Snap sn2 = track2->get_snap_node(j);
77 float dz = sn2.position.z-sn1.position.z;
81 Angle adiff = wrap_balanced(sn1.rotation+Angle::half_turn()-sn2.rotation);
82 if(abs(adiff).radians()>0.01)
85 Vector delta = rotated_vector(sn2.position-sn1.position, -sn1.rotation);
86 if(abs(delta.y)>limit)
102 set_status("No aligned endpoints found");
106 extend_tracks = create_straight(sn1.position, sn1.rotation, gap, limit);
108 if(extend_tracks.empty())
110 set_status("No connection possible");
114 extend_tracks.front()->link_to(*track1);
115 extend_tracks.back()->link_to(*track2);
121 void ExtendTool::button_press(unsigned btn)
125 for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
126 if(extend_tracks.front()->link_to(**i))
135 void ExtendTool::axis_motion(unsigned axis, float value, float rel)
137 Tool::axis_motion(axis, value, rel);
143 for(set<Object *>::const_iterator i=objects.begin(); i!=objects.end(); ++i)
145 unsigned nls = (*i)->get_n_link_slots();
146 for(unsigned j=0; j<nls; ++j)
148 if((*i)->get_link(j))
151 Snap sn = (*i)->get_snap_node(j);
152 Vector delta = rotated_vector(ground_pointer-sn.position, -sn.rotation);
165 vector<Track *> trks = create_straight(pos, dir, length, max(length/500, 0.001f));
169 for(vector<Track *>::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i)
171 extend_tracks = trks;
173 map<ArticleNumber, unsigned> counts;
175 for(vector<Track *>::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i)
177 length += (*i)->get_type().get_total_length();
178 ++counts[(*i)->get_type().get_article_number()];
182 for(map<ArticleNumber, unsigned>::const_iterator i=counts.begin(); i!=counts.end(); ++i)
186 detail += format("%dx %s", i->second, i->first);
189 signal_status.emit(format("Extend: %.0fmm (%s)", length*1000, detail));
194 vector<Track *> ExtendTool::create_straight(const Vector &start, const Angle &dir, float length, float limit)
196 const Catalogue::TrackMap &track_types = designer.get_catalogue().get_tracks();
197 map<float, const TrackType *> types_by_length;
198 unsigned preference = 0;
199 for(Catalogue::TrackMap::const_iterator i=track_types.begin(); i!=track_types.end(); ++i)
201 const vector<TrackPart> &parts = i->second->get_parts();
204 if(parts.front().is_curved() || parts.front().is_dead_end())
207 types_by_length[parts.front().get_length()] = i->second;
208 preference = max(preference, i->second->get_autofit_preference());
211 vector<float> lengths;
216 for(map<float, const TrackType *>::iterator i=types_by_length.end(); i!=types_by_length.begin(); )
219 if(i->second->get_autofit_preference()<preference)
221 if((!removed || i->first<removed) && i->first<length+limit)
223 unsigned n = static_cast<unsigned>((length+limit)/i->first);
224 lengths.insert(lengths.end(), n, i->first);
225 length -= n*i->first;
245 length += lengths.back();
246 removed = lengths.back();
250 vector<Track *> trks;
255 Transform trans = Transform::rotation(dir, Vector(0, 0, 1));
256 for(vector<float>::iterator i=lengths.begin(); i!=lengths.end(); ++i)
258 Track *track = new Track(designer.get_layout(), *get_item(types_by_length, *i));
259 track->set_position(pos);
260 track->set_rotation(dir);
263 track->link_to(*trks.back());
264 trks.push_back(track);
266 pos += trans.transform(Vector(*i, 0, 0));
273 void ExtendTool::update_selection(Selection &sel) const
275 sel.replace(extend_tracks.begin(), extend_tracks.end());