From: Mikko Rasa Date: Mon, 13 May 2013 19:54:47 +0000 (+0300) Subject: Add a generic link interface as well X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=0b75458245997b9df6da47cc4534341c8426084b;p=r2c2.git Add a generic link interface as well --- diff --git a/source/designer/manipulator.cpp b/source/designer/manipulator.cpp index 6aca114..5bf02e9 100644 --- a/source/designer/manipulator.cpp +++ b/source/designer/manipulator.cpp @@ -83,12 +83,8 @@ void Manipulator::duplicate() for(vector::iterator i=objects.begin(); i!=objects.end(); ++i) { Object *obj = i->object->clone(&designer.get_layout()); - if(Track *track = dynamic_cast(obj)) - { - for(list::iterator j=new_objs.begin(); j!=new_objs.end(); ++j) - if(Track *track2 = dynamic_cast(*j)) - track->snap_to(*track2, true); - } + for(list::iterator j=new_objs.begin(); j!=new_objs.end(); ++j) + obj->link_to(**j); new_objs.push_back(obj); } @@ -135,9 +131,8 @@ void Manipulator::even_slope(bool smooth) return; for(vector::iterator i=objects.begin(); i!=objects.end(); ++i) - if(Track *track = dynamic_cast(i->object)) - if(track->get_type().get_endpoints().size()!=2) - return; + if(i->object->get_n_link_slots()!=2) + return; list tracks2; for(vector::iterator i=objects.begin(); i!=objects.end(); ++i) @@ -173,10 +168,10 @@ void Manipulator::even_slope(bool smooth) } set::iterator nb = neighbors.begin(); - int epi = (*nb)->get_endpoint_by_link(*order.front().track); + int epi = (*nb)->get_link_slot(*order.front().track); float start_z = (*nb)->get_snap_node(epi).position.z; ++nb; - epi = (*nb)->get_endpoint_by_link(*order.back().track); + epi = (*nb)->get_link_slot(*order.back().track); float end_z = (*nb)->get_snap_node(epi).position.z; if(smooth) @@ -294,8 +289,8 @@ void Manipulator::connect() return; } - trks.front()->snap_to(*track1, true); - trks.back()->snap_to(*track2, true); + trks.front()->link_to(*track1); + trks.back()->link_to(*track2); selection.replace(trks.begin(), trks.end()); } @@ -341,8 +336,7 @@ void Manipulator::button_press(unsigned btn) { for(set::iterator i=neighbors.begin(); i!=neighbors.end(); ++i) for(vector::iterator j=objects.begin(); j!=objects.end(); ++j) - if(Track *track = dynamic_cast(j->object)) - track->break_link(**i); + j->object->break_link(**i); } const set <racks = designer.get_layout().get_tracks(); @@ -354,8 +348,7 @@ void Manipulator::button_press(unsigned btn) if(!ok) continue; for(vector::iterator j=objects.begin(); j!=objects.end(); ++j) - if(Track *track = dynamic_cast(j->object)) - track->snap_to(**i, true); + j->object->link_to(**i); } if(m==EXTEND) @@ -404,9 +397,8 @@ void Manipulator::axis_motion(unsigned axis, float value, float) continue; for(vector::iterator j=objects.begin(); (j!=objects.end() && !snapped); ++j) - if(Track *track = dynamic_cast(j->object)) - if(track->snap_to(**i, false, limit)) - snapped = &*j; + if(j->object->snap_to(**i, limit)) + snapped = &*j; } if(snapped) @@ -459,17 +451,13 @@ void Manipulator::axis_motion(unsigned axis, float value, float) float length = 0; for(vector::iterator i=objects.begin(); i!=objects.end(); ++i) { - Track *track = dynamic_cast(i->object); - if(!track) - continue; - - unsigned n_endpoints = track->get_type().get_endpoints().size(); - for(unsigned j=0; jobject->get_n_link_slots(); + for(unsigned j=0; jget_link(j)) + if(i->object->get_link(j)) continue; - Snap sn = track->get_snap_node(j); + Snap sn = i->object->get_snap_node(j); float c = cos(sn.rotation); float s = sin(sn.rotation); float dx = gpointer.x-sn.position.x; @@ -698,7 +686,7 @@ vector Manipulator::create_straight(const R2C2::Vector &start, float di track->set_rotation(dir); if(!trks.empty()) - track->snap_to(*trks.back(), true); + track->link_to(*trks.back()); trks.push_back(track); pos.x += c**i; diff --git a/source/designer/selection.cpp b/source/designer/selection.cpp index c93dd36..b351b45 100644 --- a/source/designer/selection.cpp +++ b/source/designer/selection.cpp @@ -42,18 +42,17 @@ void Selection::toggle_object(Object *o) void Selection::select_more() { - set new_tracks; + set new_objects; for(set::iterator i=objects.begin(); i!=objects.end(); ++i) - if(Track *track = dynamic_cast(*i)) - { - const vector &links = track->get_links(); - for(vector::const_iterator j=links.begin(); j!=links.end(); ++j) - if(*j) - new_tracks.insert(*j); - } + { + unsigned nls = (*i)->get_n_link_slots(); + for(unsigned j=0; jget_link(j)) + new_objects.insert(obj); + } bool changed = false; - for(set::iterator i=new_tracks.begin(); i!=new_tracks.end(); ++i) + for(set::iterator i=new_objects.begin(); i!=new_objects.end(); ++i) if(objects.insert(*i).second) changed = true; @@ -64,23 +63,21 @@ void Selection::select_more() void Selection::select_linked() { bool changed = false; - list queue; - for(set::iterator i=objects.begin(); i!=objects.end(); ++i) - if(Track *track = dynamic_cast(*i)) - queue.push_back(track); + list queue(objects.begin(), objects.end()); while(!queue.empty()) { - Track *track = queue.front(); - queue.erase(queue.begin()); - - const vector &links = track->get_links(); - for(vector::const_iterator j=links.begin(); j!=links.end(); ++j) - if(*j && objects.insert(*j).second) - { - queue.push_back(*j); - changed = true; - } + Object *obj = queue.front(); + queue.pop_front(); + + unsigned nls = obj->get_n_link_slots(); + for(unsigned j=0; jget_link(j)) + if(objects.insert(linked).second) + { + queue.push_back(linked); + changed = true; + } } if(changed) diff --git a/source/libr2c2/layout.cpp b/source/libr2c2/layout.cpp index 4679fd9..a2c97b7 100644 --- a/source/libr2c2/layout.cpp +++ b/source/libr2c2/layout.cpp @@ -442,7 +442,7 @@ void Layout::Loader::track(ArticleNumber art_nr) new_tracks = true; for(set::iterator i=obj.tracks.begin(); i!=obj.tracks.end(); ++i) if(*i!=trk) - trk->snap_to(**i, true); + trk->link_to(**i); } void Layout::Loader::train(unsigned art_nr, unsigned addr, const std::string &proto) diff --git a/source/libr2c2/object.cpp b/source/libr2c2/object.cpp index 1b48a86..ba1810f 100644 --- a/source/libr2c2/object.cpp +++ b/source/libr2c2/object.cpp @@ -57,4 +57,26 @@ bool Object::snap_to(const Object &other, float limit, SnapType what) return false; } +Object *Object::get_link(unsigned) const +{ + throw out_of_range("Object::get_link"); +} + +bool Object::break_link(Object &other) +{ + unsigned nls = get_n_link_slots(); + for(unsigned i=0; iget_turnout_id()) { - const TrackType::Endpoint &ep = links[j]->get_type().get_endpoint(links[j]->get_endpoint_by_link(**i)); + const TrackType::Endpoint &ep = links[j]->get_type().get_endpoint(links[j]->get_link_slot(**i)); int p = get_turnout(tid2); if(p>=0 && !ep.has_path(p)) { @@ -345,7 +345,7 @@ RouteValidityMask Route::check_validity(Track &trk) const if(unsigned tid = (*i)->get_turnout_id()) { - const TrackType::Endpoint &ep = (*i)->get_type().get_endpoint((*i)->get_endpoint_by_link(trk)); + const TrackType::Endpoint &ep = (*i)->get_type().get_endpoint((*i)->get_link_slot(trk)); int path = get_turnout(tid); if(path>=0) { @@ -364,7 +364,7 @@ RouteValidityMask Route::check_validity(Track &trk) const unsigned tid2 = tlinks[j]->get_turnout_id(); if(tid2) { - const TrackType::Endpoint &ep2 = tlinks[j]->get_type().get_endpoint(tlinks[j]->get_endpoint_by_link(**i)); + const TrackType::Endpoint &ep2 = tlinks[j]->get_type().get_endpoint(tlinks[j]->get_link_slot(**i)); path = get_turnout(tid2); // Ignore a linked turnout with some other path set if(path>=0 && !ep2.has_path(path)) @@ -444,7 +444,7 @@ void Route::Loader::finish() { Track *link = (*i)->get_link(k); if(!obj.tracks.count(link)) - obj.add_track_chain(*link, link->get_endpoint_by_link(**i), turnouts); + obj.add_track_chain(*link, link->get_link_slot(**i), turnouts); if(!obj.tracks.count(*i)) obj.add_track_chain(**i, k, turnouts); break; diff --git a/source/libr2c2/track.cpp b/source/libr2c2/track.cpp index e4d7bad..7b9a4a2 100644 --- a/source/libr2c2/track.cpp +++ b/source/libr2c2/track.cpp @@ -100,8 +100,8 @@ void Track::check_slope() if(links[0] && links[1]) { - Vector epp0 = links[0]->get_snap_node(links[0]->get_endpoint_by_link(*this)).position; - Vector epp1 = links[1]->get_snap_node(links[1]->get_endpoint_by_link(*this)).position; + Vector epp0 = links[0]->get_snap_node(links[0]->get_link_slot(*this)).position; + Vector epp1 = links[1]->get_snap_node(links[1]->get_link_slot(*this)).position; position.z = epp0.z; slope = epp1.z-position.z; } @@ -110,12 +110,12 @@ void Track::check_slope() slope = 0; if(links[0]) { - Vector epp = links[0]->get_snap_node(links[0]->get_endpoint_by_link(*this)).position; + Vector epp = links[0]->get_snap_node(links[0]->get_link_slot(*this)).position; position.z = epp.z; } else if(links[1]) { - Vector epp = links[1]->get_snap_node(links[1]->get_endpoint_by_link(*this)).position; + Vector epp = links[1]->get_snap_node(links[1]->get_link_slot(*this)).position; position.z = epp.z; } } @@ -155,106 +155,6 @@ void Track::set_active_path(unsigned p) layout.get_driver().set_turnout(turnout_id, p); } -int Track::get_endpoint_by_link(Track &other) const -{ - for(unsigned i=0; i &eps = type.get_endpoints(); - const vector &other_eps = other.get_type().get_endpoints(); - - for(unsigned i=0; i::iterator i=links.begin(); i!=links.end(); ++i) - if(*i==&trk) - { - *i = 0; - trk.break_link(*this); - // XXX Creates the blocks twice - layout.create_blocks(*this); - signal_link_changed.emit(i-links.begin(), 0); - return; - } -} - -void Track::break_links() -{ - for(vector::iterator i=links.begin(); i!=links.end(); ++i) - if(Track *trk=*i) - { - *i = 0; - trk->break_link(*this); - } -} - -Track *Track::get_link(unsigned i) const -{ - if(i>=links.size()) - throw out_of_range("Track::get_link"); - - return links[i]; -} - TrackPoint Track::get_point(unsigned epi, unsigned path, float d) const { TrackPoint p = type.get_point(epi, path, d); @@ -346,6 +246,89 @@ SnapType Track::get_default_snap_type_to(const Object &other) const return NO_SNAP; } +unsigned Track::get_n_link_slots() const +{ + return links.size(); +} + +Track *Track::get_link(unsigned i) const +{ + if(i>=links.size()) + throw out_of_range("Track::get_link"); + + return links[i]; +} + +int Track::get_link_slot(const Object &other) const +{ + for(unsigned i=0; i(&other); + if(!otrack) + return false; + + float limit = layout.get_catalogue().get_gauge(); + if(!flex && !otrack->get_flex()) + limit /= 10; + limit *= limit; + + unsigned nsn = get_n_snap_nodes(); + unsigned other_nsn = other.get_n_snap_nodes(); + for(unsigned i=0; iM_PI) + da -= M_PI*2; + + if(d.x*d.x+d.y*d.y-0.01 && da<0.01) + { + break_link(i); + links[i] = otrack; + otrack->links[j] = this; + layout.create_blocks(*this); + + signal_link_changed.emit(i, otrack); + otrack->signal_link_changed.emit(j, this); + return true; + } + } + } + + return false; +} + +bool Track::break_link(unsigned i) +{ + if(i>=links.size()) + throw out_of_range("Track::break_link"); + + Track *other = links[i]; + if(!other) + return false; + + links[i] = 0; + other->break_link(*this); + // XXX Creates the blocks twice, because the other track calls this too + layout.create_blocks(*this); + signal_link_changed.emit(i, 0); + + return true; +} + bool Track::collide_ray(const Vector &start, const Vector &ray) const { Vector local_start(start.x-position.x, start.y-position.y, start.z-position.z); diff --git a/source/libr2c2/track.h b/source/libr2c2/track.h index b8a9a3d..7ad7dd1 100644 --- a/source/libr2c2/track.h +++ b/source/libr2c2/track.h @@ -69,12 +69,6 @@ public: unsigned get_active_path() const { return active_path; } bool is_path_changing() const { return path_changing; } - int get_endpoint_by_link(Track &) const; - bool snap_to(Track &, bool, float = 0); - void break_link(Track &); - void break_links(); - const std::vector &get_links() const { return links; } - Track *get_link(unsigned) const; TrackPoint get_point(unsigned, unsigned, float) const; TrackPoint get_point(unsigned, float) const; @@ -85,6 +79,14 @@ private: virtual SnapType get_default_snap_type_to(const Object &) const; public: + virtual unsigned get_n_link_slots() const; + virtual Track *get_link(unsigned) const; + const std::vector &get_links() const { return links; } + virtual int get_link_slot(const Object &) const; + virtual bool link_to(Object &); + using Object::break_link; + virtual bool break_link(unsigned); + virtual bool collide_ray(const Vector &, const Vector &) const; void save(std::list &) const; diff --git a/source/libr2c2/trackiter.cpp b/source/libr2c2/trackiter.cpp index edb0d73..c3bb7d4 100644 --- a/source/libr2c2/trackiter.cpp +++ b/source/libr2c2/trackiter.cpp @@ -95,7 +95,7 @@ TrackIter TrackIter::next(unsigned path) const TrackIter result; result._track = _track->get_link(exit); - result._entry = (result._track ? result._track->get_endpoint_by_link(*_track) : 0); + result._entry = (result._track ? result._track->get_link_slot(*_track) : 0); return result; } @@ -127,7 +127,7 @@ TrackIter TrackIter::flip() const TrackIter result; result._track = _track->get_link(_entry); - result._entry = (result._track ? result._track->get_endpoint_by_link(*_track) : 0); + result._entry = (result._track ? result._track->get_link_slot(*_track) : 0); return result; } diff --git a/source/libr2c2/vehicle.cpp b/source/libr2c2/vehicle.cpp index 250aefd..d1819a0 100644 --- a/source/libr2c2/vehicle.cpp +++ b/source/libr2c2/vehicle.cpp @@ -398,6 +398,29 @@ TrackPoint Vehicle::get_point(const TrackPosition &pos, float tdist, float ratio return get_point(front.get_point().pos, back.get_point().pos, ratio); } +unsigned Vehicle::get_n_link_slots() const +{ + return 2; +} + +Vehicle *Vehicle::get_link(unsigned i) const +{ + if(i>=2) + throw out_of_range("Vehicle::get_link"); + + return (i==0 ? prev : next); +} + +int Vehicle::get_link_slot(const Object &other) const +{ + if(&other==prev) + return 0; + else if(&other==next) + return 1; + else + return -1; +} + Vehicle::Axle::Axle(const VehicleType::Axle &t): type(&t), diff --git a/source/libr2c2/vehicle.h b/source/libr2c2/vehicle.h index 54054bb..bbd156c 100644 --- a/source/libr2c2/vehicle.h +++ b/source/libr2c2/vehicle.h @@ -121,6 +121,10 @@ private: TrackPoint get_point(const TrackPosition &, float, float = 0.5) const; public: + virtual unsigned get_n_link_slots() const; + virtual Vehicle *get_link(unsigned) const; + virtual int get_link_slot(const Object &) const; + virtual bool collide_ray(const Vector &, const Vector &) const { return false; } };