From: Mikko Rasa Date: Mon, 22 Jul 2013 19:12:42 +0000 (+0300) Subject: Create another track iterator class that holds an offset as well X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=0443ca05cbd306487131f5f5bd3b91181ae4a733;p=r2c2.git Create another track iterator class that holds an offset as well --- diff --git a/source/libr2c2/beamgate.cpp b/source/libr2c2/beamgate.cpp index 614bce9..bb382ff 100644 --- a/source/libr2c2/beamgate.cpp +++ b/source/libr2c2/beamgate.cpp @@ -54,7 +54,7 @@ void BeamGate::update_attachment() if(track) { - TrackPoint tp = track->get_point(track.entry(), offset); + TrackPoint tp = track.point(); position = tp.pos; rotation = tp.dir; } diff --git a/source/libr2c2/trackattachment.cpp b/source/libr2c2/trackattachment.cpp index eb2d563..64704b1 100644 --- a/source/libr2c2/trackattachment.cpp +++ b/source/libr2c2/trackattachment.cpp @@ -8,8 +8,7 @@ using namespace std; namespace R2C2 { TrackAttachment::TrackAttachment(Layout &l): - Object(l), - offset(0) + Object(l) { layout.signal_object_removed.connect(sigc::mem_fun(this, &TrackAttachment::object_removed)); } @@ -23,18 +22,17 @@ TrackAttachment::~TrackAttachment() float TrackAttachment::get_offset_from_endpoint(unsigned epi) const { if(epi==track.entry()) - return offset; + return track.offset(); else - return track->get_type().get_path_length(0)-offset; + return track->get_type().get_path_length(0)-track.offset(); } -void TrackAttachment::attach_to(const TrackIter &t, float o) +void TrackAttachment::attach_to(const TrackOffsetIter &t) { if(track) track->remove_attachment(*this); track = t; - offset = o; if(track) track->add_attachment(*this); @@ -74,13 +72,13 @@ void TrackAttachment::attach_to_closest(float limit) if(adiff +#include "blockiter.h" +#include "route.h" +#include "track.h" +#include "tracktype.h" +#include "trackoffsetiter.h" + +using namespace std; +using namespace Msp; + +namespace R2C2 { + +incompatible_path::incompatible_path(unsigned a, unsigned e): + logic_error(format("got %d, but %d already set", a, e)) +{ } + + +TrackOffsetIter::TrackOffsetIter(): + _offset(0), + _path(0) +{ } + +TrackOffsetIter::TrackOffsetIter(Track *t, unsigned e, float o): + _track(t, e), + _offset(_track ? o : 0), + _path((_track && _offset) ? _track->get_active_path() : -1) +{ } + +TrackOffsetIter::TrackOffsetIter(Track *t, unsigned e, unsigned p, float o): + _track(t, e), + _offset(o), + _path(p) +{ } + +TrackOffsetIter::TrackOffsetIter(const TrackIter &t, float o): + _track(t), + _offset(_track ? o : 0), + _path((_track && _offset) ? _track->get_active_path() : -1) +{ } + +TrackOffsetIter::TrackOffsetIter(const TrackIter &t, unsigned p, float o): + _track(t), + _offset(o), + _path(p) +{ } + +BlockIter TrackOffsetIter::block_iter() const +{ + return _track.block_iter(); +} + +TrackPoint TrackOffsetIter::point() const +{ + if(!_track) + return TrackPoint(); + + if(_path>=0) + return _track->get_point(_track.entry(), _path, _offset); + else + return _track->get_point(_track.entry(), _offset); +} + +TrackOffsetIter TrackOffsetIter::next() const +{ + if(_path>=0) + return _track.next(_path); + else + return _track.next(); +} + +TrackOffsetIter TrackOffsetIter::next(unsigned p) const +{ + if(_path>=0 && static_cast(_path)!=p) + throw incompatible_path(_path, p); + + return _track.next(p); +} + +TrackOffsetIter TrackOffsetIter::advance(float d, const Route *r) const +{ + if(!_track) + return TrackOffsetIter(); + + if(d<0) + return reverse().advance(-d, r).reverse(); + + TrackIter t = _track; + int p = _path; + float o = _offset+d; + + while(t) + { + if(p<0) + { + if(r) + if(unsigned tid = t->get_turnout_id()) + p = r->get_turnout(tid); + if(p<0) + p = t->get_active_path(); + } + + float length = t->get_type().get_path_length(p); + if(o=0 ? _path : _track->get_active_path()); + TrackIter t = _track.reverse(p); + float o = t->get_type().get_path_length(p)-_offset; + + return TrackOffsetIter(t, p, o); +} + +bool TrackOffsetIter::operator==(const TrackOffsetIter &other) const +{ + return _track==other._track && _offset==other._offset && _path==other._path; +} + +} // namespaec R2C2 diff --git a/source/libr2c2/trackoffsetiter.h b/source/libr2c2/trackoffsetiter.h new file mode 100644 index 0000000..27b424e --- /dev/null +++ b/source/libr2c2/trackoffsetiter.h @@ -0,0 +1,54 @@ +#ifndef LIBR2C2_TRACKOFFSETITER_H_ +#define LIBR2C2_TRACKOFFSETITER_H_ + +#include +#include "trackiter.h" + +namespace R2C2 { + +class incompatible_path: public std::logic_error +{ +public: + incompatible_path(unsigned, unsigned); + virtual ~incompatible_path() throw() { } +}; + +class Route; + +class TrackOffsetIter +{ +private: + TrackIter _track; + float _offset; + int _path; + +public: + TrackOffsetIter(); + TrackOffsetIter(Track *, unsigned, float = 0); + TrackOffsetIter(Track *, unsigned, unsigned, float); + TrackOffsetIter(const TrackIter &, float = 0); + TrackOffsetIter(const TrackIter &, unsigned, float); + + Track *track() const { return _track.track(); } + unsigned entry() const { return _track.entry(); } + const TrackIter &track_iter() const { return _track; } + BlockIter block_iter() const; + float offset() const { return _offset; } + + TrackPoint point() const; + + TrackOffsetIter next() const; + TrackOffsetIter next(unsigned) const; + TrackOffsetIter advance(float, const Route * = 0) const; + TrackOffsetIter reverse() const; + + Track &operator*() const { return *_track; } + Track *operator->() const { return _track.operator->(); } + bool operator==(const TrackOffsetIter &) const; + bool operator!=(const TrackOffsetIter &other) const { return !(*this==other); } + operator bool() const { return _track; } +}; + +} // namespace R2C2 + +#endif diff --git a/source/libr2c2/train.cpp b/source/libr2c2/train.cpp index 02e9d31..9cb032e 100644 --- a/source/libr2c2/train.cpp +++ b/source/libr2c2/train.cpp @@ -510,7 +510,7 @@ float Train::get_reserved_distance_until(const Block *until_block) const Vehicle &veh = *(reverse ? vehicles.back() : vehicles.front()); - TrackIter track = veh.get_track_iter(); + TrackIter track = veh.get_track_iter().track_iter(); if(!track) // XXX Probably unnecessary return 0; diff --git a/source/libr2c2/trainrouteplanner.cpp b/source/libr2c2/trainrouteplanner.cpp index 0de707b..e75cec9 100644 --- a/source/libr2c2/trainrouteplanner.cpp +++ b/source/libr2c2/trainrouteplanner.cpp @@ -226,34 +226,19 @@ TrainRoutePlanner::TrainRoutingState::TrainRoutingState(TrainRoutingInfo &inf): state(MOVING) { const Vehicle *veh = &info->train->get_vehicle(0); - track = veh->get_track_iter(); // TODO margins - offset = veh->get_offset()+veh->get_type().get_length()/2; + float half_length = veh->get_type().get_length()/2; + TrackOffsetIter track_and_offs = veh->get_track_iter().advance(half_length); + track = track_and_offs.track_iter(); + offset = track_and_offs.offset(); path = track->get_active_path(); - float path_length = track->get_type().get_path_length(path); - while(offset>path_length) - { - offset -= path_length; - track = track.next(); - path = track->get_active_path(); - path_length = track->get_type().get_path_length(path); - } - while(Vehicle *next = veh->get_link(1)) veh = next; - back_offset = veh->get_offset()-veh->get_type().get_length()/2; - - TrackIter iter = veh->get_track_iter(); - while(back_offset<0) - { - TrackIter prev = iter.flip().reverse(); - if(!prev) - break; - iter = prev; - back_offset += iter->get_type().get_path_length(iter->get_active_path()); - } + track_and_offs = veh->get_track_iter().advance(-half_length); + back_offset = track_and_offs.offset(); + TrackIter iter = track_and_offs.track_iter(); while(1) { occupied_tracks = new OccupiedTrack(*iter, iter->get_active_path(), occupied_tracks); diff --git a/source/libr2c2/vehicle.cpp b/source/libr2c2/vehicle.cpp index a8c3b48..5ea9e5a 100644 --- a/source/libr2c2/vehicle.cpp +++ b/source/libr2c2/vehicle.cpp @@ -59,7 +59,7 @@ void Vehicle::attach_back(Vehicle &veh) next = &veh; veh.prev = this; - if(track_pos.track) + if(track) propagate_backward(); } @@ -98,16 +98,16 @@ void Vehicle::place(const TrackIter &t, float o, PlaceMode m) if(!t) throw invalid_argument("Vehicle::place"); - track_pos = TrackPosition(t, o); + track = TrackOffsetIter(t, o); if(m==FRONT_AXLE) - track_pos.advance(-type.get_front_axle_offset()); + track = track.advance(-type.get_front_axle_offset()); else if(m==FRONT_BUFFER) - track_pos.advance(-type.get_length()/2); + track = track.advance(-type.get_length()/2); else if(m==BACK_AXLE) - track_pos.advance(-type.get_back_axle_offset()); + track = track.advance(-type.get_back_axle_offset()); else if(m==BACK_BUFFER) - track_pos.advance(type.get_length()/2); + track = track.advance(type.get_length()/2); update_position(); propagate_position(); @@ -115,10 +115,10 @@ void Vehicle::place(const TrackIter &t, float o, PlaceMode m) void Vehicle::unplace() { - if(!track_pos.track) + if(!track) return; - track_pos = TrackPosition(); + track = TrackOffsetIter(); if(prev) prev->unplace(); @@ -128,7 +128,7 @@ void Vehicle::unplace() void Vehicle::advance(float d) { - track_pos.advance(d); + track = track.advance(d); update_position(); turn_axles(d); propagate_position(); @@ -171,14 +171,12 @@ void Vehicle::update_position() if(axles.size()>=2) { float wheelbase = axles.front().type->position-axles.back().type->position; - tp = get_point(track_pos, wheelbase, -axles.back().type->position/wheelbase); + tp = get_point(track, wheelbase, -axles.back().type->position/wheelbase); } else if(bogies.size()>=2) { - TrackPosition front = track_pos; - front.advance(bogies.front().type->position); - TrackPosition back = track_pos; - back.advance(bogies.back().type->position); + TrackOffsetIter front = track.advance(bogies.front().type->position); + TrackOffsetIter back = track.advance(bogies.back().type->position); float bogie_spacing = bogies.front().type->position-bogies.back().type->position; adjust_for_distance(front, back, bogie_spacing); @@ -196,7 +194,7 @@ void Vehicle::update_position() bogies.back().direction = back_point.dir-tp.dir; } else - tp = track_pos.get_point(); + tp = track.point(); if(!prev) check_sensor(type.get_front_axle_offset(), front_sensor); @@ -217,16 +215,15 @@ void Vehicle::update_position_from(const Vehicle &veh) float margin = layout.get_catalogue().get_scale(); float dist = distance(veh.position, position); - if(!track_pos.track || disttdist+margin) + if(!track || disttdist+margin) { - track_pos = veh.track_pos; - track_pos.advance(sign*tdist); + track = veh.track.advance(sign*tdist); update_position(); dist = distance(veh.position, position); } - track_pos.advance(sign*(tdist-dist)); + track = track.advance(sign*(tdist-dist)); update_position(); turn_axles(sign*(tdist-dist)); } @@ -257,9 +254,8 @@ void Vehicle::propagate_backward() void Vehicle::check_sensor(float offset, unsigned &sensor) { - TrackPosition pos = track_pos; - pos.advance(offset); - unsigned s = pos.track->get_sensor_id(); + TrackOffsetIter iter = track.advance(offset); + unsigned s = iter->get_sensor_id(); if(s!=sensor) { /* Sensor ID under axle has changed. Deduce movement direction by using @@ -268,7 +264,7 @@ void Vehicle::check_sensor(float offset, unsigned &sensor) more robust would be preferable. */ unsigned old = sensor; sensor = s; - unsigned mid = track_pos.track->get_sensor_id(); + unsigned mid = track->get_sensor_id(); if(s && s!=mid) /* There's a sensor and it's different from mid. We've just entered @@ -345,14 +341,14 @@ void Vehicle::update_rods() } } -void Vehicle::adjust_for_distance(TrackPosition &front, TrackPosition &back, float tdist, float ratio) const +void Vehicle::adjust_for_distance(TrackOffsetIter &front, TrackOffsetIter &back, float tdist, float ratio) const { float margin = 0.01*layout.get_catalogue().get_scale(); int adjust_dir = 0; while(1) { - Vector front_point = front.get_point().pos; - Vector back_point = back.get_point().pos; + Vector front_point = front.point().pos; + Vector back_point = back.point().pos; float dist = distance(front_point, back_point); @@ -370,8 +366,8 @@ void Vehicle::adjust_for_distance(TrackPosition &front, TrackPosition &back, flo else return; - front.advance(diff*(1-ratio)); - back.advance(-diff*ratio); + front = front.advance(diff*(1-ratio)); + back = back.advance(-diff*ratio); } } @@ -386,16 +382,13 @@ TrackPoint Vehicle::get_point(const Vector &front, const Vector &back, float rat return tp; } -TrackPoint Vehicle::get_point(const TrackPosition &pos, float tdist, float ratio) const +TrackPoint Vehicle::get_point(const TrackOffsetIter &iter, float tdist, float ratio) const { - TrackPosition front = pos; - front.advance(tdist*(1-ratio)); - - TrackPosition back = pos; - back.advance(-tdist*ratio); + TrackOffsetIter front = iter.advance(tdist*(1-ratio)); + TrackOffsetIter back = iter.advance(-tdist*ratio); adjust_for_distance(front, back, tdist, ratio); - return get_point(front.get_point().pos, back.get_point().pos, ratio); + return get_point(front.point().pos, back.point().pos, ratio); } unsigned Vehicle::get_n_link_slots() const @@ -439,56 +432,4 @@ Vehicle::Rod::Rod(const VehicleType::Rod &t): type(&t) { } - -Vehicle::TrackPosition::TrackPosition(): - offs(0) -{ } - -Vehicle::TrackPosition::TrackPosition(const TrackIter &t, float o): - track(t), - offs(o) -{ } - -void Vehicle::TrackPosition::advance(float d) -{ - if(!track) - return; - - offs += d; - while(track) - { - float path_len = track->get_type().get_path_length(track->get_active_path()); - - if(offs>path_len) - { - offs -= path_len; - track = track.next(); - } - else - break; - } - - while(track && offs<0) - { - track = track.flip().reverse(); - - if(track) - { - float path_len = track->get_type().get_path_length(track->get_active_path()); - offs += path_len; - } - } - - if(!track) - offs = 0; -} - -TrackPoint Vehicle::TrackPosition::get_point() const -{ - if(track) - return track->get_point(track.entry(), offs); - else - return TrackPoint(); -} - } // namespace R2C2 diff --git a/source/libr2c2/vehicle.h b/source/libr2c2/vehicle.h index 94ae2b1..5095a28 100644 --- a/source/libr2c2/vehicle.h +++ b/source/libr2c2/vehicle.h @@ -3,7 +3,7 @@ #include "geometry.h" #include "object.h" -#include "trackiter.h" +#include "trackoffsetiter.h" #include "vehicletype.h" namespace R2C2 { @@ -58,22 +58,11 @@ public: }; private: - struct TrackPosition - { - TrackIter track; - float offs; - - TrackPosition(); - TrackPosition(const TrackIter &, float); - void advance(float); - TrackPoint get_point() const; - }; - const VehicleType &type; Train *train; Vehicle *next; Vehicle *prev; - TrackPosition track_pos; + TrackOffsetIter track; std::vector axles; std::vector bogies; std::vector rods; @@ -103,10 +92,10 @@ public: void place(const TrackIter &, float, PlaceMode = CENTER); void unplace(); void advance(float); - const TrackIter &get_track_iter() const { return track_pos.track; } - Track *get_track() const { return track_pos.track.track(); } - unsigned get_entry() const { return track_pos.track.entry(); } - float get_offset() const { return track_pos.offs; } + const TrackOffsetIter &get_track_iter() const { return track; } + Track *get_track() const { return track.track(); } + unsigned get_entry() const { return track.entry(); } + float get_offset() const { return track.offset(); } const Axle &get_fixed_axle(unsigned) const; const Bogie &get_bogie(unsigned) const; const Axle &get_bogie_axle(unsigned, unsigned) const; @@ -121,9 +110,9 @@ private: void turn_axles(float); void update_rods(); - void adjust_for_distance(TrackPosition &, TrackPosition &, float, float = 0.5) const; + void adjust_for_distance(TrackOffsetIter &, TrackOffsetIter &, float, float = 0.5) const; TrackPoint get_point(const Vector &, const Vector &, float = 0.5) const; - TrackPoint get_point(const TrackPosition &, float, float = 0.5) const; + TrackPoint get_point(const TrackOffsetIter &, float, float = 0.5) const; public: virtual unsigned get_n_link_slots() const;