X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;ds=sidebyside;f=source%2Fdesigner%2Fmanipulator.cpp;h=aad20a084b84bcd0511192e25d2f7fb087502821;hb=283542ae424b94786652fbf0c67b883b63a8e7a0;hp=35779a8ccc2896234f91e330b1872e7d75b7d58f;hpb=52ba962c6f24873e8db99f2452a8ace216b9540a;p=r2c2.git diff --git a/source/designer/manipulator.cpp b/source/designer/manipulator.cpp index 35779a8..aad20a0 100644 --- a/source/designer/manipulator.cpp +++ b/source/designer/manipulator.cpp @@ -56,6 +56,14 @@ void Manipulator::start_elevate() mode = ELEVATE; } +void Manipulator::start_extend() +{ + if(mode) + cancel(); + + mode = EXTEND; +} + void Manipulator::duplicate() { if(mode) @@ -64,7 +72,7 @@ void Manipulator::duplicate() list new_tracks; for(vector::iterator i=tracks.begin(); i!=tracks.end(); ++i) { - Track *track = new Track(*designer.get_layout(), i->track->get_type()); + Track *track = new Track(designer.get_layout(), i->track->get_type()); track->set_position(i->track->get_position()); track->set_rotation(i->track->get_rotation()); new_tracks.push_back(track); @@ -192,6 +200,88 @@ void Manipulator::even_slope(bool smooth) update_tracks(); } +void Manipulator::connect() +{ + if(tracks.size()!=2) + { + signal_status.emit("Exactly two tracks must be selected"); + return; + } + + float limit = 0.001; + + Track *track1 = tracks.front().track; + Point pos1; + float dir1; + Track *track2 = tracks.back().track; + bool ok = false; + float gap = 0; + for(unsigned i=0; iget_type().get_endpoints().size(); ++i) + { + if(track1->get_link(i)) + continue; + + pos1 = track1->get_endpoint_position(i); + dir1 = track1->get_endpoint_direction(i); + + for(unsigned j=0; jget_type().get_endpoints().size(); ++j) + { + if(track2->get_link(j)) + continue; + + Point pos2 = track2->get_endpoint_position(j); + float dir2 = track2->get_endpoint_direction(j); + + float dz = pos2.z-pos1.z; + if(abs(dz)>0.02) + continue; + + float adiff = dir1+M_PI-dir2; + while(adiff<-M_PI) + adiff += M_PI*2; + while(adiff>M_PI) + adiff -= M_PI*2; + if(abs(adiff)>0.01) + continue; + + float c = cos(dir1); + float s = sin(dir1); + float dx = pos2.x-pos1.x; + float dy = pos2.y-pos1.y; + if(abs(dx*s-dy*c)>limit) + continue; + + gap = dx*c+dy*s; + if(gap<0) + continue; + + ok = true; + } + + if(ok) + break; + } + + if(!ok) + { + signal_status.emit("No aligned endpoints found"); + return; + } + + vector trks = create_straight(pos1, dir1, gap, limit); + + if(trks.empty()) + { + signal_status.emit("No connection possible"); + return; + } + + trks.front()->snap_to(*track1, true); + trks.back()->snap_to(*track2, true); + + selection.replace(trks.begin(), trks.end()); +} + void Manipulator::cancel() { if(!mode) @@ -207,6 +297,10 @@ void Manipulator::cancel() for(set::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) (*i)->check_slope(); + for(vector::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i) + delete *i; + extend_tracks.clear(); + angle = 0; signal_done.emit(false); @@ -216,16 +310,20 @@ void Manipulator::button_press(int, int, float, float, unsigned btn) { if(btn==3) cancel(); - else if(mode) + else if(btn==1 && mode) { + Mode m = mode; mode = NONE; angle = 0; - for(set::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) - for(vector::iterator j=tracks.begin(); j!=tracks.end(); ++j) - j->track->break_link(**i); + if(m!=EXTEND) + { + for(set::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) + for(vector::iterator j=tracks.begin(); j!=tracks.end(); ++j) + j->track->break_link(**i); + } - const set <racks = designer.get_layout()->get_tracks(); + const set <racks = designer.get_layout().get_tracks(); for(set::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i) { bool ok = true; @@ -237,8 +335,16 @@ void Manipulator::button_press(int, int, float, float, unsigned btn) j->track->snap_to(**i, true); } - update_tracks(); - update_neighbors(); + if(m==EXTEND) + { + selection.replace(extend_tracks.begin(), extend_tracks.end()); + extend_tracks.clear(); + } + else + { + update_tracks(); + update_neighbors(); + } signal_done.emit(true); } @@ -259,7 +365,7 @@ void Manipulator::pointer_motion(int, int y, float gx, float gy) i->track->set_rotation(i->rot); } - const set <racks = designer.get_layout()->get_tracks(); + const set <racks = designer.get_layout().get_tracks(); MTrack *snapped = 0; for(set::const_iterator i=ltracks.begin(); (i!=ltracks.end() && !snapped); ++i) { @@ -316,6 +422,54 @@ void Manipulator::pointer_motion(int, int y, float gx, float gy) for(set::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) (*i)->check_slope(); } + else if(mode==EXTEND) + { + Point pos; + float dir = 0; + float length = 0; + for(vector::iterator i=tracks.begin(); i!=tracks.end(); ++i) + { + unsigned n_endpoints = i->track->get_type().get_endpoints().size(); + for(unsigned j=0; jtrack->get_link(j)) + continue; + + Point ep_pos = i->track->get_endpoint_position(j); + float ep_dir = i->track->get_endpoint_direction(j); + float c = cos(ep_dir); + float s = sin(ep_dir); + float dx = gx-ep_pos.x; + float dy = gy-ep_pos.y; + + float len = dx*c+dy*s; + if(len trks = create_straight(pos, dir, length, max(length/500, 0.001f)); + + if(!trks.empty()) + { + for(vector::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i) + delete *i; + extend_tracks = trks; + + length = 0; + for(vector::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i) + length += (*i)->get_type().get_total_length(); + + signal_status.emit(format("Extend: %.0fmm", length*1000)); + } + } + } } void Manipulator::selection_changed() @@ -400,6 +554,92 @@ void Manipulator::set_slope(TrackOrder &track, float z, float dz) } } +vector Manipulator::create_straight(const Marklin::Point &start, float dir, float length, float limit) +{ + const Catalogue::TrackMap &track_types = designer.get_catalogue().get_tracks(); + std::map types_by_length; + unsigned preference = 0; + for(Catalogue::TrackMap::const_iterator i=track_types.begin(); i!=track_types.end(); ++i) + { + const vector &parts = i->second->get_parts(); + if(parts.size()!=1) + continue; + if(parts.front().is_curved() || parts.front().is_dead_end()) + continue; + + types_by_length[parts.front().get_length()] = i->second; + preference = max(preference, i->second->get_autofit_preference()); + } + + vector lengths; + float removed = 0; + while(length>limit) + { + bool found = false; + for(map::iterator i=types_by_length.end(); i!=types_by_length.begin(); ) + { + --i; + if(i->second->get_autofit_preference()firstfirst((length+limit)/i->first); + lengths.insert(lengths.end(), n, i->first); + length -= n*i->first; + found = true; + break; + } + } + + if(found) + continue; + + if(lengths.empty()) + { + if(preference>0) + { + --preference; + removed = 0; + continue; + } + break; + } + + length += lengths.back(); + removed = lengths.back(); + lengths.pop_back(); + } + + vector trks; + + if(!lengths.empty()) + { + Point pos = start; + float c = cos(dir); + float s = sin(dir); + for(vector::iterator i=lengths.begin(); i!=lengths.end(); ++i) + { + map::iterator j = types_by_length.find(*i); + if(j==types_by_length.end()) + throw LogicError("Internal error"); + + Track *track = new Track(designer.get_layout(), *j->second); + track->set_position(pos); + track->set_rotation(dir); + + if(!trks.empty()) + track->snap_to(*trks.back(), true); + trks.push_back(track); + + pos.x += c**i; + pos.y += s**i; + } + } + + return trks; +} + + Manipulator::MTrack::MTrack(Track *t): track(t), pos(track->get_position()),