]> git.tdb.fi Git - libs/math.git/commitdiff
Add a loading system for shapes
authorMikko Rasa <tdb@tdb.fi>
Sat, 22 Nov 2014 09:15:15 +0000 (11:15 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 22 Nov 2014 10:37:54 +0000 (12:37 +0200)
Build
source/geometry/dummy.cpp
source/geometry/loader.h [new file with mode: 0644]

diff --git a/Build b/Build
index 62e7375baa3202bc77181c7db4342eb9b0f4b10f..5e5297d3712333bb0e0338e0b12db659961af620 100644 (file)
--- a/Build
+++ b/Build
@@ -1,5 +1,7 @@
 package "mspmath"
 {
+       require "mspdatafile";
+
        library "mspmath"
        {
                source "source/linal";
index a262e268caf98bd4022297bba8a310762aa0280e..b40a5fc2b7510bb77c35dd1d73e6feeed2128c52 100644 (file)
@@ -6,6 +6,7 @@
 #include "hyperbox.h"
 #include "hypersphere.h"
 #include "intersection.h"
+#include "loader.h"
 #include "negation.h"
 #include "ray.h"
 #include "rectangle.h"
diff --git a/source/geometry/loader.h b/source/geometry/loader.h
new file mode 100644 (file)
index 0000000..e73a8e3
--- /dev/null
@@ -0,0 +1,424 @@
+#ifndef MSP_GEOMETRY_LOADER_H_
+#define MSP_GEOMETRY_LOADER_H_
+
+#include <list>
+#include <msp/datafile/loader.h>
+#include "extrudedshape.h"
+#include "halfspace.h"
+#include "hyperbox.h"
+#include "hypersphere.h"
+#include "intersection.h"
+#include "negation.h"
+#include "shape.h"
+#include "transformedshape.h"
+#include "union.h"
+
+namespace Msp {
+namespace Geometry {
+
+template<typename T, unsigned D>
+class DimensionIndependentLoader: public DataFile::Loader
+{
+protected:
+       bool single;
+       std::list<Shape<T, D> *> shapes;
+
+       DimensionIndependentLoader(bool = true);
+public:
+       virtual ~DimensionIndependentLoader();
+
+       const Shape<T, D> &get_shape() const;
+
+protected:
+       template<typename S>
+       void shape();
+};
+
+
+template<typename T, unsigned D, bool = (D>1)>
+class Loader;
+
+template<typename T, unsigned D>
+class Loader<T, D, false>: public DimensionIndependentLoader<T, D>
+{
+public:
+       Loader(bool = true);
+};
+
+template<typename T, unsigned D>
+class Loader<T, D, true>: public DimensionIndependentLoader<T, D>
+{
+public:
+       Loader(bool = true);
+};
+
+
+template<typename S>
+class ShapeLoader;
+
+template<typename T, unsigned D>
+class ShapeLoader<ExtrudedShape<T, D> >: public Loader<T, D-1>
+{
+private:
+       T length_;
+
+public:
+       ShapeLoader();
+
+       ExtrudedShape<T, D> *create() const;
+
+private:
+       void length(T);
+};
+
+template<typename T, unsigned D>
+class ShapeLoader<HalfSpace<T, D> >: public DataFile::Loader
+{
+private:
+       LinAl::Vector<T, D> normal_;
+
+public:
+       ShapeLoader();
+
+       HalfSpace<T, D> *create() const;
+
+private:
+       void normal(const std::vector<T> &);
+};
+
+template<typename T, unsigned D>
+class ShapeLoader<HyperBox<T, D> >: public DataFile::Loader
+{
+private:
+       LinAl::Vector<T, D> dimensions_;
+
+public:
+       ShapeLoader();
+
+       HyperBox<T, D> *create() const;
+
+private:
+       void dimensions(const std::vector<T> &);
+};
+
+template<typename T, unsigned D>
+class ShapeLoader<HyperSphere<T, D> >: public DataFile::Loader
+{
+private:
+       T radius_;
+
+public:
+       ShapeLoader();
+
+       HyperSphere<T, D> *create() const;
+
+private:
+       void radius(T);
+};
+
+template<typename T, unsigned D, typename S>
+class CompositeLoader: public Loader<T, D>
+{
+public:
+       CompositeLoader();
+
+       S *create() const;
+};
+
+template<typename T, unsigned D>
+class ShapeLoader<Intersection<T, D> >: public CompositeLoader<T, D, Intersection<T, D> >
+{ };
+
+template<typename T, unsigned D>
+class ShapeLoader<Negation<T, D> >: public Loader<T, D>
+{
+public:
+       Negation<T, D> *create() const;
+};
+
+template<typename T, unsigned D>
+class TransformationLoader: public Loader<T, D>
+{
+protected:
+       AffineTransformation<T, D> transformation;
+
+public:
+       TransformationLoader();
+
+       TransformedShape<T, D> *create() const;
+
+       void translate(const std::vector<T> &);
+       void scale(const std::vector<T> &);
+       void shear(const std::vector<T> &);
+};
+
+template<typename T, unsigned D>
+class ShapeLoader<TransformedShape<T, D> >: public TransformationLoader<T, D>
+{ };
+
+template<typename T>
+class ShapeLoader<TransformedShape<T, 2> >: public TransformationLoader<T, 2>
+{
+public:
+       ShapeLoader();
+
+       void rotate(T);
+};
+
+template<typename T>
+class ShapeLoader<TransformedShape<T, 3> >: public TransformationLoader<T, 3>
+{
+public:
+       ShapeLoader();
+
+       void rotate(T, T, T, T);
+};
+
+template<typename T, unsigned D>
+class ShapeLoader<Union<T, D> >: public CompositeLoader<T, D, Union<T, D> >
+{ };
+
+
+template<typename T, unsigned D>
+inline DimensionIndependentLoader<T, D>::DimensionIndependentLoader(bool s):
+       single(s)
+{
+       add("box", &DimensionIndependentLoader::shape<HyperBox<T, D> >);
+       add("halfspace", &DimensionIndependentLoader::shape<HalfSpace<T, D> >);
+       add("intersection", &DimensionIndependentLoader::shape<Intersection<T, D> >);
+       add("negation", &DimensionIndependentLoader::shape<Negation<T, D> >);
+       add("sphere", &DimensionIndependentLoader::shape<HyperSphere<T, D> >);
+       add("transformed", &DimensionIndependentLoader::shape<TransformedShape<T, D> >);
+       add("union", &DimensionIndependentLoader::shape<Union<T, D> >);
+}
+
+template<typename T, unsigned D>
+inline DimensionIndependentLoader<T, D>::~DimensionIndependentLoader()
+{
+       for(typename std::list<Shape<T, D> *>::iterator i=shapes.begin(); i!=shapes.end(); ++i)
+               delete *i;
+}
+
+template<typename T, unsigned D>
+inline const Shape<T, D> &DimensionIndependentLoader<T, D>::get_shape() const
+{
+       if(shapes.empty())
+               throw std::runtime_error("no shape");
+       return *shapes.front();
+}
+
+template<typename T, unsigned D>
+template<typename S>
+inline void DimensionIndependentLoader<T, D>::shape()
+{
+       if(single && !shapes.empty())
+               throw std::runtime_error("shape already loaded");
+
+       ShapeLoader<S> ldr;
+       load_sub_with(ldr);
+       shapes.push_back(ldr.create());
+}
+
+
+template<typename T, unsigned D>
+inline Loader<T, D, false>::Loader(bool s):
+       DimensionIndependentLoader<T, D>(s)
+{ }
+
+template<typename T, unsigned D>
+inline Loader<T, D, true>::Loader(bool s):
+       DimensionIndependentLoader<T, D>(s)
+{
+       this->add("extruded", &DimensionIndependentLoader<T, D>::template shape<ExtrudedShape<T, D> >);
+}
+
+
+template<typename T, unsigned D>
+inline ShapeLoader<ExtrudedShape<T, D> >::ShapeLoader():
+       length_(T(1))
+{
+       this->add("length", &ShapeLoader::length);
+}
+
+template<typename T, unsigned D>
+inline ExtrudedShape<T, D> *ShapeLoader<ExtrudedShape<T, D> >::create() const
+{
+       return new ExtrudedShape<T, D>(*this->shapes.front(), length_);
+}
+
+template<typename T, unsigned D>
+inline void ShapeLoader<ExtrudedShape<T, D> >::length(T l)
+{
+       length_ = l;
+}
+
+
+template<typename T, unsigned D>
+inline ShapeLoader<HalfSpace<T, D> >::ShapeLoader()
+{
+       normal_[D-1] = T(1);
+
+       add("normal", &ShapeLoader::normal);
+}
+
+template<typename T, unsigned D>
+inline HalfSpace<T, D> *ShapeLoader<HalfSpace<T, D> >::create() const
+{
+       return new HalfSpace<T, D>(normal_);
+}
+
+template<typename T, unsigned D>
+inline void ShapeLoader<HalfSpace<T, D> >::normal(const std::vector<T> &d)
+{
+       if(d.size()!=D)
+               throw std::invalid_argument("ShapeLoader<HalfSpace>::normal");
+
+       normal_ = LinAl::Vector<T, D>(&d[0]);
+}
+
+
+template<typename T, unsigned D>
+inline ShapeLoader<HyperBox<T, D> >::ShapeLoader()
+{
+       for(unsigned i=0; i<D; ++i)
+               dimensions_[i] = T(1);
+
+       add("dimensions", &ShapeLoader::dimensions);
+}
+
+template<typename T, unsigned D>
+inline HyperBox<T, D> *ShapeLoader<HyperBox<T, D> >::create() const
+{
+       return new HyperBox<T, D>(dimensions_);
+}
+
+template<typename T, unsigned D>
+inline void ShapeLoader<HyperBox<T, D> >::dimensions(const std::vector<T> &d)
+{
+       if(d.size()!=D)
+               throw std::invalid_argument("ShapeLoader<HyperBox>::dimensions");
+
+       dimensions_ = LinAl::Vector<T, D>(&d[0]);
+}
+
+
+template<typename T, unsigned D>
+inline ShapeLoader<HyperSphere<T, D> >::ShapeLoader():
+       radius_(T(1))
+{
+       add("radius", &ShapeLoader::radius);
+}
+
+template<typename T, unsigned D>
+inline HyperSphere<T, D> *ShapeLoader<HyperSphere<T, D> >::create() const
+{
+       return new HyperSphere<T, D>(radius_);
+}
+
+template<typename T, unsigned D>
+inline void ShapeLoader<HyperSphere<T, D> >::radius(T r)
+{
+       radius_ = r;
+}
+
+
+template<typename T, unsigned D>
+inline Negation<T, D> *ShapeLoader<Negation<T, D> >::create() const
+{
+       return new Negation<T, D>(*this->shapes.front());
+}
+
+
+template<typename T, unsigned D>
+inline TransformationLoader<T, D>::TransformationLoader()
+{
+       this->add("translate", &TransformationLoader::translate);
+       this->add("scale", &TransformationLoader::scale);
+       this->add("shear", &TransformationLoader::shear);
+}
+
+template<typename T, unsigned D>
+inline TransformedShape<T, D> *TransformationLoader<T, D>::create() const
+{
+       return new TransformedShape<T, D>(*this->shapes.front(), transformation);
+}
+
+template<typename T, unsigned D>
+inline void TransformationLoader<T, D>::translate(const std::vector<T> &offset)
+{
+       if(offset.size()!=D)
+               throw std::invalid_argument("TransformationLoader::translate");
+
+       transformation *= AffineTransformation<T, D>::translation(LinAl::Vector<T, D>(&offset[0]));
+}
+
+template<typename T, unsigned D>
+inline void TransformationLoader<T, D>::scale(const std::vector<T> &s)
+{
+       if(s.size()!=1 && s.size()!=D)
+               throw std::invalid_argument("TransformationLoader::scale");
+
+       if(s.size()==1)
+       {
+               LinAl::Vector<T, D> us;
+               for(unsigned i=0; i<D; ++i)
+                       us[i] = s.front();
+               transformation *= AffineTransformation<T, D>::scaling(us);
+       }
+       else
+               transformation *= AffineTransformation<T, D>::scaling(LinAl::Vector<T, D>(&s[0]));
+}
+
+template<typename T, unsigned D>
+inline void TransformationLoader<T, D>::shear(const std::vector<T> &s)
+{
+       if(s.size()!=2*D)
+               throw std::invalid_argument("TransformationLoader::shear");
+
+       transformation *= AffineTransformation<T, D>::shear(LinAl::Vector<T, D>(&s[0]), LinAl::Vector<T, D>(&s[D]));
+}
+
+
+template<typename T>
+inline ShapeLoader<TransformedShape<T, 2> >::ShapeLoader()
+{
+       this->add("rotate", &ShapeLoader::rotate);
+}
+
+template<typename T>
+inline void ShapeLoader<TransformedShape<T, 2> >::rotate(T a)
+{
+       TransformationLoader<T, 2>::transformation *= AffineTransformation<T, 2>::rotation(Angle<T>::from_degrees(a));
+}
+
+
+template<typename T>
+inline ShapeLoader<TransformedShape<T, 3> >::ShapeLoader()
+{
+       this->add("rotate", &ShapeLoader::rotate);
+}
+
+template<typename T>
+inline void ShapeLoader<TransformedShape<T, 3> >::rotate(T a, T x, T y, T z)
+{
+       TransformationLoader<T, 3>::transformation *= AffineTransformation<T, 3>::rotation(Angle<T>::from_degrees(a), LinAl::Vector<T, 3>(x, y, z));
+}
+
+
+template<typename T, unsigned D, typename S>
+inline CompositeLoader<T, D, S>::CompositeLoader():
+       Loader<T, D>(false)
+{ }
+
+template<typename T, unsigned D, typename S>
+inline S *CompositeLoader<T, D, S>::create() const
+{
+       if(this->shapes.empty())
+               throw std::runtime_error("no shapes");
+       return S::from_iterator_range(this->shapes.begin(), this->shapes.end()).clone();
+}
+
+} // namespace Geometry
+} // namespace Msp
+
+#endif