]> git.tdb.fi Git - r2c2.git/commitdiff
Add a common base class for tangible objects
authorMikko Rasa <tdb@tdb.fi>
Mon, 6 May 2013 17:23:15 +0000 (20:23 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 6 May 2013 17:23:15 +0000 (20:23 +0300)
23 files changed:
source/3d/axle.cpp
source/3d/bogie.cpp
source/3d/rod.cpp
source/3d/signal.cpp
source/3d/vehicle.cpp
source/engineer/trainview.cpp
source/libr2c2/layout.cpp
source/libr2c2/layout.h
source/libr2c2/object.h [new file with mode: 0644]
source/libr2c2/objecttype.cpp [new file with mode: 0644]
source/libr2c2/objecttype.h [new file with mode: 0644]
source/libr2c2/signal.cpp
source/libr2c2/signal.h
source/libr2c2/signaltype.cpp
source/libr2c2/signaltype.h
source/libr2c2/track.cpp
source/libr2c2/track.h
source/libr2c2/tracktype.cpp
source/libr2c2/tracktype.h
source/libr2c2/vehicle.cpp
source/libr2c2/vehicle.h
source/libr2c2/vehicletype.cpp
source/libr2c2/vehicletype.h

index 6b0e1f58315ced7adbcc774efff0d2e035b7da5e..c9f7a7023995c45eccfc4863c0257db6119feaf8 100644 (file)
@@ -36,7 +36,7 @@ void Axle3D::setup_render(GL::Renderer &renderer, const GL::Tag &) const
 
        const Vector &pos = vehicle.get_position();
        matrix.translate(pos.x, pos.y, pos.z);
-       matrix.rotate(vehicle.get_direction(), 0, 0, 1);
+       matrix.rotate(vehicle.get_rotation(), 0, 0, 1);
 
        if(bogie)
        {
index a36fc9b773c8fb9374b164ffc148c5beb3875ab2..8e99ceb0d9a6bd7fa5350382d8be75a65083eb7d 100644 (file)
@@ -28,7 +28,7 @@ void Bogie3D::setup_render(Msp::GL::Renderer &renderer, const GL::Tag &) const
 
        const Vector &pos = vehicle.get_position();
        matrix.translate(pos.x, pos.y, pos.z);
-       matrix.rotate(vehicle.get_direction(), 0, 0, 1);
+       matrix.rotate(vehicle.get_rotation(), 0, 0, 1);
 
        matrix.translate(bogie.type->position, 0, 0);
        float dir = bogie.direction;
index c59dd836e7e120526058ba667ae8fc96206b2391..10b5f46ecc6ee0ee304d2c318ad30220263d787f 100644 (file)
@@ -27,7 +27,7 @@ void Rod3D::setup_render(GL::Renderer &renderer, const GL::Tag &) const
        GL::Matrix matrix;
        const Vector &pos = vehicle.get_position();
        matrix.translate(pos.x, pos.y, pos.z);
-       matrix.rotate(vehicle.get_direction(), 0, 0, 1);
+       matrix.rotate(vehicle.get_rotation(), 0, 0, 1);
 
        matrix.translate(rod.position.x, rod.position.y, rod.position.z);
        if(rod.type->mirror_object)
index 8601bcc8d935aaa381d137275602fe263a67e673..0942bce22e1389aee4798c6376d2eb7e7cc7ac2e 100644 (file)
@@ -27,7 +27,7 @@ void Signal3D::setup_render(GL::Renderer &renderer, const GL::Tag &) const
 {
        const Vector &pos = signal.get_position();
        renderer.matrix_stack() *= GL::Matrix::translation(pos.x, pos.y, pos.z);
-       renderer.matrix_stack() *= GL::Matrix::rotation(signal.get_direction(), 0, 0, 1);
+       renderer.matrix_stack() *= GL::Matrix::rotation(signal.get_rotation(), 0, 0, 1);
        // XXX Use track gauge, configure signal side
        renderer.matrix_stack() *= GL::Matrix::translation(0, -0.035, 0);
 }
index 0bd57e95da2b80d276fdf82cef0015649dc1d53d..d1e5657a0a9095c277cef53a95255ae7e27afddf 100644 (file)
@@ -95,10 +95,10 @@ void Vehicle3D::setup_render(GL::Renderer &renderer, const GL::Tag &) const
        GL::Matrix matrix;
        const Vector &pos = vehicle.get_position();
        matrix.translate(pos.x, pos.y, pos.z);
-       float dir = vehicle.get_direction();
+       float rot = vehicle.get_rotation();
        if(vehicle.get_type().get_rotate_object())
-               dir += M_PI;
-       matrix.rotate(dir, 0, 0, 1);
+               rot += M_PI;
+       matrix.rotate(rot, 0, 0, 1);
        renderer.matrix_stack() *= matrix;
 }
 
index 1ab236f4c797a7464bc7e42d5d8369d92b89febd..79f9c946f82a51eef1865ea90a0433949d69f22f 100644 (file)
@@ -86,7 +86,7 @@ void TrainView::prepare()
 {
        const Vehicle &veh = train.get_vehicle(0);
        const Vector &pos = veh.get_position();
-       float angle = veh.get_direction();
+       float angle = veh.get_rotation();
        if(!forward)
                angle += M_PI;
        float c = cos(angle);
index a4c7309e472fc30d122b0a532508813cf212be37..4679fd9e166674fec43a8ba01947b015bc8c294c 100644 (file)
@@ -74,11 +74,7 @@ void Layout::add_track(Track &t)
 
 Track *Layout::pick_track(const Vector &start, const Vector &ray)
 {
-  for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
-     if((*i)->collide_ray(start, ray))
-        return *i;
-
-       return 0;
+       return pick(tracks, start, ray);
 }
 
 void Layout::remove_track(Track &t)
@@ -111,12 +107,36 @@ void Layout::add_signal(Signal &s)
                signal_signal_added.emit(s);
 }
 
+Signal *Layout::pick_signal(const Vector &start, const Vector &ray)
+{
+       return pick(signals, start, ray);
+}
+
 void Layout::remove_signal(Signal &s)
 {
        if(signals.erase(&s))
                signal_signal_removed.emit(s);
 }
 
+Object *Layout::pick_object(const Vector &start, const Vector &ray)
+{
+       if(Object *obj = pick_track(start, ray))
+               return obj;
+       else if((obj = pick_signal(start, ray)))
+               return obj;
+       return 0;
+}
+
+template<typename T>
+T *Layout::pick(const set<T *> &objs, const Vector &start, const Vector &ray)
+{
+       for(typename set<T *>::const_iterator i=objs.begin(); i!=objs.end(); ++i)
+               if((*i)->collide_ray(start, ray))
+                       return *i;
+
+       return 0;
+}
+
 void Layout::add_block(Block &b)
 {
        blocks.insert(&b);
index 73c74b8d4c6cc1177415aead1990360a58080b96..c32795594bd253b43d03299e0dfe2e30f3b74d81 100644 (file)
@@ -93,8 +93,16 @@ public:
 
        void add_signal(Signal &);
        const std::set<Signal *> &get_signals() const { return signals; }
+       Signal *pick_signal(const Vector &, const Vector &);
        void remove_signal(Signal &);
 
+       Object *pick_object(const Vector &, const Vector &);
+
+private:
+       template<typename T>
+       static T *pick(const std::set<T *> &, const Vector &, const Vector &);
+
+public:
        void add_block(Block &);
        Block &get_block(unsigned) const;
        const std::set<Block *> &get_blocks() const { return blocks; }
diff --git a/source/libr2c2/object.h b/source/libr2c2/object.h
new file mode 100644 (file)
index 0000000..206ec33
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef LIBR2C2_OBJECT_H_
+#define LIBR2C2_OBJECT_H_
+
+#include "geometry.h"
+#include "objecttype.h"
+
+namespace R2C2 {
+
+class Layout;
+
+class Object
+{
+protected:
+       Layout &layout;
+       Vector position;
+       float rotation;
+
+       Object(Layout &l): layout(l) { }
+public:
+       virtual ~Object() { }
+
+       virtual Object *clone(Layout * = 0) const = 0;
+       virtual const ObjectType &get_type() const = 0;
+       Layout &get_layout() const { return layout; }
+       virtual void set_position(const Vector &) = 0;
+       virtual void set_rotation(float) = 0;
+       const Vector &get_position() const { return position; }
+       float get_rotation() const { return rotation; }
+       virtual Object *get_parent() const { return 0; }
+       virtual bool collide_ray(const Vector &, const Vector &) const = 0;
+};
+
+} // namespace R2C2
+
+#endif
diff --git a/source/libr2c2/objecttype.cpp b/source/libr2c2/objecttype.cpp
new file mode 100644 (file)
index 0000000..10d9c88
--- /dev/null
@@ -0,0 +1,14 @@
+#include "objecttype.h"
+
+using namespace Msp;
+
+namespace R2C2 {
+
+ObjectType::Loader::Loader(ObjectType &ot):
+       DataFile::ObjectLoader<ObjectType>(ot)
+{
+       add("description", &ObjectType::description);
+       add("name",        &ObjectType::name);
+}
+
+} // namespace R2C2
diff --git a/source/libr2c2/objecttype.h b/source/libr2c2/objecttype.h
new file mode 100644 (file)
index 0000000..0cca264
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef LIBR2C2_OBJECTTYPE_H_
+#define LIBR2C2_OBJECTTYPE_H_
+
+#include <string>
+#include <msp/datafile/objectloader.h>
+#include "articlenumber.h"
+
+namespace R2C2 {
+
+class ObjectType
+{
+public:
+       class Loader: public Msp::DataFile::ObjectLoader<ObjectType>
+       {
+       public:
+               Loader(ObjectType &);
+       };
+
+protected:
+       ArticleNumber art_nr;
+       std::string name;
+       std::string description;
+
+       ObjectType(const ArticleNumber &a): art_nr(a) { }
+public:
+       virtual ~ObjectType() { }
+
+       const ArticleNumber &get_article_number() const { return art_nr; }
+       const std::string &get_name() const { return name; }
+       const std::string &get_description() const { return description; }
+};
+
+} // namespace R2C2
+
+#endif
index a8b0be029799afdcec0c5c379b2788e31919583d..72cf235193e6a9c537e67a003ede7a221b8c7673 100644 (file)
@@ -13,7 +13,7 @@ using namespace Msp;
 namespace R2C2 {
 
 Signal::Signal(Layout &l, const SignalType &t):
-       layout(l),
+       Object(l),
        type(t),
        address(0),
        track(0),
@@ -33,6 +33,14 @@ Signal::~Signal()
        layout.remove_signal(*this);
 }
 
+Signal *Signal::clone(Layout *to_layout) const
+{
+       Signal *sig = new Signal((to_layout ? *to_layout : layout), type);
+       sig->set_position(position);
+       sig->set_rotation(rotation);
+       return sig;
+}
+
 void Signal::set_address(unsigned a)
 {
        address = a;
@@ -53,7 +61,7 @@ void Signal::set_position(const Vector &p)
                        if(d<dist || dist<0)
                        {
                                position = n.pos;
-                               direction = n.dir;
+                               rotation = n.dir;
                                track = *i;
                                dist = d;
                        }
@@ -69,7 +77,7 @@ void Signal::normalize_location()
        unsigned n_endpoints = track->get_type().get_endpoints().size();
        for(unsigned j=0; j<n_endpoints; ++j)
        {
-               float a = track->get_endpoint_direction(j)-direction;
+               float a = track->get_endpoint_direction(j)-rotation;
                while(a<-M_PI/2)
                        a += M_PI*2;
                while(a>M_PI*3/2)
@@ -82,23 +90,37 @@ void Signal::normalize_location()
        }
 }
 
-void Signal::set_direction(float d)
+void Signal::set_rotation(float r)
 {
-       float a = direction-d;
+       float a = rotation-r;
        while(a>M_PI*3/2)
                a -= M_PI*2;
        while(a<-M_PI/2)
                a += M_PI*2;
        if(a>=M_PI/2)
        {
-               direction += M_PI;
-               if(direction>M_PI*2)
-                       direction -= M_PI*2;
+               rotation += M_PI;
+               if(rotation>M_PI*2)
+                       rotation -= M_PI*2;
        }
 
        normalize_location();
 }
 
+bool Signal::collide_ray(const Vector &start, const Vector &ray) const
+{
+       // XXX Totally hardcoded stuff, should be replaced with a geometry system
+       Vector center = position;
+       center.x += sin(rotation)*0.035;
+       center.y -= cos(rotation)*0.035;
+       Vector d(center.x-start.x, center.y-start.y);
+       float x = (d.x*ray.x+d.y*ray.y)/(ray.x*ray.x+ray.y*ray.y);
+       Vector nearest(start.x+ray.x*x-center.x, start.y+ray.y*x-center.y, start.z+ray.z*x-center.z);
+       if(nearest.z<0|| nearest.z>0.12)
+               return false;
+       return nearest.x*nearest.x+nearest.y*nearest.y<0.0001;
+}
+
 void Signal::tick(const Time::TimeDelta &)
 {
        if(check_allocated_blocks)
@@ -176,7 +198,7 @@ void Signal::reset()
 void Signal::save(list<DataFile::Statement> &st) const
 {
        st.push_back((DataFile::Statement("position"), position.x, position.y, position.z));
-       st.push_back((DataFile::Statement("direction"), direction));
+       st.push_back((DataFile::Statement("rotation"), rotation));
        if(address)
                st.push_back((DataFile::Statement("address"), address));
 }
@@ -185,9 +207,9 @@ void Signal::save(list<DataFile::Statement> &st) const
 Signal::Loader::Loader(Signal &s):
        DataFile::ObjectLoader<Signal>(s)
 {
-       add("address",   &Loader::address);
-       add("direction", &Loader::direction);
-       add("position",  &Loader::position);
+       add("address",  &Loader::address);
+       add("position", &Loader::position);
+       add("rotation", &Loader::rotation);
 }
 
 void Signal::Loader::address(unsigned a)
@@ -195,14 +217,14 @@ void Signal::Loader::address(unsigned a)
        obj.set_address(a);
 }
 
-void Signal::Loader::direction(float d)
+void Signal::Loader::position(float x, float y, float z)
 {
-       obj.set_direction(d);
+       obj.set_position(Vector(x, y, z));
 }
 
-void Signal::Loader::position(float x, float y, float z)
+void Signal::Loader::rotation(float d)
 {
-       obj.set_position(Vector(x, y, z));
+       obj.set_rotation(d);
 }
 
 } // namespace R2C2
index dcaa17a3cd997dba36a5cdedc03badae601cc8df..92e197744ba975f257198cb4984d559963b08e7e 100644 (file)
@@ -4,16 +4,17 @@
 #include <msp/datafile/objectloader.h>
 #include <msp/time/timedelta.h>
 #include "geometry.h"
+#include "object.h"
+#include "signaltype.h"
+#include "track.h"
 
 namespace R2C2 {
 
 class Block;
 class Layout;
-class SignalType;
-class Track;
 class Train;
 
-class Signal
+class Signal: public Object
 {
 public:
        class Loader: public Msp::DataFile::ObjectLoader<Signal>
@@ -23,16 +24,13 @@ public:
 
        private:
                void address(unsigned);
-               void direction(float);
                void position(float, float, float);
+               void rotation(float);
        };
 
 private:
-       Layout &layout;
        const SignalType &type;
        unsigned address;
-       Vector position;
-       float direction;
        Track *track;
        Block *block;
        unsigned entry;
@@ -45,16 +43,18 @@ public:
        Signal(Layout &, const SignalType &);
        ~Signal();
 
-       const SignalType &get_type() const { return type; }
+       virtual Signal *clone(Layout * = 0) const;
+       virtual const SignalType &get_type() const { return type; }
 
        void set_address(unsigned);
-       void set_position(const Vector &);
-       void set_direction(float);
+       virtual void set_position(const Vector &);
+       virtual void set_rotation(float);
 private:
        void normalize_location();
 public:
-       const Vector &get_position() const { return position; }
-       float get_direction() const { return direction; }
+       virtual Track *get_parent() const { return track; }
+
+       virtual bool collide_ray(const Vector &, const Vector &) const;
 
        void tick(const Msp::Time::TimeDelta &);
 
index 9fb25e90e0808ac6304e1727c71f9bea01c9c3ec..d3f48d9066dc68914dcb8b6771ca9c60dc48a87e 100644 (file)
@@ -1,19 +1,19 @@
 #include "signaltype.h"
 
 using namespace std;
+using namespace Msp;
 
 namespace R2C2 {
 
 SignalType::SignalType(const ArticleNumber &an):
-       art_nr(an)
+       ObjectType(an)
 {
 }
 
 
 SignalType::Loader::Loader(SignalType &st):
-       ObjectLoader<SignalType>(st)
+       DataFile::DerivedObjectLoader<SignalType, ObjectType::Loader>(st)
 {
-       add("description", &SignalType::description);
        add("indication",  &Loader::indication);
        add("object",      &SignalType::object);
 }
index 4499d7ee0b6573b6e8090ac5d67519d5125b9df8..97de833d71b5b7cdf59b93e57438ff44d9f46e94 100644 (file)
@@ -2,11 +2,11 @@
 #define LIBR2C2_SIGNALTYPE_H_
 
 #include <msp/datafile/objectloader.h>
-#include "articlenumber.h"
+#include "objecttype.h"
 
 namespace R2C2 {
 
-class SignalType
+class SignalType: public ObjectType
 {
 public:
        struct Indication
@@ -22,7 +22,7 @@ public:
                unsigned free_blocks;
        };
 
-       class Loader: public Msp::DataFile::ObjectLoader<SignalType>
+       class Loader: public Msp::DataFile::DerivedObjectLoader<SignalType, ObjectType::Loader>
        {
        public:
                Loader(SignalType &);
@@ -33,15 +33,12 @@ public:
        typedef std::list<Indication> IndicationList;
 
 private:
-       ArticleNumber art_nr;
-       std::string description;
        IndicationList indications;
        std::string object;
 
 public:
        SignalType(const ArticleNumber &);
 
-       const ArticleNumber &get_article_number() const { return art_nr; }
        const IndicationList &get_indications() const { return indications; }
        const std::string &get_object() const { return object; }
 };
index d4e9d12d8ef7b08682f0f9c97d5f4cb36a3cce38..b679af783867f72746793f205179f004a9e02baa 100644 (file)
@@ -12,10 +12,9 @@ using namespace Msp;
 namespace R2C2 {
 
 Track::Track(Layout &l, const TrackType &t):
-       layout(l),
+       Object(l),
        type(t),
        block(0),
-       rot(0),
        slope(0),
        flex(false),
        turnout_id(0),
@@ -41,6 +40,14 @@ Track::~Track()
        layout.remove_track(*this);
 }
 
+Track *Track::clone(Layout *to_layout) const
+{
+       Track *track = new Track((to_layout ? *to_layout : layout), type);
+       track->set_position(position);
+       track->set_rotation(rotation);
+       return track;
+}
+
 void Track::set_block(Block *b)
 {
        if(b && !b->has_track(*this))
@@ -61,16 +68,16 @@ Block &Track::get_block() const
 
 void Track::set_position(const Vector &p)
 {
-       pos = p;
+       position = p;
 }
 
 void Track::set_rotation(float r)
 {
-       rot = r;
-       while(rot<0)
-               rot += M_PI*2;
-       while(rot>M_PI*2)
-               rot -= M_PI*2;
+       rotation = r;
+       while(rotation<0)
+               rotation += M_PI*2;
+       while(rotation>M_PI*2)
+               rotation -= M_PI*2;
 }
 
 void Track::set_slope(float s)
@@ -95,8 +102,8 @@ void Track::check_slope()
        {
                Vector epp0 = links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this));
                Vector epp1 = links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this));
-               pos.z = epp0.z;
-               slope = epp1.z-pos.z;
+               position.z = epp0.z;
+               slope = epp1.z-position.z;
        }
        else
        {
@@ -104,12 +111,12 @@ void Track::check_slope()
                if(links[0])
                {
                        Vector epp = links[0]->get_endpoint_position(links[0]->get_endpoint_by_link(*this));
-                       pos.z = epp.z;
+                       position.z = epp.z;
                }
                else if(links[1])
                {
                        Vector epp = links[1]->get_endpoint_position(links[1]->get_endpoint_by_link(*this));
-                       pos.z = epp.z;
+                       position.z = epp.z;
                }
        }
 }
