From 895fdb9568cda40898e5bb646061c14a41dc0124 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 4 Jul 2013 23:51:15 +0300 Subject: [PATCH] Add an abstraction for things that are attached to tracks --- source/libr2c2/signal.cpp | 67 +++++---------------- source/libr2c2/signal.h | 13 ++-- source/libr2c2/track.cpp | 16 +++++ source/libr2c2/track.h | 8 +++ source/libr2c2/trackattachment.cpp | 95 ++++++++++++++++++++++++++++++ source/libr2c2/trackattachment.h | 34 +++++++++++ 6 files changed, 174 insertions(+), 59 deletions(-) create mode 100644 source/libr2c2/trackattachment.cpp create mode 100644 source/libr2c2/trackattachment.h diff --git a/source/libr2c2/signal.cpp b/source/libr2c2/signal.cpp index c4a83b9..96c44d8 100644 --- a/source/libr2c2/signal.cpp +++ b/source/libr2c2/signal.cpp @@ -14,12 +14,9 @@ using namespace Msp; namespace R2C2 { Signal::Signal(Layout &l, const SignalType &t): - Object(l), + TrackAttachment(l), type(t), address(0), - track(0), - block(0), - entry(0), train(0), check_allocated_blocks(false), passing(false) @@ -54,57 +51,26 @@ void Signal::set_position(const Vector &p) { position = p; - update_location(); + update_attachment(); signal_moved.emit(); } -void Signal::update_location() +void Signal::set_rotation(const Angle &r) { - const set &tracks = layout.get_all(); - float limit = layout.get_catalogue().get_gauge()*2; - float dist = -1; - for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) - if(!(*i)->get_type().is_turnout()) - { - Snap sn; - sn.position = position; - sn.rotation = rotation; - (*i)->snap(sn, limit, SNAP_SEGMENT); - float d = distance(position, sn.position); - if(dget_type().get_endpoints().size(); - for(unsigned j=0; jget_snap_node(j).rotation-rotation, -Angle::quarter_turn()); - if(a>=Angle::quarter_turn()) - { - BlockIter biter = TrackIter(track, j).block_iter(); - if(biter) - { - block = &track->get_block(); - entry = biter.entry(); - } - } - } + update_attachment(); + signal_moved.emit(); } -void Signal::set_rotation(const Angle &r) +void Signal::update_attachment() { - rotation = r; + attach_to_closest(layout.get_catalogue().get_gauge()*2); - update_location(); - signal_moved.emit(); + if(track) + block = track.block_iter(); + else + block = BlockIter(); } unsigned Signal::get_n_snap_nodes() const @@ -136,8 +102,7 @@ void Signal::tick(const Time::TimeDelta &) if(check_allocated_blocks) { unsigned n_blocks = 0; - BlockIter iter(block, entry); - iter = iter.next(); + BlockIter iter = block.next(); while(iter && iter->get_train()==train) { if(iter->get_sensor_id()) @@ -161,12 +126,12 @@ void Signal::tick(const Time::TimeDelta &) void Signal::block_reserved(const Block &b, Train *t) { - if(&b==block) + if(&b==block.block()) { if(t) { const BlockIter &b_iter = t->get_block_allocator().iter_for(b); - if(b_iter && b_iter.entry()==entry) + if(b_iter && b_iter.entry()==block.entry()) { if(train_conn) train_conn.disconnect(); @@ -188,7 +153,7 @@ void Signal::block_reserved(const Block &b, Train *t) void Signal::train_advanced(Block &b) { - if(&b==block) + if(&b==block.block()) passing = true; else if(passing && b.get_sensor_id()) { diff --git a/source/libr2c2/signal.h b/source/libr2c2/signal.h index 2f77f06..7f6e011 100644 --- a/source/libr2c2/signal.h +++ b/source/libr2c2/signal.h @@ -3,18 +3,18 @@ #include #include +#include "blockiter.h" #include "geometry.h" -#include "object.h" #include "signaltype.h" #include "track.h" +#include "trackattachment.h" namespace R2C2 { -class Block; class Layout; class Train; -class Signal: public Object +class Signal: public TrackAttachment { public: class Loader: public Msp::DataFile::ObjectLoader @@ -31,9 +31,7 @@ public: private: const SignalType &type; unsigned address; - Track *track; - Block *block; - unsigned entry; + BlockIter block; Train *train; sigc::connection train_conn; bool check_allocated_blocks; @@ -51,9 +49,8 @@ public: virtual void set_rotation(const Angle &); virtual void set_tilt(const Angle &) { } private: - void update_location(); + void update_attachment(); public: - virtual Track *get_parent() const { return track; } virtual unsigned get_n_snap_nodes() const; virtual Snap get_snap_node(unsigned) const; diff --git a/source/libr2c2/track.cpp b/source/libr2c2/track.cpp index 43bacc3..26fb59e 100644 --- a/source/libr2c2/track.cpp +++ b/source/libr2c2/track.cpp @@ -1,4 +1,5 @@ #include +#include #include "block.h" #include "catalogue.h" #include "driver.h" @@ -331,6 +332,21 @@ bool Track::break_link(unsigned i) return true; } +void Track::add_attachment(TrackAttachment &a) +{ + if(find(attachments.begin(), attachments.end(), &a)!=attachments.end()) + throw key_error(&a); + attachments.push_back(&a); +} + +void Track::remove_attachment(TrackAttachment &a) +{ + AttachmentList::iterator i = find(attachments.begin(), attachments.end(), &a); + if(i==attachments.end()) + throw key_error(&a); + attachments.erase(i); +} + void Track::save(list &st) const { st.push_back((DataFile::Statement("position"), position.x, position.y, position.z)); diff --git a/source/libr2c2/track.h b/source/libr2c2/track.h index 916ea19..994712d 100644 --- a/source/libr2c2/track.h +++ b/source/libr2c2/track.h @@ -13,6 +13,7 @@ namespace R2C2 { class Block; class Layout; +class TrackAttachment; class Track: public Object, public sigc::trackable { @@ -30,6 +31,8 @@ public: void turnout_id(unsigned); }; + typedef std::list AttachmentList; + sigc::signal signal_link_changed; sigc::signal signal_path_changing; sigc::signal signal_path_changed; @@ -44,6 +47,7 @@ private: std::vector links; unsigned active_path; bool path_changing; + AttachmentList attachments; Track(const Track &); Track &operator=(const Track &); @@ -92,6 +96,10 @@ public: using Object::break_link; virtual bool break_link(unsigned); + void add_attachment(TrackAttachment &); + void remove_attachment(TrackAttachment &); + const AttachmentList &get_attachments() const { return attachments; } + void save(std::list &) const; private: void turnout_event(unsigned, unsigned); diff --git a/source/libr2c2/trackattachment.cpp b/source/libr2c2/trackattachment.cpp new file mode 100644 index 0000000..bed7db8 --- /dev/null +++ b/source/libr2c2/trackattachment.cpp @@ -0,0 +1,95 @@ +#include "catalogue.h" +#include "layout.h" +#include "track.h" +#include "trackattachment.h" + +using namespace std; + +namespace R2C2 { + +TrackAttachment::TrackAttachment(Layout &l): + Object(l), + offset(0) +{ } + +TrackAttachment::~TrackAttachment() +{ + if(track) + track->remove_attachment(*this); +} + +void TrackAttachment::attach_to(const TrackIter &t, float o) +{ + if(track) + track->remove_attachment(*this); + + track = t; + offset = o; + + if(track) + track->add_attachment(*this); +} + +void TrackAttachment::attach_to_closest(float limit) +{ + const set &tracks = layout.get_all(); + float dist = -1; + Track *trk = 0; + Vector closest; + for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + if(!(*i)->get_type().is_turnout()) + { + Snap sn; + sn.position = position; + sn.rotation = rotation; + if((*i)->snap(sn, limit, SNAP_SEGMENT)) + { + float d = distance(position, sn.position); + if(dget_n_snap_nodes(); + for(unsigned i=0; iget_snap_node(i); + Angle adiff = abs(wrap_balanced(sn.rotation-rotation)); + if(adiffget_snap_node(trk.entry()).position; + + float dist = distance(epp, point); + float offs = dist; + while(1) + { + TrackPoint tp = trk->get_point(trk.entry(), offs); + float diff = dist-distance(epp, tp.pos); + if(abs(diff)