From: Mikko Rasa Date: Wed, 27 Oct 2010 12:10:03 +0000 (+0000) Subject: Add a feature to autofit straight runs of track X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=258600f95f62ba4fbe745da4aebdd1a496af0050;p=r2c2.git Add a feature to autofit straight runs of track --- diff --git a/source/designer/designer.cpp b/source/designer/designer.cpp index cb327c5..92c2f25 100644 --- a/source/designer/designer.cpp +++ b/source/designer/designer.cpp @@ -362,6 +362,8 @@ void Designer::key_press(unsigned key, unsigned mod, wchar_t) set_sensor_id(); else if(key==Msp::Input::KEY_A) add_selection_to_route(); + else if(key==Msp::Input::KEY_C) + manipulator.connect(); } void Designer::button_press(int x, int y, unsigned btn, unsigned mod) diff --git a/source/designer/designer.h b/source/designer/designer.h index d229324..d0f8e81 100644 --- a/source/designer/designer.h +++ b/source/designer/designer.h @@ -85,6 +85,7 @@ public: void save(); void quit(); + const Marklin::Catalogue &get_catalogue() const { return catalogue; } Marklin::Layout *get_layout() { return layout; } Marklin::Layout3D *get_layout_3d() { return layout_3d; } const Msp::GL::Camera &get_camera() const { return camera; } diff --git a/source/designer/manipulator.cpp b/source/designer/manipulator.cpp index 35779a8..42c4229 100644 --- a/source/designer/manipulator.cpp +++ b/source/designer/manipulator.cpp @@ -212,6 +212,156 @@ void Manipulator::cancel() signal_done.emit(false); } +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; + 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 matching endpoints found"); + return; + } + + const map &track_types = designer.get_catalogue().get_tracks(); + std::map types_by_length; + unsigned preference = 0; + for(map::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(gap>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((gap+limit)/i->first); + lengths.insert(lengths.end(), n, i->first); + gap -= n*i->first; + found = true; + break; + } + } + + if(found) + continue; + + if(lengths.empty()) + { + if(preference>0) + { + --preference; + removed = 0; + continue; + } + break; + } + + gap += lengths.back(); + removed = lengths.back(); + lengths.pop_back(); + } + + if(lengths.empty()) + { + signal_status.emit("No connection possible"); + return; + } + + float c = cos(dir1); + float s = sin(dir1); + 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(pos1); + track->set_rotation(dir1); + + track->snap_to(*track1, true); + track1 = track; + + pos1.x += c**i; + pos1.y += s**i; + } + + track1->snap_to(*track2, true); +} + void Manipulator::button_press(int, int, float, float, unsigned btn) { if(btn==3) diff --git a/source/designer/manipulator.h b/source/designer/manipulator.h index fa8598d..8115ab4 100644 --- a/source/designer/manipulator.h +++ b/source/designer/manipulator.h @@ -69,6 +69,7 @@ public: void duplicate(); void flatten(); void even_slope(bool =false); + void connect(); void cancel(); void button_press(int, int, float, float, unsigned); void pointer_motion(int, int, float, float); diff --git a/source/libmarklin/tracktype.cpp b/source/libmarklin/tracktype.cpp index 8c1505b..53c2bc4 100644 --- a/source/libmarklin/tracktype.cpp +++ b/source/libmarklin/tracktype.cpp @@ -15,7 +15,8 @@ namespace Marklin { TrackType::TrackType(unsigned a): art_nr(a), - double_address(false) + double_address(false), + autofit_preference(1) { } float TrackType::get_total_length() const @@ -164,6 +165,7 @@ TrackType::Endpoint::Endpoint(float x, float y, float d, unsigned p): TrackType::Loader::Loader(TrackType &t): Msp::DataFile::BasicLoader(t) { + add("autofit_preference", &TrackType::autofit_preference); add("description", &TrackType::description); add("double_address", &TrackType::double_address); add("part", &Loader::part); diff --git a/source/libmarklin/tracktype.h b/source/libmarklin/tracktype.h index 902a2f6..b443740 100644 --- a/source/libmarklin/tracktype.h +++ b/source/libmarklin/tracktype.h @@ -42,6 +42,7 @@ private: std::vector parts; std::vector endpoints; bool double_address; + unsigned autofit_preference; public: TrackType(unsigned); @@ -55,6 +56,7 @@ public: bool is_turnout() const; bool is_dead_end() const; bool is_double_address() const { return double_address; } + unsigned get_autofit_preference() const { return autofit_preference; } const std::vector &get_parts() const { return parts; } const std::vector &get_endpoints() const { return endpoints; } TrackPoint get_point(unsigned, unsigned, float) const; diff --git a/tracks.dat b/tracks.dat index fac3dfc..96d0772 100644 --- a/tracks.dat +++ b/tracks.dat @@ -35,6 +35,7 @@ track 24071 { length 70.8; }; + autofit_preference 0; }; track 24077 @@ -44,6 +45,7 @@ track 24077 { length 77.5; }; + autofit_preference 2; }; track 24094 @@ -53,6 +55,7 @@ track 24094 { length 94.2; }; + autofit_preference 2; }; track 24172 @@ -62,6 +65,7 @@ track 24172 { length 171.7; }; + autofit_preference 2; }; track 24188 @@ -71,6 +75,7 @@ track 24188 { length 188.3; }; + autofit_preference 2; }; track 24229