]> git.tdb.fi Git - r2c2.git/commitdiff
Create another track iterator class that holds an offset as well
authorMikko Rasa <tdb@tdb.fi>
Mon, 22 Jul 2013 19:12:42 +0000 (22:12 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 22 Jul 2013 19:12:42 +0000 (22:12 +0300)
source/libr2c2/beamgate.cpp
source/libr2c2/trackattachment.cpp
source/libr2c2/trackattachment.h
source/libr2c2/trackoffsetiter.cpp [new file with mode: 0644]
source/libr2c2/trackoffsetiter.h [new file with mode: 0644]
source/libr2c2/train.cpp
source/libr2c2/trainrouteplanner.cpp
source/libr2c2/vehicle.cpp
source/libr2c2/vehicle.h

index 614bce9657916152431cda52c1ce0853ba76c318..bb382ffe89c04681dd559c52ca844621229a2109 100644 (file)
@@ -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;
        }
index eb2d563561c6fcf7864d00c1a8a170f943c7e624..64704b11b5290bab5e17d24da21e06f61b9eb230 100644 (file)
@@ -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<Angle::quarter_turn())
                        {
                                TrackIter iter(trk, i);
-                               attach_to(iter, find_offset(iter, closest));
+                               attach_to(TrackOffsetIter(iter, find_offset(iter, closest)));
                                break;
                        }
                }
        }
        else
-               attach_to(TrackIter(), 0);
+               attach_to(TrackOffsetIter());
 }
 
 float TrackAttachment::find_offset(const TrackIter &trk, const Vector &point)
index 1572f619db1ede100ea9cfa8e22d4298ba9a2edc..bd8712b83981ecb7a3634e78ee334865d0a65835 100644 (file)
@@ -3,27 +3,26 @@
 
 #include "object.h"
 #include "track.h"
-#include "trackiter.h"
+#include "trackoffsetiter.h"
 
 namespace R2C2 {
 
 class TrackAttachment: public Object, public sigc::trackable
 {
 protected:
-       TrackIter track;
-       float offset;
+       TrackOffsetIter track;
 
        TrackAttachment(Layout &);
 public:
        virtual ~TrackAttachment();
 
-       const TrackIter &get_track_iter() const { return track; }
+       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 offset; }
+       float get_offset() const { return track.offset(); }
        float get_offset_from_endpoint(unsigned) const;
 protected:
-       void attach_to(const TrackIter &, float);
+       void attach_to(const TrackOffsetIter &);
        void attach_to_closest(float);
        float find_offset(const TrackIter &, const Vector &);
 
diff --git a/source/libr2c2/trackoffsetiter.cpp b/source/libr2c2/trackoffsetiter.cpp
new file mode 100644 (file)
index 0000000..a614569
--- /dev/null
@@ -0,0 +1,131 @@
+#include <msp/strings/format.h>
+#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<unsigned>(_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<length)
+                       return TrackOffsetIter(t, p, o);
+
+               o -= length;
+               t = t.next(p);
+               p = -1;
+       }
+
+       return TrackOffsetIter();
+}
+       
+TrackOffsetIter TrackOffsetIter::reverse() const
+{
+       if(!_track)
+               return TrackOffsetIter();
+
+       int p = (_path>=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 (file)
index 0000000..27b424e
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef LIBR2C2_TRACKOFFSETITER_H_
+#define LIBR2C2_TRACKOFFSETITER_H_
+
+#include <stdexcept>
+#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
index 02e9d31797e2faf6737288ba68c38829b98a0bdb..9cb032ec3f4a9a5663eece64a3048b76a103c10e 100644 (file)
@@ -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;
 
index 0de707b16d21c167a88b9f153ac4945c719c647a..e75cec9cc6f9921f248dd76f89ecc8af80dc6067 100644 (file)
@@ -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);
index a8c3b48dc2f925e9b00812799f4f4afd0c77c95d..5ea9e5a8d7cb3089c3a2938573a4a9508b2a9c5c 100644 (file)
@@ -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 || dist<tdist-margin || dist>tdist+margin)
+       if(!track || dist<tdist-margin || dist>tdist+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
index 94ae2b1683e648cc8f07cb9edfc1ff56d107ecdf..5095a2812a9d02c587748d58b49de8292d4fd96b 100644 (file)
@@ -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<Axle> axles;
        std::vector<Bogie> bogies;
        std::vector<Rod> 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;