From: Mikko Rasa Date: Sat, 22 Nov 2014 09:15:15 +0000 (+0200) Subject: Add a loading system for shapes X-Git-Url: http://git.tdb.fi/?p=libs%2Fmath.git;a=commitdiff_plain;h=d12977f0eea8aec74e25402dce05d768556ffaef Add a loading system for shapes --- diff --git a/Build b/Build index 62e7375..5e5297d 100644 --- a/Build +++ b/Build @@ -1,5 +1,7 @@ package "mspmath" { + require "mspdatafile"; + library "mspmath" { source "source/linal"; diff --git a/source/geometry/dummy.cpp b/source/geometry/dummy.cpp index a262e26..b40a5fc 100644 --- a/source/geometry/dummy.cpp +++ b/source/geometry/dummy.cpp @@ -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 index 0000000..e73a8e3 --- /dev/null +++ b/source/geometry/loader.h @@ -0,0 +1,424 @@ +#ifndef MSP_GEOMETRY_LOADER_H_ +#define MSP_GEOMETRY_LOADER_H_ + +#include +#include +#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 +class DimensionIndependentLoader: public DataFile::Loader +{ +protected: + bool single; + std::list *> shapes; + + DimensionIndependentLoader(bool = true); +public: + virtual ~DimensionIndependentLoader(); + + const Shape &get_shape() const; + +protected: + template + void shape(); +}; + + +template1)> +class Loader; + +template +class Loader: public DimensionIndependentLoader +{ +public: + Loader(bool = true); +}; + +template +class Loader: public DimensionIndependentLoader +{ +public: + Loader(bool = true); +}; + + +template +class ShapeLoader; + +template +class ShapeLoader >: public Loader +{ +private: + T length_; + +public: + ShapeLoader(); + + ExtrudedShape *create() const; + +private: + void length(T); +}; + +template +class ShapeLoader >: public DataFile::Loader +{ +private: + LinAl::Vector normal_; + +public: + ShapeLoader(); + + HalfSpace *create() const; + +private: + void normal(const std::vector &); +}; + +template +class ShapeLoader >: public DataFile::Loader +{ +private: + LinAl::Vector dimensions_; + +public: + ShapeLoader(); + + HyperBox *create() const; + +private: + void dimensions(const std::vector &); +}; + +template +class ShapeLoader >: public DataFile::Loader +{ +private: + T radius_; + +public: + ShapeLoader(); + + HyperSphere *create() const; + +private: + void radius(T); +}; + +template +class CompositeLoader: public Loader +{ +public: + CompositeLoader(); + + S *create() const; +}; + +template +class ShapeLoader >: public CompositeLoader > +{ }; + +template +class ShapeLoader >: public Loader +{ +public: + Negation *create() const; +}; + +template +class TransformationLoader: public Loader +{ +protected: + AffineTransformation transformation; + +public: + TransformationLoader(); + + TransformedShape *create() const; + + void translate(const std::vector &); + void scale(const std::vector &); + void shear(const std::vector &); +}; + +template +class ShapeLoader >: public TransformationLoader +{ }; + +template +class ShapeLoader >: public TransformationLoader +{ +public: + ShapeLoader(); + + void rotate(T); +}; + +template +class ShapeLoader >: public TransformationLoader +{ +public: + ShapeLoader(); + + void rotate(T, T, T, T); +}; + +template +class ShapeLoader >: public CompositeLoader > +{ }; + + +template +inline DimensionIndependentLoader::DimensionIndependentLoader(bool s): + single(s) +{ + add("box", &DimensionIndependentLoader::shape >); + add("halfspace", &DimensionIndependentLoader::shape >); + add("intersection", &DimensionIndependentLoader::shape >); + add("negation", &DimensionIndependentLoader::shape >); + add("sphere", &DimensionIndependentLoader::shape >); + add("transformed", &DimensionIndependentLoader::shape >); + add("union", &DimensionIndependentLoader::shape >); +} + +template +inline DimensionIndependentLoader::~DimensionIndependentLoader() +{ + for(typename std::list *>::iterator i=shapes.begin(); i!=shapes.end(); ++i) + delete *i; +} + +template +inline const Shape &DimensionIndependentLoader::get_shape() const +{ + if(shapes.empty()) + throw std::runtime_error("no shape"); + return *shapes.front(); +} + +template +template +inline void DimensionIndependentLoader::shape() +{ + if(single && !shapes.empty()) + throw std::runtime_error("shape already loaded"); + + ShapeLoader ldr; + load_sub_with(ldr); + shapes.push_back(ldr.create()); +} + + +template +inline Loader::Loader(bool s): + DimensionIndependentLoader(s) +{ } + +template +inline Loader::Loader(bool s): + DimensionIndependentLoader(s) +{ + this->add("extruded", &DimensionIndependentLoader::template shape >); +} + + +template +inline ShapeLoader >::ShapeLoader(): + length_(T(1)) +{ + this->add("length", &ShapeLoader::length); +} + +template +inline ExtrudedShape *ShapeLoader >::create() const +{ + return new ExtrudedShape(*this->shapes.front(), length_); +} + +template +inline void ShapeLoader >::length(T l) +{ + length_ = l; +} + + +template +inline ShapeLoader >::ShapeLoader() +{ + normal_[D-1] = T(1); + + add("normal", &ShapeLoader::normal); +} + +template +inline HalfSpace *ShapeLoader >::create() const +{ + return new HalfSpace(normal_); +} + +template +inline void ShapeLoader >::normal(const std::vector &d) +{ + if(d.size()!=D) + throw std::invalid_argument("ShapeLoader::normal"); + + normal_ = LinAl::Vector(&d[0]); +} + + +template +inline ShapeLoader >::ShapeLoader() +{ + for(unsigned i=0; i +inline HyperBox *ShapeLoader >::create() const +{ + return new HyperBox(dimensions_); +} + +template +inline void ShapeLoader >::dimensions(const std::vector &d) +{ + if(d.size()!=D) + throw std::invalid_argument("ShapeLoader::dimensions"); + + dimensions_ = LinAl::Vector(&d[0]); +} + + +template +inline ShapeLoader >::ShapeLoader(): + radius_(T(1)) +{ + add("radius", &ShapeLoader::radius); +} + +template +inline HyperSphere *ShapeLoader >::create() const +{ + return new HyperSphere(radius_); +} + +template +inline void ShapeLoader >::radius(T r) +{ + radius_ = r; +} + + +template +inline Negation *ShapeLoader >::create() const +{ + return new Negation(*this->shapes.front()); +} + + +template +inline TransformationLoader::TransformationLoader() +{ + this->add("translate", &TransformationLoader::translate); + this->add("scale", &TransformationLoader::scale); + this->add("shear", &TransformationLoader::shear); +} + +template +inline TransformedShape *TransformationLoader::create() const +{ + return new TransformedShape(*this->shapes.front(), transformation); +} + +template +inline void TransformationLoader::translate(const std::vector &offset) +{ + if(offset.size()!=D) + throw std::invalid_argument("TransformationLoader::translate"); + + transformation *= AffineTransformation::translation(LinAl::Vector(&offset[0])); +} + +template +inline void TransformationLoader::scale(const std::vector &s) +{ + if(s.size()!=1 && s.size()!=D) + throw std::invalid_argument("TransformationLoader::scale"); + + if(s.size()==1) + { + LinAl::Vector us; + for(unsigned i=0; i::scaling(us); + } + else + transformation *= AffineTransformation::scaling(LinAl::Vector(&s[0])); +} + +template +inline void TransformationLoader::shear(const std::vector &s) +{ + if(s.size()!=2*D) + throw std::invalid_argument("TransformationLoader::shear"); + + transformation *= AffineTransformation::shear(LinAl::Vector(&s[0]), LinAl::Vector(&s[D])); +} + + +template +inline ShapeLoader >::ShapeLoader() +{ + this->add("rotate", &ShapeLoader::rotate); +} + +template +inline void ShapeLoader >::rotate(T a) +{ + TransformationLoader::transformation *= AffineTransformation::rotation(Angle::from_degrees(a)); +} + + +template +inline ShapeLoader >::ShapeLoader() +{ + this->add("rotate", &ShapeLoader::rotate); +} + +template +inline void ShapeLoader >::rotate(T a, T x, T y, T z) +{ + TransformationLoader::transformation *= AffineTransformation::rotation(Angle::from_degrees(a), LinAl::Vector(x, y, z)); +} + + +template +inline CompositeLoader::CompositeLoader(): + Loader(false) +{ } + +template +inline S *CompositeLoader::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