@@ -165,10 +172,10 @@ Vector Track::get_endpoint_position(unsigned epi) const
 
        const TrackType::Endpoint &ep = eps[epi];
 
-       float c = cos(rot);
-       float s = sin(rot);
+       float c = cos(rotation);
+       float s = sin(rotation);
 
-       Vector p(pos.x+c*ep.pos.x-s*ep.pos.y, pos.y+s*ep.pos.x+c*ep.pos.y, pos.z);
+       Vector p(position.x+c*ep.pos.x-s*ep.pos.y, position.y+s*ep.pos.x+c*ep.pos.y, position.z);
        if(eps.size()==2 && epi==1)
                p.z += slope;
        return p;
@@ -182,7 +189,7 @@ float Track::get_endpoint_direction(unsigned epi) const
 
        const TrackType::Endpoint &ep = eps[epi];
 
-       return rot+ep.dir;
+       return rotation+ep.dir;
 }
 
 bool Track::snap_to(Track &other, bool link, float limit)
@@ -215,9 +222,9 @@ bool Track::snap_to(Track &other, bool link, float limit)
                        {
                                if(!link || (!flex && !other.get_flex()))
                                {
-                                       set_rotation(other.rot+other_eps[j].dir-eps[i].dir+M_PI);
-                                       Vector p(epp2.x-(eps[i].pos.x*cos(rot)-eps[i].pos.y*sin(rot)),
-                                               epp2.y-(eps[i].pos.y*cos(rot)+eps[i].pos.x*sin(rot)),
+                                       set_rotation(other.rotation+other_eps[j].dir-eps[i].dir+M_PI);
+                                       Vector p(epp2.x-(eps[i].pos.x*cos(rotation)-eps[i].pos.y*sin(rotation)),
+                                               epp2.y-(eps[i].pos.y*cos(rotation)+eps[i].pos.x*sin(rotation)),
                                                epp2.z);
                                        if(eps.size()==2 && i==1)
                                                p.z -= slope;
@@ -256,7 +263,7 @@ bool Track::snap(Vector &pt, float &d) const
                if(dx*dx+dy*dy<1e-4)
                {
                        pt = epp;
-                       d = rot+eps[i].dir;
+                       d = rotation+eps[i].dir;
                        return true;
                }
        }
@@ -299,11 +306,11 @@ Track *Track::get_link(unsigned i) const
 TrackPoint Track::get_point(unsigned epi, unsigned path, float d) const
 {
        TrackPoint p = type.get_point(epi, path, d);
-       float c = cos(rot);
-       float s = sin(rot);
+       float c = cos(rotation);
+       float s = sin(rotation);
 
-       p.pos = Vector(pos.x+c*p.pos.x-s*p.pos.y, pos.y+s*p.pos.x+c*p.pos.y, pos.z);
-       p.dir += rot;
+       p.pos = Vector(position.x+c*p.pos.x-s*p.pos.y, position.y+s*p.pos.x+c*p.pos.y, position.z);
+       p.dir += rotation;
        if(type.get_endpoints().size()==2)
        {
                float len = type.get_path_length(path);
@@ -330,22 +337,22 @@ TrackPoint Track::get_point(unsigned epi, float d) const
 
 TrackPoint Track::get_nearest_point(const Vector &p) const
 {
-       Vector local(p.x-pos.x, p.y-pos.y, p.z-pos.z);
-       float c = cos(rot);
-       float s = sin(rot);
+       Vector local(p.x-position.x, p.y-position.y, p.z-position.z);
+       float c = cos(rotation);
+       float s = sin(rotation);
        local = Vector(c*local.x+s*local.y, c*local.y-s*local.x, local.z);
 
        TrackPoint tp = type.get_nearest_point(local);
-       tp.pos = Vector(pos.x+tp.pos.x*c-tp.pos.y*s, pos.y+tp.pos.y*c+tp.pos.x*s, pos.z+tp.pos.z);
-       tp.dir += rot;
+       tp.pos = Vector(position.x+tp.pos.x*c-tp.pos.y*s, position.y+tp.pos.y*c+tp.pos.x*s, position.z+tp.pos.z);
+       tp.dir += rotation;
        return tp;
 }
 
-bool Track::collide_ray(const Vector &start, const Vector &ray)
+bool Track::collide_ray(const Vector &start, const Vector &ray) const
 {
-       Vector local_start(start.x-pos.x, start.y-pos.y, start.z-pos.z);
-       float c = cos(rot);
-       float s = sin(rot);
+       Vector local_start(start.x-position.x, start.y-position.y, start.z-position.z);
+       float c = cos(rotation);
+       float s = sin(rotation);
        local_start = Vector(c*local_start.x+s*local_start.y, c*local_start.y-s*local_start.x, local_start.z);
        Vector local_ray(c*ray.x+s*ray.y, c*ray.y-s*ray.x, ray.z);
 
@@ -356,8 +363,8 @@ bool Track::collide_ray(const Vector &start, const Vector &ray)
 
 void Track::save(list<DataFile::Statement> &st) const
 {
-       st.push_back((DataFile::Statement("position"), pos.x, pos.y, pos.z));
-       st.push_back((DataFile::Statement("rotation"), rot));
+       st.push_back((DataFile::Statement("position"), position.x, position.y, position.z));
+       st.push_back((DataFile::Statement("rotation"), rotation));
        st.push_back((DataFile::Statement("slope"), slope));
        if(turnout_id)
                st.push_back((DataFile::Statement("turnout_id"), turnout_id));
@@ -385,7 +392,7 @@ Track::Loader::Loader(Track &t):
        DataFile::ObjectLoader<Track>(t)
 {
        add("position",   &Loader::position);
-       add("rotation",   &Track::rot);
+       add("rotation",   &Loader::rotation);
        add("slope",      &Track::slope);
        add("turnout_id", &Loader::turnout_id);
        add("sensor_id",  &Loader::sensor_id);
@@ -394,7 +401,12 @@ Track::Loader::Loader(Track &t):
 
 void Track::Loader::position(float x, float y, float z)
 {
-       obj.pos = Vector(x, y, z);
+       obj.position = Vector(x, y, z);
+}
+
+void Track::Loader::rotation(float r)
+{
+       obj.rotation = r;
 }
 
 void Track::Loader::sensor_id(unsigned id)
index 4dbfa2db87eabd56c12616f759adebdef1f4ca2c..883fb5eda506ab04a0614bbbebf1333560bbe41f 100644 (file)
@@ -6,14 +6,15 @@
 #include <sigc++/trackable.h>
 #include <msp/datafile/objectloader.h>
 #include "geometry.h"
+#include "object.h"
+#include "tracktype.h"
 
 namespace R2C2 {
 
 class Block;
 class Layout;
-class TrackType;
 
-class Track: public sigc::trackable
+class Track: public Object, public sigc::trackable
 {
 public:
        class Loader: public Msp::DataFile::ObjectLoader<Track>
@@ -22,6 +23,7 @@ public:
                Loader(Track &);
        private:
                void position(float, float, float);
+               void rotation(float);
                void sensor_id(unsigned);
                void turnout_id(unsigned);
        };
@@ -30,11 +32,8 @@ public:
        sigc::signal<void, unsigned> signal_path_changed;
 
 private:
-       Layout &layout;
        const TrackType &type;
        Block *block;
-       Vector pos;
-       float rot;
        float slope;
        bool flex;
        unsigned turnout_id;
@@ -49,17 +48,15 @@ public:
        Track(Layout &, const TrackType &);
        ~Track();
 
-       Layout &get_layout() const { return layout; }
-       const TrackType &get_type() const { return type; }
+       virtual Track *clone(Layout * = 0) const;
+       virtual const TrackType &get_type() const { return type; }
 
        void set_block(Block *);
        Block &get_block() const;
-       void set_position(const Vector &);
-       void set_rotation(float);
+       virtual void set_position(const Vector &);
+       virtual void set_rotation(float);
        void set_slope(float);
        void set_flex(bool);
-       const Vector &get_position() const { return pos; }
-       float get_rotation() const { return rot; }
        float get_slope() const { return slope; }
        bool get_flex() const { return flex; }
        void check_slope();
@@ -85,7 +82,7 @@ public:
        TrackPoint get_point(unsigned, float) const;
        TrackPoint get_nearest_point(const Vector &) const;
 
-       bool collide_ray(const Vector &, const Vector &);
+       virtual bool collide_ray(const Vector &, const Vector &) const;
 
        void save(std::list<Msp::DataFile::Statement> &) const;
 private:
index bf038c52d76c2d19576e5b9a1b30e059a4837306..3be1ecb364e8631a84ac216960bc154a82277510 100644 (file)
@@ -7,7 +7,7 @@ using namespace Msp;
 namespace R2C2 {
 
 TrackType::TrackType(const ArticleNumber &an):
-       art_nr(an),
+       ObjectType(an),
        state_bits(0),
        autofit_preference(1)
 { }
@@ -192,11 +192,10 @@ TrackType::Endpoint::Endpoint(float x, float y, float d, unsigned p):
 
 
 TrackType::Loader::Loader(TrackType &t):
-       Msp::DataFile::ObjectLoader<TrackType>(t),
+       DataFile::DerivedObjectLoader<TrackType, ObjectType::Loader>(t),
        state_bits_set(false)
 {
        add("autofit_preference", &TrackType::autofit_preference);
-       add("description", &TrackType::description);
        add("object",      &TrackType::object);
        add("state_bits",  &Loader::state_bits);
        add("part",        &Loader::part);
index dd2a7c4ddf29f83c67d8bed648382d449412db46..afc85215bfe0366e0e107d21371a218ea8ab282a 100644 (file)
@@ -4,11 +4,12 @@
 #include <msp/datafile/objectloader.h>
 #include "articlenumber.h"
 #include "geometry.h"
+#include "objecttype.h"
 #include "trackpart.h"
 
 namespace R2C2 {
 
-class TrackType
+class TrackType: public ObjectType
 {
 public:
        struct Endpoint
@@ -23,7 +24,7 @@ public:
                bool has_common_paths(const Endpoint &e) const { return paths&e.paths; }
        };
 
-       class Loader: public Msp::DataFile::ObjectLoader<TrackType>
+       class Loader: public Msp::DataFile::DerivedObjectLoader<TrackType, ObjectType::Loader>
        {
        private:
                bool state_bits_set;
@@ -38,8 +39,6 @@ public:
        };
 
 private:
-       ArticleNumber art_nr;
-       std::string description;
        std::vector<TrackPart> parts;
        std::vector<Endpoint> endpoints;
        unsigned state_bits;
@@ -49,8 +48,6 @@ private:
 public:
        TrackType(const ArticleNumber &);
 
-       const ArticleNumber &get_article_number() const { return art_nr; }
-       const std::string &get_description() const { return description; }
        float get_total_length() const;
        float get_path_length(int) const;
        unsigned get_paths() const;
index 4259c7dcde26a2b0a441210387bf4da011ef8a10..250aefd568064e2d3ee979d354af27626803587e 100644 (file)
@@ -14,11 +14,10 @@ using namespace Msp;
 namespace R2C2 {
 
 Vehicle::Vehicle(Layout &l, const VehicleType &t):
-       layout(l),
+       Object(l),
        type(t),
        next(0),
        prev(0),
-       direction(0),
        front_sensor(0),
        back_sensor(0)
 {
@@ -38,6 +37,14 @@ Vehicle::~Vehicle()
        layout.remove_vehicle(*this);
 }
 
+Vehicle *Vehicle::clone(Layout *to_layout) const
+{
+       Vehicle *veh = new Vehicle((to_layout ? *to_layout : layout), type);
+       veh->set_position(position);
+       veh->set_rotation(rotation);
+       return veh;
+}
+
 void Vehicle::attach_back(Vehicle &veh)
 {
        if(next || veh.prev)
@@ -189,7 +196,7 @@ void Vehicle::update_position()
 
        position = tp.pos;
        position.z += layout.get_catalogue().get_rail_elevation();
-       direction = tp.dir;
+       rotation = tp.dir;
 }
 
 void Vehicle::update_position_from(const Vehicle &veh)
index 8990a5b538d68c0f144b2404db636229ec6f9f00..54054bb50e325cb1babf87408fbbf637999a3ca4 100644 (file)
@@ -2,6 +2,7 @@
 #define LIBR2C2_VEHICLE_H_
 
 #include "geometry.h"
+#include "object.h"
 #include "vehicletype.h"
 
 namespace R2C2 {
@@ -17,7 +18,7 @@ public:
 };
 
 
-class Vehicle
+class Vehicle: public Object
 {
 public:
        enum PlaceMode
@@ -68,13 +69,10 @@ private:
                TrackPoint get_point() const;
        };
 
-       Layout &layout;
        const VehicleType &type;
        Vehicle *next;
        Vehicle *prev;
        TrackPosition track_pos;
-       Vector position;
-       float direction;
        std::vector<Axle> axles;
        std::vector<Bogie> bogies;
        std::vector<Rod> rods;
@@ -85,7 +83,8 @@ public:
        Vehicle(Layout &, const VehicleType &);
        ~Vehicle();
 
-       const VehicleType &get_type() const { return type; }
+       virtual Vehicle *clone(Layout * = 0) const;
+       virtual const VehicleType &get_type() const { return type; }
 
        void attach_back(Vehicle &);
        void attach_front(Vehicle &);
@@ -94,14 +93,15 @@ public:
        Vehicle *get_next() const { return next; }
        Vehicle *get_previous() const { return prev; }
 
+       // TODO implement these - should call place() with suitable parameters
+       virtual void set_position(const Vector &) { }
+       virtual void set_rotation(float) { }
        void place(Track &, unsigned, float, PlaceMode = CENTER);
        void unplace();
        void advance(float);
        Track *get_track() const { return track_pos.track; }
        unsigned get_entry() const { return track_pos.ep; }
        float get_offset() const { return track_pos.offs; }
-       const Vector &get_position() const { return position; }
-       float get_direction() const { return direction; }
        const Axle &get_fixed_axle(unsigned) const;
        const Bogie &get_bogie(unsigned) const;
        const Axle &get_bogie_axle(unsigned, unsigned) const;
@@ -119,6 +119,9 @@ private:
        void adjust_for_distance(TrackPosition &, TrackPosition &, 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;
+
+public:
+       virtual bool collide_ray(const Vector &, const Vector &) const { return false; }
 };
 
 } // namespace R2C2
index 2da44cc992f340f7c73e7f44e104fc4285327078..973070ceafc158fe2fddfd4fb966115c5c1ca2a6 100644 (file)
@@ -8,7 +8,7 @@ using namespace Msp;
 namespace R2C2 {
 
 VehicleType::VehicleType(const ArticleNumber &an):
-       art_nr(an),
+       ObjectType(an),
        locomotive(false),
        swap_direction(false),
        length(0),
@@ -105,7 +105,7 @@ VehicleType::Rod::Rod():
 
 
 VehicleType::Loader::Loader(VehicleType &vt):
-       DataFile::ObjectLoader<VehicleType>(vt)
+       DataFile::DerivedObjectLoader<VehicleType, ObjectType::Loader>(vt)
 {
        add("axle",       &Loader::axle);
        add("bogie",      &Loader::bogie);
@@ -113,7 +113,6 @@ VehicleType::Loader::Loader(VehicleType &vt):
        add("height",     &Loader::height);
        add("length",     &Loader::length);
        add("locomotive", &VehicleType::locomotive);
-       add("name",       &VehicleType::name);
        add("object",     &VehicleType::object);
        add("rod",        &Loader::rod);
        add("rotate_object", &VehicleType::rotate_object);
index d8bec87a31a1ff9d47ddc2b702e26d1c190389f0..841664e375f10f61b079b52a535318c79cd4ea76 100644 (file)
@@ -2,15 +2,15 @@
 #define LIBR2C2_VEHICLETYPE_H_
 
 #include <msp/datafile/objectloader.h>
-#include "articlenumber.h"
 #include "geometry.h"
+#include "objecttype.h"
 
 namespace R2C2 {
 
-class VehicleType
+class VehicleType: public ObjectType
 {
 public:
-       class Loader: public Msp::DataFile::ObjectLoader<VehicleType>
+       class Loader: public Msp::DataFile::DerivedObjectLoader<VehicleType, ObjectType::Loader>
        {
        private:
                std::map<std::string, unsigned> rod_tags;
@@ -125,8 +125,6 @@ public:
        typedef std::map<unsigned, std::string> FunctionMap;
 
 private:
-       ArticleNumber art_nr;
-       std::string name;
        bool locomotive;
        FunctionMap functions;
        bool swap_direction;
@@ -142,8 +140,6 @@ private:
 public:
        VehicleType(const ArticleNumber &);
 
-       const ArticleNumber &get_article_number() const { return art_nr; }
-       const std::string &get_name() const { return name; }
        bool is_locomotive() const { return locomotive; }
        unsigned get_max_function() const;
        const FunctionMap &get_functions() const { return functions; }