From: Mikko Rasa Date: Mon, 1 Nov 2010 14:40:38 +0000 (+0000) Subject: Move the fitting part of Manipulator::connect to a separate function X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=283542ae424b94786652fbf0c67b883b63a8e7a0;p=r2c2.git Move the fitting part of Manipulator::connect to a separate function Add a manipulator mode to extend tracks out of an endpoint Add a method to replace the entire selection at once --- diff --git a/source/designer/designer.cpp b/source/designer/designer.cpp index a31d244..83164b5 100644 --- a/source/designer/designer.cpp +++ b/source/designer/designer.cpp @@ -6,6 +6,7 @@ Distributed under the GPL */ #include +#include #include #include #include @@ -68,6 +69,7 @@ Designer::Designer(int argc, char **argv): layout_3d = new Layout3D(*layout); layout->signal_track_added.connect(sigc::mem_fun(this, &Designer::track_added)); + layout->signal_track_removed.connect(sigc::mem_fun(this, &Designer::track_removed)); if(argc>1) { @@ -282,7 +284,12 @@ void Designer::key_press(unsigned key, unsigned mod, wchar_t) key = Input::key_from_sys(key); mod = Input::mod_from_sys(mod); - if(key==Msp::Input::KEY_N) + if(key==Msp::Input::KEY_N && (mod&Input::MOD_SHIFT)) + { + manipulator.start_extend(); + mode = MANIPULATE; + } + else if(key==Msp::Input::KEY_N) new_track(); else if(key==Msp::Input::KEY_G) { @@ -482,6 +489,13 @@ void Designer::track_added(Track &trk) new_tracks.push_back(&trk); } +void Designer::track_removed(Track &trk) +{ + list::iterator i = find(new_tracks.begin(), new_tracks.end(), &trk); + if(i!=new_tracks.end()) + new_tracks.erase(i); +} + Track3D *Designer::pick_track(int x, int y) { Layout3D *l = layout_3d; diff --git a/source/designer/designer.h b/source/designer/designer.h index 3aeb08c..7ab3d1d 100644 --- a/source/designer/designer.h +++ b/source/designer/designer.h @@ -110,6 +110,7 @@ private: void apply_camera(); void render(); void track_added(Marklin::Track &); + void track_removed(Marklin::Track &); Marklin::Track3D *pick_track(int, int); void update_track_icon(Marklin::Track3D &); void selection_changed(); diff --git a/source/designer/manipulator.cpp b/source/designer/manipulator.cpp index 850f79f..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) @@ -192,26 +200,6 @@ void Manipulator::even_slope(bool smooth) update_tracks(); } -void Manipulator::cancel() -{ - if(!mode) - return; - mode = NONE; - - for(vector::iterator i=tracks.begin(); i!=tracks.end(); ++i) - { - i->track->set_position(Point(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z)); - i->track->set_rotation(i->rot); - } - - for(set::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) - (*i)->check_slope(); - - angle = 0; - - signal_done.emit(false); -} - void Manipulator::connect() { if(tracks.size()!=2) @@ -276,104 +264,64 @@ void Manipulator::connect() if(!ok) { - signal_status.emit("No matching endpoints found"); + signal_status.emit("No aligned endpoints found"); return; } - 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 trks = create_straight(pos1, dir1, gap, limit); - vector lengths; - float removed = 0; - while(gap>limit) + if(trks.empty()) { - bool found = false; - for(map::iterator i=types_by_length.end(); i!=types_by_length.begin(); ) - { - --i; - if(i->second->get_autofit_preference()firstfirst((gap+limit)/i->first); - lengths.insert(lengths.end(), n, i->first); - gap -= n*i->first; - found = true; - break; - } - } + signal_status.emit("No connection possible"); + return; + } - if(found) - continue; + trks.front()->snap_to(*track1, true); + trks.back()->snap_to(*track2, true); - if(lengths.empty()) - { - if(preference>0) - { - --preference; - removed = 0; - continue; - } - break; - } - - gap += lengths.back(); - removed = lengths.back(); - lengths.pop_back(); - } + selection.replace(trks.begin(), trks.end()); +} - if(lengths.empty()) - { - signal_status.emit("No connection possible"); +void Manipulator::cancel() +{ + if(!mode) return; - } + mode = NONE; - float c = cos(dir1); - float s = sin(dir1); - for(vector::iterator i=lengths.begin(); i!=lengths.end(); ++i) + for(vector::iterator i=tracks.begin(); i!=tracks.end(); ++i) { - map::iterator j = types_by_length.find(*i); - if(j==types_by_length.end()) - throw LogicError("Internal error"); + i->track->set_position(Point(center.x+i->pos.x, center.y+i->pos.y, center.z+i->pos.z)); + i->track->set_rotation(i->rot); + } - Track *track = new Track(designer.get_layout(), *j->second); - track->set_position(pos1); - track->set_rotation(dir1); + for(set::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) + (*i)->check_slope(); - track->snap_to(*track1, true); - track1 = track; + for(vector::iterator i=extend_tracks.begin(); i!=extend_tracks.end(); ++i) + delete *i; + extend_tracks.clear(); - pos1.x += c**i; - pos1.y += s**i; - } + angle = 0; - track1->snap_to(*track2, true); + signal_done.emit(false); } 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(); for(set::const_iterator i=ltracks.begin(); i!=ltracks.end(); ++i) @@ -387,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); } @@ -466,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() @@ -550,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()), diff --git a/source/designer/manipulator.h b/source/designer/manipulator.h index 8115ab4..8fddced 100644 --- a/source/designer/manipulator.h +++ b/source/designer/manipulator.h @@ -21,7 +21,8 @@ private: NONE, MOVE, ROTATE, - ELEVATE + ELEVATE, + EXTEND }; struct MTrack @@ -59,6 +60,7 @@ private: float rot_origin; int elev_origin; std::set neighbors; + std::vector extend_tracks; public: Manipulator(Designer &, Selection &); @@ -66,6 +68,7 @@ public: void start_move(); void start_rotate(); void start_elevate(); + void start_extend(); void duplicate(); void flatten(); void even_slope(bool =false); @@ -78,6 +81,7 @@ private: void update_tracks(); void update_neighbors(); void set_slope(TrackOrder &, float, float); + std::vector create_straight(const Marklin::Point &, float, float, float); }; #endif diff --git a/source/designer/selection.h b/source/designer/selection.h index 24d9354..9d49c76 100644 --- a/source/designer/selection.h +++ b/source/designer/selection.h @@ -24,10 +24,21 @@ public: const std::set &get_tracks() const { return tracks; } Marklin::Track *get_track() const; unsigned size() const { return tracks.size(); } + void clear(); + + template + void replace(Iter begin, Iter end) + { + tracks.clear(); + tracks.insert(begin, end); + signal_changed.emit(); + } + void add_track(Marklin::Track *); void remove_track(Marklin::Track *); void toggle_track(Marklin::Track *); + void select_more(); void select_linked(); void select_blocks();