]> git.tdb.fi Git - r2c2.git/commitdiff
Split mesh generation from Track3D to TrackType3D
authorMikko Rasa <tdb@tdb.fi>
Fri, 19 Feb 2010 15:44:09 +0000 (15:44 +0000)
committerMikko Rasa <tdb@tdb.fi>
Fri, 19 Feb 2010 15:44:09 +0000 (15:44 +0000)
Add a Catalogue3D to hold the TrackType3D objects
Better parametrization of track profile
Make track profile loadable from the catalogue file
Track colors and path rendering is non-funtional at the moment

13 files changed:
source/3d/catalogue.cpp [new file with mode: 0644]
source/3d/catalogue.h [new file with mode: 0644]
source/3d/layout.cpp
source/3d/layout.h
source/3d/track.cpp
source/3d/track.h
source/3d/tracktype.cpp [new file with mode: 0644]
source/3d/tracktype.h [new file with mode: 0644]
source/libmarklin/catalogue.cpp
source/libmarklin/catalogue.h
source/libmarklin/profile.cpp [new file with mode: 0644]
source/libmarklin/profile.h [new file with mode: 0644]
tracks.dat

diff --git a/source/3d/catalogue.cpp b/source/3d/catalogue.cpp
new file mode 100644 (file)
index 0000000..994d5f4
--- /dev/null
@@ -0,0 +1,33 @@
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include "catalogue.h"
+#include "tracktype.h"
+
+using namespace std;
+using namespace Msp;
+
+namespace Marklin {
+
+Catalogue3D::Catalogue3D(const Catalogue &c):
+       catalogue(c)
+{
+       const map<unsigned, TrackType *> &trks = catalogue.get_tracks();
+       for(map<unsigned, TrackType *>::const_iterator i=trks.begin(); i!=trks.end(); ++i)
+               tracks[i->second] = new TrackType3D(*this, *i->second);
+}
+
+const TrackType3D &Catalogue3D::get_track(const TrackType &tt) const
+{
+       map<const TrackType *, TrackType3D *>::const_iterator i = tracks.find(&tt);
+       if(i==tracks.end())
+               throw KeyError("Unknown track type");
+
+       return *i->second;
+}
+
+} // namespace Marklin
diff --git a/source/3d/catalogue.h b/source/3d/catalogue.h
new file mode 100644 (file)
index 0000000..689756d
--- /dev/null
@@ -0,0 +1,34 @@
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#ifndef MARKLIN3D_CATALOGUE_H_
+#define MARKLIN3D_CATALOGUE_H_
+
+#include <msp/gl/material.h>
+#include "libmarklin/catalogue.h"
+
+namespace Marklin {
+
+class TrackType3D;
+
+class Catalogue3D
+{
+private:
+       const Catalogue &catalogue;
+       std::map<const TrackType *, TrackType3D *> tracks;
+       Msp::GL::Material *ballast_material;
+
+public:
+       Catalogue3D(const Catalogue &);
+
+       const Catalogue &get_catalogue() const { return catalogue; }
+       const TrackType3D &get_track(const TrackType &) const;
+};
+
+}
+
+#endif
index dcf5544e8dfb8435d793dc7aa98fd300971c9ace..633baa1957668a6fc77af6a6f39c0f2fb55f072c 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -20,6 +20,7 @@ namespace Marklin {
 
 Layout3D::Layout3D(Layout &l):
        layout(l),
+       catalogue(layout.get_catalogue()),
        quality(4)
 {
        layout.signal_track_added.connect(sigc::mem_fun(this, &Layout3D::track_added));
@@ -35,8 +36,6 @@ Layout3D::~Layout3D()
 void Layout3D::set_quality(unsigned q)
 {
        quality = q;
-       for(list<Track3D *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
-               (*i)->set_quality(quality);
 }
 
 void Layout3D::render(bool endpoints) const
@@ -122,7 +121,7 @@ Track3D *Layout3D::pick_track(float x, float y, float size) const
 
 void Layout3D::track_added(Track &t)
 {
-       tracks.push_back(new Track3D(t, quality));
+       tracks.push_back(new Track3D(*this, t));
 }
 
 void Layout3D::track_removed(Track &t)
index 208ddacacba28254f267b6d121e44190f0f15d46..21686de5f9c8bbc4a19e1fdc21acffd2276b4267 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -9,6 +9,7 @@ Distributed under the GPL
 #define MARKLIN3D_LAYOUT_H_
 
 #include "libmarklin/layout.h"
+#include "catalogue.h"
 #include "track.h"
 
 namespace Marklin {
@@ -17,6 +18,7 @@ class Layout3D
 {
 private:
        Layout &layout;
+       Catalogue3D catalogue;
        std::list<Track3D *> tracks;
        unsigned quality;
 
@@ -24,6 +26,7 @@ public:
        Layout3D(Layout &);
        ~Layout3D();
 
+       const Catalogue3D &get_catalogue() const { return catalogue; }
        void set_quality(unsigned);
        const std::list<Track3D *> &get_tracks() const { return tracks; }
        void render(bool =false) const;
index 1df93a29ca76a60f49904636dd7151dc682c2765..c3eb388dc8bb4a96b35a4a797319cf53db8dd949 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2009 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -9,60 +9,45 @@ Distributed under the GPL
 #include <GL/gl.h>
 #include <msp/gl/misc.h>
 #include "libmarklin/tracktype.h"
+#include "layout.h"
 #include "track.h"
+#include "tracktype.h"
 
 using namespace std;
 using namespace Msp;
 
 namespace Marklin {
 
-Track3D::Track3D(Track &t, unsigned q):
+Track3D::Track3D(Layout3D &l, Track &t):
+       layout(l),
        track(t),
-       color(1, 1, 1),
-       varray((GL::NORMAL3, GL::VERTEX3)),
-       quality(q)
-{
-       build_object();
-}
+       type(layout.get_catalogue().get_track(track.get_type())),
+       color(1, 1, 1)
+{ }
 
 void Track3D::set_color(const Msp::GL::Color &c)
 {
        color = c;
 }
 
-void Track3D::set_quality(unsigned q)
-{
-       quality = q;
-       build_object();
-}
-
 void Track3D::get_bounds(float angle, Point &minp, Point &maxp) const
 {
-       const Point &pos = track.get_position();
-       float rot = track.get_rotation();
-       float slope = track.get_slope();
+       type.get_bounds(angle-track.get_rotation(), minp, maxp);
 
        float c = cos(-angle);
        float s = sin(-angle);
 
-       minp.x = maxp.x = c*pos.x-s*pos.y;
-       minp.y = maxp.y = s*pos.x+c*pos.y;
-       minp.z = pos.z+min(slope, 0.0f);
-       maxp.z = pos.z+0.01+max(slope, 0.0f);
-
-       float c2 = cos(rot-angle);
-       float s2 = sin(rot-angle);
-
-       for(vector<Point>::const_iterator i=border.begin(); i!=border.end(); ++i)
-       {
-               float x = c*pos.x-s*pos.y + c2*i->x-s2*i->y;
-               float y = s*pos.x+c*pos.y + s2*i->x+c2*i->y;
+       const Point &pos = track.get_position();
+       minp.x += c*pos.x-s*pos.y;
+       maxp.x += c*pos.x-s*pos.y;
+       minp.y += s*pos.x+c*pos.y;
+       maxp.y += s*pos.x+c*pos.y;
 
-               minp.x = min(minp.x, x);
-               minp.y = min(minp.y, y);
-               maxp.x = max(maxp.x, x);
-               maxp.y = max(maxp.y, y);
-       }
+       float slope = track.get_slope();
+       if(slope>0)
+               maxp.z += slope;
+       else
+               minp.z += slope;
 }
 
 void Track3D::render() const
@@ -71,14 +56,7 @@ void Track3D::render() const
 
        glPushName(reinterpret_cast<unsigned>(this));
 
-       varray.apply();
-       glColor4f(0.25*color.r, 0.25*color.g, 0.25*color.b, 1);
-       glDrawElements(GL_QUADS, base_seq.size(), GL_UNSIGNED_INT, &base_seq[0]);
-       if(quality>1)
-       {
-               glColor4f(0.85*color.r, 0.85*color.g, 0.85*color.b, 1);
-               glDrawElements(GL_QUADS, rail_seq.size(), GL_UNSIGNED_INT, &rail_seq[0]);
-       }
+       type.render();
 
        glPopName();
        glPopMatrix();
@@ -139,14 +117,15 @@ void Track3D::render_path(int path) const
 {
        prepare_render(true);
 
-       varray.apply();
+       (void)path;
+       /*varray.apply();
        if(path>=0 && static_cast<unsigned>(path)<path_seq.size())
                glDrawElements(GL_QUADS, path_seq[path].size(), GL_UNSIGNED_INT, &path_seq[path][0]);
        else
        {
                for(unsigned i=0; i<path_seq.size(); ++i)
                        glDrawElements(GL_QUADS, path_seq[i].size(), GL_UNSIGNED_INT, &path_seq[i][0]);
-       }
+       }*/
 
        glPopMatrix();
 }
@@ -163,97 +142,4 @@ void Track3D::prepare_render(bool slope) const
                glRotatef(track.get_slope()/track.get_type().get_total_length()*180/M_PI, 0, -1, 0);
 }
 
-void Track3D::build_object()
-{
-       varray.clear();
-       GL::VertexArrayBuilder builder(varray);
-
-       base_seq.clear();
-       rail_seq.clear();
-       path_seq.clear();
-       path_seq.resize(track.get_type().get_n_paths());
-
-       const vector<TrackPart> &parts = track.get_type().get_parts();
-       unsigned index = 0;
-       for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
-               build_part(*i, builder, index);
-}
-
-void Track3D::build_part(const TrackPart &part, GL::VertexArrayBuilder &va_builder, unsigned &base_index)
-{
-       static vector<Point> profile;
-       if(profile.empty())
-       {
-               profile.push_back(Point(0, -0.02, 0));
-               profile.push_back(Point(0, -0.014, 0.008));
-               profile.push_back(Point(0, -0.014, 0.008));
-               profile.push_back(Point(0, 0.014, 0.008));
-               profile.push_back(Point(0, 0.014, 0.008));
-               profile.push_back(Point(0, 0.02, 0));
-               for(unsigned i=0; i<2; ++i)
-               {
-                       profile.push_back(Point(0, -0.009+i*0.017, 0.008));
-                       profile.push_back(Point(0, -0.009+i*0.017, 0.0103));
-                       profile.push_back(Point(0, -0.009+i*0.017, 0.0103));
-                       profile.push_back(Point(0, -0.008+i*0.017, 0.0103));
-                       profile.push_back(Point(0, -0.008+i*0.017, 0.0103));
-                       profile.push_back(Point(0, -0.008+i*0.017, 0.008));
-               }
-               profile.push_back(Point(0, -0.002, 0.012));
-               profile.push_back(Point(0, 0.002, 0.012));
-       }
-       static unsigned psize = profile.size();
-
-       unsigned nsegs = (part.radius ? static_cast<unsigned>(part.length*(1<<quality))+1 : 1);
-       float plen = part.length;
-       if(part.radius)
-               plen *= abs(part.radius);
-
-       for(unsigned i=0; i<=nsegs; ++i)
-       {
-               float a = part.dir+(part.radius ? i*plen/nsegs/part.radius : 0);
-               float c = cos(a);
-               float s = sin(a);
-               Point p = part.get_point(i*plen/nsegs);
-
-               for(unsigned j=0; j<psize; ++j)
-               {
-                       unsigned k = j&~1;
-                       float dy = profile[k+1].y-profile[k].y;
-                       float dz = profile[k+1].z-profile[k].z;
-                       float d = sqrt(dy*dy+dz*dz);
-                       va_builder.normal(s*dz/d, -c*dz/d, dy/d);
-
-                       Point v(p.x+c*profile[j].x-s*profile[j].y, p.y+c*profile[j].y+s*profile[j].x, profile[j].z);
-                       va_builder.vertex(v.x, v.y, v.z);
-                       if(profile[j].z==0)
-                               border.push_back(v);
-               }
-       }
-
-       for(unsigned i=0; i<nsegs; ++i)
-       {
-               for(unsigned j=0; j<3; ++j)
-               {
-                       base_seq.push_back(base_index+i*psize+j*2);
-                       base_seq.push_back(base_index+(i+1)*psize+j*2);
-                       base_seq.push_back(base_index+(i+1)*psize+1+j*2);
-                       base_seq.push_back(base_index+i*psize+1+j*2);
-               }
-               for(unsigned j=3; j<9; ++j)
-               {
-                       rail_seq.push_back(base_index+i*psize+j*2);
-                       rail_seq.push_back(base_index+(i+1)*psize+j*2);
-                       rail_seq.push_back(base_index+(i+1)*psize+1+j*2);
-                       rail_seq.push_back(base_index+i*psize+1+j*2);
-               }
-               path_seq[part.path].push_back(base_index+i*psize+18);
-               path_seq[part.path].push_back(base_index+(i+1)*psize+18);
-               path_seq[part.path].push_back(base_index+(i+1)*psize+19);
-               path_seq[part.path].push_back(base_index+i*psize+19);
-       }
-
-       base_index += (nsegs+1)*psize;
-}
-
 } // namespace Marklin
index adc046b9fc13c9b53f069d16ff4f10b75225c4b4..fe24b9a9e1a9e0fd3740d90c531841a44785d3d5 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2008 Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2010 Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -17,32 +17,28 @@ Distributed under the GPL
 
 namespace Marklin {
 
+class Layout3D;
+class TrackType3D;
+
 class Track3D
 {
 private:
+       Layout3D &layout;
        Track &track;
+       const TrackType3D &type;
        Msp::GL::Color color;
-       std::vector<Point> border;
-       Msp::GL::VertexArray varray;
-       std::vector<unsigned> base_seq;
-       std::vector<unsigned> rail_seq;
-       std::vector<std::vector<unsigned> > path_seq;
-       unsigned quality;
 
 public:
-       Track3D(Track &, unsigned);
+       Track3D(Layout3D &, Track &);
 
        Track &get_track() const { return track; }
        void set_color(const Msp::GL::Color &);
-       void set_quality(unsigned);
        void get_bounds(float, Point &, Point &) const;
        void render() const;
        void render_endpoints() const;
        void render_path(int) const;
 private:
        void prepare_render(bool) const;
-       void build_object();
-       void build_part(const TrackPart &, Msp::GL::VertexArrayBuilder &, unsigned &);
 };
 
 } // namespace Marklin
diff --git a/source/3d/tracktype.cpp b/source/3d/tracktype.cpp
new file mode 100644 (file)
index 0000000..26be527
--- /dev/null
@@ -0,0 +1,199 @@
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <algorithm>
+#include <cmath>
+#include <msp/gl/meshbuilder.h>
+#include "catalogue.h"
+#include "tracktype.h"
+
+using namespace std;
+using namespace Msp;
+
+namespace {
+
+bool compare_z(const Marklin::Point &p1, const Marklin::Point &p2)
+{
+       return p1.z<p2.z;
+}
+
+template<typename Iter>
+Iter graham_scan(Iter begin, Iter end)
+{
+       // http://en.wikipedia.org/wiki/Graham_scan
+
+       // Find point with lowest X coordinate
+       Marklin::Point lowest = *begin;
+       for(Iter i=begin; i!=end; ++i)
+               if(i->x<lowest.x || (i->x==lowest.x && i->y>lowest.y))
+                       lowest = *i;
+
+       // Compute tangents and sort points
+       for(Iter i=begin; i!=end; ++i)
+               i->z = (i->x==lowest.x ? 1e5/(i->y-lowest.y-1) : (i->y-lowest.y)/(i->x-lowest.x));
+       sort(begin, end, compare_z);
+
+       for(Iter k=begin, i=k++, j=k++;; )
+       {
+               // Compute winding by cross product
+               float turn = (j->x-i->x)*(k->y-j->y) - (k->x-j->x)*(j->y-i->y);
+
+               if(turn<1e-5)
+               {
+                       // Right turn - throw the middle point away
+                       // Special case for collinear vertices in the beginning
+                       if(i==begin)
+                               j = k++;
+                       else
+                               j = i--;
+               }
+               else
+               {
+                       // Left turn - store the middle point and advance
+                       if(++i!=j)
+                               *i = *j;
+                       j = k++;
+               }
+
+               // Cycle back to beginning and terminate after checking the last point
+               if(k==end)
+                       k = begin;
+               else if(j==begin)
+                       return ++i;
+       }
+}
+
+}
+
+namespace Marklin {
+
+TrackType3D::TrackType3D(const Catalogue3D &cat3d, const TrackType &tt):
+       ballast_mesh((GL::NORMAL3, GL::COLOR4_UBYTE, GL::VERTEX3)),
+       rail_mesh((GL::NORMAL3, GL::COLOR4_UBYTE, GL::VERTEX3))
+{
+       const Catalogue &cat = cat3d.get_catalogue();
+       const vector<TrackPart> &parts = tt.get_parts();
+
+       const Profile &ballast_profile = cat.get_ballast_profile();
+       const Point &ballast_min = ballast_profile.get_min_coords();
+       const Point &ballast_max = ballast_profile.get_max_coords();
+
+       const Profile &rail_profile = cat.get_rail_profile();
+       const Point &rail_min = rail_profile.get_min_coords();
+       const Point &rail_max = rail_profile.get_max_coords();
+
+       float gauge = cat.get_gauge();
+
+       {
+               unsigned index = 0;
+               GL::MeshBuilder bld(ballast_mesh);
+               bld.color(0.25f, 0.25f, 0.25f);
+               for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+                       build_part(*i, ballast_profile, Point(0, -ballast_min.y), bld, index);
+       }
+
+       {
+               unsigned index = 0;
+               GL::MeshBuilder bld(rail_mesh);
+               bld.color(0.85f, 0.85f, 0.85f);
+               float y = ballast_max.y-ballast_min.y-rail_min.y;
+               for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+                       build_part(*i, rail_profile, Point(-gauge/2-rail_max.x, y), bld, index);
+               for(vector<TrackPart>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+                       build_part(*i, rail_profile, Point(gauge/2-rail_min.x, y), bld, index);
+       }
+
+       min_z = max_z = border.front().z;
+       for(vector<Point>::iterator i=border.begin(); i!=border.end(); ++i)
+       {
+               min_z = min(min_z, i->z);
+               max_z = max(max_z, i->z);
+       }
+       border.erase(graham_scan(border.begin(), border.end()), border.end());
+}
+
+void TrackType3D::get_bounds(float angle, Point &minp, Point &maxp) const
+{
+       float c = cos(-angle);
+       float s = sin(-angle);
+
+       minp = maxp = Point();
+       minp.z = min_z;
+       maxp.z = max_z;
+
+       for(vector<Point>::const_iterator i=border.begin(); i!=border.end(); ++i)
+       {
+               float x = c*i->x-s*i->y;
+               float y = s*i->x+c*i->y;
+
+               minp.x = min(minp.x, x);
+               minp.y = min(minp.y, y);
+               maxp.x = max(maxp.x, x);
+               maxp.y = max(maxp.y, y);
+       }
+}
+
+void TrackType3D::render() const
+{
+       ballast_mesh.draw();
+       rail_mesh.draw();
+}
+
+void TrackType3D::build_part(const TrackPart &part, const Profile &profile, const Point &offset, GL::MeshBuilder &bld, unsigned &base_index)
+{
+       unsigned nsegs = (part.radius ? static_cast<unsigned>(part.length*16)+1 : 1);
+       float plen = part.length;
+       if(part.radius)
+               plen *= abs(part.radius);
+
+       unsigned n_points = profile.get_n_points();
+       for(unsigned i=0; i<=nsegs; ++i)
+       {
+               float a = part.dir+(part.radius ? i*plen/nsegs/part.radius : 0);
+               float c = cos(a);
+               float s = sin(a);
+               Point basep = part.get_point(i*plen/nsegs);
+
+               Point p;
+               for(unsigned j=0; j<n_points; ++j)
+               {
+                       // TODO: smoothing - only duplicate vertex if the angle is large enough
+
+                       p = profile.get_point(j);
+                       p.z = basep.z+p.y+offset.y;
+                       p.y = basep.y-c*(p.x+offset.x);
+                       p.x = basep.x+s*(p.x+offset.x);
+                       if(j>0)
+                               bld.vertex(p.x, p.y, p.z);
+
+                       if(j+1<n_points)
+                       {
+                               Point n = profile.get_edge_normal(j);
+                               bld.normal(s*n.x, -c*n.x, n.y);
+                               bld.vertex(p.x, p.y, p.z);
+                       }
+
+                       border.push_back(p);
+               }
+       }
+
+       for(unsigned i=0; i+1<n_points; ++i)
+       {
+               bld.begin(GL::TRIANGLE_STRIP);
+               for(unsigned j=0; j<=nsegs; ++j)
+               {
+                       unsigned k = (j*(n_points-1)+i)*2;
+                       bld.element(base_index+k+1);
+                       bld.element(base_index+k);
+               }
+               bld.end();
+       }
+
+       base_index += (nsegs+1)*(n_points-1)*2;
+}
+
+} // namespace Marklin
diff --git a/source/3d/tracktype.h b/source/3d/tracktype.h
new file mode 100644 (file)
index 0000000..e0bd938
--- /dev/null
@@ -0,0 +1,43 @@
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#ifndef MARKLIN3D_TRACKTYPE_H_
+#define MARKLIN3D_TRACKTYPE_H_
+
+#include <msp/gl/mesh.h>
+#include <msp/gl/meshbuilder.h>
+#include "libmarklin/profile.h"
+#include "libmarklin/tracktype.h"
+
+namespace Marklin {
+
+class Catalogue3D;
+
+class TrackType3D
+{
+private:
+       Msp::GL::Mesh ballast_mesh;
+       Msp::GL::Mesh rail_mesh;
+       std::vector<Point> border;
+       float min_z;
+       float max_z;
+
+public:
+       TrackType3D(const Catalogue3D &, const TrackType &);
+
+       void get_bounds(float, Point &, Point &) const;
+
+       void render() const;
+
+private:
+       void build_part(const TrackPart &, const Profile &, const Point &, Msp::GL::MeshBuilder &, unsigned &);
+       //void optimize_border();
+};
+
+} // namespace Marklin
+
+#endif
index 55a5a440a3903efbff54e86b61dc8fa7382e654d..3c9cf7d6c2392bf0bf73cdd9efe191de0b9740a7 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2009  Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -16,6 +16,11 @@ using namespace Msp;
 
 namespace Marklin {
 
+Catalogue::Catalogue():
+       scale(1),
+       gauge(1.524)
+{ }
+
 Catalogue::~Catalogue()
 {
        for(map<unsigned, TrackType *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
@@ -46,10 +51,24 @@ LocoType &Catalogue::get_locomotive(unsigned art_nr) const
 Catalogue::Loader::Loader(Catalogue &c):
        DataFile::BasicLoader<Catalogue>(c)
 {
+       add("ballast_profile", &Loader::ballast_profile);
+       add("gauge", &Loader::gauge);
        add("locomotive", &Loader::locomotive);
+       add("rail_profile", &Loader::rail_profile);
+       add("scale", &Loader::scale);
        add("track", &Loader::track);
 }
 
+void Catalogue::Loader::ballast_profile()
+{
+       load_sub(obj.ballast_profile);
+}
+
+void Catalogue::Loader::gauge(float g)
+{
+       obj.gauge = g/1000;
+}
+
 void Catalogue::Loader::locomotive(unsigned art_nr)
 {
        if(obj.locos.count(art_nr))
@@ -60,6 +79,16 @@ void Catalogue::Loader::locomotive(unsigned art_nr)
        obj.locos[art_nr] = loco.release();
 }
 
+void Catalogue::Loader::rail_profile()
+{
+       load_sub(obj.rail_profile);
+}
+
+void Catalogue::Loader::scale(float n, float d)
+{
+       obj.scale = n/d;
+}
+
 void Catalogue::Loader::track(unsigned art_nr)
 {
        if(obj.tracks.count(art_nr))
index 4ce6fb1b712de8daa3d32f988d5ec5d43f0b6623..5d88c28dcd0dac2543421bad27e6ced57da3e0ba 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of the MSP Märklin suite
-Copyright © 2006-2009  Mikkosoft Productions, Mikko Rasa
+Copyright © 2006-2010  Mikkosoft Productions, Mikko Rasa
 Distributed under the GPL
 */
 
@@ -10,6 +10,7 @@ Distributed under the GPL
 
 #include <map>
 #include <msp/datafile/loader.h>
+#include "profile.h"
 
 namespace Marklin {
 
@@ -24,17 +25,30 @@ public:
        public:
                Loader(Catalogue &);
        private:
+               void ballast_profile();
+               void gauge(float);
                void locomotive(unsigned);
+               void rail_profile();
+               void scale(float, float);
                void track(unsigned);
        };
 
 private:
+       float scale;
+       float gauge;
+       Profile rail_profile;
+       Profile ballast_profile;
        std::map<unsigned, TrackType *> tracks;
        std::map<unsigned, LocoType *> locos;
 
 public:
+       Catalogue();
        ~Catalogue();
 
+       float get_scale() const { return scale; }
+       float get_gauge() const { return gauge; }
+       const Profile &get_rail_profile() const { return rail_profile; }
+       const Profile &get_ballast_profile() const { return ballast_profile; }
        TrackType &get_track(unsigned) const;
        const std::map<unsigned, TrackType *> &get_tracks() const { return tracks; }
        LocoType &get_locomotive(unsigned) const;
diff --git a/source/libmarklin/profile.cpp b/source/libmarklin/profile.cpp
new file mode 100644 (file)
index 0000000..f4dcf18
--- /dev/null
@@ -0,0 +1,58 @@
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <cmath>
+#include "profile.h"
+
+using namespace std;
+using namespace Msp;
+
+namespace Marklin {
+
+const Point &Profile::get_point(unsigned i) const
+{
+       if(i>=points.size())
+               throw InvalidParameterValue("Index out of range");
+       return points[i];
+}
+
+Point Profile::get_edge_normal(unsigned i) const
+{
+       if(i+1>=points.size())
+               throw InvalidParameterValue("Index out of range");
+       float dx = points[i+1].x-points[i].x;
+       float dy = points[i+1].y-points[i].y;
+       float len = sqrt(dx*dx+dy*dy);
+       return Point(-dx/len, dy/len);
+}
+
+
+Profile::Loader::Loader(Profile &p):
+       DataFile::ObjectLoader<Profile>(p)
+{
+       add("point", &Loader::point);
+}
+
+void Profile::Loader::finish()
+{
+       obj.min_coords = obj.points[0];
+       obj.max_coords = obj.points[0];
+       for(unsigned i=1; i<obj.points.size(); ++i)
+       {
+               obj.min_coords.x = min(obj.min_coords.x, obj.points[i].x);
+               obj.min_coords.y = min(obj.min_coords.y, obj.points[i].y);
+               obj.max_coords.x = max(obj.max_coords.x, obj.points[i].x);
+               obj.max_coords.y = max(obj.max_coords.y, obj.points[i].y);
+       }
+}
+
+void Profile::Loader::point(float x, float y)
+{
+       obj.points.push_back(Point(x/1000, y/1000));
+}
+
+} // namespace Marklin
diff --git a/source/libmarklin/profile.h b/source/libmarklin/profile.h
new file mode 100644 (file)
index 0000000..3b194c8
--- /dev/null
@@ -0,0 +1,44 @@
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#ifndef LIBMARKLIN_PROFILE_H_
+#define LIBMARKLIN_PROFILE_H_
+
+#include <vector>
+#include <msp/datafile/objectloader.h>
+#include "geometry.h"
+
+namespace Marklin {
+
+class Profile
+{
+public:
+       class Loader: public Msp::DataFile::ObjectLoader<Profile>
+       {
+       public:
+               Loader(Profile &);
+       private:
+               virtual void finish();
+               void point(float, float);
+       };
+
+private:
+       std::vector<Point> points;
+       Point min_coords;
+       Point max_coords;
+
+public:
+       unsigned get_n_points() const { return points.size(); }
+       const Point &get_point(unsigned) const;
+       const Point &get_min_coords() const { return min_coords; }
+       const Point &get_max_coords() const { return max_coords; }
+       Point get_edge_normal(unsigned) const;
+};
+
+} // namespace Marklin
+
+#endif
index 86089d021c9b870d4c48aff4dfa3c812ac8aafe4..7b7ba57dcc44b77385cba5700cda5b168aaa41d0 100644 (file)
@@ -1,5 +1,22 @@
 /* $Id$ */
 
+scale 1 87;
+gauge 16.5;
+rail_profile
+{
+       point 0.5 0.0;
+       point 0.5 2.3;
+       point -0.5 2.3;
+       point -0.5 0.0;
+};
+ballast_profile
+{
+       point 20.0 0.0;
+       point 14.0 8.0;
+       point -14.0 8.0;
+       point -20.0 0.0;
+};
+
 // Straight
 
 track 24064