From 3e32b5c08ca629d85c6af084547199c5392a4cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Tue, 4 Sep 2018 16:55:34 -0700 Subject: [PATCH 1/5] [feature] Add 3D Cuboid --- .../Geometry/3D/Objects/Cuboid.hpp | 437 ++++++ .../Geometry/3D/Objects.cpp | 2 + .../Geometry/3D/Objects/Cuboid.cpp | 68 + .../Mathematics/Geometry/2D/Objects/Point.cpp | 12 +- .../Geometry/2D/Objects/PointSet.cpp | 7 + .../Geometry/3D/Objects/Cuboid.cpp | 548 ++++++++ .../Geometry/3D/Objects/Ellipsoid.cpp | 8 +- .../Mathematics/Geometry/3D/Objects/Point.cpp | 16 +- .../Geometry/3D/Objects/PointSet.cpp | 7 + .../Geometry/3D/Objects/Cuboid.test.cpp | 1228 +++++++++++++++++ 10 files changed, 2305 insertions(+), 28 deletions(-) create mode 100755 include/Library/Mathematics/Geometry/3D/Objects/Cuboid.hpp create mode 100755 share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Cuboid.cpp create mode 100644 src/Library/Mathematics/Geometry/3D/Objects/Cuboid.cpp create mode 100644 test/Library/Mathematics/Geometry/3D/Objects/Cuboid.test.cpp diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Cuboid.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Cuboid.hpp new file mode 100755 index 00000000..a81b10fd --- /dev/null +++ b/include/Library/Mathematics/Geometry/3D/Objects/Cuboid.hpp @@ -0,0 +1,437 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Cuboid.hpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __Library_Mathematics_Geometry_3D_Objects_Cuboid__ +#define __Library_Mathematics_Geometry_3D_Objects_Cuboid__ + +#include +#include +#include + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using library::core::types::Real ; +using library::core::ctnr::Array ; + +using library::math::obj::Vector3d ; +using library::math::geom::d3::Object ; +using library::math::geom::d3::objects::Point ; +using library::math::geom::d3::objects::Segment ; +using library::math::geom::d3::Intersection ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class PointSet ; +class Line ; +class Ray ; +class Segment ; +class Plane ; +class Polygon ; +class Sphere ; +class Pyramid ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @brief Cuboid +/// +/// @ref https://en.wikipedia.org/wiki/Cuboid + +class Cuboid : public Object +{ + + public: + + typedef Point Vertex ; + typedef Segment Edge ; + + /// @brief Constructor + /// + /// @code + /// Cuboid cuboid = { { 0.0, 0.0, 0.0 }, { { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 } }, { 1.0, 2.0, 3.0 } } ; + /// @endcode + /// + + Cuboid ( const Point& aCenter, + const std::array& aAxisArray, + const std::array& anExtent ) ; + + /// @brief Clone cuboid + /// + /// @return Pointer to cloned cuboid + + virtual Cuboid* clone ( ) const override ; + + /// @brief Equal to operator + /// + /// @code + /// Cuboid cuboid = { { 0.0, 0.0, 0.0 }, { { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 } }, { 1.0, 2.0, 3.0 } } ; + /// cuboid == cuboid ; // True + /// @endcode + /// + /// @param [in] aCuboid An cuboid + /// @return True if cuboids are equal + + bool operator == ( const Cuboid& aCuboid ) const ; + + /// @brief Not equal to operator + /// + /// @code + /// Cuboid cuboid = { { 0.0, 0.0, 0.0 }, { { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 } }, { 1.0, 2.0, 3.0 } } ; + /// cuboid != cuboid ; // False + /// @endcode + /// + /// @param [in] aCuboid An cuboid + /// @return True if cuboids not are equal + + bool operator != ( const Cuboid& aCuboid ) const ; + + /// @brief Check if cuboid is defined + /// + /// @code + /// Cuboid cuboid = { { 0.0, 0.0, 0.0 }, { { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 } }, { 1.0, 2.0, 3.0 } } ; + /// cuboid.isDefined() ; // True + /// @endcode + /// + /// @return True if cuboid is defined + + virtual bool isDefined ( ) const override ; + + /// @brief Check if cuboid is near another cuboid + /// + /// @code + /// Point(0.0, 0.0, 0.0).isNear(Point(0.0, 0.0, 0.0), 1e-15) ; // True + /// @endcode + /// + /// @param [in] aCuboid A cuboid + /// @param [in] aTolerance A tolerance + /// @return True if cuboid is near another cuboid + + bool isNear ( const Cuboid& aCuboid, + const Real& aTolerance ) const ; + + /// @brief Check if cuboid intersects point + /// + /// @code + /// Cuboid cuboid = ... ; + /// Point point = ... ; + /// cuboid.intersects(point) ; + /// @endcode + /// + /// @param [in] aPoint A point + /// @return True if cuboid intersects point + + bool intersects ( const Point& aPoint ) const ; + + /// @brief Check if cuboid intersects point set + /// + /// @code + /// Cuboid cuboid = ... ; + /// PointSet pointSet = ... ; + /// cuboid.intersects(pointSet) ; + /// @endcode + /// + /// @param [in] aPointSet A point set + /// @return True if cuboid intersects point set + + bool intersects ( const PointSet& aPointSet ) const ; + + /// @brief Check if cuboid intersects line + /// + /// @code + /// Cuboid cuboid = ... ; + /// Line line = ... ; + /// cuboid.intersects(line) ; + /// @endcode + /// + /// @param [in] aLine A line + /// @return True if cuboid intersects line + + bool intersects ( const Line& aLine ) const ; + + /// @brief Check if cuboid intersects ray + /// + /// @code + /// Cuboid cuboid = ... ; + /// Ray ray = ... ; + /// cuboid.intersects(ray) ; + /// @endcode + /// + /// @param [in] aRay A ray + /// @return True if cuboid intersects ray + + bool intersects ( const Ray& aRay ) const ; + + /// @brief Check if cuboid intersects segment + /// + /// @code + /// Cuboid cuboid = ... ; + /// Segment segment = ... ; + /// cuboid.intersects(segment) ; + /// @endcode + /// + /// @param [in] aSegment A segment + /// @return True if cuboid intersects segment + + bool intersects ( const Segment& aSegment ) const ; + + /// @brief Check if cuboid intersects plane + /// + /// @code + /// Cuboid cuboid = ... ; + /// Plane plane = ... ; + /// cuboid.intersects(plane) ; + /// @endcode + /// + /// @param [in] aPlane A plane + /// @return True if cuboid intersects plane + + bool intersects ( const Plane& aPlane ) const ; + + /// @brief Check if cuboid intersects sphere + /// + /// @code + /// Cuboid cuboid = ... ; + /// Sphere sphere = ... ; + /// cuboid.intersects(sphere) ; + /// @endcode + /// + /// @param [in] aSphere A sphere + /// @return True if cuboid intersects sphere + + bool intersects ( const Sphere& aSphere ) const ; + + /// @brief Check if cuboid intersects cuboid + /// + /// @code + /// Cuboid cuboid = ... ; + /// Cuboid anotherCuboid = ... ; + /// cuboid.intersects(anotherCuboid) ; + /// @endcode + /// + /// @param [in] aCuboid An cuboid + /// @return True if cuboid intersects cuboid + + bool intersects ( const Cuboid& aCuboid ) const ; + + /// @brief Check if cuboid intersects pyramid + /// + /// @code + /// Cuboid cuboid = ... ; + /// Pyramid pyramid = ... ; + /// cuboid.intersects(pyramid) ; + /// @endcode + /// + /// @param [in] aPyramid A pyramid + /// @return True if cuboid intersects pyramid + + bool intersects ( const Pyramid& aPyramid ) const ; + + /// @brief Check if cuboid contains point + /// + /// @code + /// Cuboid cuboid = ... ; + /// Point point = ... ; + /// cuboid.contains(point) ; + /// @endcode + /// + /// @param [in] aPoint A point + /// @return True if cuboid contains point + + bool contains ( const Point& aPoint ) const ; + + /// @brief Check if cuboid contains point set + /// + /// @code + /// Cuboid cuboid = ... ; + /// PointSet pointSet = ... ; + /// cuboid.contains(pointSet) ; + /// @endcode + /// + /// @param [in] aPointSet A point set + /// @return True if cuboid contains point set + + bool contains ( const PointSet& aPointSet ) const ; + + /// @brief Check if cuboid contains segment + /// + /// @code + /// Cuboid cuboid = ... ; + /// Segment segment = ... ; + /// cuboid.contains(segment) ; + /// @endcode + /// + /// @param [in] aSegment A segment + /// @return True if cuboid contains segment + + bool contains ( const Segment& aSegment ) const ; + + /// @brief Get cuboid center + /// + /// @code + /// Cuboid cuboid = { { 0.0, 0.0, 0.0 }, { { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 } }, { 1.0, 2.0, 3.0 } } ; + /// cuboid.getCenter() ; // [0.0, 0.0, 0.0] + /// @endcode + /// + /// @return Cuboid center + + Point getCenter ( ) const ; + + /// @brief Get cuboid first axis + /// + /// @return Cuboid first axis + + Vector3d getFirstAxis ( ) const ; + + /// @brief Get cuboid second axis + /// + /// @return Cuboid second axis + + Vector3d getSecondAxis ( ) const ; + + /// @brief Get cuboid third axis + /// + /// @return Cuboid third axis + + Vector3d getThirdAxis ( ) const ; + + /// @brief Get cuboid first extent + /// + /// @return Cuboid first extent + + Real getFirstExtent ( ) const ; + + /// @brief Get cuboid second extent + /// + /// @return Cuboid second extent + + Real getSecondExtent ( ) const ; + + /// @brief Get cuboid third extent + /// + /// @return Cuboid third extent + + Real getThirdExtent ( ) const ; + + /// @brief Get cuboid vertices + /// + /// @return Cuboid vertices + + Array getVertices ( ) const ; + + /// @brief Compute intersection of cuboid with line + /// + /// @param [in] aLine A line + /// @return Intersection of cuboid with line + + Intersection intersectionWith ( const Line& aLine ) const ; + + /// @brief Compute intersection of cuboid with ray + /// + /// @param [in] aRay A ray + /// @param [in] onlyInSight (optional) If true, only return intersection points that are in sight + /// @return Intersection of cuboid with ray + + Intersection intersectionWith ( const Ray& aRay, + const bool onlyInSight = false ) const ; + + /// @brief Compute intersection of cuboid with segment + /// + /// @param [in] aSegment A segment + /// @return Intersection of cuboid with segment + + Intersection intersectionWith ( const Segment& aSegment ) const ; + + /// @brief Compute intersection of cuboid with cuboid + /// + /// @param [in] aSegment A cuboid + /// @return Intersection of cuboid with cuboid + + Intersection intersectionWith ( const Cuboid& aCuboid ) const ; + + /// @brief Compute intersection of cuboid with pyramid + /// + /// @param [in] aPyramid A pyramid + /// @param [in] onlyInSight (optional) If true, only return intersection points that are in sight + /// @return Intersection of cuboid with pyramid + + Intersection intersectionWith ( const Pyramid& aPyramid, + const bool onlyInSight = false ) const ; + + /// @brief Print cuboid + /// + /// @param [in] anOutputStream An output stream + /// @param [in] (optional) displayDecorators If true, display decorators + + virtual void print ( std::ostream& anOutputStream, + bool displayDecorators = true ) const override ; + + /// @brief Apply transformation to cuboid + /// + /// @param [in] aTransformation A transformation + + virtual void applyTransformation ( const Transformation& aTransformation ) override ; + + /// @brief Constructs an undefined cuboid + /// + /// @code + /// Cuboid cuboid = Cuboid::Undefined() ; // Undefined + /// @endcode + /// + /// @return Undefined cuboid + + static Cuboid Undefined ( ) ; + + /// @brief Constructs a a cube + /// + /// @code + /// Cuboid cube = Cuboid::Cube({ 0.0, 0.0, 0.0 }, 1.0) ; + /// @endcode + /// + /// @return Cube + + static Cuboid Cube ( const Point& aCenter, + const Real& anExtent ) ; + + private: + + Point center_ ; + std::array axes_ ; + std::array extent_ ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects.cpp index 809941da..ddc50f2b 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects.cpp @@ -11,6 +11,7 @@ // #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects ( ) // LibraryMathematicsPy_Geometry_3D_Objects_MultiLineString() ; LibraryMathematicsPy_Geometry_3D_Objects_Plane() ; LibraryMathematicsPy_Geometry_3D_Objects_Polygon() ; + LibraryMathematicsPy_Geometry_3D_Objects_Cuboid() ; LibraryMathematicsPy_Geometry_3D_Objects_Sphere() ; LibraryMathematicsPy_Geometry_3D_Objects_Ellipsoid() ; LibraryMathematicsPy_Geometry_3D_Objects_Pyramid() ; diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Cuboid.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Cuboid.cpp new file mode 100755 index 00000000..92c22814 --- /dev/null +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Cuboid.cpp @@ -0,0 +1,68 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file LibraryMathematicsPy/Geometry/3D/Objects/Cuboid.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void LibraryMathematicsPy_Geometry_3D_Objects_Cuboid ( ) +{ + + using namespace boost::python ; + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::PointSet ; + using library::math::geom::d3::objects::Line ; + using library::math::geom::d3::objects::Ray ; + using library::math::geom::d3::objects::Segment ; + using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::Sphere ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::Intersection ; + using library::math::geom::d3::trf::rot::Quaternion ; + + scope in_Cuboid = class_>("Cuboid", init&, const std::array&>()) + + .def(self == self) + .def(self != self) + + .def(self_ns::str(self_ns::self)) + .def(self_ns::repr(self_ns::self)) + + .def("isDefined", &Cuboid::isDefined) + .def("isNear", &Cuboid::isNear) + .def("intersectsPoint", +[] (const Cuboid& aCuboid, const Point& aPoint) -> bool { return aCuboid.intersects(aPoint) ; }) + .def("intersectsPointSet", +[] (const Cuboid& aCuboid, const PointSet& aPointSet) -> bool { return aCuboid.intersects(aPointSet) ; }) + .def("intersectsLine", +[] (const Cuboid& aCuboid, const Line& aLine) -> bool { return aCuboid.intersects(aLine) ; }) + .def("intersectsCuboid", +[] (const Cuboid& aFirstCuboid, const Cuboid& aSecondCuboid) -> bool { return aFirstCuboid.intersects(aSecondCuboid) ; }) + + .def("getCenter", &Cuboid::getCenter) + .def("getFirstAxis", &Cuboid::getFirstAxis) + .def("getSecondAxis", &Cuboid::getSecondAxis) + .def("getThirdAxis", &Cuboid::getThirdAxis) + .def("getFirstExtent", &Cuboid::getFirstExtent) + .def("getSecondExtent", &Cuboid::getSecondExtent) + .def("getThirdExtent", &Cuboid::getThirdExtent) + .def("getVertices", &Cuboid::getVertices) + .def("applyTransformation", &Cuboid::applyTransformation) + + .def("Undefined", &Cuboid::Undefined).staticmethod("Undefined") + .def("Cube", &Cuboid::Cube).staticmethod("Cube") + + ; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/Library/Mathematics/Geometry/2D/Objects/Point.cpp b/src/Library/Mathematics/Geometry/2D/Objects/Point.cpp index 183f6ab5..d9026847 100644 --- a/src/Library/Mathematics/Geometry/2D/Objects/Point.cpp +++ b/src/Library/Mathematics/Geometry/2D/Objects/Point.cpp @@ -125,22 +125,12 @@ bool Point::isNear ( const Real& aTolerance ) const { - if (!this->isDefined()) - { - throw library::core::error::runtime::Undefined("Point") ; - } - - if (!aPoint.isDefined()) - { - throw library::core::error::runtime::Undefined("Point") ; - } - if (!aTolerance.isDefined()) { throw library::core::error::runtime::Undefined("Tolerance") ; } - return (this->Vector2d::operator - (aPoint)).norm() <= aTolerance ; + return this->distanceTo(aPoint) <= aTolerance ; } diff --git a/src/Library/Mathematics/Geometry/2D/Objects/PointSet.cpp b/src/Library/Mathematics/Geometry/2D/Objects/PointSet.cpp index 4135917c..1ac96be6 100644 --- a/src/Library/Mathematics/Geometry/2D/Objects/PointSet.cpp +++ b/src/Library/Mathematics/Geometry/2D/Objects/PointSet.cpp @@ -69,6 +69,11 @@ bool PointSet::isNear ( return false ; } + if (this->getSize() != aPointSet.getSize()) + { + return false ; + } + PointSet::Container firstPointSetBuffer = points_ ; PointSet::Container secondPointSetBuffer = aPointSet.points_ ; @@ -91,6 +96,8 @@ bool PointSet::isNear ( secondPointSetBuffer.erase(secondPointSetBufferIt) ; + break ; + } } diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Cuboid.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Cuboid.cpp new file mode 100644 index 00000000..6f72cd18 --- /dev/null +++ b/src/Library/Mathematics/Geometry/3D/Objects/Cuboid.cpp @@ -0,0 +1,548 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Cuboid.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +// #include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +gte::Vector3 CuboidGteVectorFromVector3d ( const Vector3d& aVector ) +{ + return { aVector.x(), aVector.y(), aVector.z() } ; +} + +Vector3d CuboidVector3dFromGteVector ( const gte::Vector3& aVector ) +{ + return { aVector[0], aVector[1], aVector[2] } ; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Cuboid::Cuboid ( const Point& aCenter, + const std::array& aAxisArray, + const std::array& anExtent ) + : Object(), + center_(aCenter), + axes_(aAxisArray), + extent_(anExtent) +{ + +} + +Cuboid* Cuboid::clone ( ) const +{ + return new Cuboid(*this) ; +} + +bool Cuboid::operator == ( const Cuboid& aCuboid ) const +{ + + if ((!this->isDefined()) || (!aCuboid.isDefined())) + { + return false ; + } + + if (center_ == aCuboid.center_) + { + + if (((axes_[0] == aCuboid.axes_[0]) || (axes_[0] == -aCuboid.axes_[0])) && (extent_[0] == aCuboid.extent_[0])) + { + + if (((axes_[1] == aCuboid.axes_[1]) || (axes_[1] == -aCuboid.axes_[1])) && (extent_[1] == aCuboid.extent_[1])) + { + + if (((axes_[2] == aCuboid.axes_[2]) || (axes_[2] == -aCuboid.axes_[2])) && (extent_[2] == aCuboid.extent_[2])) + { + return true ; // (0 == 0) && (1 == 1) && (2 == 2) + } + + } + else if (((axes_[1] == aCuboid.axes_[2]) || (axes_[1] == -aCuboid.axes_[2])) && (extent_[1] == aCuboid.extent_[2])) + { + + if (((axes_[2] == aCuboid.axes_[1]) || (axes_[2] == -aCuboid.axes_[1])) && (extent_[2] == aCuboid.extent_[1])) + { + return true ; // (0 == 0) && (1 == 2) && (2 == 1) + } + + } + + } + else if (((axes_[0] == aCuboid.axes_[1]) || (axes_[0] == -aCuboid.axes_[1])) && (extent_[0] == aCuboid.extent_[1])) + { + + if (((axes_[1] == aCuboid.axes_[0]) || (axes_[1] == -aCuboid.axes_[0])) && (extent_[1] == aCuboid.extent_[0])) + { + + if (((axes_[2] == aCuboid.axes_[2]) || (axes_[2] == -aCuboid.axes_[2])) && (extent_[2] == aCuboid.extent_[2])) + { + return true ; // (0 == 1) && (1 == 0) && (2 == 2) + } + + } + else if (((axes_[1] == aCuboid.axes_[2]) || (axes_[1] == -aCuboid.axes_[2])) && (extent_[1] == aCuboid.extent_[2])) + { + + if (((axes_[2] == aCuboid.axes_[0]) || (axes_[2] == -aCuboid.axes_[0])) && (extent_[2] == aCuboid.extent_[0])) + { + return true ; // (0 == 1) && (1 == 2) && (2 == 0) + } + + } + + } + else if (((axes_[0] == aCuboid.axes_[2]) || (axes_[0] == -aCuboid.axes_[2])) && (extent_[0] == aCuboid.extent_[2])) + { + + if (((axes_[1] == aCuboid.axes_[0]) || (axes_[1] == -aCuboid.axes_[0])) && (extent_[1] == aCuboid.extent_[0])) + { + + if (((axes_[2] == aCuboid.axes_[1]) || (axes_[2] == -aCuboid.axes_[1])) && (extent_[2] == aCuboid.extent_[1])) + { + return true ; // (0 == 2) && (1 == 0) && (2 == 1) + } + + } + else if (((axes_[1] == aCuboid.axes_[1]) || (axes_[1] == -aCuboid.axes_[1])) && (extent_[1] == aCuboid.extent_[1])) + { + + if (((axes_[2] == aCuboid.axes_[0]) || (axes_[2] == -aCuboid.axes_[0])) && (extent_[2] == aCuboid.extent_[0])) + { + return true ; // (0 == 2) && (1 == 1) && (2 == 0) + } + + } + + } + + } + + return false ; + +} + +bool Cuboid::operator != ( const Cuboid& aCuboid ) const +{ + return !((*this) == aCuboid) ; +} + +bool Cuboid::isDefined ( ) const +{ + + return center_.isDefined() + && axes_[0].isDefined() && axes_[1].isDefined() && axes_[2].isDefined() + && extent_[0].isDefined() && extent_[1].isDefined() && extent_[2].isDefined() ; + +} + +bool Cuboid::isNear ( const Cuboid& aCuboid, + const Real& aTolerance ) const +{ + + if (!aCuboid.isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + if (!aTolerance.isDefined()) + { + throw library::core::error::runtime::Undefined("Tolerance") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + return PointSet(this->getVertices()).isNear(PointSet(aCuboid.getVertices()), aTolerance) ; + +} + +bool Cuboid::intersects ( const Point& aPoint ) const +{ + return this->contains(aPoint) ; +} + +bool Cuboid::intersects ( const PointSet& aPointSet ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + return (!aPointSet.isEmpty()) && std::any_of(aPointSet.begin(), aPointSet.end(), [this] (const Point& aPoint) -> bool { return this->contains(aPoint) ; }) ; + +} + +bool Cuboid::intersects ( const Line& aLine ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + if (!aLine.isDefined()) + { + throw library::core::error::runtime::Undefined("Line") ; + } + + // Line + + const gte::Line3 line = { CuboidGteVectorFromVector3d(aLine.getOrigin()), CuboidGteVectorFromVector3d(aLine.getDirection()) } ; + + // Cuboid + + const gte::Vector3 center = CuboidGteVectorFromVector3d(center_) ; + const std::array, 3> axis = { CuboidGteVectorFromVector3d(axes_[0]), CuboidGteVectorFromVector3d(axes_[1]), CuboidGteVectorFromVector3d(axes_[2]) } ; + const gte::Vector3 extent = { extent_[0], extent_[1], extent_[2] } ; + + const gte::OrientedBox3 cuboid = { center, axis, extent } ; + + // Intersection + + gte::TIQuery, gte::OrientedBox3> intersectionQuery ; + + auto intersectionResult = intersectionQuery(line, cuboid) ; + + return intersectionResult.intersect ; + +} + +bool Cuboid::intersects ( const Cuboid& aCuboid ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + if (!aCuboid.isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + // First cuboid + + const gte::Vector3 firstCenter = CuboidGteVectorFromVector3d(center_) ; + const std::array, 3> firstAxis = { CuboidGteVectorFromVector3d(axes_[0]), CuboidGteVectorFromVector3d(axes_[1]), CuboidGteVectorFromVector3d(axes_[2]) } ; + const gte::Vector3 firstExtent = { extent_[0], extent_[1], extent_[2] } ; + + const gte::OrientedBox3 firstCuboid = { firstCenter, firstAxis, firstExtent } ; + + // Second cuboid + + const gte::Vector3 secondCenter = CuboidGteVectorFromVector3d(aCuboid.center_) ; + const std::array, 3> secondAxis = { CuboidGteVectorFromVector3d(aCuboid.axes_[0]), CuboidGteVectorFromVector3d(aCuboid.axes_[1]), CuboidGteVectorFromVector3d(aCuboid.axes_[2]) } ; + const gte::Vector3 secondExtent = { aCuboid.extent_[0], aCuboid.extent_[1], aCuboid.extent_[2] } ; + + const gte::OrientedBox3 secondCuboid = { secondCenter, secondAxis, secondExtent } ; + + // Intersection + + gte::TIQuery, gte::OrientedBox3> intersectionQuery ; + + auto intersectionResult = intersectionQuery(firstCuboid, secondCuboid) ; + + return intersectionResult.intersect ; + +} + +bool Cuboid::contains ( const Point& aPoint ) const +{ + + if (!aPoint.isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + const Vector3d dx = aPoint - center_ ; + + const Real a = std::abs(dx.dot(axes_[0])) ; + const Real b = std::abs(dx.dot(axes_[1])) ; + const Real c = std::abs(dx.dot(axes_[2])) ; + + if (std::abs(a - extent_[0]) < Real::Epsilon()) + { + return (b <= extent_[1]) && (c <= extent_[2]) ; + } + + if (std::abs(b - extent_[1]) < Real::Epsilon()) + { + return (a <= extent_[0]) && (c <= extent_[2]) ; + } + + if (std::abs(c - extent_[2]) < Real::Epsilon()) + { + return (a <= extent_[0]) && (b <= extent_[1]) ; + } + + return false ; + +} + +bool Cuboid::contains ( const PointSet& aPointSet ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + return (!aPointSet.isEmpty()) && std::all_of(aPointSet.begin(), aPointSet.end(), [this] (const Point& aPoint) -> bool { return this->contains(aPoint) ; }) ; + +} + +bool Cuboid::contains ( const Segment& aSegment ) const +{ + return this->contains(aSegment.getFirstPoint()) && this->contains(aSegment.getSecondPoint()) ; +} + +Point Cuboid::getCenter ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + return center_ ; + +} + +Vector3d Cuboid::getFirstAxis ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + return axes_[0] ; + +} + +Vector3d Cuboid::getSecondAxis ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + return axes_[1] ; + +} + +Vector3d Cuboid::getThirdAxis ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + return axes_[2] ; + +} + +Real Cuboid::getFirstExtent ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + return extent_[0] ; + +} + +Real Cuboid::getSecondExtent ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + return extent_[1] ; + +} + +Real Cuboid::getThirdExtent ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + return extent_[2] ; + +} + +Array Cuboid::getVertices ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + Array vertices = Array::Empty() ; + + vertices.reserve(8) ; + + const Real halfFirstExtent = extent_[0] / 2.0 ; + const Real halfSecondExtent = extent_[1] / 2.0 ; + const Real halfThirdExtent = extent_[2] / 2.0 ; + + vertices.add(center_ + (halfFirstExtent * axes_[0]) + (halfSecondExtent * axes_[1]) + (halfThirdExtent * axes_[2])) ; + vertices.add(center_ + (halfFirstExtent * axes_[0]) + (halfSecondExtent * axes_[1]) - (halfThirdExtent * axes_[2])) ; + vertices.add(center_ + (halfFirstExtent * axes_[0]) - (halfSecondExtent * axes_[1]) - (halfThirdExtent * axes_[2])) ; + vertices.add(center_ + (halfFirstExtent * axes_[0]) - (halfSecondExtent * axes_[1]) + (halfThirdExtent * axes_[2])) ; + vertices.add(center_ - (halfFirstExtent * axes_[0]) + (halfSecondExtent * axes_[1]) + (halfThirdExtent * axes_[2])) ; + vertices.add(center_ - (halfFirstExtent * axes_[0]) + (halfSecondExtent * axes_[1]) - (halfThirdExtent * axes_[2])) ; + vertices.add(center_ - (halfFirstExtent * axes_[0]) - (halfSecondExtent * axes_[1]) - (halfThirdExtent * axes_[2])) ; + vertices.add(center_ - (halfFirstExtent * axes_[0]) - (halfSecondExtent * axes_[1]) + (halfThirdExtent * axes_[2])) ; + + return vertices ; + +} + +void Cuboid::print ( std::ostream& anOutputStream, + bool displayDecorators ) const +{ + + displayDecorators ? library::core::utils::Print::Header(anOutputStream, "Cuboid") : void () ; + + library::core::utils::Print::Line(anOutputStream) << "Center:" << (center_.isDefined() ? center_.toString() : "Undefined") ; + + library::core::utils::Print::Line(anOutputStream) << "First axis:" << (axes_[0].isDefined() ? axes_[0].toString() : "Undefined") ; + library::core::utils::Print::Line(anOutputStream) << "Second axis:" << (axes_[1].isDefined() ? axes_[1].toString() : "Undefined") ; + library::core::utils::Print::Line(anOutputStream) << "Third axis:" << (axes_[2].isDefined() ? axes_[2].toString() : "Undefined") ; + + library::core::utils::Print::Line(anOutputStream) << "First extent:" << (extent_[0].isDefined() ? extent_[0].toString() : "Undefined") ; + library::core::utils::Print::Line(anOutputStream) << "Second extent:" << (extent_[1].isDefined() ? extent_[1].toString() : "Undefined") ; + library::core::utils::Print::Line(anOutputStream) << "Third extent:" << (extent_[2].isDefined() ? extent_[2].toString() : "Undefined") ; + + displayDecorators ? library::core::utils::Print::Footer(anOutputStream) : void () ; + +} + +void Cuboid::applyTransformation ( const Transformation& aTransformation ) +{ + + using library::math::geom::d3::trf::rot::RotationMatrix ; + + if (!aTransformation.isDefined()) + { + throw library::core::error::runtime::Undefined("Transformation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Cuboid") ; + } + + if (aTransformation.isIdentity()) + { + return ; + } + + center_.applyTransformation(aTransformation) ; + + axes_[0] = aTransformation.applyTo(axes_[0]) ; + axes_[1] = aTransformation.applyTo(axes_[1]) ; + axes_[2] = aTransformation.applyTo(axes_[2]) ; + + extent_[0] *= axes_[0].norm() ; + extent_[1] *= axes_[1].norm() ; + extent_[2] *= axes_[2].norm() ; + + axes_[0].normalize() ; + axes_[1].normalize() ; + axes_[2].normalize() ; + +} + +Cuboid Cuboid::Undefined ( ) +{ + return { Point::Undefined(), { Vector3d::Undefined(), Vector3d::Undefined(), Vector3d::Undefined() }, { Real::Undefined(), Real::Undefined(), Real::Undefined() } } ; +} + +Cuboid Cuboid::Cube ( const Point& aCenter, + const Real& anExtent ) +{ + + if (!aCenter.isDefined()) + { + throw library::core::error::runtime::Undefined("Center") ; + } + + if (!anExtent.isDefined()) + { + throw library::core::error::runtime::Undefined("Extent") ; + } + + return { aCenter, { Vector3d::X(), Vector3d::Y(), Vector3d::Z() }, { anExtent, anExtent, anExtent } } ; + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp index ca3b8790..8b2223e1 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp @@ -169,7 +169,7 @@ bool Ellipsoid::intersects ( // Line - const gte::Line3 segment = { GteVectorFromVector3d(aLine.getOrigin()), GteVectorFromVector3d(aLine.getDirection()) } ; + const gte::Line3 line = { GteVectorFromVector3d(aLine.getOrigin()), GteVectorFromVector3d(aLine.getDirection()) } ; // Ellipsoid @@ -183,7 +183,7 @@ bool Ellipsoid::intersects ( gte::TIQuery, gte::Ellipsoid3> intersectionQuery ; - auto intersectionResult = intersectionQuery(segment, ellipsoid) ; + auto intersectionResult = intersectionQuery(line, ellipsoid) ; return intersectionResult.intersect ; @@ -204,7 +204,7 @@ bool Ellipsoid::intersects ( // Ray - const gte::Ray3 segment = { GteVectorFromVector3d(aRay.getOrigin()), GteVectorFromVector3d(aRay.getDirection()) } ; + const gte::Ray3 ray = { GteVectorFromVector3d(aRay.getOrigin()), GteVectorFromVector3d(aRay.getDirection()) } ; // Ellipsoid @@ -218,7 +218,7 @@ bool Ellipsoid::intersects ( gte::TIQuery, gte::Ellipsoid3> intersectionQuery ; - auto intersectionResult = intersectionQuery(segment, ellipsoid) ; + auto intersectionResult = intersectionQuery(ray, ellipsoid) ; return intersectionResult.intersect ; diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp index 59359d1a..5b4a9953 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp @@ -103,12 +103,12 @@ Point Point::operator - ( Vector3d Point::operator - ( const Point& aPoint ) const { - if (!this->isDefined()) + if (!aPoint.isDefined()) { throw library::core::error::runtime::Undefined("Point") ; } - if (!aPoint.isDefined()) + if (!this->isDefined()) { throw library::core::error::runtime::Undefined("Point") ; } @@ -126,22 +126,12 @@ bool Point::isNear ( const Real& aTolerance ) const { - if (!this->isDefined()) - { - throw library::core::error::runtime::Undefined("Point") ; - } - - if (!aPoint.isDefined()) - { - throw library::core::error::runtime::Undefined("Point") ; - } - if (!aTolerance.isDefined()) { throw library::core::error::runtime::Undefined("Tolerance") ; } - return (this->Vector3d::operator - (aPoint)).norm() <= aTolerance ; + return this->distanceTo(aPoint) <= aTolerance ; } diff --git a/src/Library/Mathematics/Geometry/3D/Objects/PointSet.cpp b/src/Library/Mathematics/Geometry/3D/Objects/PointSet.cpp index f19dbb46..1932bd3d 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/PointSet.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/PointSet.cpp @@ -69,6 +69,11 @@ bool PointSet::isNear ( return false ; } + if (this->getSize() != aPointSet.getSize()) + { + return false ; + } + PointSet::Container firstPointSetBuffer = points_ ; PointSet::Container secondPointSetBuffer = aPointSet.points_ ; @@ -91,6 +96,8 @@ bool PointSet::isNear ( secondPointSetBuffer.erase(secondPointSetBufferIt) ; + break ; + } } diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Cuboid.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Cuboid.test.cpp new file mode 100644 index 00000000..8ed1df64 --- /dev/null +++ b/test/Library/Mathematics/Geometry/3D/Objects/Cuboid.test.cpp @@ -0,0 +1,1228 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Cuboid.test.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Constructor) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_NO_THROW(Cuboid(center, axes, extent)) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Clone) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_NO_THROW(Cuboid(center, axes, extent).clone()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, EqualToOperator) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_TRUE(Cuboid(center, axes, extent) == Cuboid(center, axes, extent)) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + + const Cuboid firstCuboid = { center, { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } }, { 1.0, 2.0, 3.0 } } ; + const Cuboid secondCuboid = { center, { Vector3d { 0.0, 1.0, 0.0 }, Vector3d { -1.0, 0.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } }, { 2.0, 1.0, 3.0 } } ; + + EXPECT_TRUE(firstCuboid == secondCuboid) ; + + } + + { + + const Point center = { 1.0, 2.0, 3.0 } ; + + const Cuboid firstCuboid = { center, { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } }, { 1.0, 2.0, 3.0 } } ; + const Cuboid secondCuboid = { center, { Vector3d { 0.0, 0.0, -1.0 }, Vector3d { 0.0, -1.0, 0.0 }, Vector3d { -1.0, 0.0, 0.0 } }, { 3.0, 2.0, 1.0 } } ; + + EXPECT_TRUE(firstCuboid == secondCuboid) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_FALSE(Cuboid(center, axes, extent) == Cuboid::Undefined()) ; + EXPECT_FALSE(Cuboid::Undefined() == Cuboid(center, axes, extent)) ; + EXPECT_FALSE(Cuboid::Undefined() == Cuboid::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, NotEqualToOperator) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_FALSE(Cuboid(center, axes, extent) != Cuboid(center, axes, extent)) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + + const Cuboid firstCuboid = { center, { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } }, { 1.0, 2.0, 3.0 } } ; + const Cuboid secondCuboid = { center, { Vector3d { 0.0, 1.0, 0.0 }, Vector3d { -1.0, 0.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } }, { 2.0, 1.0, 3.0 } } ; + + EXPECT_FALSE(firstCuboid != secondCuboid) ; + + } + + { + + const Point center = { 1.0, 2.0, 3.0 } ; + + const Cuboid firstCuboid = { center, { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } }, { 1.0, 2.0, 3.0 } } ; + const Cuboid secondCuboid = { center, { Vector3d { 0.0, 0.0, -1.0 }, Vector3d { 0.0, -1.0, 0.0 }, Vector3d { -1.0, 0.0, 0.0 } }, { 3.0, 2.0, 1.0 } } ; + + EXPECT_FALSE(firstCuboid != secondCuboid) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_TRUE(Cuboid(center, axes, extent) != Cuboid::Undefined()) ; + EXPECT_TRUE(Cuboid::Undefined() != Cuboid(center, axes, extent)) ; + EXPECT_TRUE(Cuboid::Undefined() != Cuboid::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, StreamOperator) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + testing::internal::CaptureStdout() ; + + EXPECT_NO_THROW(std::cout << Cuboid(center, axes, extent) << std::endl) ; + + EXPECT_FALSE(testing::internal::GetCapturedStdout().empty()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, IsDefined) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_TRUE(Cuboid(center, axes, extent).isDefined()) ; + + } + + { + + EXPECT_FALSE(Cuboid::Undefined().isDefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, IsNear) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + EXPECT_TRUE(cuboid.isNear(cuboid, 0.0)) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid firstCuboid = { center, axes, extent } ; + const Cuboid secondCuboid = { { 0.0, 0.0, 1e-6 }, axes, extent } ; + + EXPECT_TRUE(firstCuboid.isNear(secondCuboid, 1e-5)) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid firstCuboid = { center, axes, extent } ; + const Cuboid secondCuboid = { center, axes, { 1.0 + 1e-6, 2.0, 3.0 } } ; + + EXPECT_TRUE(firstCuboid.isNear(secondCuboid, 1e-5)) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid firstCuboid = { center, axes, extent } ; + const Cuboid secondCuboid = { center, axes, { 1.0 + 1e-4, 2.0, 3.0 } } ; + + EXPECT_FALSE(firstCuboid.isNear(secondCuboid, 1e-5)) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + EXPECT_ANY_THROW(Cuboid::Undefined().isNear(Cuboid::Undefined(), Real::Undefined())) ; + EXPECT_ANY_THROW(cuboid.isNear(Cuboid::Undefined(), Real::Undefined())) ; + EXPECT_ANY_THROW(Cuboid::Undefined().isNear(cuboid, Real::Undefined())) ; + EXPECT_ANY_THROW(cuboid.isNear(cuboid, Real::Undefined())) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Intersects_Point) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + EXPECT_TRUE(cuboid.intersects(Point(+1.0, 0.0, 0.0))) ; + EXPECT_TRUE(cuboid.intersects(Point(-1.0, 0.0, 0.0))) ; + + EXPECT_TRUE(cuboid.intersects(Point(0.0, +2.0, 0.0))) ; + EXPECT_TRUE(cuboid.intersects(Point(0.0, -2.0, 0.0))) ; + + EXPECT_TRUE(cuboid.intersects(Point(0.0, 0.0, +3.0))) ; + EXPECT_TRUE(cuboid.intersects(Point(0.0, 0.0, -3.0))) ; + + EXPECT_TRUE(cuboid.intersects(Point(+1.0, +2.0, +3.0))) ; + EXPECT_TRUE(cuboid.intersects(Point(-1.0, -2.0, -3.0))) ; + + EXPECT_TRUE(cuboid.intersects(Point(+1.0, +0.5, 0.0))) ; + EXPECT_TRUE(cuboid.intersects(Point(+1.0, -0.5, 0.0))) ; + + EXPECT_TRUE(cuboid.intersects(Point(+1.0, +0.5, +1.0))) ; + EXPECT_TRUE(cuboid.intersects(Point(+1.0, -0.5, +1.0))) ; + + EXPECT_TRUE(cuboid.intersects(Point(+1.0, +0.5, -1.0))) ; + EXPECT_TRUE(cuboid.intersects(Point(+1.0, -0.5, -1.0))) ; + + EXPECT_TRUE(cuboid.intersects(Point(+0.5, +2.0, -1.0))) ; + EXPECT_TRUE(cuboid.intersects(Point(+0.5, -2.0, -1.0))) ; + + EXPECT_FALSE(cuboid.intersects(Point(+0.5, +2.0, +3.1))) ; + EXPECT_FALSE(cuboid.intersects(Point(+0.5, -2.0, -3.1))) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_ANY_THROW(Cuboid(center, axes, extent).intersects(Point::Undefined())) ; + EXPECT_ANY_THROW(Cuboid::Undefined().intersects(Point(0.0, 0.0, 0.0))) ; + EXPECT_ANY_THROW(Cuboid::Undefined().intersects(Point::Undefined())) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Intersects_PointSet) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::PointSet ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + const PointSet pointSet = + { + { + { +1.0, 0.0, 0.0 }, + { -1.0, 0.0, 0.0 }, + { 0.0, +2.0, 0.0 }, + { 0.0, -2.0, 0.0 }, + { 0.0, 0.0, +3.0 }, + { 0.0, 0.0, -3.0 }, + { +1.0, +2.0, +3.0 }, + { -1.0, -2.0, -3.0 }, + { +1.0, +0.5, 0.0 }, + { +1.0, -0.5, 0.0 }, + { +1.0, +0.5, +1.0 }, + { +1.0, -0.5, +1.0 }, + { +1.0, +0.5, -1.0 }, + { +1.0, -0.5, -1.0 }, + { +0.5, +2.0, -1.0 }, + { +0.5, -2.0, -1.0 } + } + } ; + + EXPECT_TRUE(cuboid.intersects(pointSet)) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + const PointSet pointSet = + { + { + { +1.0, 0.0, 0.0 }, + { -1.0, 0.0, 0.0 }, + { 0.0, +2.0, 0.0 }, + { 0.0, -2.0, 0.0 }, + { 0.0, 0.0, +3.0 }, + { 0.0, 0.0, -3.0 }, + { +1.0, +2.0, +3.0 }, + { -1.0, -2.0, -3.0 }, + { +1.0, +0.5, 0.0 }, + { +1.0, -0.5, 0.0 }, + { +1.0, +0.5, +1.0 }, + { +1.0, -0.5, +1.0 }, + { +1.0, +0.5, -1.0 }, + { +1.0, -0.5, -1.0 }, + { +0.5, +2.0, -1.0 }, + { +0.5, -2.0, -1.0 }, + { +0.5, -2.0, -3.1 } + } + } ; + + EXPECT_TRUE(cuboid.intersects(pointSet)) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + const PointSet pointSet = + { + { + { +0.5, +2.0, +3.1 }, + { +0.5, -2.0, -3.1 } + } + } ; + + EXPECT_FALSE(cuboid.intersects(pointSet)) ; + + } + + { + + EXPECT_ANY_THROW(Cuboid::Undefined().intersects(PointSet::Empty())) ; + EXPECT_ANY_THROW(Cuboid::Undefined().intersects(PointSet({ { +5.0, +2.0, +3.0 }, { +5.0, +2.0, +3.0 } }))) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Intersects_Line) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::PointSet ; + using library::math::geom::d3::objects::Line ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_TRUE(cuboid.intersects(Line({ +1.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ +1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ +1.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_TRUE(cuboid.intersects(Line({ -1.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ -1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ -1.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, +2.0, 0.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, +2.0, 0.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, +2.0, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, -2.0, 0.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, -2.0, 0.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, -2.0, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, +3.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, +3.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, +3.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, -3.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, -3.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, -3.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_TRUE(cuboid.intersects(Line({ +1.1, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_FALSE(cuboid.intersects(Line({ +1.1, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_FALSE(cuboid.intersects(Line({ +1.1, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_TRUE(cuboid.intersects(Line({ -1.1, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_FALSE(cuboid.intersects(Line({ -1.1, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_FALSE(cuboid.intersects(Line({ -1.1, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_FALSE(cuboid.intersects(Line({ 0.0, +2.1, 0.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, +2.1, 0.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_FALSE(cuboid.intersects(Line({ 0.0, +2.1, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_FALSE(cuboid.intersects(Line({ 0.0, -2.1, 0.0 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, -2.1, 0.0 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_FALSE(cuboid.intersects(Line({ 0.0, -2.1, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_FALSE(cuboid.intersects(Line({ 0.0, 0.0, +3.1 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_FALSE(cuboid.intersects(Line({ 0.0, 0.0, +3.1 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, +3.1 }, { 0.0, 0.0, 1.0 }))) ; + + EXPECT_FALSE(cuboid.intersects(Line({ 0.0, 0.0, -3.1 }, { 1.0, 0.0, 0.0 }))) ; + EXPECT_FALSE(cuboid.intersects(Line({ 0.0, 0.0, -3.1 }, { 0.0, 1.0, 0.0 }))) ; + EXPECT_TRUE(cuboid.intersects(Line({ 0.0, 0.0, -3.1 }, { 0.0, 0.0, 1.0 }))) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + EXPECT_ANY_THROW(Cuboid::Undefined().intersects(Line::Undefined())) ; + EXPECT_ANY_THROW(cuboid.intersects(Line::Undefined())) ; + EXPECT_ANY_THROW(Cuboid::Undefined().intersects(Line({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + + } + +} + +// TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Intersects_Ray) +// { + +// using library::core::types::Real ; + +// using library::math::geom::d3::objects::Point ; +// using library::math::geom::d3::objects::Ray ; +// using library::math::geom::d3::objects::Cuboid ; + +// { + +// EXPECT_ANY_THROW(Cuboid::Undefined().intersects(Ray::Undefined())) ; +// EXPECT_ANY_THROW(Cuboid(Point::Origin(), 1.0, 1.0, 1.0).intersects(Ray::Undefined())) ; +// EXPECT_ANY_THROW(Cuboid::Undefined().intersects(Ray({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }))) ; + +// } + +// } + +// TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Intersects_Segment) +// { + +// using library::core::types::Real ; + +// using library::math::geom::d3::objects::Point ; +// using library::math::geom::d3::objects::Segment ; +// using library::math::geom::d3::objects::Cuboid ; + +// { + +// EXPECT_ANY_THROW(Cuboid(Point::Origin(), 1.0, 1.0, 1.0).intersects(Segment::Undefined())) ; + +// } + +// } + +// TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Intersects_Plane) +// { + +// using library::core::types::Real ; + +// using library::math::geom::d3::objects::Point ; +// using library::math::geom::d3::objects::Plane ; +// using library::math::geom::d3::objects::Cuboid ; + +// { + +// EXPECT_ANY_THROW(Cuboid::Undefined().intersects(Plane::Undefined())) ; +// EXPECT_ANY_THROW(Cuboid(Point::Origin(), 1.0, 1.0, 1.0).intersects(Plane::Undefined())) ; + +// } + +// } + +// TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Intersects_Pyramid) +// { + +// using library::math::geom::d3::objects::Point ; +// using library::math::geom::d3::objects::Cuboid ; +// using library::math::geom::d3::objects::Pyramid ; + +// { + +// EXPECT_ANY_THROW(Cuboid::Undefined().intersects(Pyramid::Undefined())) ; +// EXPECT_ANY_THROW(Cuboid(Point::Origin(), 1.0, 1.0, 1.0).intersects(Pyramid::Undefined())) ; + +// } + +// } + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Contains_Point) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + EXPECT_TRUE(cuboid.contains(Point(+1.0, 0.0, 0.0))) ; + EXPECT_TRUE(cuboid.contains(Point(-1.0, 0.0, 0.0))) ; + + EXPECT_TRUE(cuboid.contains(Point(0.0, +2.0, 0.0))) ; + EXPECT_TRUE(cuboid.contains(Point(0.0, -2.0, 0.0))) ; + + EXPECT_TRUE(cuboid.contains(Point(0.0, 0.0, +3.0))) ; + EXPECT_TRUE(cuboid.contains(Point(0.0, 0.0, -3.0))) ; + + EXPECT_TRUE(cuboid.contains(Point(+1.0, +2.0, +3.0))) ; + EXPECT_TRUE(cuboid.contains(Point(-1.0, -2.0, -3.0))) ; + + EXPECT_TRUE(cuboid.contains(Point(+1.0, +0.5, 0.0))) ; + EXPECT_TRUE(cuboid.contains(Point(+1.0, -0.5, 0.0))) ; + + EXPECT_TRUE(cuboid.contains(Point(+1.0, +0.5, +1.0))) ; + EXPECT_TRUE(cuboid.contains(Point(+1.0, -0.5, +1.0))) ; + + EXPECT_TRUE(cuboid.contains(Point(+1.0, +0.5, -1.0))) ; + EXPECT_TRUE(cuboid.contains(Point(+1.0, -0.5, -1.0))) ; + + EXPECT_TRUE(cuboid.contains(Point(+0.5, +2.0, -1.0))) ; + EXPECT_TRUE(cuboid.contains(Point(+0.5, -2.0, -1.0))) ; + + EXPECT_FALSE(cuboid.contains(Point(+0.5, +2.0, +3.1))) ; + EXPECT_FALSE(cuboid.contains(Point(+0.5, -2.0, -3.1))) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_ANY_THROW(Cuboid(center, axes, extent).contains(Point::Undefined())) ; + EXPECT_ANY_THROW(Cuboid::Undefined().contains(Point(0.0, 0.0, 0.0))) ; + EXPECT_ANY_THROW(Cuboid::Undefined().contains(Point::Undefined())) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Contains_PointSet) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::PointSet ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + const PointSet pointSet = + { + { + { +1.0, 0.0, 0.0 }, + { -1.0, 0.0, 0.0 }, + { 0.0, +2.0, 0.0 }, + { 0.0, -2.0, 0.0 }, + { 0.0, 0.0, +3.0 }, + { 0.0, 0.0, -3.0 }, + { +1.0, +2.0, +3.0 }, + { -1.0, -2.0, -3.0 }, + { +1.0, +0.5, 0.0 }, + { +1.0, -0.5, 0.0 }, + { +1.0, +0.5, +1.0 }, + { +1.0, -0.5, +1.0 }, + { +1.0, +0.5, -1.0 }, + { +1.0, -0.5, -1.0 }, + { +0.5, +2.0, -1.0 }, + { +0.5, -2.0, -1.0 } + } + } ; + + EXPECT_TRUE(cuboid.contains(pointSet)) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + const PointSet pointSet = + { + { + { +1.0, 0.0, 0.0 }, + { -1.0, 0.0, 0.0 }, + { 0.0, +2.0, 0.0 }, + { 0.0, -2.0, 0.0 }, + { 0.0, 0.0, +3.0 }, + { 0.0, 0.0, -3.0 }, + { +1.0, +2.0, +3.0 }, + { -1.0, -2.0, -3.0 }, + { +1.0, +0.5, 0.0 }, + { +1.0, -0.5, 0.0 }, + { +1.0, +0.5, +1.0 }, + { +1.0, -0.5, +1.0 }, + { +1.0, +0.5, -1.0 }, + { +1.0, -0.5, -1.0 }, + { +0.5, +2.0, -1.0 }, + { +0.5, -2.0, -1.0 }, + { +0.5, -2.0, -3.1 } + } + } ; + + EXPECT_FALSE(cuboid.contains(pointSet)) ; + + } + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + const PointSet pointSet = + { + { + { +0.5, +2.0, +3.1 }, + { +0.5, -2.0, -3.1 } + } + } ; + + EXPECT_FALSE(cuboid.contains(pointSet)) ; + + } + + { + + EXPECT_ANY_THROW(Cuboid::Undefined().contains(PointSet::Empty())) ; + EXPECT_ANY_THROW(Cuboid::Undefined().contains(PointSet({ { +5.0, +2.0, +3.0 }, { +5.0, +2.0, +3.0 } }))) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, GetCenter) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_EQ(center, Cuboid(center, axes, extent).getCenter()) ; + + } + + { + + EXPECT_ANY_THROW(Cuboid::Undefined().getCenter()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, GetFirstAxis) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_EQ(axes[0], Cuboid(center, axes, extent).getFirstAxis()) ; + + } + + { + + EXPECT_ANY_THROW(Cuboid::Undefined().getFirstAxis()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, GetSecondAxis) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_EQ(axes[1], Cuboid(center, axes, extent).getSecondAxis()) ; + + } + + { + + EXPECT_ANY_THROW(Cuboid::Undefined().getSecondAxis()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, GetThirdAxis) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_EQ(axes[2], Cuboid(center, axes, extent).getThirdAxis()) ; + + } + + { + + EXPECT_ANY_THROW(Cuboid::Undefined().getThirdAxis()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, GetFirstExtent) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_EQ(extent[0], Cuboid(center, axes, extent).getFirstExtent()) ; + + } + + { + + EXPECT_ANY_THROW(Cuboid::Undefined().getFirstExtent()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, GetSecondExtent) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_EQ(extent[1], Cuboid(center, axes, extent).getSecondExtent()) ; + + } + + { + + EXPECT_ANY_THROW(Cuboid::Undefined().getSecondExtent()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, GetThirdExtent) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + EXPECT_EQ(extent[2], Cuboid(center, axes, extent).getThirdExtent()) ; + + } + + { + + EXPECT_ANY_THROW(Cuboid::Undefined().getThirdExtent()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, GetVertices) +{ + + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + const Array referenceVertices = + { + { + { +0.5, +1.0, +1.5 }, + { +0.5, +1.0, -1.5 }, + { +0.5, -1.0, -1.5 }, + { +0.5, -1.0, +1.5 }, + { -0.5, +1.0, +1.5 }, + { -0.5, +1.0, -1.5 }, + { -0.5, -1.0, -1.5 }, + { -0.5, -1.0, +1.5 } + } + } ; + + EXPECT_EQ(referenceVertices, cuboid.getVertices()) << referenceVertices << cuboid.getVertices() ; + + } + + { + + EXPECT_ANY_THROW(Cuboid::Undefined().getVertices()) ; + + } + +} + +// TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, IntersectionWith_Line) +// { + +// using library::core::types::Real ; + +// using library::math::geom::d3::objects::Point ; +// using library::math::geom::d3::objects::PointSet ; +// using library::math::geom::d3::objects::Line ; +// using library::math::geom::d3::objects::Cuboid ; +// using library::math::geom::d3::Intersection ; + +// { + +// FAIL() ; + +// } + +// { + +// EXPECT_ANY_THROW(Cuboid::Undefined().intersectionWith(Line::Undefined())) ; + +// } + +// } + +// TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, IntersectionWith_Ray) +// { + +// using library::core::types::Real ; + +// using library::math::geom::d3::objects::Point ; +// using library::math::geom::d3::objects::PointSet ; +// using library::math::geom::d3::objects::Ray ; +// using library::math::geom::d3::objects::Cuboid ; +// using library::math::geom::d3::Intersection ; + +// { + +// FAIL() ; + +// } + +// { + +// EXPECT_ANY_THROW(Cuboid::Undefined().intersectionWith(Ray::Undefined())) ; + +// } + +// } + +// TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, IntersectionWith_Segment) +// { + +// using library::core::types::Real ; + +// using library::math::geom::d3::objects::Point ; +// using library::math::geom::d3::objects::PointSet ; +// using library::math::geom::d3::objects::Segment ; +// using library::math::geom::d3::objects::Cuboid ; +// using library::math::geom::d3::Intersection ; + +// { + +// FAIL() ; + +// } + +// { + +// EXPECT_ANY_THROW(Cuboid::Undefined().intersectionWith(Segment::Undefined())) ; + +// } + +// } + +// TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, IntersectionWith_Pyramid) +// { + +// using library::math::geom::d3::objects::Point ; +// using library::math::geom::d3::objects::Cuboid ; +// using library::math::geom::d3::objects::Pyramid ; + +// { + +// FAIL() ; + +// } + +// { + +// EXPECT_ANY_THROW(Cuboid::Undefined().intersectionWith(Pyramid::Undefined())) ; + +// } + +// } + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, ApplyTransformation) +{ + + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::Angle ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::Transformation ; + using library::math::geom::d3::trf::rot::Quaternion ; + using library::math::geom::d3::trf::rot::RotationVector ; + + // Translation + + { + + const Point center = { 1.0, 2.0, 3.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + Cuboid cuboid = { center, axes, extent } ; + + cuboid.applyTransformation(Transformation::Translation({ 4.0, 5.0, 6.0 })) ; + + const Cuboid referenceCuboid = { { 5.0, 7.0, 9.0 }, axes, extent } ; + + EXPECT_EQ(referenceCuboid, cuboid) << cuboid ; + + } + + // Rotation + + { + + const Point center = { 1.0, 2.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + Cuboid cuboid = { center, axes, extent } ; + + cuboid.applyTransformation(Transformation::Rotation(RotationVector({ 1.0, 0.0, 0.0 }, Angle::Degrees(90.0)))) ; + + const Cuboid referenceCuboid = { { 1.0, 0.0, 2.0 }, axes, { 1.0, 3.0, 2.0 } } ; + + EXPECT_TRUE(cuboid.isNear(referenceCuboid, Real::Epsilon())) << referenceCuboid << cuboid ; + + } + + { + + const Point center = { 1.0, 2.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + Cuboid cuboid = { center, axes, extent } ; + + EXPECT_ANY_THROW(cuboid.applyTransformation(Transformation::Undefined())) ; + EXPECT_ANY_THROW(Cuboid::Undefined().applyTransformation(Transformation::Undefined())) ; + EXPECT_ANY_THROW(Cuboid::Undefined().applyTransformation(Transformation::Identity())) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Undefined) +{ + + using library::math::geom::d3::objects::Cuboid ; + + { + + EXPECT_NO_THROW(Cuboid::Undefined()) ; + EXPECT_FALSE(Cuboid::Undefined().isDefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Cuboid, Cube) +{ + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Cuboid ; + + { + + const Cuboid cube = Cuboid::Cube({ 0.0, 0.0, 0.0 }, 1.0) ; + + EXPECT_TRUE(cube.isDefined()) ; + + EXPECT_EQ(Vector3d(0.0, 0.0, 0.0), cube.getCenter()) ; + + } + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file From 3936e0bdffd18aa8b98bbe854990669e6bd6c74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Tue, 4 Sep 2018 17:47:04 -0700 Subject: [PATCH 2/5] [feature] Add Cuboid bindings --- share/python/notebooks/Tutorial.ipynb | 263 +++++++++++++++--- .../Geometry/3D/Objects/Cuboid.cpp | 22 +- .../Mathematics/Geometry/2D/Objects/Point.cpp | 2 +- .../Mathematics/Geometry/3D/Objects/Point.cpp | 2 +- 4 files changed, 240 insertions(+), 49 deletions(-) diff --git a/share/python/notebooks/Tutorial.ipynb b/share/python/notebooks/Tutorial.ipynb index 47df4316..8f993257 100644 --- a/share/python/notebooks/Tutorial.ipynb +++ b/share/python/notebooks/Tutorial.ipynb @@ -196,7 +196,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -212,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -228,11 +228,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ - "point = Point(0.0, 0.0)" + "point = Point(0.0, 0.0) ;" ] }, { @@ -241,16 +241,28 @@ "metadata": {}, "outputs": [], "source": [ - "Point.Undefined()" + "Point.Undefined() ;" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Point' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mPoint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mOrigin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m;\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'Point' is not defined" + ] + } + ], "source": [ - "Point.Origin()" + "Point.Origin() ;" ] }, { @@ -770,8 +782,7 @@ "metadata": {}, "outputs": [], "source": [ - "segment.translate(numpy.array((0.0, 0.0, 0.0))) ;\n", - "segment.rotate(Geometry.Transformations.Rotations.Quaternion.Unit()) ;" + "segment.applyTransformation(Transformation.Identity()) ;" ] }, { @@ -820,6 +831,178 @@ "*To be completed...*" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Cuboid" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Cuboid = D3.Objects.Cuboid" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Cuboid ▸ Constructors**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "center = Point(0.0, 0.0, 0.0)\n", + "axes = [numpy.array((1.0, 0.0, 0.0)), numpy.array((0.0, 1.0, 0.0)), numpy.array((0.0, 0.0, 1.0))]\n", + "extent = [1.0, 2.0, 3.0]\n", + "\n", + "cuboid = Cuboid(center, axes, extent) ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Cuboid.Undefined() ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Cuboid ▸ Operators**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid == cuboid ;\n", + "cuboid != cuboid ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Cuboid ▸ Methods**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.isDefined() ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.isNear(cuboid, 0.0) ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.intersectsPoint(Point(0.0, 0.0, 0.0)) ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.intersectsPointSet(PointSet([Point(0.0, 0.0, 0.0), Point(0.0, 0.0, 0.0)])) ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.intersectsLine(Line(Point(0.0, 0.0, 0.0), numpy.array((0.0, 0.0, 1.0)))) ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.intersectsCuboid(cuboid) ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.getCenter() ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.getFirstAxis() ;\n", + "cuboid.getSecondAxis() ;\n", + "cuboid.getThirdAxis() ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.getFirstExtent() ;\n", + "cuboid.getSecondExtent() ;\n", + "cuboid.getThirdExtent() ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.getVertices() ;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cuboid.applyTransformation(Transformation.Identity()) ;" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -1233,7 +1416,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1249,7 +1432,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1265,7 +1448,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1281,7 +1464,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1304,7 +1487,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1326,7 +1509,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1335,7 +1518,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1344,28 +1527,16 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'Angle' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mquaternion\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0misNear\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mquaternion\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mAngle\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mRadians\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0.0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m;\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mNameError\u001b[0m: name 'Angle' is not defined" - ] - } - ], + "outputs": [], "source": [ "quaternion.isNear(quaternion, Angle.Radians(0.0)) ;" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1377,7 +1548,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1387,7 +1558,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1396,7 +1567,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1405,7 +1576,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1414,7 +1585,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1426,7 +1597,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1435,7 +1606,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1444,7 +1615,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1453,7 +1624,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1462,7 +1633,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1471,7 +1642,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1480,7 +1651,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1489,7 +1660,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1498,7 +1669,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Cuboid.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Cuboid.cpp index 92c22814..d7bbc0c8 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Cuboid.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Cuboid.cpp @@ -10,6 +10,8 @@ #include #include +#include + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline void LibraryMathematicsPy_Geometry_3D_Objects_Cuboid ( ) @@ -17,6 +19,7 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Cuboid using namespace boost::python ; + using library::core::types::Shared ; using library::core::types::Real ; using library::math::obj::Vector3d ; @@ -33,7 +36,24 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Cuboid using library::math::geom::d3::Intersection ; using library::math::geom::d3::trf::rot::Quaternion ; - scope in_Cuboid = class_>("Cuboid", init&, const std::array&>()) + scope in_Cuboid = class_, bases>("Cuboid", no_init) + + .def + ( + "__init__", + make_constructor + ( + +[] (const Point& aCenter, const boost::python::list& anAxisList, const boost::python::list& anExtent) -> Shared + { + + const std::array axes = { boost::python::extract(anAxisList[0]), boost::python::extract(anAxisList[1]), boost::python::extract(anAxisList[2]) } ; + const std::array extent = { boost::python::extract(anExtent[0]), boost::python::extract(anExtent[1]), boost::python::extract(anExtent[2]) } ; + + return std::make_shared(aCenter, axes, extent) ; + + } + ) + ) .def(self == self) .def(self != self) diff --git a/src/Library/Mathematics/Geometry/2D/Objects/Point.cpp b/src/Library/Mathematics/Geometry/2D/Objects/Point.cpp index d9026847..ab738ab6 100644 --- a/src/Library/Mathematics/Geometry/2D/Objects/Point.cpp +++ b/src/Library/Mathematics/Geometry/2D/Objects/Point.cpp @@ -210,7 +210,7 @@ void Point::applyTransformation ( Point Point::Undefined ( ) { - return Vector2d::Undefined() ; + return { Vector2d::Undefined() } ; } Point Point::Origin ( ) diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp index 5b4a9953..8ea7ddff 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp @@ -183,7 +183,7 @@ void Point::applyTransformation ( Point Point::Undefined ( ) { - return Vector3d::Undefined() ; + return { Vector3d::Undefined() } ; } Point Point::Origin ( ) From 48856abc4e7d1a9db59714917c378874b240dcdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Fri, 7 Sep 2018 14:55:39 -0700 Subject: [PATCH 3/5] [feature] Improve Python bindings --- share/python/notebooks/Tutorial.ipynb | 16 +- share/python/notebooks/Untitled.ipynb | 179 ++++++++++++++++++ .../Transformations/Rotations/Quaternion.cpp | 4 +- .../Transformations/Rotations/Quaternion.cpp | 94 --------- .../Rotations/RotationMatrix.cpp | 62 ------ .../Rotations/RotationVector.cpp | 51 ----- tools/python/debug.sh | 72 +++++++ tools/python/docker/Dockerfile.debug | 26 +++ tools/python/docker/build.sh | 7 + tools/python/helpers/debug.sh | 24 +++ tools/python/helpers/install.sh | 20 ++ 11 files changed, 331 insertions(+), 224 deletions(-) create mode 100644 share/python/notebooks/Untitled.ipynb delete mode 100644 share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/Quaternion.cpp delete mode 100644 share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/RotationMatrix.cpp delete mode 100644 share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/RotationVector.cpp create mode 100755 tools/python/debug.sh create mode 100644 tools/python/docker/Dockerfile.debug create mode 100755 tools/python/helpers/debug.sh create mode 100755 tools/python/helpers/install.sh diff --git a/share/python/notebooks/Tutorial.ipynb b/share/python/notebooks/Tutorial.ipynb index 8f993257..33badbbc 100644 --- a/share/python/notebooks/Tutorial.ipynb +++ b/share/python/notebooks/Tutorial.ipynb @@ -246,21 +246,9 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'Point' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mPoint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mOrigin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m;\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mNameError\u001b[0m: name 'Point' is not defined" - ] - } - ], + "outputs": [], "source": [ "Point.Origin() ;" ] diff --git a/share/python/notebooks/Untitled.ipynb b/share/python/notebooks/Untitled.ipynb new file mode 100644 index 00000000..2c353009 --- /dev/null +++ b/share/python/notebooks/Untitled.ipynb @@ -0,0 +1,179 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import Library.Core as Core\n", + "import Library.Mathematics as Mathematics" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "D3 = Mathematics.Geometry.D3" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "Point = D3.Objects.Point\n", + "Cuboid = D3.Objects.Cuboid" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "Transformation = D3.Transformation" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "center = Point(0.0, 0.0, 0.0)\n", + "axes = [numpy.array((1.0, 0.0, 0.0)), numpy.array((0.0, 1.0, 0.0)), numpy.array((0.0, 0.0, 1.0))]\n", + "extent = [1.0, 2.0, 3.0]\n", + "\n", + "cuboid = Cuboid(center, axes, extent) ;" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-- Cuboid ------------------------------------------------------------------------------------------\n", + " Center: [0.0, 0.0, 0.0] \n", + " First axis: [1.0, 0.0, 0.0] \n", + " Second axis: [0.0, 1.0, 0.0] \n", + " Third axis: [0.0, 0.0, 1.0] \n", + " First extent: 1.0 \n", + " Second extent: 2.0 \n", + " Third extent: 3.0 \n", + "----------------------------------------------------------------------------------------------------" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cuboid" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cuboid.intersectsCuboid(cuboid)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Transformation.Translation(numpy.array((1.0, 2.0, 3.0)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "transformation = Transformation.Translation(numpy.array((1.0, 2.0, 3.0)))" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'cuboid' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mcuboid\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapplyTransformation\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtransformation\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'cuboid' is not defined" + ] + } + ], + "source": [ + "cuboid.applyTransformation(transformation)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Transformations/Rotations/Quaternion.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Transformations/Rotations/Quaternion.cpp index e6850b6e..157b645e 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Transformations/Rotations/Quaternion.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Transformations/Rotations/Quaternion.cpp @@ -13,8 +13,6 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS (LibraryMathematicsPy_Geometry_3D_Transformations_Rotations_Quaternion_toString_overloads, library::math::geom::d3::trf::rot::Quaternion::toString, 0, 2) - inline void LibraryMathematicsPy_Geometry_3D_Transformations_Rotations_Quaternion ( ) { @@ -65,8 +63,8 @@ inline void LibraryMathematicsPy_Geometry_3D_Transformations .def("dotMultiply", &Quaternion::dotMultiply) .def("rotateVector", &Quaternion::rotateVector) .def("toVector", &Quaternion::toVector) + .def("toString", +[] (const Quaternion& aQuaternion) -> String { return aQuaternion.toString() ; }) .def("toString", +[] (const Quaternion& aQuaternion, const Quaternion::Format aFormat) -> String { return aQuaternion.toString(aFormat) ; }) - // .def("toString", &Quaternion::toString(), LibraryMathematicsPy_Geometry_3D_Transformations_Rotations_Quaternion_toString_overloads()) .def("normalize", +[] (Quaternion& aQuaternion) -> void { aQuaternion.normalize() ; }) .def("conjugate", +[] (Quaternion& aQuaternion) -> void { aQuaternion.conjugate() ; }) .def("inverse", +[] (Quaternion& aQuaternion) -> void { aQuaternion.inverse() ; }) diff --git a/share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/Quaternion.cpp b/share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/Quaternion.cpp deleted file mode 100644 index e6850b6e..00000000 --- a/share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/Quaternion.cpp +++ /dev/null @@ -1,94 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/// @project Library/Mathematics -/// @file LibraryMathematicsPy/Geometry/3D/Transformations/Rotations/Quaternion.cpp -/// @author Lucas Brémond -/// @license TBD - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS (LibraryMathematicsPy_Geometry_3D_Transformations_Rotations_Quaternion_toString_overloads, library::math::geom::d3::trf::rot::Quaternion::toString, 0, 2) - -inline void LibraryMathematicsPy_Geometry_3D_Transformations_Rotations_Quaternion ( ) -{ - - using namespace boost::python ; - - using library::core::types::Real ; - using library::core::types::String ; - - using library::math::obj::Vector3d ; - using library::math::obj::Vector4d ; - using library::math::geom::d3::trf::rot::Quaternion ; - - scope in_Quaternion = class_("Quaternion", init()) - - .def(init()) - .def(init()) - - .def(self == self) - .def(self != self) - - .def(self * self) - .def(self * Vector3d()) - - .def(self / self) - - .def(self_ns::str(self_ns::self)) - - .def("__repr__", +[] (const Quaternion& aQuaternion) -> std::string { return aQuaternion.toString() ; }) - - .def("isDefined", &Quaternion::isDefined) - .def("isUnitary", &Quaternion::isUnitary) - .def("isNear", &Quaternion::isNear) - - .def("x", &Quaternion::x) - .def("y", &Quaternion::y) - .def("z", &Quaternion::z) - .def("s", &Quaternion::s) - .def("getVectorPart", &Quaternion::getVectorPart) - .def("getScalarPart", &Quaternion::getScalarPart) - .def("toNormalized", &Quaternion::toNormalized) - .def("toConjugate", &Quaternion::toConjugate) - .def("toInverse", &Quaternion::toInverse) - // .def("pow", &Quaternion::pow) - // .def("exp", &Quaternion::exp) - // .def("log", &Quaternion::log) - .def("norm", &Quaternion::norm) - .def("crossMultiply", &Quaternion::crossMultiply) - .def("dotMultiply", &Quaternion::dotMultiply) - .def("rotateVector", &Quaternion::rotateVector) - .def("toVector", &Quaternion::toVector) - .def("toString", +[] (const Quaternion& aQuaternion, const Quaternion::Format aFormat) -> String { return aQuaternion.toString(aFormat) ; }) - // .def("toString", &Quaternion::toString(), LibraryMathematicsPy_Geometry_3D_Transformations_Rotations_Quaternion_toString_overloads()) - .def("normalize", +[] (Quaternion& aQuaternion) -> void { aQuaternion.normalize() ; }) - .def("conjugate", +[] (Quaternion& aQuaternion) -> void { aQuaternion.conjugate() ; }) - .def("inverse", +[] (Quaternion& aQuaternion) -> void { aQuaternion.inverse() ; }) - .def("rectify", +[] (Quaternion& aQuaternion) -> void { aQuaternion.rectify() ; }) - .def("angularDifferenceWith", &Quaternion::angularDifferenceWith) - - .def("Undefined", &Quaternion::Undefined).staticmethod("Undefined") - .def("Unit", &Quaternion::Unit).staticmethod("Unit") - .def("XYZS", &Quaternion::XYZS).staticmethod("XYZS") - .def("RotationVector", &Quaternion::RotationVector).staticmethod("RotationVector") - .def("RotationMatrix", &Quaternion::RotationMatrix).staticmethod("RotationMatrix") - .def("Parse", &Quaternion::Parse).staticmethod("Parse") - - ; - - enum_("Format") - - .value("XYZS", Quaternion::Format::XYZS) - .value("SXYZ", Quaternion::Format::SXYZ) - - ; - -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/RotationMatrix.cpp b/share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/RotationMatrix.cpp deleted file mode 100644 index 1da88e0f..00000000 --- a/share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/RotationMatrix.cpp +++ /dev/null @@ -1,62 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/// @project Library/Mathematics -/// @file LibraryMathematicsPy/Geometry/3D/Transformations/Rotations/RotationMatrix.cpp -/// @author Lucas Brémond -/// @license TBD - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -inline void LibraryMathematicsPy_Geometry_3D_Transformations_Rotations_RotationMatrix ( ) -{ - - using namespace boost::python ; - - using library::core::types::Real ; - using library::core::types::String ; - - using library::math::obj::Vector3d ; - using library::math::obj::Matrix3d ; - using library::math::geom::d3::trf::rot::RotationMatrix ; - - scope in_RotationMatrix = class_("RotationMatrix", init()) - - .def(init()) - - .def(self == self) - .def(self != self) - - .def(self * self) - .def(self * Vector3d()) - - .def(self_ns::str(self_ns::self)) - .def(self_ns::repr(self_ns::self)) - - .def("isDefined", &RotationMatrix::isDefined) - - .def("getRowAt", &RotationMatrix::getRowAt) - .def("getColumnAt", &RotationMatrix::getColumnAt) - .def("toTransposed", &RotationMatrix::toTransposed) - .def("transpose", +[] (RotationMatrix& aRotationMatrix) -> void { aRotationMatrix.transpose() ; }) - - .def("Undefined", &RotationMatrix::Undefined).staticmethod("Undefined") - .def("Unit", &RotationMatrix::Unit).staticmethod("Unit") - .def("RX", &RotationMatrix::RX).staticmethod("RX") - .def("RY", &RotationMatrix::RY).staticmethod("RY") - .def("RZ", &RotationMatrix::RZ).staticmethod("RZ") - .def("Rows", &RotationMatrix::Rows).staticmethod("Rows") - .def("Columns", &RotationMatrix::Columns).staticmethod("Columns") - .def("Quaternion", &RotationMatrix::Quaternion).staticmethod("Quaternion") - .def("RotationVector", &RotationMatrix::RotationVector).staticmethod("RotationVector") - - ; - -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/RotationVector.cpp b/share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/RotationVector.cpp deleted file mode 100644 index ce1fc9a8..00000000 --- a/share/python/src/LibraryMathematicsPy/Geometry/Transformations/Rotations/RotationVector.cpp +++ /dev/null @@ -1,51 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/// @project Library/Mathematics -/// @file LibraryMathematicsPy/Geometry/3D/Transformations/Rotations/RotationVector.cpp -/// @author Lucas Brémond -/// @license TBD - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -inline void LibraryMathematicsPy_Geometry_3D_Transformations_Rotations_RotationVector ( ) -{ - - using namespace boost::python ; - - using library::core::types::Real ; - using library::core::types::String ; - - using library::math::obj::Vector3d ; - using library::math::geom::Angle ; - using library::math::geom::d3::trf::rot::RotationVector ; - - scope in_RotationVector = class_("RotationVector", init()) - - .def(self == self) - .def(self != self) - - .def(self_ns::str(self_ns::self)) - .def(self_ns::repr(self_ns::self)) - - .def("isDefined", &RotationVector::isDefined) - - .def("getAxis", &RotationVector::getAxis) - .def("getAngle", &RotationVector::getAngle) - .def("toString", &RotationVector::toString) - - .def("Undefined", &RotationVector::Undefined) - .def("Unit", &RotationVector::Unit).staticmethod("Unit") - .def("Quaternion", &RotationVector::Quaternion).staticmethod("Quaternion") - .def("RotationMatrix", &RotationVector::RotationMatrix).staticmethod("RotationMatrix") - - ; - -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/tools/python/debug.sh b/tools/python/debug.sh new file mode 100755 index 00000000..8efc82a3 --- /dev/null +++ b/tools/python/debug.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +################################################################################################################################################################ + +# @project Library/Mathematics +# @file tools/python/debug.sh +# @author Lucas Brémond +# @license TBD + +################################################################################################################################################################ + +script_directory="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +pushd "${script_directory}" > /dev/null + +source ../.env + +if [[ ! -z $1 ]] && [[ $1 == "--link" ]]; then + + docker run \ + --name="${container_name}-python-debug" \ + -it \ + --rm \ + --privileged \ + --user="" \ + --env="LD_LIBRARY_PATH=/usr/local/lib:/opt/conda/lib/python3.6/site-packages:/home/jovyan/lib" \ + --env="PYTHONPATH=/opt/conda/lib/python3.6/site-packages:/home/jovyan/lib" \ + --volume="$(pwd)/../../../library-core/lib:/opt/library-core:ro" \ + --volume="$(pwd)/../../../library-mathematics/lib:/opt/library-mathematics:ro" \ + --volume="$(pwd)/../../lib:/opt/lib:ro" \ + --volume="$(pwd)/../../share/python/notebooks:/home/jovyan/notebooks" \ + --volume="$(pwd)/helpers:/home/jovyan/notebooks/helpers:ro" \ + --volume="$(pwd)/../../share/data:/app/share/data" \ + --workdir="/home/jovyan/notebooks" \ + "${repository_name}/${project_name}-python-debug" \ + bash -c "mkdir -p /opt/conda/lib/python3.6/site-packages/Library/Core \ + && ln -s /opt/library-core/liblibrary-core.so.0 /opt/conda/lib/python3.6/site-packages/Library/Core/liblibrary-core.so.0 \ + && ln -s /opt/library-core/LibraryCorePy.so /opt/conda/lib/python3.6/site-packages/Library/Core/LibraryCorePy.so \ + && echo 'from .LibraryCorePy import *' > /opt/conda/lib/python3.6/site-packages/Library/Core/__init__.py \ + && mkdir -p /opt/conda/lib/python3.6/site-packages/Library/Mathematics \ + && ln -s /opt/lib/liblibrary-mathematics.so.0 /opt/conda/lib/python3.6/site-packages/Library/Mathematics/liblibrary-mathematics.so.0 \ + && ln -s /opt/lib/LibraryMathematicsPy.so /opt/conda/lib/python3.6/site-packages/Library/Mathematics/LibraryMathematicsPy.so \ + && echo 'from .LibraryMathematicsPy import *' > /opt/conda/lib/python3.6/site-packages/Library/Mathematics/__init__.py \ + && /bin/bash" + +else + + docker run \ + --name="${container_name}-python-debug" \ + -it \ + --rm \ + --privileged \ + --user="" \ + --env="LD_LIBRARY_PATH=/usr/local/lib:/opt/conda/lib/python3.6/site-packages:/home/jovyan/lib" \ + --env="PYTHONPATH=/opt/conda/lib/python3.6/site-packages:/home/jovyan/lib" \ + --volume="$(pwd)/../../lib:/opt/lib:ro" \ + --volume="$(pwd)/../../share/python/notebooks:/home/jovyan/notebooks" \ + --volume="$(pwd)/helpers:/home/jovyan/notebooks/helpers:ro" \ + --volume="$(pwd)/../../share/data:/app/share/data" \ + --workdir="/home/jovyan/notebooks" \ + "${repository_name}/${project_name}-python-debug" \ + bash -c "mkdir -p /opt/conda/lib/python3.6/site-packages/Library/Mathematics \ + && ln -s /opt/lib/liblibrary-mathematics.so.0 /opt/conda/lib/python3.6/site-packages/Library/Mathematics/liblibrary-mathematics.so.0 \ + && ln -s /opt/lib/LibraryMathematicsPy.so /opt/conda/lib/python3.6/site-packages/Library/Mathematics/LibraryMathematicsPy.so \ + && echo 'from .LibraryMathematicsPy import *' > /opt/conda/lib/python3.6/site-packages/Library/Mathematics/__init__.py \ + && /bin/bash" + +fi + +popd > /dev/null + +################################################################################################################################################################ \ No newline at end of file diff --git a/tools/python/docker/Dockerfile.debug b/tools/python/docker/Dockerfile.debug new file mode 100644 index 00000000..59c21f0f --- /dev/null +++ b/tools/python/docker/Dockerfile.debug @@ -0,0 +1,26 @@ +################################################################################################################################################################ + +# @project Library/Mathematics +# @file tools/python/docker/Dockerfile.debug +# @author Lucas Brémond +# @license TBD + +################################################################################################################################################################ + +ARG repository_name +ARG project_name + +FROM ${repository_name}/${project_name}-python:latest + +LABEL maintainer="lucas@loftorbital.com" + +USER root + +RUN apt-get update \ + && apt-get install -y gdb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +USER $NB_UID + +################################################################################################################################################################ \ No newline at end of file diff --git a/tools/python/docker/build.sh b/tools/python/docker/build.sh index c71ada93..c693e491 100755 --- a/tools/python/docker/build.sh +++ b/tools/python/docker/build.sh @@ -19,6 +19,13 @@ docker build \ --tag="${repository_name}/${project_name}-python" \ . +docker build \ +--tag="${repository_name}/${project_name}-python-debug" \ +--file="Dockerfile.debug" \ +--build-arg="repository_name=${repository_name}" \ +--build-arg="project_name=${project_name}" \ +. + popd > /dev/null ################################################################################################################################################################ \ No newline at end of file diff --git a/tools/python/helpers/debug.sh b/tools/python/helpers/debug.sh new file mode 100755 index 00000000..b4c90fbe --- /dev/null +++ b/tools/python/helpers/debug.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +################################################################################################################################################################ + +# @project Library/Mathematics +# @file tools/python/helpers/debug.sh +# @author Lucas Brémond +# @license TBD + +################################################################################################################################################################ + +script_directory="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +pushd "${script_directory}" > /dev/null + +gdb `which python` + +# gdb `which python` --args /home/jovyan/notebooks/A.py + +# set args /home/jovyan/notebooks/A.py + +popd > /dev/null + +################################################################################################################################################################ \ No newline at end of file diff --git a/tools/python/helpers/install.sh b/tools/python/helpers/install.sh new file mode 100755 index 00000000..da98a8dd --- /dev/null +++ b/tools/python/helpers/install.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +################################################################################################################################################################ + +# @project Library/Mathematics +# @file tools/python/helpers/install.sh +# @author Lucas Brémond +# @license TBD + +################################################################################################################################################################ + +script_directory="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +pushd "${script_directory}" > /dev/null + +pip install numpy --upgrade + +popd > /dev/null + +################################################################################################################################################################ \ No newline at end of file From 821b9b38653a85472050ce187a2ea2da0f97ce75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Mon, 10 Sep 2018 17:00:15 -0700 Subject: [PATCH 4/5] [feature] Add Composite 3D geometry, update Intersection --- .../Mathematics/Geometry/3D/Intersection.hpp | 72 +- .../Mathematics/Geometry/3D/Object.hpp | 33 +- .../Geometry/3D/Objects/Composite.hpp | 298 +++++ .../Geometry/3D/Intersection.cpp | 21 +- .../Geometry/3D/Object.cpp | 34 + .../Geometry/3D/Objects/Composite.cpp | 89 ++ .../Geometry/2D/Objects/LineString.cpp | 2 +- .../Mathematics/Geometry/3D/Intersection.cpp | 151 ++- .../Mathematics/Geometry/3D/Object.cpp | 93 +- .../Geometry/3D/Objects/Composite.cpp | 428 +++++++ .../Geometry/3D/Objects/LineString.cpp | 2 +- .../Geometry/3D/Objects/Polygon.cpp | 4 +- .../Geometry/3D/Objects/Pyramid.cpp | 8 +- .../Geometry/3D/Objects/Composite.test.cpp | 1040 +++++++++++++++++ .../Geometry/3D/Objects/Ellipsoid.test.cpp | 96 +- .../Geometry/3D/Objects/Pyramid.test.cpp | 4 +- tools/.env | 2 +- tools/development/docker/Dockerfile | 6 +- 18 files changed, 2206 insertions(+), 177 deletions(-) create mode 100755 include/Library/Mathematics/Geometry/3D/Objects/Composite.hpp create mode 100755 share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Composite.cpp create mode 100644 src/Library/Mathematics/Geometry/3D/Objects/Composite.cpp create mode 100644 test/Library/Mathematics/Geometry/3D/Objects/Composite.test.cpp diff --git a/include/Library/Mathematics/Geometry/3D/Intersection.hpp b/include/Library/Mathematics/Geometry/3D/Intersection.hpp index c71daa87..f3d81f21 100755 --- a/include/Library/Mathematics/Geometry/3D/Intersection.hpp +++ b/include/Library/Mathematics/Geometry/3D/Intersection.hpp @@ -12,19 +12,26 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include #include +#include #include #include +#include +#include #include #include -#include #include #include #include #include #include +#include +#include #include +#include //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -40,9 +47,12 @@ namespace d3 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// using library::core::types::Unique ; +using library::core::types::Index ; +using library::core::types::Size ; using library::core::ctnr::Array ; using library::math::geom::d3::Object ; +using library::math::geom::d3::objects::Composite ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -61,12 +71,15 @@ class Intersection Point, PointSet, Line, - LineString, Ray, Segment, + LineString, + Polygon, Plane, + Cuboid, Sphere, Ellipsoid, + Pyramid, Complex } ; @@ -75,7 +88,7 @@ class Intersection /// /// @param [in] anObjectArray An array of objects - Intersection ( const Array>& anObjectArray ) ; + Intersection ( Array>&& anObjectArray ) ; /// @brief Copy constructor /// @@ -117,6 +130,15 @@ class Intersection Intersection operator + ( const Intersection& anIntersection ) const ; + /// @brief Addition assignment operator (intersection concatenation) + /// + /// Concatenate (merge) intersection with another intersection. + /// + /// @param [in] anIntersection An intersection + /// @return Reference to concatenated intersection + + Intersection& operator += ( const Intersection& anIntersection ) ; + /// @brief Output stream operator /// /// @code @@ -142,45 +164,25 @@ class Intersection bool isEmpty ( ) const ; - /// @brief Returns true if intersection can be converted to underlying object + /// @brief Check if intersection is complex /// - /// @return True if intersection can be converted to underlying object - - template - bool is ( ) const - { - return (!objects_.isEmpty()) && (dynamic_cast(objects_.accessFirst().get()) != nullptr) ; - } - - /// @brief Get intersection type + /// A complex intersection contains more than one object. /// - /// @return Intersection type + /// @return True if intersection is complex - Intersection::Type getType ( ) const ; + bool isComplex ( ) const ; - /// @brief Access intersection as its underlying object + /// @brief Access composite object /// - /// @return Reference to underlying object - - template - const Type& as ( ) const - { + /// @return Reference to composite object - if (objects_.isEmpty()) - { - throw library::core::error::RuntimeError("Cannot convert intersection: it is empty.") ; - } + const Composite& accessComposite ( ) const ; - const Type* objectPtr = dynamic_cast(objects_.accessFirst().get()) ; - - if (objectPtr == nullptr) - { - throw library::core::error::RuntimeError("Cannot convert intersection: wrong type.") ; - } - - return *objectPtr ; + /// @brief Get intersection type + /// + /// @return Intersection type - } + Intersection::Type getType ( ) const ; /// @brief Constructs an undefined intersection /// @@ -242,7 +244,7 @@ class Intersection Intersection::Type type_ ; - Array> objects_ ; + Composite composite_ ; Intersection ( ) ; diff --git a/include/Library/Mathematics/Geometry/3D/Object.hpp b/include/Library/Mathematics/Geometry/3D/Object.hpp index c3f30cf6..c316f444 100755 --- a/include/Library/Mathematics/Geometry/3D/Object.hpp +++ b/include/Library/Mathematics/Geometry/3D/Object.hpp @@ -15,6 +15,8 @@ #include #include +#include + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// namespace library @@ -45,7 +47,7 @@ class Object public: - /// @brief Default constructor + /// @brief Default constructor (default) Object ( ) = default ; @@ -88,6 +90,16 @@ class Object virtual bool isDefined ( ) const = 0 ; + /// @brief Returns true if object can be converted to type + /// + /// @return True if object can be converted to type + + template + bool is ( ) const + { + return dynamic_cast(this) != nullptr ; + } + /// @brief Check if object intersects another object /// /// @code @@ -114,6 +126,25 @@ class Object virtual bool contains ( const Object& anObject ) const ; + /// @brief Access object as its underlying type + /// + /// @return Reference to underlying type + + template + const Type& as ( ) const + { + + const Type* objectPtr = dynamic_cast(this) ; + + if (objectPtr == nullptr) + { + throw library::core::error::RuntimeError("Cannot convert object to underlying type.") ; + } + + return *objectPtr ; + + } + /// @brief Compute intersection of object with another object /// /// @code diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Composite.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Composite.hpp new file mode 100755 index 00000000..77e4d53d --- /dev/null +++ b/include/Library/Mathematics/Geometry/3D/Objects/Composite.hpp @@ -0,0 +1,298 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Composite.hpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __Library_Mathematics_Geometry_3D_Objects_Composite__ +#define __Library_Mathematics_Geometry_3D_Objects_Composite__ + +#include + +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using library::core::types::Unique ; +using library::core::types::Index ; +using library::core::types::Size ; +using library::core::ctnr::Array ; + +using library::math::geom::d3::Object ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @brief Composite object + +class Composite : public Object +{ + + public: + + typedef Array>::ConstIterator ConstIterator ; + + /// @brief Constructor + /// + /// @param [in] anObject An object + + explicit Composite ( const Object& anObject ) ; + + /// @brief Constructor + /// + /// @param [in] anObjectUPtr A unique pointer to object + + explicit Composite ( const Unique& anObjectUPtr ) ; + + /// @brief Constructor + /// + /// @param [in] anObjectArray An array of unique pointers to object + + explicit Composite ( Array>&& anObjectArray ) ; + + /// @brief Copy constructor + /// + /// @param [in] aComposite A composite + + Composite ( const Composite& aComposite ) ; + + /// @brief Clone composite + /// + /// @return Pointer to cloned composite + + virtual Composite* clone ( ) const override ; + + /// @brief Copy assignment operator + /// + /// @param [in] aComposite A composite + /// @return Reference to composite + + Composite& operator = ( const Composite& aComposite ) ; + + /// @brief Equal to operator + /// + /// @param [in] aComposite A composite object + /// @return True if composites are equal + + bool operator == ( const Composite& aComposite ) const ; + + /// @brief Not equal to operator + /// + /// @param [in] aComposite A composite object + /// @return True if composites not are equal + + bool operator != ( const Composite& aComposite ) const ; + + /// @brief Addition operator (composite concatenation) + /// + /// Concatenate (merge) composite with another composite. + /// + /// @param [in] aComposite A composite + /// @return Concatenated composite + + Composite operator + ( const Composite& aComposite ) const ; + + /// @brief Addition assignment operator (composite concatenation) + /// + /// Concatenate (merge) composite with another composite. + /// + /// @param [in] aComposite A composite + /// @return Reference to concatenated composite + + Composite& operator += ( const Composite& aComposite ) ; + + /// @brief Check if composite is defined + /// + /// @code + /// Composite(...).isDefined() ; + /// @endcode + /// + /// @return True if composite is defined + + virtual bool isDefined ( ) const override ; + + /// @brief Returns true if composite can be converted to underlying object + /// + /// Only valid if the composite only contains one object. + /// + /// @return True if composite can be converted to underlying object + + template + bool is ( ) const + { + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + return (objects_.getSize() == 1) && (dynamic_cast(objects_.accessFirst().get()) != nullptr) ; + + } + + /// @brief Access composite as its underlying object + /// + /// Only valid if the composite only contains one object. + /// + /// @return Reference to underlying object + + template + const Type& as ( ) const + { + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + if (objects_.getSize() != 1) + { + throw library::core::error::RuntimeError("Cannot convert composite: it is complex.") ; + } + + const Type* objectPtr = dynamic_cast(objects_.accessFirst().get()) ; + + if (objectPtr == nullptr) + { + throw library::core::error::RuntimeError("Cannot convert composite: wrong type.") ; + } + + return *objectPtr ; + + } + + /// @brief Check if composite intersects object + /// + /// @param [in] anObject An object + /// @return True if composite intersects object + + bool intersects ( const Object& anObject ) const ; + + /// @brief Check if composite intersects composite + /// + /// @param [in] aComposite A composite + /// @return True if composite intersects composite + + bool intersects ( const Composite& aComposite ) const ; + + /// @brief Check if composite contains object + /// + /// @param [in] anObject An object + /// @return True if composite contains object + + bool contains ( const Object& anObject ) const ; + + /// @brief Check if composite contains composite + /// + /// @param [in] aComposite A composite + /// @return True if composite contains composite + + bool contains ( const Composite& aComposite ) const ; + + /// @brief Access object at index + /// + /// @param [in] anIndex An object index + /// @return Reference to object + + const Object& accessObjectAt ( const Index& anIndex ) const ; + + /// @brief Access objects in composite + /// + /// @return Reference to objects in composite + + const Array>& accessObjects ( ) const ; + + /// @brief Get number of objects in composite + /// + /// @return Number of objects in composite + + Size getObjectCount ( ) const ; + + /// @brief Compute intersection of composite with object + /// + /// @param [in] anObject An object + /// @return Intersection of composite with object + + Intersection intersectionWith ( const Object& anObject ) const ; + + /// @brief Compute intersection of composite with composite + /// + /// @param [in] aComposite A composite + /// @return Intersection of composite with composite + + Intersection intersectionWith ( const Composite& aComposite ) const ; + + /// @brief Get const iterator to begin + /// + /// @return Const iterator to begin + + Composite::ConstIterator begin ( ) const ; + + /// @brief Get const iterator to end + /// + /// @return Const iterator to end + + Composite::ConstIterator end ( ) const ; + + /// @brief Print composite + /// + /// @param [in] anOutputStream An output stream + /// @param [in] (optional) displayDecorators If true, display decorators + + virtual void print ( std::ostream& anOutputStream, + bool displayDecorators = true ) const override ; + + /// @brief Apply transformation to composite + /// + /// @param [in] aTransformation A transformation + + virtual void applyTransformation ( const Transformation& aTransformation ) override ; + + /// @brief Constructs an undefined composite + /// + /// @code + /// Composite composite = Composite::Undefined() ; // Undefined + /// @endcode + /// + /// @return Undefined composite + + static Composite Undefined ( ) ; + + private: + + Array> objects_ ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Intersection.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Intersection.cpp index 55c96157..f3d69eb5 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Intersection.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Intersection.cpp @@ -25,6 +25,8 @@ inline void LibraryMathematicsPy_Geometry_3D_Intersection ( using library::math::geom::d3::objects::Line ; using library::math::geom::d3::objects::Ray ; using library::math::geom::d3::objects::Segment ; + using library::math::geom::d3::objects::LineString ; + using library::math::geom::d3::objects::Polygon ; using library::math::geom::d3::objects::Plane ; using library::math::geom::d3::objects::Sphere ; using library::math::geom::d3::objects::Ellipsoid ; @@ -42,26 +44,11 @@ inline void LibraryMathematicsPy_Geometry_3D_Intersection ( .def("isDefined", &Intersection::isDefined) .def("isEmpty", &Intersection::isEmpty) + .def("isComplex", &Intersection::isComplex) - .def("isPoint", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) - .def("isPointSet", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) - .def("isLine", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) - .def("isRay", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) - .def("isSegment", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) - .def("isPlane", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) - .def("isSphere", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) - .def("isEllipsoid", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("accessComposite", &Intersection::accessComposite, return_value_policy()) .def("getType", &Intersection::getType) - - .def("asPoint", +[] (const Intersection& anIntersection) -> Point { return anIntersection.as() ; }) - .def("asPointSet", +[] (const Intersection& anIntersection) -> PointSet { return anIntersection.as() ; }) - .def("asLine", +[] (const Intersection& anIntersection) -> Line { return anIntersection.as() ; }) - .def("asRay", +[] (const Intersection& anIntersection) -> Ray { return anIntersection.as() ; }) - .def("asSegment", +[] (const Intersection& anIntersection) -> Segment { return anIntersection.as() ; }) - .def("asPlane", +[] (const Intersection& anIntersection) -> Plane { return anIntersection.as() ; }) - .def("asSphere", +[] (const Intersection& anIntersection) -> Sphere { return anIntersection.as() ; }) - .def("asEllipsoid", +[] (const Intersection& anIntersection) -> Ellipsoid { return anIntersection.as() ; }) .def("Undefined", &Intersection::Undefined).staticmethod("Undefined") .def("Empty", &Intersection::Empty).staticmethod("Empty") diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Object.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Object.cpp index 445d645d..d08c2453 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Object.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Object.cpp @@ -17,6 +17,17 @@ inline void LibraryMathematicsPy_Geometry_3D_Object ( ) using namespace boost::python ; using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::PointSet ; + using library::math::geom::d3::objects::Line ; + using library::math::geom::d3::objects::Ray ; + using library::math::geom::d3::objects::Segment ; + using library::math::geom::d3::objects::LineString ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::Sphere ; + using library::math::geom::d3::objects::Ellipsoid ; + using library::math::geom::d3::objects::Pyramid ; scope in_Object = class_("Object", no_init) @@ -27,9 +38,32 @@ inline void LibraryMathematicsPy_Geometry_3D_Object ( ) .def(self_ns::repr(self_ns::self)) .def("isDefined", &Object::isDefined) + .def("isPoint", +[] (const Object& anObject) -> bool { return anObject.is() ; }) + .def("isPointSet", +[] (const Object& anObject) -> bool { return anObject.is() ; }) + .def("isLine", +[] (const Object& anObject) -> bool { return anObject.is() ; }) + .def("isRay", +[] (const Object& anObject) -> bool { return anObject.is() ; }) + .def("isSegment", +[] (const Object& anObject) -> bool { return anObject.is() ; }) + .def("isLineString", +[] (const Object& anObject) -> bool { return anObject.is() ; }) + .def("isPolygon", +[] (const Object& anObject) -> bool { return anObject.is() ; }) + .def("isPlane", +[] (const Object& anObject) -> bool { return anObject.is() ; }) + .def("isSphere", +[] (const Object& anObject) -> bool { return anObject.is() ; }) + .def("isEllipsoid", +[] (const Object& anObject) -> bool { return anObject.is() ; }) + .def("isPyramid", +[] (const Object& anObject) -> bool { return anObject.is() ; }) .def("intersects", &Object::intersects) .def("contains", &Object::contains) + .def("asPoint", +[] (const Object& anObject) -> Point { return anObject.as() ; }) + .def("asPointSet", +[] (const Object& anObject) -> PointSet { return anObject.as() ; }) + .def("asLine", +[] (const Object& anObject) -> Line { return anObject.as() ; }) + .def("asRay", +[] (const Object& anObject) -> Ray { return anObject.as() ; }) + .def("asSegment", +[] (const Object& anObject) -> Segment { return anObject.as() ; }) + .def("asLineString", +[] (const Object& anObject) -> LineString { return anObject.as() ; }) + .def("asPolygon", +[] (const Object& anObject) -> Polygon { return anObject.as() ; }) + .def("asPlane", +[] (const Object& anObject) -> Plane { return anObject.as() ; }) + .def("asSphere", +[] (const Object& anObject) -> Sphere { return anObject.as() ; }) + .def("asEllipsoid", +[] (const Object& anObject) -> Ellipsoid { return anObject.as() ; }) + .def("asPyramid", +[] (const Object& anObject) -> Pyramid { return anObject.as() ; }) + // .def("intersectionWith", &Object::intersectionWith) .def("applyTransformation", &Object::applyTransformation) diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Composite.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Composite.cpp new file mode 100755 index 00000000..7b47d069 --- /dev/null +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Composite.cpp @@ -0,0 +1,89 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file LibraryMathematicsPy/Geometry/3D/Objects/Composite.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void LibraryMathematicsPy_Geometry_3D_Objects_Composite ( ) +{ + + using namespace boost::python ; + + using library::core::types::Shared ; + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::PointSet ; + using library::math::geom::d3::objects::Line ; + using library::math::geom::d3::objects::Ray ; + using library::math::geom::d3::objects::Segment ; + using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::Sphere ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + using library::math::geom::d3::Intersection ; + using library::math::geom::d3::trf::rot::Quaternion ; + + scope in_Composite = class_, bases>("Composite", no_init) + + .def(self == self) + .def(self != self) + + .def(self_ns::str(self_ns::self)) + .def(self_ns::repr(self_ns::self)) + + .def("isDefined", &Composite::isDefined) + + .def("isPoint", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isPointSet", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isLine", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isRay", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isLineString", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isSegment", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isPolygon", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isPlane", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isSphere", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isEllipsoid", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isPyramid", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + + .def("intersects", &Composite::intersects) + .def("contains", &Composite::contains) + + .def("asPoint", +[] (const Composite& aComposite) -> Point { return aComposite.as() ; }) + .def("asPointSet", +[] (const Composite& aComposite) -> PointSet { return aComposite.as() ; }) + .def("asLine", +[] (const Composite& aComposite) -> Line { return aComposite.as() ; }) + .def("asRay", +[] (const Composite& aComposite) -> Ray { return aComposite.as() ; }) + .def("asSegment", +[] (const Composite& aComposite) -> Segment { return aComposite.as() ; }) + .def("asLineString", +[] (const Composite& aComposite) -> LineString { return aComposite.as() ; }) + .def("asPolygon", +[] (const Composite& aComposite) -> Polygon { return aComposite.as() ; }) + .def("asPlane", +[] (const Composite& aComposite) -> Plane { return aComposite.as() ; }) + .def("asSphere", +[] (const Composite& aComposite) -> Sphere { return aComposite.as() ; }) + .def("asEllipsoid", +[] (const Composite& aComposite) -> Ellipsoid { return aComposite.as() ; }) + .def("asPyramid", +[] (const Composite& aComposite) -> Pyramid { return aComposite.as() ; }) + + .def("accessObjectAt", &Composite::accessObjectAt, return_value_policy()) + .def("accessObjects", &Composite::accessObjects, return_value_policy()) + .def("getObjectCount", &Composite::getObjectCount) + + .def("applyTransformation", &Composite::applyTransformation) + + .def("Undefined", &Composite::Undefined).staticmethod("Undefined") + + ; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/Library/Mathematics/Geometry/2D/Objects/LineString.cpp b/src/Library/Mathematics/Geometry/2D/Objects/LineString.cpp index 2ebd9aae..1cea123b 100644 --- a/src/Library/Mathematics/Geometry/2D/Objects/LineString.cpp +++ b/src/Library/Mathematics/Geometry/2D/Objects/LineString.cpp @@ -75,7 +75,7 @@ bool LineString::isNear ( return false ; } - for (auto pointTuple : library::core::ctnr::iterators::Zip(points_, aLineString.points_)) + for (const auto pointTuple : library::core::ctnr::iterators::Zip(points_, aLineString.points_)) { if (!std::get<0>(pointTuple).isNear(std::get<1>(pointTuple), aTolerance)) diff --git a/src/Library/Mathematics/Geometry/3D/Intersection.cpp b/src/Library/Mathematics/Geometry/3D/Intersection.cpp index 8af09603..fe8a6edc 100644 --- a/src/Library/Mathematics/Geometry/3D/Intersection.cpp +++ b/src/Library/Mathematics/Geometry/3D/Intersection.cpp @@ -25,24 +25,18 @@ namespace d3 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - Intersection::Intersection ( const Array>& anObjectArray ) + Intersection::Intersection ( Array>&& anObjectArray ) : type_(Intersection::TypeFromObjects(anObjectArray)), - objects_(Array>::Empty()) + composite_(std::move(anObjectArray)) { - objects_.reserve(anObjectArray.getSize()) ; - std::transform(anObjectArray.begin(), anObjectArray.end(), std::back_inserter(objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; - } Intersection::Intersection ( const Intersection& anIntersection ) : type_(anIntersection.type_), - objects_(Array>::Empty()) + composite_(anIntersection.composite_) { - objects_.reserve(anIntersection.objects_.getSize()) ; - std::transform(anIntersection.objects_.begin(), anIntersection.objects_.end(), std::back_inserter(objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; - } Intersection::~Intersection ( ) @@ -57,10 +51,7 @@ Intersection& Intersection::operator = ( { type_ = anIntersection.type_ ; - - objects_.clear() ; - objects_.reserve(anIntersection.objects_.getSize()) ; - std::transform(anIntersection.objects_.begin(), anIntersection.objects_.end(), std::back_inserter(objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; + composite_ = anIntersection.composite_ ; } @@ -76,16 +67,7 @@ bool Intersection::operator == ( return false ; } - if (type_ != anIntersection.type_) - { - return false ; - } - - // [TBI] - - throw library::core::error::runtime::ToBeImplemented("Intersection :: operator ==") ; - - return false ; + return (type_ == anIntersection.type_) && (composite_ == anIntersection.composite_) ; } @@ -97,24 +79,37 @@ bool Intersection::operator != ( Intersection Intersection::operator + ( const Intersection& anIntersection ) const { - if ((!this->isDefined()) || (!anIntersection.isDefined())) + if (!anIntersection.isDefined()) { throw library::core::error::runtime::Undefined("Intersection") ; } Intersection intersection ; - intersection.type_ = Intersection::Type::Complex ; + intersection.composite_ = composite_ + anIntersection.composite_ ; - intersection.objects_.reserve(objects_.getSize() + anIntersection.objects_.getSize()) ; + intersection.type_ = Intersection::TypeFromObjects(intersection.composite_.accessObjects()) ; - std::transform(objects_.begin(), objects_.end(), std::back_inserter(intersection.objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; - std::transform(anIntersection.objects_.begin(), anIntersection.objects_.end(), std::back_inserter(intersection.objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; - return intersection ; } +Intersection& Intersection::operator += ( const Intersection& anIntersection ) +{ + + if (!anIntersection.isDefined()) + { + throw library::core::error::runtime::Undefined("Intersection") ; + } + + composite_ += anIntersection.composite_ ; + + type_ = Intersection::TypeFromObjects(composite_.accessObjects()) ; + + return *this ; + +} + std::ostream& operator << ( std::ostream& anOutputStream, const Intersection& anIntersection ) { @@ -122,18 +117,10 @@ std::ostream& operator << ( library::core::utils::Print::Header(anOutputStream, "Intersection") ; library::core::utils::Print::Line(anOutputStream) << "Type:" << Intersection::StringFromType(anIntersection.type_) ; + + library::core::utils::Print::Line(anOutputStream) << "Composite:" ; - if (!anIntersection.objects_.isEmpty()) - { - - library::core::utils::Print::Separator(anOutputStream, "Objects") ; - - for (const auto& objectUPtr : anIntersection.objects_) - { - anOutputStream << (*objectUPtr) ; - } - - } + anIntersection.composite_.print(anOutputStream, false) ; library::core::utils::Print::Footer(anOutputStream) ; @@ -143,7 +130,7 @@ std::ostream& operator << ( bool Intersection::isDefined ( ) const { - return type_ != Intersection::Type::Undefined ; + return (type_ != Intersection::Type::Undefined) && composite_.isDefined() ; } bool Intersection::isEmpty ( ) const @@ -151,6 +138,23 @@ bool Intersection::isEmpty ( ) return type_ == Intersection::Type::Empty ; } +bool Intersection::isComplex ( ) const +{ + return type_ == Intersection::Type::Complex ; +} + +const Composite& Intersection::accessComposite ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Intersection") ; + } + + return composite_ ; + +} + Intersection::Type Intersection::getType ( ) const { @@ -176,7 +180,7 @@ Intersection Intersection::Undefined ( ) Intersection Intersection::Empty ( ) { - return Intersection(Array>::Empty()) ; + return { Array>::Empty() } ; } Intersection Intersection::Point ( const objects::Point& aPoint ) @@ -186,7 +190,7 @@ Intersection Intersection::Point ( intersection.type_ = Intersection::Type::Point ; - intersection.objects_.emplace_back(Unique(aPoint.clone())) ; + intersection.composite_ = Composite { aPoint } ; return intersection ; @@ -199,7 +203,7 @@ Intersection Intersection::PointSet ( intersection.type_ = Intersection::Type::PointSet ; - intersection.objects_.emplace_back(Unique(aPointSet.clone())) ; + intersection.composite_ = Composite { aPointSet } ; return intersection ; @@ -212,7 +216,7 @@ Intersection Intersection::LineString ( intersection.type_ = Intersection::Type::LineString ; - intersection.objects_.emplace_back(Unique(aLineString.clone())) ; + intersection.composite_ = Composite { aLineString } ; return intersection ; @@ -239,15 +243,18 @@ String Intersection::StringFromType ( case Intersection::Type::Line: return "Line" ; - case Intersection::Type::LineString: - return "LineString" ; - case Intersection::Type::Ray: return "Ray" ; case Intersection::Type::Segment: return "Segment" ; + case Intersection::Type::LineString: + return "LineString" ; + + case Intersection::Type::Polygon: + return "Polygon" ; + case Intersection::Type::Plane: return "Plane" ; @@ -257,6 +264,9 @@ String Intersection::StringFromType ( case Intersection::Type::Ellipsoid: return "Ellipsoid" ; + case Intersection::Type::Pyramid: + return "Pyramid" ; + case Intersection::Type::Complex: return "Complex" ; @@ -272,7 +282,7 @@ String Intersection::StringFromType ( Intersection::Intersection ( ) : type_(Intersection::Type::Undefined), - objects_(Array>::Empty()) + composite_(Composite::Undefined()) { } @@ -315,18 +325,46 @@ Intersection::Type Intersection::TypeFromObject ( return Intersection::Type::Point ; } - // if (dynamic_cast(anObjectUPtr.get())) - // { - // return Intersection::Type::PointSet ; - // } + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::PointSet ; + } - // [TBI] + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::Line ; + } + + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::Ray ; + } if (dynamic_cast(anObjectUPtr.get())) { return Intersection::Type::Segment ; } + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::LineString ; + } + + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::Polygon ; + } + + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::Plane ; + } + + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::Cuboid ; + } + if (dynamic_cast(anObjectUPtr.get())) { return Intersection::Type::Sphere ; @@ -337,6 +375,11 @@ Intersection::Type Intersection::TypeFromObject ( return Intersection::Type::Ellipsoid ; } + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::Pyramid ; + } + return Intersection::Type::Undefined ; } diff --git a/src/Library/Mathematics/Geometry/3D/Object.cpp b/src/Library/Mathematics/Geometry/3D/Object.cpp index e829e907..1ea0983e 100644 --- a/src/Library/Mathematics/Geometry/3D/Object.cpp +++ b/src/Library/Mathematics/Geometry/3D/Object.cpp @@ -8,14 +8,18 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include -#include +#include #include +#include +#include #include #include #include +#include #include #include @@ -44,14 +48,18 @@ bool Object::operator == ( { using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::PointSet ; using library::math::geom::d3::objects::Line ; using library::math::geom::d3::objects::Ray ; using library::math::geom::d3::objects::Segment ; - using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::LineString ; using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::Cuboid ; using library::math::geom::d3::objects::Sphere ; using library::math::geom::d3::objects::Ellipsoid ; using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; if ((!this->isDefined()) || (!anObject.isDefined())) { @@ -75,6 +83,18 @@ bool Object::operator == ( } + // PointSet + + if (const PointSet* objectPtr = dynamic_cast(this)) + { + + if (const PointSet* otherObjectPtr = dynamic_cast(&anObject)) + { + return (*objectPtr) == (*otherObjectPtr) ; + } + + } + // Line if (const Line* objectPtr = dynamic_cast(this)) @@ -111,12 +131,12 @@ bool Object::operator == ( } - // Plane + // LineString - if (const Plane* objectPtr = dynamic_cast(this)) + if (const LineString* objectPtr = dynamic_cast(this)) { - if (const Plane* otherObjectPtr = dynamic_cast(&anObject)) + if (const LineString* otherObjectPtr = dynamic_cast(&anObject)) { return (*objectPtr) == (*otherObjectPtr) ; } @@ -135,6 +155,30 @@ bool Object::operator == ( } + // Plane + + if (const Plane* objectPtr = dynamic_cast(this)) + { + + if (const Plane* otherObjectPtr = dynamic_cast(&anObject)) + { + return (*objectPtr) == (*otherObjectPtr) ; + } + + } + + // Cuboid + + if (const Cuboid* objectPtr = dynamic_cast(this)) + { + + if (const Cuboid* otherObjectPtr = dynamic_cast(&anObject)) + { + return (*objectPtr) == (*otherObjectPtr) ; + } + + } + // Sphere if (const Sphere* objectPtr = dynamic_cast(this)) @@ -171,6 +215,21 @@ bool Object::operator == ( } + // Composite + + if (const Composite* objectPtr = dynamic_cast(this)) + { + + if (const Composite* otherObjectPtr = dynamic_cast(&anObject)) + { + return (*objectPtr) == (*otherObjectPtr) ; + } + + } + + std::cout << (*this) << std::endl ; + std::cout << anObject << std::endl ; + throw library::core::error::runtime::ToBeImplemented("Object :: operator ==") ; return false ; @@ -196,14 +255,18 @@ bool Object::intersects ( { using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::PointSet ; using library::math::geom::d3::objects::Line ; using library::math::geom::d3::objects::Ray ; using library::math::geom::d3::objects::Segment ; - using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::LineString ; using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::Cuboid ; using library::math::geom::d3::objects::Sphere ; using library::math::geom::d3::objects::Ellipsoid ; using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; if (!anObject.isDefined()) { @@ -303,6 +366,9 @@ bool Object::intersects ( } + std::cout << (*this) << std::endl ; + std::cout << anObject << std::endl ; + throw library::core::error::runtime::ToBeImplemented("Object :: intersects") ; return false ; @@ -313,14 +379,18 @@ bool Object::contains ( { using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::PointSet ; using library::math::geom::d3::objects::Line ; using library::math::geom::d3::objects::Ray ; using library::math::geom::d3::objects::Segment ; - using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::LineString ; using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::Cuboid ; using library::math::geom::d3::objects::Sphere ; using library::math::geom::d3::objects::Ellipsoid ; using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; if (!anObject.isDefined()) { @@ -379,14 +449,18 @@ Intersection Object::intersectionWith ( { using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::PointSet ; using library::math::geom::d3::objects::Line ; using library::math::geom::d3::objects::Ray ; using library::math::geom::d3::objects::Segment ; - using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::LineString ; using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Plane ; + using library::math::geom::d3::objects::Cuboid ; using library::math::geom::d3::objects::Sphere ; using library::math::geom::d3::objects::Ellipsoid ; using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; if (!anObject.isDefined()) { @@ -435,6 +509,9 @@ Intersection Object::intersectionWith ( } + std::cout << (*this) << std::endl ; + std::cout << anObject << std::endl ; + throw library::core::error::runtime::ToBeImplemented("Object :: intersectionWith") ; return Intersection::Undefined() ; diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Composite.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Composite.cpp new file mode 100644 index 00000000..b8235a90 --- /dev/null +++ b/src/Library/Mathematics/Geometry/3D/Objects/Composite.cpp @@ -0,0 +1,428 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Composite.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Composite::Composite ( const Object& anObject ) + : Object(), + objects_(Array>::Empty()) +{ + + objects_.emplace_back(Unique(anObject.clone())) ; + +} + + Composite::Composite ( const Unique& anObjectUPtr ) + : Object(), + objects_(Array>::Empty()) +{ + + objects_.emplace_back(Unique(anObjectUPtr->clone())) ; + +} + + Composite::Composite ( Array>&& anObjectArray ) + : Object(), + objects_(Array>::Empty()) +{ + + objects_.reserve(anObjectArray.getSize()) ; + + std::transform(anObjectArray.begin(), anObjectArray.end(), std::back_inserter(objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; + +} + + Composite::Composite ( const Composite& aComposite ) + : Object(), + objects_(Array>::Empty()) +{ + + objects_.reserve(aComposite.objects_.getSize()) ; + + std::transform(aComposite.objects_.begin(), aComposite.objects_.end(), std::back_inserter(objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; + +} + +Composite* Composite::clone ( ) const +{ + return new Composite(*this) ; +} + +Composite& Composite::operator = ( const Composite& aComposite ) +{ + + if (this != &aComposite) + { + + objects_.clear() ; + + objects_.reserve(aComposite.objects_.getSize()) ; + + std::transform(aComposite.objects_.begin(), aComposite.objects_.end(), std::back_inserter(objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; + + } + + return *this ; + +} + +bool Composite::operator == ( const Composite& aComposite ) const +{ + + if ((!this->isDefined()) || (!aComposite.isDefined())) + { + return false ; + } + + if (objects_.getSize() != aComposite.objects_.getSize()) + { + return false ; + } + + for (const auto objectTuple : library::core::ctnr::iterators::Zip(objects_, aComposite.objects_)) + { + + if ((*std::get<0>(objectTuple)) != (*std::get<1>(objectTuple))) + { + return false ; + } + + } + + return true ; + +} + +bool Composite::operator != ( const Composite& aComposite ) const +{ + return !((*this) == aComposite) ; +} + +Composite Composite::operator + ( const Composite& aComposite ) const +{ + + if (!aComposite.isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + Composite composite = Composite::Undefined() ; + + composite.objects_.reserve(objects_.getSize() + aComposite.objects_.getSize()) ; + + std::transform(objects_.begin(), objects_.end(), std::back_inserter(composite.objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; + std::transform(aComposite.objects_.begin(), aComposite.objects_.end(), std::back_inserter(composite.objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; + + return composite ; + +} + +Composite& Composite::operator += ( const Composite& aComposite ) +{ + + if (!aComposite.isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + objects_.reserve(objects_.getSize() + aComposite.objects_.getSize()) ; + + std::transform(aComposite.objects_.begin(), aComposite.objects_.end(), std::back_inserter(objects_), [] (const Unique& anObjectUPtr) -> Unique { return Unique(anObjectUPtr->clone()) ; }) ; + + return *this ; + +} + +bool Composite::isDefined ( ) const +{ + return (!objects_.isEmpty()) && std::all_of(objects_.begin(), objects_.end(), [] (const Unique& anObjectUPtr) -> bool { return anObjectUPtr->isDefined() ; }) ; ; +} + +bool Composite::intersects ( const Object& anObject ) const +{ + + if (!anObject.isDefined()) + { + throw library::core::error::runtime::Undefined("Object") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + return std::any_of(objects_.begin(), objects_.end(), [&anObject] (const Unique& anObjectUPtr) -> bool { return anObjectUPtr->intersects(anObject) ; }) ; + +} + +bool Composite::intersects ( const Composite& aComposite ) const +{ + + if (!aComposite.isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + return std::any_of(aComposite.objects_.begin(), aComposite.objects_.end(), [this] (const Unique& anObjectUPtr) -> bool { return this->intersects(*anObjectUPtr) ; }) ; + +} + +bool Composite::contains ( const Object& anObject ) const +{ + + if (!anObject.isDefined()) + { + throw library::core::error::runtime::Undefined("Object") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + return std::all_of(objects_.begin(), objects_.end(), [&anObject] (const Unique& anObjectUPtr) -> bool { return anObjectUPtr->contains(anObject) ; }) ; + +} + +bool Composite::contains ( const Composite& aComposite ) const +{ + + if (!aComposite.isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + return std::all_of(aComposite.objects_.begin(), aComposite.objects_.end(), [this] (const Unique& anObjectUPtr) -> bool { return this->contains(*anObjectUPtr) ; }) ; + +} + +const Object& Composite::accessObjectAt ( const Index& anIndex ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + if (anIndex >= objects_.getSize()) + { + throw library::core::error::RuntimeError("Object index [{}] out of bounds [{}].", anIndex, objects_.getSize()) ; + } + + return *(objects_.at(anIndex).get()) ; + +} + +const Array>& Composite::accessObjects ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + return objects_ ; + +} + +Size Composite::getObjectCount ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + return objects_.getSize() ; + +} + +Intersection Composite::intersectionWith ( const Object& anObject ) const +{ + + if (!anObject.isDefined()) + { + throw library::core::error::runtime::Undefined("Object") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + Intersection intersection = Intersection::Empty() ; + + for (const auto& objectUPtr : objects_) + { + + const Intersection objectToObjectIntersection = objectUPtr->intersectionWith(anObject) ; + + if (objectToObjectIntersection.isDefined() && (!objectToObjectIntersection.isEmpty())) + { + intersection += objectToObjectIntersection ; + } + + } + + return intersection ; + +} + +Intersection Composite::intersectionWith ( const Composite& aComposite ) const +{ + + if (!aComposite.isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + Intersection intersection = Intersection::Empty() ; + + for (const auto& objectUPtr : aComposite.objects_) + { + + const Intersection compositeToObjectIntersection = this->intersectionWith(*objectUPtr) ; + + if (compositeToObjectIntersection.isDefined() && (!compositeToObjectIntersection.isEmpty())) + { + intersection += compositeToObjectIntersection ; + } + + } + + return intersection ; + +} + +Composite::ConstIterator Composite::begin ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + return objects_.begin() ; + +} + +Composite::ConstIterator Composite::end ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + return objects_.end() ; + +} + +void Composite::print ( std::ostream& anOutputStream, + bool displayDecorators ) const +{ + + displayDecorators ? library::core::utils::Print::Header(anOutputStream, "Composite") : void () ; + + if (!objects_.isEmpty()) + { + + library::core::utils::Print::Separator(anOutputStream, "Objects") ; + + for (const auto& objectUPtr : objects_) + { + anOutputStream << (*objectUPtr) ; + } + + } + else + { + library::core::utils::Print::Line(anOutputStream) << "Empty" ; + } + + displayDecorators ? library::core::utils::Print::Footer(anOutputStream) : void () ; + +} + +void Composite::applyTransformation ( const Transformation& aTransformation ) +{ + + using library::math::geom::d3::trf::rot::RotationMatrix ; + + if (!aTransformation.isDefined()) + { + throw library::core::error::runtime::Undefined("Transformation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Composite") ; + } + + if (aTransformation.isIdentity()) + { + return ; + } + + for (auto& objectUPtr : objects_) + { + objectUPtr->applyTransformation(aTransformation) ; + } + +} + +Composite Composite::Undefined ( ) +{ + return Composite { Array>::Empty() } ; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/Library/Mathematics/Geometry/3D/Objects/LineString.cpp b/src/Library/Mathematics/Geometry/3D/Objects/LineString.cpp index 3526aaea..a6f2599f 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/LineString.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/LineString.cpp @@ -75,7 +75,7 @@ bool LineString::isNear ( return false ; } - for (auto pointTuple : library::core::ctnr::iterators::Zip(points_, aLineString.points_)) + for (const auto pointTuple : library::core::ctnr::iterators::Zip(points_, aLineString.points_)) { if (!std::get<0>(pointTuple).isNear(std::get<1>(pointTuple), aTolerance)) diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Polygon.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Polygon.cpp index 0eac597f..50368356 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Polygon.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Polygon.cpp @@ -107,8 +107,8 @@ bool Polygon::isNear ( const Array firstVertices = this->getVertices() ; const Array secondVertices = aPolygon.getVertices() ; - // for (auto vertexTuple : library::core::ctnr::iterators::Zip(this->getVertices(), aPolygon.getVertices())) - for (auto vertexTuple : library::core::ctnr::iterators::Zip(firstVertices, secondVertices)) + // for (const auto vertexTuple : library::core::ctnr::iterators::Zip(this->getVertices(), aPolygon.getVertices())) + for (const auto vertexTuple : library::core::ctnr::iterators::Zip(firstVertices, secondVertices)) { if (!std::get<0>(vertexTuple).isNear(std::get<1>(vertexTuple), aTolerance)) diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Pyramid.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Pyramid.cpp index b4c52466..e8b4e1d9 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Pyramid.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Pyramid.cpp @@ -276,14 +276,14 @@ Intersection Pyramid::intersectionWith ( if (!intersection.isEmpty()) { - if (intersection.is()) + if (intersection.accessComposite().is()) { - firstIntersectionPoints.add(intersection.as()) ; + firstIntersectionPoints.add(intersection.accessComposite().as()) ; } - else if (intersection.is()) + else if (intersection.accessComposite().is()) { - const PointSet& pointSet = intersection.as() ; + const PointSet& pointSet = intersection.accessComposite().as() ; bool secondIntersectionPointAdded = false ; diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Composite.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Composite.test.cpp new file mode 100644 index 00000000..ed65a75a --- /dev/null +++ b/test/Library/Mathematics/Geometry/3D/Objects/Composite.test.cpp @@ -0,0 +1,1040 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Composite.test.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, Constructor) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + EXPECT_NO_THROW(Composite composite(pyramid) ;) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Unique pyramidUPtr = std::make_unique(base, apex) ; + + EXPECT_NO_THROW(Composite composite(pyramidUPtr) ;) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + Unique pyramidUPtr = std::make_unique(base, apex) ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + Unique cuboidUPtr = std::make_unique(center, axes, extent) ; + + Array> objects = Array>::Empty() ; + + objects.emplace_back(std::move(pyramidUPtr)) ; + objects.emplace_back(std::move(cuboidUPtr)) ; + + EXPECT_NO_THROW(Composite composite(std::move(objects)) ;) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, Clone) +{ + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + EXPECT_NO_THROW(Composite(pyramid).clone() ;) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, CopyConstructor) +{ + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_NO_THROW(Composite otherComposite(composite) ;) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, EqualToOperator) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_TRUE(composite == composite) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + Unique pyramidUPtr = std::make_unique(base, apex) ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + Unique cuboidUPtr = std::make_unique(center, axes, extent) ; + + Array> objects = Array>::Empty() ; + + objects.emplace_back(std::move(pyramidUPtr)) ; + objects.emplace_back(std::move(cuboidUPtr)) ; + + const Composite composite = Composite { std::move(objects) } ; + + EXPECT_TRUE(composite == composite) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite firstComposite = Composite { pyramid } ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + const Composite secondComposite = Composite { cuboid } ; + + EXPECT_FALSE(firstComposite == secondComposite) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Unique pyramidUPtr = std::make_unique(base, apex) ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Unique cuboidUPtr = std::make_unique(center, axes, extent) ; + + Array> firstObjects = Array>::Empty() ; + + firstObjects.emplace_back(std::move(pyramidUPtr->clone())) ; + firstObjects.emplace_back(std::move(cuboidUPtr->clone())) ; + + const Composite firstComposite = Composite { std::move(firstObjects) } ; + + Array> secondObjects = Array>::Empty() ; + + secondObjects.emplace_back(std::move(cuboidUPtr->clone())) ; + secondObjects.emplace_back(std::move(pyramidUPtr->clone())) ; + + const Composite secondComposite = Composite { std::move(secondObjects) } ; + + EXPECT_FALSE(firstComposite == secondComposite) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_FALSE(Composite::Undefined() == Composite::Undefined()) ; + EXPECT_FALSE(Composite::Undefined() == composite) ; + EXPECT_FALSE(composite == Composite::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, NotEqualToOperator) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_FALSE(composite != composite) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + Unique pyramidUPtr = std::make_unique(base, apex) ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + Unique cuboidUPtr = std::make_unique(center, axes, extent) ; + + Array> objects = Array>::Empty() ; + + objects.emplace_back(std::move(pyramidUPtr)) ; + objects.emplace_back(std::move(cuboidUPtr)) ; + + const Composite composite = Composite { std::move(objects) } ; + + EXPECT_FALSE(composite != composite) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite firstComposite = Composite { pyramid } ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Cuboid cuboid = { center, axes, extent } ; + + const Composite secondComposite = Composite { cuboid } ; + + EXPECT_TRUE(firstComposite != secondComposite) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Unique pyramidUPtr = std::make_unique(base, apex) ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + const Unique cuboidUPtr = std::make_unique(center, axes, extent) ; + + Array> firstObjects = Array>::Empty() ; + + firstObjects.emplace_back(std::move(pyramidUPtr->clone())) ; + firstObjects.emplace_back(std::move(cuboidUPtr->clone())) ; + + const Composite firstComposite = Composite { std::move(firstObjects) } ; + + Array> secondObjects = Array>::Empty() ; + + secondObjects.emplace_back(std::move(cuboidUPtr->clone())) ; + secondObjects.emplace_back(std::move(pyramidUPtr->clone())) ; + + const Composite secondComposite = Composite { std::move(secondObjects) } ; + + EXPECT_TRUE(firstComposite != secondComposite) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_TRUE(Composite::Undefined() != Composite::Undefined()) ; + EXPECT_TRUE(Composite::Undefined() != composite) ; + EXPECT_TRUE(composite != Composite::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, AdditionOperator) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_NO_THROW(composite + composite) ; + + } + + { + + EXPECT_ANY_THROW(Composite::Undefined() + Composite::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, AdditionAssignmentOperator) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + Composite composite = Composite { pyramid } ; + + EXPECT_NO_THROW(composite += composite) ; + + } + + { + + Composite firstComposite = Composite::Undefined() ; + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_NO_THROW(firstComposite += composite) ; + + } + + { + + Composite composite = Composite::Undefined() ; + + EXPECT_ANY_THROW(composite += Composite::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, StreamOperator) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + testing::internal::CaptureStdout() ; + + EXPECT_NO_THROW(std::cout << composite << std::endl) ; + + EXPECT_FALSE(testing::internal::GetCapturedStdout().empty()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, IsDefined) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_TRUE(composite.isDefined()) ; + + } + + { + + EXPECT_FALSE(Composite::Undefined().isDefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, Intersects) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + // [TBI] + + // { + + // const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + // const Point apex = { 0.0, 0.0, 1.0 } ; + + // const Pyramid pyramid = { base, apex } ; + + // const Composite composite = Composite { pyramid } ; + + // EXPECT_TRUE(composite.intersects(composite)) ; + + // } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_ANY_THROW(Composite::Undefined().intersects(Composite::Undefined())) ; + EXPECT_ANY_THROW(Composite::Undefined().intersects(composite)) ; + EXPECT_ANY_THROW(composite.intersects(Composite::Undefined())) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, Contains) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + // [TBI] + + // { + + // const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + // const Point apex = { 0.0, 0.0, 1.0 } ; + + // const Pyramid pyramid = { base, apex } ; + + // const Composite composite = Composite { pyramid } ; + + // EXPECT_TRUE(composite.contains(composite)) ; + + // } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_ANY_THROW(Composite::Undefined().contains(Composite::Undefined())) ; + EXPECT_ANY_THROW(Composite::Undefined().contains(composite)) ; + EXPECT_ANY_THROW(composite.contains(Composite::Undefined())) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, Is) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_TRUE(composite.is()) ; + + EXPECT_FALSE(composite.is()) ; + + } + + { + + EXPECT_ANY_THROW(Composite::Undefined().is()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, As) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_EQ(pyramid, composite.as()) ; + + EXPECT_ANY_THROW(composite.as()) ; + + } + + { + + EXPECT_ANY_THROW(Composite::Undefined().as()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, AccessObjectAt) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_TRUE(composite.accessObjectAt(0).is()) ; + + EXPECT_ANY_THROW(composite.accessObjectAt(1)) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + Unique pyramidUPtr = std::make_unique(base, apex) ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + Unique cuboidUPtr = std::make_unique(center, axes, extent) ; + + Array> objects = Array>::Empty() ; + + objects.emplace_back(std::move(pyramidUPtr)) ; + objects.emplace_back(std::move(cuboidUPtr)) ; + + const Composite composite = Composite { std::move(objects) } ; + + EXPECT_TRUE(composite.accessObjectAt(0).is()) ; + EXPECT_TRUE(composite.accessObjectAt(1).is()) ; + + EXPECT_ANY_THROW(composite.accessObjectAt(2)) ; + + } + + { + + EXPECT_ANY_THROW(Composite::Undefined().accessObjectAt(0)) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, AccessObjects) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_EQ(1, composite.accessObjects().getSize()) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + Unique pyramidUPtr = std::make_unique(base, apex) ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + Unique cuboidUPtr = std::make_unique(center, axes, extent) ; + + Array> objects = Array>::Empty() ; + + objects.emplace_back(std::move(pyramidUPtr)) ; + objects.emplace_back(std::move(cuboidUPtr)) ; + + const Composite composite = Composite { std::move(objects) } ; + + EXPECT_EQ(2, composite.accessObjects().getSize()) ; + + } + + { + + EXPECT_ANY_THROW(Composite::Undefined().accessObjects()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, GetObjectCount) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_EQ(1, composite.getObjectCount()) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + Unique pyramidUPtr = std::make_unique(base, apex) ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + Unique cuboidUPtr = std::make_unique(center, axes, extent) ; + + Array> objects = Array>::Empty() ; + + objects.emplace_back(std::move(pyramidUPtr)) ; + objects.emplace_back(std::move(cuboidUPtr)) ; + + const Composite composite = Composite { std::move(objects) } ; + + EXPECT_EQ(2, composite.getObjectCount()) ; + + } + + { + + EXPECT_ANY_THROW(Composite::Undefined().getObjectCount()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, ConstIterator) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + const Composite composite = Composite { pyramid } ; + + EXPECT_NO_THROW + ( + + for (const auto& objectUPtr : composite) + { + EXPECT_TRUE(objectUPtr->isDefined()) ; + } + + ) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + Unique pyramidUPtr = std::make_unique(base, apex) ; + + const Point center = { 0.0, 0.0, 0.0 } ; + const std::array axes = { Vector3d { 1.0, 0.0, 0.0 }, Vector3d { 0.0, 1.0, 0.0 }, Vector3d { 0.0, 0.0, 1.0 } } ; + const std::array extent = { 1.0, 2.0, 3.0 } ; + + Unique cuboidUPtr = std::make_unique(center, axes, extent) ; + + Array> objects = Array>::Empty() ; + + objects.emplace_back(std::move(pyramidUPtr)) ; + objects.emplace_back(std::move(cuboidUPtr)) ; + + const Composite composite = Composite { std::move(objects) } ; + + EXPECT_NO_THROW + ( + + for (const auto& objectUPtr : composite) + { + EXPECT_TRUE(objectUPtr->isDefined()) ; + } + + ) ; + + } + + { + + EXPECT_ANY_THROW + ( + + for (const auto& objectUPtr : Composite::Undefined()) + { + (void) objectUPtr ; + } + + ) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, ApplyTransformation) +{ + + using library::core::types::Unique ; + using library::core::types::Real ; + using library::core::ctnr::Array ; + + using library::math::obj::Vector3d ; + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Polygon ; + using library::math::geom::d3::objects::Cuboid ; + using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; + using library::math::geom::d3::Transformation ; + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + Composite composite = Composite { pyramid } ; + + EXPECT_NO_THROW(composite.applyTransformation(Transformation::Identity())) ; + + } + + { + + const Polygon base = { { { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } } }, { 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 } } ; + const Point apex = { 0.0, 0.0, 1.0 } ; + + const Pyramid pyramid = { base, apex } ; + + Composite composite = Composite { pyramid } ; + + EXPECT_ANY_THROW(composite.applyTransformation(Transformation::Undefined())) ; + EXPECT_ANY_THROW(Composite::Undefined().applyTransformation(Transformation::Undefined())) ; + EXPECT_ANY_THROW(Composite::Undefined().applyTransformation(Transformation::Identity())) ; + + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Composite, Undefined) +{ + + using library::math::geom::d3::objects::Composite ; + + { + + EXPECT_NO_THROW(Composite::Undefined()) ; + EXPECT_FALSE(Composite::Undefined().isDefined()) ; + + } + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp index a3963943..725b2178 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp @@ -1046,9 +1046,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Line) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const PointSet pointSet = intersection.as() ; + const PointSet pointSet = intersection.accessComposite().as() ; EXPECT_EQ(2, pointSet.getSize()) ; @@ -1065,9 +1065,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Line) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const PointSet pointSet = intersection.as() ; + const PointSet pointSet = intersection.accessComposite().as() ; EXPECT_EQ(2, pointSet.getSize()) ; @@ -1084,9 +1084,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Line) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const PointSet pointSet = intersection.as() ; + const PointSet pointSet = intersection.accessComposite().as() ; EXPECT_EQ(2, pointSet.getSize()) ; @@ -1103,9 +1103,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Line) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(0.0, 0.0, +3.0), Real::Epsilon())) ; @@ -1120,9 +1120,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Line) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(0.0, 0.0, -3.0), Real::Epsilon())) ; @@ -1169,9 +1169,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(1.0, 0.0, 0.0), Real::Epsilon())) ; @@ -1186,9 +1186,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const PointSet pointSet = intersection.as() ; + const PointSet pointSet = intersection.accessComposite().as() ; EXPECT_EQ(2, pointSet.getSize()) ; @@ -1205,9 +1205,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const PointSet pointSet = intersection.as() ; + const PointSet pointSet = intersection.accessComposite().as() ; EXPECT_EQ(2, pointSet.getSize()) ; @@ -1224,9 +1224,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const PointSet pointSet = intersection.as() ; + const PointSet pointSet = intersection.accessComposite().as() ; EXPECT_EQ(2, pointSet.getSize()) ; @@ -1243,9 +1243,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const PointSet pointSet = intersection.as() ; + const PointSet pointSet = intersection.accessComposite().as() ; EXPECT_EQ(2, pointSet.getSize()) ; @@ -1273,9 +1273,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(0.0, 0.0, +3.0), Real::Epsilon())) ; @@ -1290,9 +1290,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(0.0, 0.0, -3.0), Real::Epsilon())) ; @@ -1320,9 +1320,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(1.0, 0.0, 0.0), Real::Epsilon())) ; @@ -1337,9 +1337,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(0.0, 0.0, -3.0), Real::Epsilon())) ; @@ -1365,9 +1365,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(0.0, 0.0, +3.0), Real::Epsilon())) ; @@ -1382,9 +1382,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Ray) EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(0.0, 0.0, -3.0), Real::Epsilon())) ; @@ -1429,9 +1429,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Segmen EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(1.0, 0.0, 0.0), Real::Epsilon())) ; @@ -1446,9 +1446,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Segmen EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(1.0, 0.0, 0.0), Real::Epsilon())) ; @@ -1463,9 +1463,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Segmen EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(-1.0, 0.0, 0.0), Real::Epsilon())) ; @@ -1480,9 +1480,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Segmen EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(-1.0, 0.0, 0.0), Real::Epsilon())) ; @@ -1497,9 +1497,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Segmen EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const PointSet pointSet = intersection.as() ; + const PointSet pointSet = intersection.accessComposite().as() ; EXPECT_EQ(2, pointSet.getSize()) ; @@ -1516,9 +1516,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Segmen EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const PointSet pointSet = intersection.as() ; + const PointSet pointSet = intersection.accessComposite().as() ; EXPECT_EQ(2, pointSet.getSize()) ; @@ -1535,9 +1535,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Segmen EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(0.0, 0.0, +3.0), Real::Epsilon())) ; @@ -1552,9 +1552,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IntersectionWith_Segmen EXPECT_TRUE(intersection.isDefined()) ; - ASSERT_TRUE(intersection.is()) ; + ASSERT_TRUE(intersection.accessComposite().is()) ; - const Point point = intersection.as() ; + const Point point = intersection.accessComposite().as() ; EXPECT_TRUE(point.isNear(Point(0.0, 0.0, +3.0), Real::Epsilon())) ; diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Pyramid.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Pyramid.test.cpp index 5bde32f8..dd813655 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Pyramid.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Pyramid.test.cpp @@ -281,9 +281,9 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Pyramid, IntersectionWith_Ellipsoi EXPECT_TRUE(intersection.isDefined()) ; EXPECT_FALSE(intersection.isEmpty()) ; - EXPECT_TRUE(intersection.is()) ; + EXPECT_TRUE(intersection.accessComposite().is()) ; - const LineString intersectionLineString = intersection.as() ; + const LineString intersectionLineString = intersection.accessComposite().as() ; EXPECT_EQ(8, intersectionLineString.getPointCount()) ; diff --git a/tools/.env b/tools/.env index c1760be6..74b067c4 100644 --- a/tools/.env +++ b/tools/.env @@ -38,7 +38,7 @@ fi repository_name="openspacecollective" # image_version="$(echo ${version} | head -c 5)" -image_version="0.1.9" +image_version="0.1.10" image_name="${repository_name}/${project_name}:${image_version}" diff --git a/tools/development/docker/Dockerfile b/tools/development/docker/Dockerfile index 6cd8227f..ab32ce7b 100644 --- a/tools/development/docker/Dockerfile +++ b/tools/development/docker/Dockerfile @@ -61,12 +61,12 @@ RUN mkdir /tmp/geometric-tools-engine \ && rm -rf /tmp/geometric-tools-engine \ && popd > /dev/null -## Library :: Core [0.1.12] +## Library :: Core [0.1.13] RUN mkdir -p /tmp/library-core \ && pushd /tmp/library-core > /dev/null \ - && wget --quiet https://github.com/open-space-collective/library-core/releases/download/0.1.12/library-core-0.1.12-1.x86_64-runtime.rpm \ - && wget --quiet https://github.com/open-space-collective/library-core/releases/download/0.1.12/library-core-0.1.12-1.x86_64-devel.rpm \ + && wget --quiet https://github.com/open-space-collective/library-core/releases/download/0.1.13/library-core-0.1.13-1.x86_64-runtime.rpm \ + && wget --quiet https://github.com/open-space-collective/library-core/releases/download/0.1.13/library-core-0.1.13-1.x86_64-devel.rpm \ && dnf install -y ./*.rpm \ && rm -rf /tmp/library-core \ && popd > /dev/null From 0fd968b337be532655f7c9ec52210c795750e15f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Mon, 10 Sep 2018 17:27:26 -0700 Subject: [PATCH 5/5] [feature] Improve Python bindings --- .../Mathematics/Geometry/3D/Intersection.hpp | 38 +++++++++++++++++++ .../Geometry/3D/Intersection.cpp | 31 +++++++++++++++ .../Geometry/3D/Objects.cpp | 2 + .../Geometry/3D/Objects/Composite.cpp | 20 ++++++++-- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/include/Library/Mathematics/Geometry/3D/Intersection.hpp b/include/Library/Mathematics/Geometry/3D/Intersection.hpp index f3d81f21..6ac5d017 100755 --- a/include/Library/Mathematics/Geometry/3D/Intersection.hpp +++ b/include/Library/Mathematics/Geometry/3D/Intersection.hpp @@ -172,6 +172,44 @@ class Intersection bool isComplex ( ) const ; + /// @brief Returns true if intersection can be converted to underlying object + /// + /// Only valid if the intersection only contains one object. + /// + /// @return True if intersection can be converted to underlying object + + template + bool is ( ) const + { + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Intersection") ; + } + + return composite_.is() ; + + } + + /// @brief Access intersection as its underlying object + /// + /// Only valid if the intersection only contains one object. + /// + /// @return Reference to underlying object + + template + const Type& as ( ) const + { + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Intersection") ; + } + + return composite_.as() ; + + } + /// @brief Access composite object /// /// @return Reference to composite object diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Intersection.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Intersection.cpp index f3d69eb5..31d048ff 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Intersection.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Intersection.cpp @@ -30,7 +30,9 @@ inline void LibraryMathematicsPy_Geometry_3D_Intersection ( using library::math::geom::d3::objects::Plane ; using library::math::geom::d3::objects::Sphere ; using library::math::geom::d3::objects::Ellipsoid ; + using library::math::geom::d3::objects::Cuboid ; using library::math::geom::d3::objects::Pyramid ; + using library::math::geom::d3::objects::Composite ; using library::math::geom::d3::Intersection ; // scope in_Intersection = class_("Intersection", init>>()) @@ -39,6 +41,9 @@ inline void LibraryMathematicsPy_Geometry_3D_Intersection ( .def(self == self) .def(self != self) + .def(self + self) + .def(self += self) + .def(self_ns::str(self_ns::self)) .def(self_ns::repr(self_ns::self)) @@ -46,6 +51,32 @@ inline void LibraryMathematicsPy_Geometry_3D_Intersection ( .def("isEmpty", &Intersection::isEmpty) .def("isComplex", &Intersection::isComplex) + .def("isPoint", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isPointSet", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isLine", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isRay", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isSegment", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isLineString", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isPolygon", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isPlane", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isSphere", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isEllipsoid", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isPyramid", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + .def("isComposite", +[] (const Intersection& anIntersection) -> bool { return anIntersection.is() ; }) + + .def("asPoint", +[] (const Intersection& anIntersection) -> Point { return anIntersection.as() ; }) + .def("asPointSet", +[] (const Intersection& anIntersection) -> PointSet { return anIntersection.as() ; }) + .def("asLine", +[] (const Intersection& anIntersection) -> Line { return anIntersection.as() ; }) + .def("asRay", +[] (const Intersection& anIntersection) -> Ray { return anIntersection.as() ; }) + .def("asSegment", +[] (const Intersection& anIntersection) -> Segment { return anIntersection.as() ; }) + .def("asLineString", +[] (const Intersection& anIntersection) -> LineString { return anIntersection.as() ; }) + .def("asPolygon", +[] (const Intersection& anIntersection) -> Polygon { return anIntersection.as() ; }) + .def("asPlane", +[] (const Intersection& anIntersection) -> Plane { return anIntersection.as() ; }) + .def("asSphere", +[] (const Intersection& anIntersection) -> Sphere { return anIntersection.as() ; }) + .def("asEllipsoid", +[] (const Intersection& anIntersection) -> Ellipsoid { return anIntersection.as() ; }) + .def("asPyramid", +[] (const Intersection& anIntersection) -> Pyramid { return anIntersection.as() ; }) + .def("asComposite", +[] (const Intersection& anIntersection) -> Composite { return anIntersection.as() ; }) + .def("accessComposite", &Intersection::accessComposite, return_value_policy()) .def("getType", &Intersection::getType) diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects.cpp index ddc50f2b..fe8a65e1 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects.cpp @@ -7,6 +7,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include #include // #include #include @@ -45,6 +46,7 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects ( ) LibraryMathematicsPy_Geometry_3D_Objects_Sphere() ; LibraryMathematicsPy_Geometry_3D_Objects_Ellipsoid() ; LibraryMathematicsPy_Geometry_3D_Objects_Pyramid() ; + LibraryMathematicsPy_Geometry_3D_Objects_Composite() ; } diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Composite.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Composite.cpp index 7b47d069..a8acc9ff 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Composite.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Composite.cpp @@ -29,8 +29,11 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Composi using library::math::geom::d3::objects::Line ; using library::math::geom::d3::objects::Ray ; using library::math::geom::d3::objects::Segment ; + using library::math::geom::d3::objects::LineString ; + using library::math::geom::d3::objects::Polygon ; using library::math::geom::d3::objects::Plane ; using library::math::geom::d3::objects::Sphere ; + using library::math::geom::d3::objects::Ellipsoid ; using library::math::geom::d3::objects::Cuboid ; using library::math::geom::d3::objects::Pyramid ; using library::math::geom::d3::objects::Composite ; @@ -40,7 +43,10 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Composi scope in_Composite = class_, bases>("Composite", no_init) .def(self == self) - .def(self != self) + .def(self == self) + + .def(self + self) + .def(self += self) .def(self_ns::str(self_ns::self)) .def(self_ns::repr(self_ns::self)) @@ -51,16 +57,19 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Composi .def("isPointSet", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) .def("isLine", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) .def("isRay", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) - .def("isLineString", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) .def("isSegment", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isLineString", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) .def("isPolygon", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) .def("isPlane", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) .def("isSphere", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) .def("isEllipsoid", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) .def("isPyramid", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) + .def("isComposite", +[] (const Composite& aComposite) -> bool { return aComposite.is() ; }) - .def("intersects", &Composite::intersects) - .def("contains", &Composite::contains) + .def("intersectsObject", +[] (const Composite& aComposite, const Object& anObject) -> bool { return aComposite.intersects(anObject) ; }) + .def("intersectsComposite", +[] (const Composite& aComposite, const Composite& anotherComposite) -> bool { return aComposite.intersects(anotherComposite) ; }) + .def("containsObject", +[] (const Composite& aComposite, const Object& anObject) -> bool { return aComposite.contains(anObject) ; }) + .def("containsComposite", +[] (const Composite& aComposite, const Composite& anotherComposite) -> bool { return aComposite.contains(anotherComposite) ; }) .def("asPoint", +[] (const Composite& aComposite) -> Point { return aComposite.as() ; }) .def("asPointSet", +[] (const Composite& aComposite) -> PointSet { return aComposite.as() ; }) @@ -73,10 +82,13 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Composi .def("asSphere", +[] (const Composite& aComposite) -> Sphere { return aComposite.as() ; }) .def("asEllipsoid", +[] (const Composite& aComposite) -> Ellipsoid { return aComposite.as() ; }) .def("asPyramid", +[] (const Composite& aComposite) -> Pyramid { return aComposite.as() ; }) + .def("asComposite", +[] (const Composite& aComposite) -> Composite { return aComposite.as() ; }) .def("accessObjectAt", &Composite::accessObjectAt, return_value_policy()) .def("accessObjects", &Composite::accessObjects, return_value_policy()) .def("getObjectCount", &Composite::getObjectCount) + .def("intersectionWithObject", +[] (const Composite& aComposite, const Object& anObject) -> Intersection { return aComposite.intersectionWith(anObject) ; }) + .def("intersectionWithComposite", +[] (const Composite& aComposite, const Composite& anotherComposite) -> Intersection { return aComposite.intersectionWith(anotherComposite) ; }) .def("applyTransformation", &Composite::applyTransformation)