From b50041fb273b264010115fb977b42646129aa7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Thu, 23 Aug 2018 13:49:10 -0700 Subject: [PATCH 1/8] [feature] Add segment geometry --- .../Geometry/3D/Objects/Ellipsoid.hpp | 2 + .../Mathematics/Geometry/3D/Objects/Point.hpp | 24 ++ .../Geometry/3D/Objects/Segment.hpp | 201 ++++++++++++++ .../Geometry/3D/Objects/Sphere.hpp | 4 +- .../Library/Mathematics/Objects/Interval.hpp | 19 +- .../Mathematics/Geometry/3D/Objects/Point.cpp | 34 +++ .../Geometry/3D/Objects/Segment.cpp | 172 ++++++++++++ .../Geometry/3D/Objects/Point.test.cpp | 44 +++ .../Geometry/3D/Objects/Segment.test.cpp | 250 ++++++++++++++++++ 9 files changed, 744 insertions(+), 6 deletions(-) create mode 100755 include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp create mode 100644 src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp create mode 100644 test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp index 31f5ec69..81752097 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp @@ -13,6 +13,7 @@ #include #include #include + #include //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -31,6 +32,7 @@ namespace objects //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// using library::core::types::Real ; + using library::math::geom::d3::Object ; using library::math::geom::d3::objects::Point ; using library::math::geom::trf::rot::Quaternion ; diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp index c5f737eb..42b599ce 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp @@ -12,6 +12,7 @@ #include #include + #include //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -30,6 +31,7 @@ namespace objects //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// using library::core::types::Real ; + using library::math::obj::Vector3d ; using library::math::geom::d3::Object ; @@ -74,6 +76,28 @@ class Point : public Object, public Vector3d virtual Point* clone ( ) const override ; + /// @brief Addition operator: translate point along vector + /// + /// @code + /// Point B = Point(0.0, 0.0, 0.0) + Vector3d(0.0, 0.0, 1.0) ; // [0.0, 0.0, 1.0] + /// @encode + /// + /// @param [in] aVector A translation vector + /// @return A point + + Point operator + ( const Vector3d& aVector ) const ; + + /// @brief Subtraction operator: translate point along opposite vector + /// + /// @code + /// Point B = Point(0.0, 0.0, 1.0) - Vector3d(0.0, 0.0, 1.0) ; // [0.0, 0.0, 0.0] + /// @encode + /// + /// @param [in] aVector A translation vector + /// @return A point + + Point operator - ( const Vector3d& aVector ) const ; + /// @brief Output stream operator /// /// @code diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp new file mode 100755 index 00000000..ebd0dd98 --- /dev/null +++ b/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp @@ -0,0 +1,201 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Segment.hpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __Library_Mathematics_Geometry_3D_Objects_Segment__ +#define __Library_Mathematics_Geometry_3D_Objects_Segment__ + +#include +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using library::core::types::Real ; + +using library::math::geom::d3::Object ; +using library::math::geom::d3::objects::Point ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @brief Segment +/// +/// @ref + +class Segment : public Object +{ + + public: + + /// @brief Constructor + /// + /// @code + /// Segment segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) ; + /// @endcode + /// + /// @param [in] aFirstPoint A first point + /// @param [in] aSecondPoint A second point + + Segment ( const Point& aFirstPoint, + const Point& aSecondPoint ) ; + + /// @brief Clone segment + /// + /// @return Pointer to cloned segment + + virtual Segment* clone ( ) const override ; + + /// @brief Equal to operator + /// + /// @code + /// Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) == Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) ; // True + /// @endcode + /// + /// @param [in] aSegment A segment + /// @return True if segments are equal + + bool operator == ( const Segment& aSegment ) const ; + + /// @brief Not equal to operator + /// + /// @code + /// Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) != Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 2.0 }) ; // True + /// @endcode + /// + /// @param [in] aSegment A segment + /// @return True if segments not are equal + + bool operator != ( const Segment& aSegment ) const ; + + /// @brief Output stream operator + /// + /// @code + /// std::cout << Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) ; + /// @endcode + /// + /// @param [in] anOutputStream An output stream + /// @param [in] aSegment A segment + /// @return An output stream + + friend std::ostream& operator << ( std::ostream& anOutputStream, + const Segment& aSegment ) ; + + /// @brief Check if segment is defined + /// + /// @code + /// Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).isDefined() ; // True + /// @endcode + /// + /// @return True if segment is defined + + virtual bool isDefined ( ) const override ; + + /// @brief Check if segment is degenerate, i.e. its length is zero + /// + /// @code + /// Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }).isDegenerate() ; // True + /// @endcode + /// + /// @return True if segment is degenerate + + bool isDegenerate ( ) const ; + + /// @brief Get segment first point + /// + /// @code + /// Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).getFirstPoint() ; // [0.0, 0.0, 0.0] + /// @endcode + /// + /// @return Segment first point + + Point getFirstPoint ( ) const ; + + /// @brief Get segment second point + /// + /// @code + /// Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).getSecondPoint() ; // [0.0, 0.0, 1.0] + /// @endcode + /// + /// @return Segment second point + + Point getSecondPoint ( ) const ; + + /// @brief Get segment center + /// + /// @code + /// Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 2.0 }).getCenter() ; // [0.0, 0.0, 1.0] + /// @endcode + /// + /// @return Segment center + + Point getCenter ( ) const ; + + /// @brief Get segment direction + /// + /// @code + /// Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 2.0 }).getDirection() ; // [0.0, 0.0, 1.0] + /// @endcode + /// + /// @return Segment direction + + Vector3d getDirection ( ) const ; + + /// @brief Get segment length + /// + /// @code + /// Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 2.0 }).getLength() ; // 2.0 + /// @endcode + /// + /// @return Segment length + + Real getLength ( ) const ; + + /// @brief Constructs an undefined segment + /// + /// @code + /// Segment segment = Segment::Undefined() ; // Undefined + /// @endcode + /// + /// @return Undefined segment + + static Segment Undefined ( ) ; + + private: + + Point firstPoint_ ; + Point secondPoint_ ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp index f9529249..5ad5ac5a 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp @@ -12,6 +12,7 @@ #include #include + #include //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -30,6 +31,7 @@ namespace objects //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// using library::core::types::Real ; + using library::math::geom::d3::Object ; using library::math::geom::d3::objects::Point ; @@ -76,7 +78,7 @@ class Sphere : public Object /// @brief Not equal to operator /// /// @code - /// Sphere(Point::Origin(), 1.0) != Sphere(2.0) ; // True + /// Sphere(Point::Origin(), 1.0) != Sphere(Point::Origin(), 2.0) ; // True /// @endcode /// /// @param [in] aSphere A sphere diff --git a/include/Library/Mathematics/Objects/Interval.hpp b/include/Library/Mathematics/Objects/Interval.hpp index 3cb3ee37..3a0ee7ca 100755 --- a/include/Library/Mathematics/Objects/Interval.hpp +++ b/include/Library/Mathematics/Objects/Interval.hpp @@ -30,12 +30,9 @@ namespace ctnr = library::core::ctnr ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// @brief Set of numbers with the property that any number that lies between two numbers in the set is also included in the set -/// -/// @ref https://en.wikipedia.org/wiki/Interval_(mathematics) +/// @brief Interval base (used to avoid having a templated enum) -template -class Interval +class IntervalBase { public: @@ -53,6 +50,18 @@ class Interval } ; +} ; + +/// @brief Set of numbers with the property that any number that lies between two numbers in the set is also included in the set +/// +/// @ref https://en.wikipedia.org/wiki/Interval_(mathematics) + +template +class Interval : public IntervalBase +{ + + public: + /// @brief Constructor /// /// @code diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp index 87a4e9b4..36e4612d 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp @@ -48,6 +48,40 @@ Point* Point::clone ( ) return new Point(*this) ; } +Point Point::operator + ( const Vector3d& aVector ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + if (!aVector.isDefined()) + { + throw library::core::error::runtime::Undefined("Vector") ; + } + + return Point(this->Vector3d::operator + (aVector)) ; + +} + +Point Point::operator - ( const Vector3d& aVector ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + if (!aVector.isDefined()) + { + throw library::core::error::runtime::Undefined("Vector") ; + } + + return Point(this->Vector3d::operator - (aVector)) ; + +} + std::ostream& operator << ( std::ostream& anOutputStream, const Point& aPoint ) { diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp new file mode 100644 index 00000000..a39ad763 --- /dev/null +++ b/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp @@ -0,0 +1,172 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Segment.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Segment::Segment ( const Point& aFirstPoint, + const Point& aSecondPoint ) + : Object(), + firstPoint_(aFirstPoint), + secondPoint_(aSecondPoint) +{ + +} + +Segment* Segment::clone ( ) const +{ + return new Segment(*this) ; +} + +bool Segment::operator == ( const Segment& aSegment ) const +{ + + if ((!this->isDefined()) || (!aSegment.isDefined())) + { + return false ; + } + + return ((firstPoint_ == aSegment.firstPoint_) && (secondPoint_ == aSegment.secondPoint_)) + || ((firstPoint_ == aSegment.secondPoint_) && (secondPoint_ == aSegment.firstPoint_)) ; + +} + +bool Segment::operator != ( const Segment& aSegment ) const +{ + return !((*this) == aSegment) ; +} + +std::ostream& operator << ( std::ostream& anOutputStream, + const Segment& aSegment ) +{ + + library::core::utils::Print::Header(anOutputStream, "Segment") ; + + library::core::utils::Print::Line(anOutputStream) << "First point:" << (aSegment.firstPoint_.isDefined() ? aSegment.firstPoint_.toString() : "Undefined") ; + library::core::utils::Print::Line(anOutputStream) << "Second point:" << (aSegment.secondPoint_.isDefined() ? aSegment.secondPoint_.toString() : "Undefined") ; + + library::core::utils::Print::Footer(anOutputStream) ; + + return anOutputStream ; + +} + +bool Segment::isDefined ( ) const +{ + return firstPoint_.isDefined() && secondPoint_.isDefined() ; +} + +bool Segment::isDegenerate ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Segment") ; + } + + return firstPoint_ == secondPoint_ ; + +} + +Point Segment::getFirstPoint ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Segment") ; + } + + return firstPoint_ ; + +} + +Point Segment::getSecondPoint ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Segment") ; + } + + return secondPoint_ ; + +} + +Point Segment::getCenter ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Segment") ; + } + + return firstPoint_ + (secondPoint_ - firstPoint_) / 2.0 ; + +} + +Vector3d Segment::getDirection ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Segment") ; + } + + if (this->isDegenerate()) + { + throw library::core::error::RuntimeError("Segment is degenerate.") ; + } + + return (secondPoint_ - firstPoint_).normalized() ; + +} + +Real Segment::getLength ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Segment") ; + } + + return (secondPoint_ - firstPoint_).norm() ; + +} + +Segment Segment::Undefined ( ) +{ + return Segment(Point::Undefined(), Point::Undefined()) ; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp index 73ef2574..b1a2e434 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp @@ -46,6 +46,50 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Point, Clone) } +TEST (Library_Mathematics_Geometry_3D_Objects_Point, AdditionOperator) +{ + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + + { + + EXPECT_EQ(Point(1.0, 2.0, 3.0), Point(1.0, 2.0, 3.0) + Vector3d(0.0, 0.0, 0.0)) ; + EXPECT_EQ(Point(2.0, 2.0, 3.0), Point(1.0, 2.0, 3.0) + Vector3d(1.0, 0.0, 0.0)) ; + + } + + { + + EXPECT_ANY_THROW(Point::Undefined() + Vector3d(0.0, 0.0, 0.0)) ; + EXPECT_ANY_THROW(Point(1.0, 2.0, 3.0) + Vector3d::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Point, SubtractionOperator) +{ + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + + { + + EXPECT_EQ(Point(1.0, 2.0, 3.0), Point(1.0, 2.0, 3.0) - Vector3d(0.0, 0.0, 0.0)) ; + EXPECT_EQ(Point(0.0, 2.0, 3.0), Point(1.0, 2.0, 3.0) - Vector3d(1.0, 0.0, 0.0)) ; + + } + + { + + EXPECT_ANY_THROW(Point::Undefined() - Vector3d(0.0, 0.0, 0.0)) ; + EXPECT_ANY_THROW(Point(1.0, 2.0, 3.0) - Vector3d::Undefined()) ; + + } + +} + TEST (Library_Mathematics_Geometry_3D_Objects_Point, EqualToOperator) { diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp new file mode 100644 index 00000000..fe487f3e --- /dev/null +++ b/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp @@ -0,0 +1,250 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Constructor) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + EXPECT_NO_THROW(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 })) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Clone) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + EXPECT_NO_THROW(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).clone()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, EqualToOperator) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) == Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 })) ; + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) == Segment({ 0.0, 0.0, 1.0 }, { 0.0, 0.0, 0.0 })) ; + + } + + { + + EXPECT_FALSE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) == Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 2.0 })) ; + + } + + { + + EXPECT_FALSE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) == Segment::Undefined()) ; + EXPECT_FALSE(Segment::Undefined() == Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 })) ; + EXPECT_FALSE(Segment::Undefined() == Segment::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, NotEqualToOperator) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + EXPECT_FALSE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) != Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 })) ; + EXPECT_FALSE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) != Segment({ 0.0, 0.0, 1.0 }, { 0.0, 0.0, 0.0 })) ; + + } + + { + + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) != Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 2.0 })) ; + + } + + { + + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) != Segment::Undefined()) ; + EXPECT_TRUE(Segment::Undefined() != Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 })) ; + EXPECT_TRUE(Segment::Undefined() != Segment::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, StreamOperator) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + testing::internal::CaptureStdout() ; + + EXPECT_NO_THROW(std::cout << Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) << std::endl) ; + + EXPECT_FALSE(testing::internal::GetCapturedStdout().empty()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, IsDefined) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }).isDefined()) ; + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).isDefined()) ; + + } + + { + + EXPECT_FALSE(Segment::Undefined().isDefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, IsDegenerate) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }).isDegenerate()) ; + EXPECT_TRUE(Segment({ 1.0, 1.0, 1.0 }, { 1.0, 1.0, 1.0 }).isDegenerate()) ; + + } + + { + + EXPECT_FALSE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).isDegenerate()) ; + EXPECT_FALSE(Segment({ 1.0, 2.0, 3.0 }, { 0.0, 0.0, 1.0 }).isDegenerate()) ; + + } + + { + + EXPECT_ANY_THROW(Segment::Undefined().isDegenerate()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, GetCenter) +{ + + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Segment ; + + { + + EXPECT_EQ(Point(0.0, 0.0, 0.0), Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }).getCenter()) ; + EXPECT_EQ(Point(0.0, 0.0, 1.0), Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 2.0 }).getCenter()) ; + + EXPECT_EQ(Point(0.0, 0.0, 0.0), Segment({ 0.0, 0.0, -1.0 }, { 0.0, 0.0, +1.0 }).getCenter()) ; + + } + + { + + EXPECT_ANY_THROW(Segment::Undefined().getCenter()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, GetDirection) +{ + + using library::math::obj::Vector3d ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Segment ; + + { + + EXPECT_EQ(Vector3d(0.0, 0.0, +1.0), Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, +2.0 }).getDirection()) ; + EXPECT_EQ(Vector3d(0.0, 0.0, -1.0), Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, -2.0 }).getDirection()) ; + + } + + { + + EXPECT_ANY_THROW(Segment::Undefined().getDirection()) ; + + EXPECT_ANY_THROW(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }).getDirection()) ; + EXPECT_ANY_THROW(Segment({ 1.0, 1.0, 1.0 }, { 1.0, 1.0, 1.0 }).getDirection()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, GetLength) +{ + + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Segment ; + + { + + EXPECT_EQ(0.0, Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }).getLength()) ; + EXPECT_EQ(0.0, Segment({ 1.0, 1.0, 1.0 }, { 1.0, 1.0, 1.0 }).getLength()) ; + + EXPECT_EQ(1.0, Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).getLength()) ; + EXPECT_EQ(2.0, Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 2.0 }).getLength()) ; + + EXPECT_EQ(4.0, Segment({ 0.0, 0.0, -2.0 }, { 0.0, 0.0, +2.0 }).getLength()) ; + + } + + { + + EXPECT_ANY_THROW(Segment::Undefined().getLength()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Undefined) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + EXPECT_NO_THROW(Segment::Undefined()) ; + EXPECT_FALSE(Segment::Undefined().isDefined()) ; + + } + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file From 3dcbdda0e2a3b0f91a18c6200b7c064d8bd315e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Thu, 23 Aug 2018 17:25:17 -0700 Subject: [PATCH 2/8] [feature] Add geometry Intersection, improve Point, Segment and Ellipsoid --- .../Mathematics/Geometry/3D/Intersection.hpp | 170 +++++++++++++++ .../Mathematics/Geometry/3D/Object.hpp | 32 +++ .../Geometry/3D/Objects/Ellipsoid.hpp | 60 ++++++ .../Mathematics/Geometry/3D/Objects/Point.hpp | 15 +- .../Geometry/3D/Objects/Segment.hpp | 30 +++ .../Geometry/3D/Objects/Sphere.hpp | 2 + .../Library/Mathematics/Objects/Interval.hpp | 4 +- .../Mathematics/Geometry/3D/Intersection.cpp | 199 +++++++++++++++++ .../Mathematics/Geometry/3D/Object.cpp | 128 +++++++++++ .../Geometry/3D/Objects/Ellipsoid.cpp | 201 ++++++++++++++++++ .../Mathematics/Geometry/3D/Objects/Point.cpp | 17 ++ .../Geometry/3D/Objects/Segment.cpp | 26 +++ src/Library/Mathematics/Objects/Interval.tpp | 2 +- .../Geometry/3D/Objects/Ellipsoid.test.cpp | 78 +++++++ .../Geometry/3D/Objects/Point.test.cpp | 14 ++ .../Geometry/3D/Objects/Segment.test.cpp | 26 +++ .../Mathematics/Objects/Interval.test.cpp | 2 +- 17 files changed, 1000 insertions(+), 6 deletions(-) create mode 100755 include/Library/Mathematics/Geometry/3D/Intersection.hpp create mode 100644 src/Library/Mathematics/Geometry/3D/Intersection.cpp diff --git a/include/Library/Mathematics/Geometry/3D/Intersection.hpp b/include/Library/Mathematics/Geometry/3D/Intersection.hpp new file mode 100755 index 00000000..3c74c4fc --- /dev/null +++ b/include/Library/Mathematics/Geometry/3D/Intersection.hpp @@ -0,0 +1,170 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Intersection.hpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __Library_Mathematics_Geometry_3D_Intersection__ +#define __Library_Mathematics_Geometry_3D_Intersection__ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using library::core::types::Unique ; +using library::core::ctnr::Array ; + +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::objects::Sphere ; +using library::math::geom::d3::objects::Ellipsoid ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @brief 3D intersection + +class Intersection +{ + + public: + + enum class Type + { + + Undefined, + Empty, + Point, + PointSet, + Line, + Ray, + Segment, + Plane, + Sphere, + Ellipsoid, + Complex + + } ; + + /// @brief Constructor + /// + /// @param [in] anObjectArray An array of objects + + Intersection ( const Array>& anObjectArray ) ; + + /// @brief Copy constructor + /// + /// @param [in] anIntersection An intersection + + Intersection ( const Intersection& anIntersection ) ; + + /// @brief Destructor + + ~Intersection ( ) ; + + /// @brief Copy assignment operator + /// + /// @param [in] anIntersection An intersection + /// @return Reference to intersection + + Intersection& operator = ( const Intersection& anIntersection ) ; + + /// @brief Equal to operator + /// + /// @param [in] anIntersection An intersection + /// @return True if intersections are equal + + bool operator == ( const Intersection& anIntersection ) const ; + + /// @brief Not equal to operator + /// + /// @param [in] anIntersection An intersection + /// @return True if intersections not are equal + + bool operator != ( const Intersection& anIntersection ) const ; + + /// @brief Check if intersection is defined + /// + /// @return True if intersection is defined + + bool isDefined ( ) const ; + + /// @brief Check if intersection is empty + /// + /// @return True if intersection is empty + + bool isEmpty ( ) const ; + + /// @brief Get intersection type + /// + /// @return Intersection type + + Intersection::Type getType ( ) const ; + + /// @brief Constructs an undefined intersection + /// + /// @code + /// Intersection intersection = Intersection::Undefined() ; // Undefined + /// @endcode + /// + /// @return Undefined intersection + + static Intersection Undefined ( ) ; + + /// @brief Constructs an empty intersection + /// + /// @code + /// Intersection intersection = Intersection::Empty() ; + /// @endcode + /// + /// @return Empty intersection + + static Intersection Empty ( ) ; + + private: + + Intersection::Type type_ ; + + Array> objects_ ; + + static Intersection::Type TypeFromObjects ( const Array>& anObjectArray ) ; + + static Intersection::Type TypeFromObject ( const Unique& anObjectUPtr ) ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/include/Library/Mathematics/Geometry/3D/Object.hpp b/include/Library/Mathematics/Geometry/3D/Object.hpp index 48d17b38..7d3e6c73 100755 --- a/include/Library/Mathematics/Geometry/3D/Object.hpp +++ b/include/Library/Mathematics/Geometry/3D/Object.hpp @@ -23,6 +23,10 @@ namespace d3 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Intersection ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// @brief 3D object class Object @@ -50,6 +54,34 @@ class Object virtual bool isDefined ( ) const = 0 ; + /// @brief Check if object intersects another object + /// + /// @code + /// Unique objectUPtr = ... ; + /// Unique anotherObjectUPtr = ... ; + /// objectUPtr->intersects(*anotherObjectUPtr) ; + /// @endcode + /// + /// @param [in] anObject An object + /// @return True if object intersects another object + + virtual bool intersects ( const Object& anObject ) const ; + + /// @brief Check if object contains another object + /// + /// @code + /// Unique objectUPtr = ... ; + /// Unique anotherObjectUPtr = ... ; + /// objectUPtr->contains(*anotherObjectUPtr) ; + /// @endcode + /// + /// @param [in] anObject An object + /// @return True if object contains another object + + virtual bool contains ( const Object& anObject ) const ; + + virtual Intersection computeIntersectionWith ( const Object& anObject ) const ; + } ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp index 81752097..5b1db353 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp @@ -33,12 +33,17 @@ namespace objects using library::core::types::Real ; +using library::math::obj::Matrix3d ; using library::math::geom::d3::Object ; using library::math::geom::d3::objects::Point ; using library::math::geom::trf::rot::Quaternion ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Segment ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// @brief Ellipsoid /// /// @ref https://en.wikipedia.org/wiki/Ellipsoid @@ -117,6 +122,45 @@ class Ellipsoid : public Object virtual bool isDefined ( ) const override ; + /// @brief Check if ellipsoid intersects segment + /// + /// @code + /// Ellipsoid ellipsoid = ... ; + /// Segment segment = ... ; + /// ellipsoid.intersects(segment) ; + /// @endcode + /// + /// @param [in] aSegment A segment + /// @return True if ellipsoid intersects segment + + bool intersects ( const Segment& aSegment ) const ; + + /// @brief Check if ellipsoid contains point + /// + /// @code + /// Ellipsoid ellipsoid = ... ; + /// Point point = ... ; + /// ellipsoid.contains(point) ; + /// @endcode + /// + /// @param [in] aPoint A point + /// @return True if ellipsoid contains point + + bool contains ( const Point& aPoint ) const ; + + /// @brief Check if ellipsoid contains segment + /// + /// @code + /// Ellipsoid ellipsoid = ... ; + /// Segment segment = ... ; + /// ellipsoid.contains(segment) ; + /// @endcode + /// + /// @param [in] aSegment A segment + /// @return True if ellipsoid contains segment + + bool contains ( const Segment& aSegment ) const ; + /// @brief Get ellipsoid center /// /// @code @@ -157,6 +201,12 @@ class Ellipsoid : public Object Real getThirdPrincipalSemiAxis ( ) const ; + Vector3d getFirstAxis ( ) const ; + + Vector3d getSecondAxis ( ) const ; + + Vector3d getThirdAxis ( ) const ; + /// @brief Get ellipsoid orientation /// /// @code @@ -167,6 +217,16 @@ class Ellipsoid : public Object Quaternion getOrientation ( ) const ; + /// @brief Get ellipsoid matrix + /// + /// @code + /// Ellipsoid(Point::Origin(), 1.0, 2.0, 3.0, Quaternion::XYZS(0.0, 0.0, 0.0, 1.0)).getMatrix() ; + /// @endcode + /// + /// @return Ellipsoid matrix + + Matrix3d getMatrix ( ) const ; + /// @brief Constructs an undefined ellipsoid /// /// @code diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp index 42b599ce..360b08a6 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp @@ -79,7 +79,7 @@ class Point : public Object, public Vector3d /// @brief Addition operator: translate point along vector /// /// @code - /// Point B = Point(0.0, 0.0, 0.0) + Vector3d(0.0, 0.0, 1.0) ; // [0.0, 0.0, 1.0] + /// Point(0.0, 0.0, 0.0) + Vector3d(0.0, 0.0, 1.0) ; // [0.0, 0.0, 1.0] /// @encode /// /// @param [in] aVector A translation vector @@ -90,7 +90,7 @@ class Point : public Object, public Vector3d /// @brief Subtraction operator: translate point along opposite vector /// /// @code - /// Point B = Point(0.0, 0.0, 1.0) - Vector3d(0.0, 0.0, 1.0) ; // [0.0, 0.0, 0.0] + /// Point(0.0, 0.0, 1.0) - Vector3d(0.0, 0.0, 1.0) ; // [0.0, 0.0, 0.0] /// @encode /// /// @param [in] aVector A translation vector @@ -98,6 +98,17 @@ class Point : public Object, public Vector3d Point operator - ( const Vector3d& aVector ) const ; + /// @brief Subtraction operator: get translation vector between two points + /// + /// @code + /// Point(0.0, 0.0, 1.0) - Point(0.0, 0.0, 0.0) ; // [0.0, 0.0, 1.0] + /// @encode + /// + /// @param [in] aPoint A point + /// @return A translation vector + + Vector3d operator - ( const Point& aPoint ) const ; + /// @brief Output stream operator /// /// @code diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp index ebd0dd98..047e7af7 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp @@ -37,6 +37,10 @@ using library::math::geom::d3::objects::Point ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class Ellipsoid ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// @brief Segment /// /// @ref @@ -119,6 +123,32 @@ class Segment : public Object bool isDegenerate ( ) const ; + /// @brief Check if segment intersects ellipsoid + /// + /// @code + /// Segment segment = ... ; + /// Ellipsoid ellipsoid = ... ; + /// segment.intersects(ellipsoid) ; + /// @endcode + /// + /// @param [in] anEllipsoid An ellipsoid + /// @return True if segment intersects ellipsoid + + bool intersects ( const Ellipsoid& anEllipsoid ) const ; + + /// @brief Check if segment contains point + /// + /// @code + /// Segment segment = ... ; + /// Ellipsoid ellipsoid = ... ; + /// segment.contains(ellipsoid) ; + /// @endcode + /// + /// @param [in] anEllipsoid An ellipsoid + /// @return True if segment contains point + + bool contains ( const Point& aPoint ) const ; + /// @brief Get segment first point /// /// @code diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp index 5ad5ac5a..7657637c 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp @@ -39,6 +39,8 @@ using library::math::geom::d3::objects::Point ; /// @brief Sphere /// +/// A sphere is a perfectly round geometrical object in three-dimensional space that is the surface of a completely round ball. +/// /// @ref https://en.wikipedia.org/wiki/Sphere class Sphere : public Object diff --git a/include/Library/Mathematics/Objects/Interval.hpp b/include/Library/Mathematics/Objects/Interval.hpp index 3a0ee7ca..e658e5a4 100755 --- a/include/Library/Mathematics/Objects/Interval.hpp +++ b/include/Library/Mathematics/Objects/Interval.hpp @@ -136,13 +136,13 @@ class Interval : public IntervalBase /// @brief Check if interval is intersecting with another interval /// /// @code - /// Interval::Closed(0.0, 1.0).isIntersectingWith(Interval::Closed(0.5, 1.5)) ; // True + /// Interval::Closed(0.0, 1.0).intersects(Interval::Closed(0.5, 1.5)) ; // True /// @endcode /// /// @param [in] anInterval An interval /// @return True if intervals are intersecting - bool isIntersectingWith ( const Interval& anInterval ) const ; + bool intersects ( const Interval& anInterval ) const ; /// @brief Check if interval contains value /// diff --git a/src/Library/Mathematics/Geometry/3D/Intersection.cpp b/src/Library/Mathematics/Geometry/3D/Intersection.cpp new file mode 100644 index 00000000..492405b0 --- /dev/null +++ b/src/Library/Mathematics/Geometry/3D/Intersection.cpp @@ -0,0 +1,199 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Intersection.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Intersection::Intersection ( const Array>& anObjectArray ) + : type_(Intersection::TypeFromObjects(anObjectArray)), + 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()) ; }) ; + +} + + Intersection::Intersection ( const Intersection& anIntersection ) + : type_(anIntersection.type_), + objects_(Array>::Empty()) +{ + + 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 ( ) +{ + +} + +Intersection& Intersection::operator = ( const Intersection& anIntersection ) +{ + + if (this != &anIntersection) + { + + 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()) ; }) ; + + } + + return (*this) ; + +} + +bool Intersection::operator == ( const Intersection& anIntersection ) const +{ + + if ((!this->isDefined()) || (!anIntersection.isDefined())) + { + return false ; + } + + if (type_ != anIntersection.type_) + { + return false ; + } + + // [TBI] + + throw library::core::error::runtime::ToBeImplemented("Intersection :: operator ==") ; + + return false ; + +} + +bool Intersection::operator != ( const Intersection& anIntersection ) const +{ + return !((*this) == anIntersection) ; +} + +bool Intersection::isDefined ( ) const +{ + return type_ != Intersection::Type::Undefined ; +} + +bool Intersection::isEmpty ( ) const +{ + return type_ == Intersection::Type::Empty ; +} + +Intersection::Type Intersection::getType ( ) const +{ + return type_ ; +} + +Intersection Intersection::Undefined ( ) +{ + + Intersection intersection = { Array>::Empty() } ; + + intersection.type_ = Intersection::Type::Undefined ; + + return intersection ; + +} + +Intersection Intersection::Empty ( ) +{ + return Intersection(Array>::Empty()) ; +} + +Intersection::Type Intersection::TypeFromObjects ( const Array>& anObjectArray ) +{ + + if (anObjectArray.isEmpty()) + { + return Intersection::Type::Empty ; + } + + Intersection::Type type = Intersection::Type::Undefined ; + + for (const auto& objectUPtr : anObjectArray) + { + + const Intersection::Type objectType = Intersection::TypeFromObject(objectUPtr) ; + + if (type == Intersection::Type::Undefined) + { + type = objectType ; + } + else if (type != objectType) + { + return Intersection::Type::Complex ; + } + + } + + return type ; + +} + +Intersection::Type Intersection::TypeFromObject ( const Unique& anObjectUPtr ) +{ + + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::Point ; + } + + // if (dynamic_cast(anObjectUPtr.get())) + // { + // return Intersection::Type::PointSet ; + // } + + // [TBI] + + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::Segment ; + } + + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::Sphere ; + } + + if (dynamic_cast(anObjectUPtr.get())) + { + return Intersection::Type::Ellipsoid ; + } + + return Intersection::Type::Undefined ; + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/Library/Mathematics/Geometry/3D/Object.cpp b/src/Library/Mathematics/Geometry/3D/Object.cpp index b36dbcbf..9aa3bc5d 100644 --- a/src/Library/Mathematics/Geometry/3D/Object.cpp +++ b/src/Library/Mathematics/Geometry/3D/Object.cpp @@ -7,8 +7,16 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include #include +#include +#include + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// namespace library @@ -27,6 +35,126 @@ namespace d3 } +bool Object::intersects ( const Object& anObject ) const +{ + + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Segment ; + using library::math::geom::d3::objects::Sphere ; + using library::math::geom::d3::objects::Ellipsoid ; + + if (!anObject.isDefined()) + { + throw library::core::error::runtime::Undefined("Object") ; + } + + // Segment + + if (const Segment* segmentPtr = dynamic_cast(this)) + { + + // if (const Segment* otherSegmentPtr = dynamic_cast(&anObject)) + // { + // return segmentPtr->intersects(*otherSegmentPtr) ; + // } + + if (const Ellipsoid* otherEllipsoidPtr = dynamic_cast(&anObject)) + { + return segmentPtr->intersects(*otherEllipsoidPtr) ; + } + + } + + // Ellipsoid + + if (const Ellipsoid* ellipsoidPtr = dynamic_cast(this)) + { + + if (const Segment* otherSegmentPtr = dynamic_cast(&anObject)) + { + return ellipsoidPtr->intersects(*otherSegmentPtr) ; + } + + // if (const Ellipsoid* otherEllipsoidPtr = dynamic_cast(&anObject)) + // { + // return ellipsoidPtr->intersects(*otherEllipsoidPtr) ; + // } + + } + + throw library::core::error::runtime::ToBeImplemented("Object :: intersects") ; + + return false ; + +} + +bool Object::contains ( const Object& anObject ) const +{ + + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Segment ; + using library::math::geom::d3::objects::Sphere ; + using library::math::geom::d3::objects::Ellipsoid ; + + if (!anObject.isDefined()) + { + throw library::core::error::runtime::Undefined("Object") ; + } + + // Segment + + if (const Segment* segmentPtr = dynamic_cast(this)) + { + + // if (const Segment* otherSegmentPtr = dynamic_cast(&anObject)) + // { + // return segmentPtr->contains(*otherSegmentPtr) ; + // } + + // if (const Ellipsoid* otherEllipsoidPtr = dynamic_cast(&anObject)) + // { + // return segmentPtr->contains(*otherEllipsoidPtr) ; + // } + + } + + // Ellipsoid + + if (const Ellipsoid* ellipsoidPtr = dynamic_cast(this)) + { + + if (const Segment* otherSegmentPtr = dynamic_cast(&anObject)) + { + return ellipsoidPtr->contains(*otherSegmentPtr) ; + } + + // if (const Ellipsoid* otherEllipsoidPtr = dynamic_cast(&anObject)) + // { + // return ellipsoidPtr->contains(*otherEllipsoidPtr) ; + // } + + } + + throw library::core::error::runtime::ToBeImplemented("Object :: contains") ; + + return false ; + +} + +Intersection Object::computeIntersectionWith ( const Object& anObject ) const +{ + + if (!anObject.isDefined()) + { + throw library::core::error::runtime::Undefined("Object") ; + } + + throw library::core::error::runtime::ToBeImplemented("Object :: computeIntersectionWith") ; + + return Intersection::Undefined() ; + +} + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp index f94fdd33..1ad38868 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp @@ -8,6 +8,8 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include +#include +#include #include #include @@ -106,6 +108,140 @@ bool Ellipsoid::isDefined ( ) return center_.isDefined() && a_.isDefined() && b_.isDefined() && c_.isDefined() && q_.isDefined() ; } +bool Ellipsoid::intersects ( const Segment& aSegment ) const +{ + + using library::math::obj::Interval ; + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Ellipsoid") ; + } + + if (!aSegment.isDefined()) + { + throw library::core::error::runtime::Undefined("Segment") ; + } + + if (aSegment.isDegenerate()) + { + return this->contains(aSegment.getFirstPoint()) ; + } + + // https://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrSegment3Ellipsoid3.h + + const Vector3d segmentDirection = aSegment.getDirection() ; + const Vector3d segmentCenter = aSegment.getCenter() ; + const Real segmentHalfLength = aSegment.getLength() / 2.0 ; + + const Matrix3d M = this->getMatrix() ; + + const Vector3d diff = segmentCenter - this->getCenter() ; + const Vector3d matDir = M * segmentDirection ; + const Vector3d matDiff = M * diff ; + + const Real a2 = segmentDirection.dot(matDir) ; + const Real a1 = segmentDirection.dot(matDiff) ; + const Real a0 = diff.dot(matDiff) - 1.0 ; + + const Real discriminant = (a1 * a1) - (a0 * a2) ; + + if (discriminant < 0.0) // No intersection + { + return false ; + } + else if (discriminant > 0.0) + { + + const Real discriminantRoot = std::sqrt(discriminant) ; + const Real a2_inverse = 1.0 / a2 ; + + const Real t0 = (-a1 - discriminantRoot) * a2_inverse ; + const Real t1 = (-a1 + discriminantRoot) * a2_inverse ; + + const Interval resultInterval = Interval::Open(t0, t1) ; + const Interval segmentInterval = Interval::Closed(-segmentHalfLength, +segmentHalfLength) ; + + if (!resultInterval.contains(segmentInterval)) + { + + if (resultInterval.intersects(segmentInterval)) + { + return true ; + } + else // No intersection + { + return false ; + } + + } + else + { + return false ; + } + + } + else + { + + const Real t0 = -a1 / a2 ; + + if (std::abs(t0) <= segmentHalfLength) // Single intersection + { + return true ; + } + else // No intersection + { + return false ; + } + + } + + return false ; + +} + +bool Ellipsoid::contains ( const Point& aPoint ) const +{ + + using library::math::obj::Vector3d ; + + if (!aPoint.isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Ellipsoid") ; + } + + Matrix3d dcm ; + + dcm.row(0) = q_ * Vector3d::X() ; + dcm.row(1) = q_ * Vector3d::Y() ; + dcm.row(2) = q_ * Vector3d::Z() ; + + const Vector3d point = dcm * (aPoint - center_) ; + + const Real& x = point.x() ; + const Real& y = point.y() ; + const Real& z = point.z() ; + + return std::abs((x * x) / (a_ * a_) + (y * y) / (b_ * b_) + (z * z) / (c_ * c_) - 1.0) < Real::Epsilon() ; + +} + +// bool Ellipsoid::contains ( const PointSet& aPointSet ) const +// { + +// } + +bool Ellipsoid::contains ( const Segment& aSegment ) const +{ + return this->contains(aSegment.getFirstPoint()) && this->contains(aSegment.getSecondPoint()) ; +} + Point Ellipsoid::getCenter ( ) const { @@ -154,6 +290,42 @@ Real Ellipsoid::getThirdPrincipalSemiAxis ( ) } +Vector3d Ellipsoid::getFirstAxis ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Ellipsoid") ; + } + + return q_.toConjugate() * Vector3d::X() ; + +} + +Vector3d Ellipsoid::getSecondAxis ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Ellipsoid") ; + } + + return q_.toConjugate() * Vector3d::Y() ; + +} + +Vector3d Ellipsoid::getThirdAxis ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Ellipsoid") ; + } + + return q_.toConjugate() * Vector3d::Z() ; + +} + Quaternion Ellipsoid::getOrientation ( ) const { @@ -166,6 +338,35 @@ Quaternion Ellipsoid::getOrientation ( ) } +Matrix3d Ellipsoid::getMatrix ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Ellipsoid") ; + } + + const Vector3d firstRatio = this->getFirstAxis() / a_ ; + const Vector3d secondRatio = this->getSecondAxis() / b_ ; + const Vector3d thirdRatio = this->getThirdAxis() / c_ ; + + auto tensorProduct = [] (const Vector3d& aFirstVector, const Vector3d& aSecondVector) -> Matrix3d + { + + Matrix3d tensorProductMatrix ; + + tensorProductMatrix << aFirstVector(0) * aSecondVector(0), aFirstVector(0) * aSecondVector(1), aFirstVector(0) * aSecondVector(2), + aFirstVector(1) * aSecondVector(0), aFirstVector(1) * aSecondVector(1), aFirstVector(1) * aSecondVector(2), + aFirstVector(2) * aSecondVector(0), aFirstVector(2) * aSecondVector(1), aFirstVector(2) * aSecondVector(2) ; + + return tensorProductMatrix ; + + } ; + + return tensorProduct(firstRatio, firstRatio) + tensorProduct(secondRatio, secondRatio) + tensorProduct(thirdRatio, thirdRatio) ; + +} + Ellipsoid Ellipsoid::Undefined ( ) { return Ellipsoid(Point::Undefined(), Real::Undefined(), Real::Undefined(), Real::Undefined(), Quaternion::Undefined()) ; diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp index 36e4612d..7865f20d 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp @@ -81,6 +81,23 @@ Point Point::operator - ( return Point(this->Vector3d::operator - (aVector)) ; } + +Vector3d Point::operator - ( const Point& aPoint ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + if (!aPoint.isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + return this->Vector3d::operator - (aPoint) ; + +} std::ostream& operator << ( std::ostream& anOutputStream, const Point& aPoint ) diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp index a39ad763..65560951 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp @@ -7,6 +7,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include #include #include @@ -91,6 +92,31 @@ bool Segment::isDegenerate ( ) } +// bool Segment::intersects ( const Segment& aSegment ) const +// { + +// } + +// bool Segment::intersects ( const Sphere& aSphere ) const +// { +// return aSphere.intersects(*this) ; +// } + +bool Segment::intersects ( const Ellipsoid& anEllipsoid ) const +{ + return anEllipsoid.intersects(*this) ; +} + +// bool Segment::contains ( const Point& aPoint ) const +// { + +// } + +// bool Segment::contains ( const PointSet& aPointSet ) const +// { + +// } + Point Segment::getFirstPoint ( ) const { diff --git a/src/Library/Mathematics/Objects/Interval.tpp b/src/Library/Mathematics/Objects/Interval.tpp index a4d28e58..a537e9d3 100644 --- a/src/Library/Mathematics/Objects/Interval.tpp +++ b/src/Library/Mathematics/Objects/Interval.tpp @@ -95,7 +95,7 @@ bool Interval::isDegenerate ( ) } template -bool Interval::isIntersectingWith ( const Interval& anInterval ) const +bool Interval::intersects ( const Interval& anInterval ) const { if (!this->isDefined()) diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp index 491bd6df..773217c5 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp @@ -151,6 +151,32 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IsDefined) } +TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Intersects) +{ + + using library::math::geom::d3::objects::Ellipsoid ; + + { + + FAIL() ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Contains) +{ + + using library::math::geom::d3::objects::Ellipsoid ; + + { + + FAIL() ; + + } + +} + TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetCenter) { @@ -228,6 +254,45 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetThirdPrincipalSemiAx } +TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetFirstAxis) +{ + + using library::math::geom::d3::objects::Ellipsoid ; + + { + + FAIL() ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetSecondAxis) +{ + + using library::math::geom::d3::objects::Ellipsoid ; + + { + + FAIL() ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetThirdAxis) +{ + + using library::math::geom::d3::objects::Ellipsoid ; + + { + + FAIL() ; + + } + +} + TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetOrientation) { @@ -254,6 +319,19 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetOrientation) } +TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetMatrix) +{ + + using library::math::geom::d3::objects::Ellipsoid ; + + { + + FAIL() ; + + } + +} + TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Undefined) { diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp index b1a2e434..3ec085fc 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp @@ -87,6 +87,20 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Point, SubtractionOperator) EXPECT_ANY_THROW(Point(1.0, 2.0, 3.0) - Vector3d::Undefined()) ; } + + { + + EXPECT_EQ(Vector3d(1.0, 2.0, 3.0), Point(1.0, 2.0, 3.0) - Point(0.0, 0.0, 0.0)) ; + EXPECT_EQ(Vector3d(0.0, 2.0, 3.0), Point(1.0, 2.0, 3.0) - Point(1.0, 0.0, 0.0)) ; + + } + + { + + EXPECT_ANY_THROW(Point::Undefined() - Point(0.0, 0.0, 0.0)) ; + EXPECT_ANY_THROW(Point(1.0, 2.0, 3.0) - Point::Undefined()) ; + + } } diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp index fe487f3e..e74b991d 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp @@ -159,6 +159,32 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Segment, IsDegenerate) } +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Intersects) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + FAIL() ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Contains) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + FAIL() ; + + } + +} + TEST (Library_Mathematics_Geometry_3D_Objects_Segment, GetCenter) { diff --git a/test/Library/Mathematics/Objects/Interval.test.cpp b/test/Library/Mathematics/Objects/Interval.test.cpp index fc14eed7..8294387b 100644 --- a/test/Library/Mathematics/Objects/Interval.test.cpp +++ b/test/Library/Mathematics/Objects/Interval.test.cpp @@ -157,7 +157,7 @@ TEST (Library_Mathematics_Objects_Interval, IsDegenerate) } -// TEST (Library_Mathematics_Objects_Interval, IsIntersectingWith) +// TEST (Library_Mathematics_Objects_Interval, Intersects) // { // using library::core::types::Real ; From 05895d0949f273dfcb5d9691c5b4b284ee50dbce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Thu, 23 Aug 2018 17:31:51 -0700 Subject: [PATCH 3/8] [misc] Typo --- src/Library/Mathematics/Geometry/3D/Intersection.cpp | 2 +- src/Library/Mathematics/Geometry/Angle.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Library/Mathematics/Geometry/3D/Intersection.cpp b/src/Library/Mathematics/Geometry/3D/Intersection.cpp index 492405b0..1e717ecc 100644 --- a/src/Library/Mathematics/Geometry/3D/Intersection.cpp +++ b/src/Library/Mathematics/Geometry/3D/Intersection.cpp @@ -64,7 +64,7 @@ Intersection& Intersection::operator = ( } - return (*this) ; + return *this ; } diff --git a/src/Library/Mathematics/Geometry/Angle.cpp b/src/Library/Mathematics/Geometry/Angle.cpp index 08030990..e4151956 100644 --- a/src/Library/Mathematics/Geometry/Angle.cpp +++ b/src/Library/Mathematics/Geometry/Angle.cpp @@ -145,7 +145,7 @@ Angle& Angle::operator += ( value_ += ((unit_ == anAngle.unit_) ? anAngle.value_ : anAngle.in(unit_)) ; - return (*this) ; + return *this ; } @@ -159,7 +159,7 @@ Angle& Angle::operator -= ( value_ -= ((unit_ == anAngle.unit_) ? anAngle.value_ : anAngle.in(unit_)) ; - return (*this) ; + return *this ; } @@ -178,7 +178,7 @@ Angle& Angle::operator *= ( value_ *= aReal ; - return (*this) ; + return *this ; } @@ -202,7 +202,7 @@ Angle& Angle::operator /= ( value_ /= aReal ; - return (*this) ; + return *this ; } From 20867a7ba3f0cebe43bf23401ee3671c78ca749f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Fri, 24 Aug 2018 16:06:28 -0700 Subject: [PATCH 4/8] [feature] Improve Geometry --- .../Mathematics/Geometry/3D/Object.hpp | 18 +++ .../Geometry/3D/Objects/Ellipsoid.hpp | 12 ++ .../Mathematics/Geometry/3D/Objects/Point.hpp | 26 ++++ .../Geometry/3D/Objects/Segment.hpp | 12 ++ .../Geometry/3D/Objects/Sphere.hpp | 12 ++ .../Transformations/Rotations/Quaternion.hpp | 18 +++ .../Library/Mathematics/Objects/Interval.hpp | 3 +- .../Mathematics/Geometry/3D/Object.cpp | 62 +++++++++ .../Geometry/3D/Objects/Ellipsoid.cpp | 42 +++++- .../Mathematics/Geometry/3D/Objects/Point.cpp | 51 +++++++ .../Geometry/3D/Objects/Segment.cpp | 36 +++++ .../Geometry/3D/Objects/Sphere.cpp | 34 +++++ .../Transformations/Rotations/Quaternion.cpp | 33 +++++ src/Library/Mathematics/Objects/Interval.tpp | 74 ++++++++++- .../Geometry/3D/Objects/Ellipsoid.test.cpp | 125 +++++++++++++++++- .../Geometry/3D/Objects/Point.test.cpp | 26 ++++ .../Geometry/3D/Objects/Segment.test.cpp | 26 ++++ .../Geometry/3D/Objects/Sphere.test.cpp | 26 ++++ .../Rotations/Quaternion.test.cpp | 26 ++++ 19 files changed, 650 insertions(+), 12 deletions(-) diff --git a/include/Library/Mathematics/Geometry/3D/Object.hpp b/include/Library/Mathematics/Geometry/3D/Object.hpp index 7d3e6c73..86963752 100755 --- a/include/Library/Mathematics/Geometry/3D/Object.hpp +++ b/include/Library/Mathematics/Geometry/3D/Object.hpp @@ -12,6 +12,11 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + namespace library { namespace math @@ -23,6 +28,11 @@ namespace d3 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +using library::math::obj::Vector3d ; +using library::math::geom::trf::rot::Quaternion ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + class Intersection ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -48,6 +58,10 @@ class Object virtual Object* clone ( ) const = 0 ; + bool operator == ( const Object& anObject ) const ; + + bool operator != ( const Object& anObject ) const ; + /// @brief Check if object is defined /// /// @return True if object is defined @@ -82,6 +96,10 @@ class Object virtual Intersection computeIntersectionWith ( const Object& anObject ) const ; + virtual void translate ( const Vector3d& aTranslation ) = 0 ; + + virtual void rotate ( const Quaternion& aRotation ) = 0 ; + } ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp index 5b1db353..a8d2074c 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.hpp @@ -227,6 +227,18 @@ class Ellipsoid : public Object Matrix3d getMatrix ( ) const ; + /// @brief Translate ellipsoid + /// + /// @param [in] aTranslation A translation vector + + virtual void translate ( const Vector3d& aTranslation ) override ; + + /// @brief Rotate ellipsoid + /// + /// @param [in] aRotation A rotation quaternion + + virtual void rotate ( const Quaternion& aRotation ) override ; + /// @brief Constructs an undefined ellipsoid /// /// @code diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp index 360b08a6..6345ee6f 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp @@ -76,6 +76,20 @@ class Point : public Object, public Vector3d virtual Point* clone ( ) const override ; + /// @brief Equal to operator + /// + /// @param [in] aPoint A point + /// @return True if points are equal + + bool operator == ( const Point& aPoint ) const ; + + /// @brief Not equal to operator + /// + /// @param [in] aPoint A point + /// @return True if points not are equal + + bool operator != ( const Point& aPoint ) const ; + /// @brief Addition operator: translate point along vector /// /// @code @@ -132,6 +146,18 @@ class Point : public Object, public Vector3d virtual bool isDefined ( ) const override ; + /// @brief Translate point + /// + /// @param [in] aTranslation A translation vector + + virtual void translate ( const Vector3d& aTranslation ) override ; + + /// @brief Rotate point + /// + /// @param [in] aRotation A rotation quaternion + + virtual void rotate ( const Quaternion& aRotation ) override ; + /// @brief Constructs an undefined point /// /// @code diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp index 047e7af7..e7daf84e 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Segment.hpp @@ -199,6 +199,18 @@ class Segment : public Object Real getLength ( ) const ; + /// @brief Translate segment + /// + /// @param [in] aTranslation A translation vector + + virtual void translate ( const Vector3d& aTranslation ) override ; + + /// @brief Rotate segment + /// + /// @param [in] aRotation A rotation quaternion + + virtual void rotate ( const Quaternion& aRotation ) override ; + /// @brief Constructs an undefined segment /// /// @code diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp index 7657637c..d49a3d07 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Sphere.hpp @@ -141,6 +141,18 @@ class Sphere : public Object Real getRadius ( ) const ; + /// @brief Translate sphere + /// + /// @param [in] aTranslation A translation vector + + virtual void translate ( const Vector3d& aTranslation ) override ; + + /// @brief Rotate sphere + /// + /// @param [in] aRotation A rotation quaternion + + virtual void rotate ( const Quaternion& aRotation ) override ; + /// @brief Constructs an undefined sphere /// /// @code diff --git a/include/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.hpp b/include/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.hpp index d96d6ec6..01f37569 100755 --- a/include/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.hpp +++ b/include/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.hpp @@ -179,6 +179,24 @@ class Quaternion Quaternion operator / ( const Quaternion& aQuaternion ) const ; + /// @brief Multiplication assignment operator (quaternion) + /// + /// @note This operator uses cross multiplication + /// + /// @param [in] aQuaternion A quaternion + /// @return A reference to quaternion + + Quaternion& operator *= ( const Quaternion& aQuaternion ) ; + + /// @brief Division assignment operator (quaternion) + /// + /// @note This is equivalent to multiplying with the inverse + /// + /// @param [in] aQuaternion A quaternion + /// @return A reference to quaternion + + Quaternion& operator /= ( const Quaternion& aQuaternion ) ; + /// @brief Output stream operator /// /// @code diff --git a/include/Library/Mathematics/Objects/Interval.hpp b/include/Library/Mathematics/Objects/Interval.hpp index e658e5a4..4b22f6a3 100755 --- a/include/Library/Mathematics/Objects/Interval.hpp +++ b/include/Library/Mathematics/Objects/Interval.hpp @@ -257,7 +257,8 @@ class Interval : public IntervalBase /// @param [in] aStep A step /// @return Array of values - ctnr::Array generateArrayWithStep ( const T& aStep ) const ; + template + ctnr::Array generateArrayWithStep ( const U& aStep ) const ; /// @brief Generate array with a given size /// diff --git a/src/Library/Mathematics/Geometry/3D/Object.cpp b/src/Library/Mathematics/Geometry/3D/Object.cpp index 9aa3bc5d..8520c793 100644 --- a/src/Library/Mathematics/Geometry/3D/Object.cpp +++ b/src/Library/Mathematics/Geometry/3D/Object.cpp @@ -35,6 +35,68 @@ namespace d3 } +bool Object::operator == ( const Object& anObject ) const +{ + + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Segment ; + using library::math::geom::d3::objects::Sphere ; + using library::math::geom::d3::objects::Ellipsoid ; + + if ((!this->isDefined()) && (!anObject.isDefined())) + { + return false ; + } + + if (typeid(*this) != typeid(anObject)) + { + return false ; + } + + if (const Point* objectPtr = dynamic_cast(this)) + { + + if (const Point* otherObjectPtr = dynamic_cast(&anObject)) + { + return (*objectPtr) == (*otherObjectPtr) ; + } + + } + + if (const Segment* objectPtr = dynamic_cast(this)) + { + + if (const Segment* otherObjectPtr = dynamic_cast(&anObject)) + { + return (*objectPtr) == (*otherObjectPtr) ; + } + + } + + if (const Sphere* objectPtr = dynamic_cast(this)) + { + + if (const Sphere* otherObjectPtr = dynamic_cast(&anObject)) + { + return (*objectPtr) == (*otherObjectPtr) ; + } + + } + + if (const Ellipsoid* objectPtr = dynamic_cast(this)) + { + + if (const Ellipsoid* otherObjectPtr = dynamic_cast(&anObject)) + { + return (*objectPtr) == (*otherObjectPtr) ; + } + + } + + return false ; + +} + bool Object::intersects ( const Object& anObject ) const { diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp index 1ad38868..a6b8fca2 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp @@ -145,12 +145,14 @@ bool Ellipsoid::intersects ( const Real a0 = diff.dot(matDiff) - 1.0 ; const Real discriminant = (a1 * a1) - (a0 * a2) ; + + static const Real tolerance = 1e-25 ; // [TBM] Tolerance parameter should be dynamic - if (discriminant < 0.0) // No intersection + if (discriminant < -tolerance) // No real roots { return false ; } - else if (discriminant > 0.0) + else if (discriminant > tolerance) // Two real roots { const Real discriminantRoot = std::sqrt(discriminant) ; @@ -181,7 +183,7 @@ bool Ellipsoid::intersects ( } } - else + else // One real root { const Real t0 = -a1 / a2 ; @@ -367,6 +369,40 @@ Matrix3d Ellipsoid::getMatrix ( ) } +void Ellipsoid::translate ( const Vector3d& aTranslation ) +{ + + if (!aTranslation.isDefined()) + { + throw library::core::error::runtime::Undefined("Translation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Ellipsoid") ; + } + + center_ += aTranslation ; + +} + +void Ellipsoid::rotate ( const Quaternion& aRotation ) +{ + + if (!aRotation.isDefined()) + { + throw library::core::error::runtime::Undefined("Rotation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Ellipsoid") ; + } + + q_ *= aRotation ; + +} + Ellipsoid Ellipsoid::Undefined ( ) { return Ellipsoid(Point::Undefined(), Real::Undefined(), Real::Undefined(), Real::Undefined(), Quaternion::Undefined()) ; diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp index 7865f20d..426c93e6 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp @@ -48,6 +48,23 @@ Point* Point::clone ( ) return new Point(*this) ; } +bool Point::operator == ( const Point& aPoint ) const +{ + + if ((!this->isDefined()) && (!aPoint.isDefined())) + { + return false ; + } + + return this->Vector3d::operator == (aPoint) ; + +} + +bool Point::operator != ( const Point& aPoint ) const +{ + return !((*this) == aPoint) ; +} + Point Point::operator + ( const Vector3d& aVector ) const { @@ -118,6 +135,40 @@ bool Point::isDefined ( ) return Vector3d::isDefined() ; } +void Point::translate ( const Vector3d& aTranslation ) +{ + + if (!aTranslation.isDefined()) + { + throw library::core::error::runtime::Undefined("Translation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + (*this) += aTranslation ; + +} + +void Point::rotate ( const Quaternion& aRotation ) +{ + + if (!aRotation.isDefined()) + { + throw library::core::error::runtime::Undefined("Rotation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + // Do nothing + +} + Point Point::Undefined ( ) { return Vector3d::Undefined() ; diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp index 65560951..ec728ebe 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp @@ -182,6 +182,42 @@ Real Segment::getLength ( ) } +void Segment::translate ( const Vector3d& aTranslation ) +{ + + if (!aTranslation.isDefined()) + { + throw library::core::error::runtime::Undefined("Translation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Segment") ; + } + + firstPoint_ += aTranslation ; + secondPoint_ += aTranslation ; + +} + +void Segment::rotate ( const Quaternion& aRotation ) +{ + + if (!aRotation.isDefined()) + { + throw library::core::error::runtime::Undefined("Rotation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Segment") ; + } + + firstPoint_ = aRotation * firstPoint_ ; + secondPoint_ = aRotation * secondPoint_ ; + +} + Segment Segment::Undefined ( ) { return Segment(Point::Undefined(), Point::Undefined()) ; diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Sphere.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Sphere.cpp index 2d22e809..1e36c3dd 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Sphere.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Sphere.cpp @@ -121,6 +121,40 @@ Real Sphere::getRadius ( ) } +void Sphere::translate ( const Vector3d& aTranslation ) +{ + + if (!aTranslation.isDefined()) + { + throw library::core::error::runtime::Undefined("Translation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Sphere") ; + } + + center_ += aTranslation ; + +} + +void Sphere::rotate ( const Quaternion& aRotation ) +{ + + if (!aRotation.isDefined()) + { + throw library::core::error::runtime::Undefined("Rotation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Sphere") ; + } + + // Do nothing + +} + Sphere Sphere::Undefined ( ) { return Sphere(Point::Undefined(), Real::Undefined()) ; diff --git a/src/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.cpp b/src/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.cpp index 95cdcead..7ccc2ad9 100644 --- a/src/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.cpp +++ b/src/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.cpp @@ -127,6 +127,39 @@ Quaternion Quaternion::operator / ( } +Quaternion& Quaternion::operator *= ( const Quaternion& aQuaternion ) +{ + + if ((!this->isDefined()) || (!aQuaternion.isDefined())) + { + throw library::core::error::runtime::Undefined("Quaternion") ; + } + + (*this) = this->crossMultiply(aQuaternion) ; // [TBI] This is a shortcut... could be optimized + + return *this ; + +} + +Quaternion& Quaternion::operator /= ( const Quaternion& aQuaternion ) +{ + + if ((!this->isDefined()) || (!aQuaternion.isDefined())) + { + throw library::core::error::runtime::Undefined("Quaternion") ; + } + + if (aQuaternion.norm() < Real::Epsilon()) + { + throw library::core::error::RuntimeError("Cannot divide by quaternion with zero norm.") ; + } + + (*this) = this->crossMultiply(aQuaternion.toInverse()) ; // [TBI] This is a shortcut... could be optimized + + return *this ; + +} + std::ostream& operator << ( std::ostream& anOutputStream, const Quaternion& aQuaternion ) { diff --git a/src/Library/Mathematics/Objects/Interval.tpp b/src/Library/Mathematics/Objects/Interval.tpp index a537e9d3..c2b20031 100644 --- a/src/Library/Mathematics/Objects/Interval.tpp +++ b/src/Library/Mathematics/Objects/Interval.tpp @@ -245,11 +245,75 @@ T Interval::getUpperBound ( ) // return Interval::Undefined() ; // [TBI] // } -// template -// ctnr::Array Interval::generateArrayWithStep ( const T& aStep ) const -// { -// return ctnr::Array::Empty() ; // [TBI] -// } + template + template +ctnr::Array Interval::generateArrayWithStep ( const U& aStep ) const +{ + + using library::core::types::Index ; + using library::core::types::Size ; + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Interval") ; + } + + if (!aStep.isDefined()) + { + throw library::core::error::runtime::Undefined("Step") ; + } + + if (aStep.isZero()) + { + throw library::core::error::RuntimeError("Step is zero.") ; + } + + ctnr::Array grid = ctnr::Array::Empty() ; + + if (aStep.isPositive()) + { + + T value = this->accessLowerBound() ; + + while (value <= this->accessUpperBound()) + { + + grid.add(value) ; + + value += aStep ; + + } + + if (grid.accessLast() < this->accessUpperBound()) + { + grid.add(this->accessUpperBound()) ; + } + + } + else + { + + T value = this->accessUpperBound() ; + + while (value >= this->accessLowerBound()) + { + + grid.add(value) ; + + value += aStep ; + + } + + if (grid.accessLast() > this->accessLowerBound()) + { + grid.add(this->accessLowerBound()) ; + } + + } + + return grid ; + +} // template // ctnr::Array Interval::generateArrayWithSize ( const types::Size& anArraySize ) const diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp index 773217c5..968a0545 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp @@ -8,6 +8,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include +#include #include @@ -154,11 +155,103 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, IsDefined) TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Intersects) { - using library::math::geom::d3::objects::Ellipsoid ; + 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::Ellipsoid ; - FAIL() ; + // Segment + + { + + { + + const Ellipsoid ellipsoid = { Point::Origin(), 1.0, 2.0, 3.0 } ; + + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10.0, -3.0, 0.0 }, { +10.0, -3.0, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10.0, -2.1, 0.0 }, { +10.0, -2.1, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, -2.0, 0.0 }, { +10.0, -2.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, -1.0, 0.0 }, { +10.0, -1.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, +0.0, 0.0 }, { +10.0, +0.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, +1.0, 0.0 }, { +10.0, +1.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, +2.0, 0.0 }, { +10.0, +2.0, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10.0, +2.1, 0.0 }, { +10.0, +2.1, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10.0, +3.0, 0.0 }, { +10.0, +3.0, 0.0 }))) ; + + EXPECT_FALSE(ellipsoid.intersects(Segment({ -2.0, -10.0, 0.0 }, { -2.0, +10.0, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -1.1, -10.0, 0.0 }, { -1.1, +10.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -1.0, -10.0, 0.0 }, { -1.0, +10.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ +0.0, -10.0, 0.0 }, { +0.0, +10.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ +1.0, -10.0, 0.0 }, { +1.0, +10.0, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ +1.1, -10.0, 0.0 }, { +1.1, +10.0, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ +2.0, -10.0, 0.0 }, { +2.0, +10.0, 0.0 }))) ; + + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10.0, 0.0, -4.0 }, { +10.0, 0.0, -4.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10.0, 0.0, -3.1 }, { +10.0, 0.0, -3.1 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, 0.0, -3.0 }, { +10.0, 0.0, -3.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, 0.0, -2.0 }, { +10.0, 0.0, -2.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, 0.0, -1.0 }, { +10.0, 0.0, -1.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, 0.0, +0.0 }, { +10.0, 0.0, +0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, 0.0, +1.0 }, { +10.0, 0.0, +1.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, 0.0, +2.0 }, { +10.0, 0.0, +2.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, 0.0, +3.0 }, { +10.0, 0.0, +3.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10.0, 0.0, +3.1 }, { +10.0, 0.0, +3.1 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10.0, 0.0, +4.0 }, { +10.0, 0.0, +4.0 }))) ; + + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10.0, 0.0, 0.0 }, { -1.1, 0.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, 0.0, 0.0 }, { -1.0, 0.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10.0, 0.0, 0.0 }, { -0.9, 0.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ +10.0, 0.0, 0.0 }, { +0.9, 0.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ +10.0, 0.0, 0.0 }, { +1.0, 0.0, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ +10.0, 0.0, 0.0 }, { +1.1, 0.0, 0.0 }))) ; + + } + + { + + const Real equatorialRadius_m = 6378136.3 ; + const Real polarRadius_m = equatorialRadius_m * (1.0 - 0.003352810664747) ; + + const Ellipsoid ellipsoid = { Point::Origin(), equatorialRadius_m, equatorialRadius_m, polarRadius_m } ; + + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10000e3, -7000e3, 0.0 }, { +10000e3, -7000e3, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10000e3, -equatorialRadius_m - 0.1, 0.0 }, { +10000e3, -equatorialRadius_m - 0.1, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10000e3, -equatorialRadius_m, 0.0 }, { +10000e3, -equatorialRadius_m, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10000e3, -equatorialRadius_m + 0.1, 0.0 }, { +10000e3, -equatorialRadius_m + 0.1, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10000e3, +0.0, 0.0 }, { +10000e3, +0.0, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10000e3, +equatorialRadius_m - 0.1, 0.0 }, { +10000e3, +equatorialRadius_m - 0.1, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10000e3, +equatorialRadius_m, 0.0 }, { +10000e3, +equatorialRadius_m, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10000e3, +equatorialRadius_m + 0.1, 0.0 }, { +10000e3, +equatorialRadius_m + 0.1, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10000e3, +7000e3, 0.0 }, { +10000e3, +7000e3, 0.0 }))) ; + + EXPECT_FALSE(ellipsoid.intersects(Segment({ -7000e3, -10000e3, 0.0 }, { -7000e3, +10000e3, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -equatorialRadius_m - 0.1, -10000e3, 0.0 }, { -equatorialRadius_m - 0.1, +10000e3, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -equatorialRadius_m, -10000e3, 0.0 }, { -equatorialRadius_m, +10000e3, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -equatorialRadius_m + 0.1, -10000e3, 0.0 }, { -equatorialRadius_m + 0.1, +10000e3, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ +0.0, -10000e3, 0.0 }, { +0.0, +10000e3, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ +equatorialRadius_m - 0.1, -10000e3, 0.0 }, { +equatorialRadius_m - 0.1, +10000e3, 0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ +equatorialRadius_m, -10000e3, 0.0 }, { +equatorialRadius_m, +10000e3, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ +equatorialRadius_m + 0.1, -10000e3, 0.0 }, { +equatorialRadius_m + 0.1, +10000e3, 0.0 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ +7000e3, -10000e3, 0.0 }, { +7000e3, +10000e3, 0.0 }))) ; + + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10000e3, 0.0, -7000e3 }, { +10000e3, 0.0, -7000e3 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10000e3, 0.0, -polarRadius_m - 0.1 }, { +10000e3, 0.0, -polarRadius_m - 0.1 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10000e3, 0.0, -polarRadius_m }, { +10000e3, 0.0, -polarRadius_m }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10000e3, 0.0, -polarRadius_m + 0.1 }, { +10000e3, 0.0, -polarRadius_m + 0.1 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10000e3, 0.0, +0.0 }, { +10000e3, 0.0, +0.0 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10000e3, 0.0, +polarRadius_m - 0.1 }, { +10000e3, 0.0, +polarRadius_m - 0.1 }))) ; + EXPECT_TRUE(ellipsoid.intersects(Segment({ -10000e3, 0.0, +polarRadius_m }, { +10000e3, 0.0, +polarRadius_m }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10000e3, 0.0, +polarRadius_m + 0.1 }, { +10000e3, 0.0, +polarRadius_m + 0.1 }))) ; + EXPECT_FALSE(ellipsoid.intersects(Segment({ -10000e3, 0.0, +7000e3 }, { +10000e3, 0.0, +7000e3 }))) ; + + } + + { + + EXPECT_ANY_THROW(Ellipsoid(Point::Origin(), 1.0, 1.0, 1.0).intersects(Segment::Undefined())) ; + + } } @@ -332,6 +425,32 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetMatrix) } +TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Translate) +{ + + using library::math::geom::d3::objects::Ellipsoid ; + + { + + FAIL() ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Rotate) +{ + + using library::math::geom::d3::objects::Ellipsoid ; + + { + + FAIL() ; + + } + +} + TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Undefined) { diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp index 3ec085fc..655dfabc 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp @@ -195,6 +195,32 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Point, IsDefined) } +TEST (Library_Mathematics_Geometry_3D_Objects_Point, Translate) +{ + + using library::math::geom::d3::objects::Point ; + + { + + FAIL() ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Point, Rotate) +{ + + using library::math::geom::d3::objects::Point ; + + { + + FAIL() ; + + } + +} + TEST (Library_Mathematics_Geometry_3D_Objects_Point, Undefined) { diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp index e74b991d..98c85271 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp @@ -259,6 +259,32 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Segment, GetLength) } +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Translate) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + FAIL() ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Rotate) +{ + + using library::math::geom::d3::objects::Segment ; + + { + + FAIL() ; + + } + +} + TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Undefined) { diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Sphere.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Sphere.test.cpp index 340d2a1a..13be9bfe 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Sphere.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Sphere.test.cpp @@ -198,6 +198,32 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Sphere, GetRadius) } +TEST (Library_Mathematics_Geometry_3D_Objects_Sphere, Translate) +{ + + using library::math::geom::d3::objects::Sphere ; + + { + + FAIL() ; + + } + +} + +TEST (Library_Mathematics_Geometry_3D_Objects_Sphere, Rotate) +{ + + using library::math::geom::d3::objects::Sphere ; + + { + + FAIL() ; + + } + +} + TEST (Library_Mathematics_Geometry_3D_Objects_Sphere, Undefined) { diff --git a/test/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.test.cpp b/test/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.test.cpp index 5da2e0ff..3d2c14bc 100644 --- a/test/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.test.cpp +++ b/test/Library/Mathematics/Geometry/Transformations/Rotations/Quaternion.test.cpp @@ -165,6 +165,32 @@ TEST (Library_Mathematics_Geometry_Transformations_Rotations_Quaternion, NotEqua // } +// TEST (Library_Mathematics_Geometry_Transformations_Rotations_Quaternion, MultiplicationAssignmentOperator) +// { + +// using library::math::geom::trf::rot::Quaternion ; + +// { + +// FAIL() ; + +// } + +// } + +// TEST (Library_Mathematics_Geometry_Transformations_Rotations_Quaternion, DivisionAssignmentOperator) +// { + +// using library::math::geom::trf::rot::Quaternion ; + +// { + +// FAIL() ; + +// } + +// } + TEST (Library_Mathematics_Geometry_Transformations_Rotations_Quaternion, StreamOperator) { From 8900c5e0309f55e42e952f7b1ee0c5b8c7d9665f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Sun, 26 Aug 2018 12:13:01 -0700 Subject: [PATCH 5/8] [feature] Add Python bindings --- .../src/LibraryMathematicsPy/Geometry.cpp | 4 +- .../src/LibraryMathematicsPy/Geometry/3D.cpp | 29 ++++++++++ .../Geometry/3D/Object.cpp | 38 ++++++++++++ .../Geometry/3D/Objects.cpp | 33 +++++++++++ .../Geometry/3D/Objects/Ellipsoid.cpp | 58 +++++++++++++++++++ .../Geometry/3D/Objects/Point.cpp | 51 ++++++++++++++++ .../Geometry/3D/Objects/Segment.cpp | 50 ++++++++++++++++ .../Geometry/3D/Objects/Sphere.cpp | 48 +++++++++++++++ .../Mathematics/Geometry/3D/Object.cpp | 5 ++ 9 files changed, 315 insertions(+), 1 deletion(-) create mode 100755 share/python/src/LibraryMathematicsPy/Geometry/3D.cpp create mode 100755 share/python/src/LibraryMathematicsPy/Geometry/3D/Object.cpp create mode 100755 share/python/src/LibraryMathematicsPy/Geometry/3D/Objects.cpp create mode 100755 share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Ellipsoid.cpp create mode 100755 share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp create mode 100755 share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Segment.cpp create mode 100755 share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Sphere.cpp diff --git a/share/python/src/LibraryMathematicsPy/Geometry.cpp b/share/python/src/LibraryMathematicsPy/Geometry.cpp index e1c5f6f0..380890ae 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry.cpp @@ -7,8 +7,9 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#include #include +#include +#include //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -22,6 +23,7 @@ inline void LibraryMathematicsPy_Geometry ( ) boost::python::scope scope = module ; LibraryMathematicsPy_Geometry_Angle() ; + LibraryMathematicsPy_Geometry_3D() ; LibraryMathematicsPy_Geometry_Transformations() ; } diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D.cpp new file mode 100755 index 00000000..104df919 --- /dev/null +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D.cpp @@ -0,0 +1,29 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file LibraryMathematicsPy/Geometry/3D.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void LibraryMathematicsPy_Geometry_3D ( ) +{ + + boost::python::object module(boost::python::handle<>(boost::python::borrowed(PyImport_AddModule("Library.Mathematics.Geometry.3D")))) ; + + boost::python::scope().attr("3D") = module ; + + boost::python::scope scope = module ; + + LibraryMathematicsPy_Geometry_3D_Object() ; + LibraryMathematicsPy_Geometry_3D_Objects() ; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Object.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Object.cpp new file mode 100755 index 00000000..f1ba8ed9 --- /dev/null +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Object.cpp @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file LibraryMathematicsPy/Geometry/3D/Object.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void LibraryMathematicsPy_Geometry_3D_Object ( ) +{ + + using namespace boost::python ; + + using library::math::geom::d3::Object ; + + scope in_Object = class_("Object", no_init) + + .def(self == self) + .def(self != self) + + .def("isDefined", &Object::isDefined) + .def("intersects", &Object::intersects) + .def("contains", &Object::contains) + + // .def("computeIntersectionWith", &Object::computeIntersectionWith) + .def("translate", &Object::translate) + .def("rotate", &Object::rotate) + + ; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ 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 new file mode 100755 index 00000000..1f0eb4d2 --- /dev/null +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects.cpp @@ -0,0 +1,33 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file LibraryMathematicsPy/Geometry/3D/Objects.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void LibraryMathematicsPy_Geometry_3D_Objects ( ) +{ + + boost::python::object module(boost::python::handle<>(boost::python::borrowed(PyImport_AddModule("Library.Mathematics.Geometry.3D.Objects")))) ; + + boost::python::scope().attr("Objects") = module ; + + boost::python::scope scope = module ; + + LibraryMathematicsPy_Geometry_3D_Objects_Point() ; + LibraryMathematicsPy_Geometry_3D_Objects_Segment() ; + LibraryMathematicsPy_Geometry_3D_Objects_Sphere() ; + LibraryMathematicsPy_Geometry_3D_Objects_Ellipsoid() ; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Ellipsoid.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Ellipsoid.cpp new file mode 100755 index 00000000..0716dd49 --- /dev/null +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Ellipsoid.cpp @@ -0,0 +1,58 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file LibraryMathematicsPy/Geometry/3D/Objects/Ellipsoid.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void LibraryMathematicsPy_Geometry_3D_Objects_Ellipsoid ( ) +{ + + using namespace boost::python ; + + using library::core::types::Real ; + + 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::objects::Ellipsoid ; + using library::math::geom::trf::rot::Quaternion ; + + scope in_Ellipsoid = class_>("Ellipsoid", init()) + + .def(self == self) + .def(self != self) + + .def(self_ns::str(self_ns::self)) + .def(self_ns::repr(self_ns::self)) + + .def("isDefined", &Ellipsoid::isDefined) + .def("intersects", &Ellipsoid::intersects) + .def("containsPoint", +[] (const Ellipsoid& anEllipsoid, const Point& aPoint) -> bool { return anEllipsoid.contains(aPoint) ; }) + .def("containsSegment", +[] (const Ellipsoid& anEllipsoid, const Segment& aSegment) -> bool { return anEllipsoid.contains(aSegment) ; }) + + .def("getCenter", &Ellipsoid::getCenter) + .def("getFirstPrincipalSemiAxis", &Ellipsoid::getFirstPrincipalSemiAxis) + .def("getSecondPrincipalSemiAxis", &Ellipsoid::getSecondPrincipalSemiAxis) + .def("getThirdPrincipalSemiAxis", &Ellipsoid::getThirdPrincipalSemiAxis) + .def("getFirstAxis", &Ellipsoid::getFirstAxis) + .def("getSecondAxis", &Ellipsoid::getSecondAxis) + .def("getThirdAxis", &Ellipsoid::getThirdAxis) + .def("getOrientation", &Ellipsoid::getOrientation) + .def("getMatrix", &Ellipsoid::getMatrix) + .def("translate", &Ellipsoid::translate) + .def("rotate", &Ellipsoid::rotate) + + .def("Undefined", &Ellipsoid::Undefined).staticmethod("Undefined") + + ; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp new file mode 100755 index 00000000..be1b7be6 --- /dev/null +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp @@ -0,0 +1,51 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void LibraryMathematicsPy_Geometry_3D_Objects_Point ( ) +{ + + 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 ; + + scope in_Point = class_>("Point", init()) + + .def(self == self) + .def(self != self) + + .def(self + other()) + .def(self - other()) + + .def(self - self) + + .def(self_ns::str(self_ns::self)) + + .def("__repr__", +[] (const Point& aPoint) -> std::string { return aPoint.toString() ; }) + + .def("isDefined", &Point::isDefined) + + .def("translate", &Point::translate) + .def("rotate", &Point::rotate) + + .def("Undefined", &Point::Undefined).staticmethod("Undefined") + .def("Origin", &Point::Origin).staticmethod("Origin") + + ; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Segment.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Segment.cpp new file mode 100755 index 00000000..4b4ab369 --- /dev/null +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Segment.cpp @@ -0,0 +1,50 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file LibraryMathematicsPy/Geometry/3D/Objects/Segment.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void LibraryMathematicsPy_Geometry_3D_Objects_Segment ( ) +{ + + using namespace boost::python ; + + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Segment ; + + scope in_Segment = class_>("Segment", init()) + + .def(self == self) + .def(self != self) + + .def(self_ns::str(self_ns::self)) + .def(self_ns::repr(self_ns::self)) + + .def("isDefined", &Segment::isDefined) + .def("isDegenerate", &Segment::isDegenerate) + .def("intersects", &Segment::intersects) + // .def("contains", &Segment::contains) + + .def("getFirstPoint", &Segment::getFirstPoint) + .def("getSecondPoint", &Segment::getSecondPoint) + .def("getCenter", &Segment::getCenter) + .def("getDirection", &Segment::getDirection) + .def("getLength", &Segment::getLength) + .def("translate", &Segment::translate) + .def("rotate", &Segment::rotate) + + .def("Undefined", &Segment::Undefined).staticmethod("Undefined") + + ; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Sphere.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Sphere.cpp new file mode 100755 index 00000000..c911e35a --- /dev/null +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Sphere.cpp @@ -0,0 +1,48 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file LibraryMathematicsPy/Geometry/3D/Objects/Sphere.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void LibraryMathematicsPy_Geometry_3D_Objects_Sphere ( ) +{ + + using namespace boost::python ; + + using library::core::types::Real ; + + using library::math::geom::d3::Object ; + using library::math::geom::d3::objects::Point ; + using library::math::geom::d3::objects::Sphere ; + + scope in_Sphere = class_>("Sphere", init()) + + .def(self == self) + .def(self != self) + + .def(self_ns::str(self_ns::self)) + .def(self_ns::repr(self_ns::self)) + + .def("isDefined", &Sphere::isDefined) + .def("isUnitary", &Sphere::isUnitary) + + .def("getCenter", &Sphere::getCenter) + .def("getRadius", &Sphere::getRadius) + .def("translate", &Sphere::translate) + .def("rotate", &Sphere::rotate) + + .def("Undefined", &Sphere::Undefined).staticmethod("Undefined") + .def("Unit", &Sphere::Unit).staticmethod("Unit") + + ; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/Library/Mathematics/Geometry/3D/Object.cpp b/src/Library/Mathematics/Geometry/3D/Object.cpp index 8520c793..056ba03e 100644 --- a/src/Library/Mathematics/Geometry/3D/Object.cpp +++ b/src/Library/Mathematics/Geometry/3D/Object.cpp @@ -97,6 +97,11 @@ bool Object::operator == ( } +bool Object::operator != ( const Object& anObject ) const +{ + return !((*this) == anObject) ; +} + bool Object::intersects ( const Object& anObject ) const { From e386805c8d91a0acdfed8411e54b06e67eb74a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Sun, 26 Aug 2018 17:07:38 -0700 Subject: [PATCH 6/8] [feature] Improve Python bindings --- share/python/notebooks/Tutorial.ipynb | 628 +++++++++++++++++- .../src/LibraryMathematicsPy/Geometry/3D.cpp | 4 +- .../Geometry/3D/Objects/Ellipsoid.cpp | 2 +- .../Geometry/3D/Objects/Point.cpp | 3 +- .../Geometry/3D/Objects/Segment.cpp | 3 +- 5 files changed, 599 insertions(+), 41 deletions(-) diff --git a/share/python/notebooks/Tutorial.ipynb b/share/python/notebooks/Tutorial.ipynb index 187e6037..abab3ada 100644 --- a/share/python/notebooks/Tutorial.ipynb +++ b/share/python/notebooks/Tutorial.ipynb @@ -23,12 +23,12 @@ "import sys\n", "\n", "! {sys.executable} -m pip install --quiet numpy --upgrade\n", - "# ! {sys.executable} -m pip install --quiet --index-url https://test.pypi.org/simple/ LibraryCorePy==0.1.8" + "! {sys.executable} -m pip install --quiet --index-url https://test.pypi.org/simple/ LibraryCorePy==0.1.8" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -37,7 +37,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 29, "metadata": {}, "outputs": [], "source": [ @@ -68,7 +68,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 30, "metadata": {}, "outputs": [], "source": [ @@ -84,7 +84,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 31, "metadata": {}, "outputs": [], "source": [ @@ -100,7 +100,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 32, "metadata": {}, "outputs": [], "source": [ @@ -122,7 +122,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 33, "metadata": {}, "outputs": [], "source": [ @@ -146,7 +146,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 34, "metadata": {}, "outputs": [], "source": [ @@ -155,7 +155,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 35, "metadata": {}, "outputs": [], "source": [ @@ -164,7 +164,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 36, "metadata": {}, "outputs": [], "source": [ @@ -179,7 +179,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 37, "metadata": {}, "outputs": [], "source": [ @@ -187,6 +187,562 @@ "angle.toString(3) ;" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Mathematics ▸ Geometry ▸ 3D" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [], + "source": [ + "D3 = Geometry.D3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Point" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [], + "source": [ + "Point = D3.Objects.Point" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Point ▸ Constructors**" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "point = Point(0.0, 0.0, 0.0)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [], + "source": [ + "point = Point.Undefined()" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [], + "source": [ + "point = Point.Origin()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Point ▸ Operators**" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "point == point ;\n", + "point != point ;" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "point = point + numpy.array((0.0, 0.0, 0.0)) ;\n", + "point = point - numpy.array((0.0, 0.0, 0.0)) ;" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [], + "source": [ + "vector = point - point ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Point ▸ Methods**" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [], + "source": [ + "point.isDefined() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [], + "source": [ + "point.translate(numpy.array((0.0, 0.0, 0.0))) ;\n", + "point.rotate(Geometry.Transformations.Rotations.Quaternion.Unit()) ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Segment" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [], + "source": [ + "Segment = D3.Objects.Segment" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Segment ▸ Constructors**" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "segment = Segment.Undefined() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [], + "source": [ + "segment = Segment(Point(0.0, 0.0, 0.0), Point(1.0, 0.0, 0.0)) ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Segment ▸ Operators**" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [], + "source": [ + "segment == segment ;\n", + "segment != segment ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Segment ▸ Methods**" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [], + "source": [ + "segment.isDefined() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [], + "source": [ + "segment.isDegenerate() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [], + "source": [ + "# segment.intersectsEllipsoid(D3.Objects.Ellipsoid.Undefined()) ;" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "# segment.contains() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [], + "source": [ + "segment.getFirstPoint() ;\n", + "segment.getSecondPoint() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [], + "source": [ + "segment.getCenter() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [], + "source": [ + "segment.getDirection() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [], + "source": [ + "segment.getLength() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [], + "source": [ + "segment.translate(numpy.array((0.0, 0.0, 0.0))) ;\n", + "segment.rotate(Geometry.Transformations.Rotations.Quaternion.Unit()) ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Sphere" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [], + "source": [ + "Sphere = D3.Objects.Sphere" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Sphere ▸ Constructors**" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [], + "source": [ + "sphere = Sphere(Point.Origin(), 1.0) ;" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [], + "source": [ + "sphere = Sphere.Undefined() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [], + "source": [ + "sphere = Sphere.Unit(Point.Origin()) ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Sphere ▸ Operators**" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [], + "source": [ + "sphere == sphere ;\n", + "sphere != sphere ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Sphere ▸ Methods**" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [], + "source": [ + "sphere.isDefined() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [], + "source": [ + "sphere.isUnitary() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [], + "source": [ + "sphere.getCenter() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [], + "source": [ + "sphere.getRadius() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [], + "source": [ + "sphere.translate(numpy.array((0.0, 0.0, 0.0))) ;\n", + "sphere.rotate(Geometry.Transformations.Rotations.Quaternion.Unit()) ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Ellipsoid" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [], + "source": [ + "Ellipsoid = D3.Objects.Ellipsoid" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Ellipsoid ▸ Constructors**" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid = Ellipsoid.Undefined() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid = Ellipsoid(Point.Origin(), 1.0, 2.0, 3.0, Geometry.Transformations.Rotations.Quaternion.Unit()) ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Ellipsoid ▸ Operators**" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid == ellipsoid ;\n", + "ellipsoid != ellipsoid ;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Mathematics ▸ Geometry ▸ 3D ▸ Objects ▸ Ellipsoid ▸ Methods**" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid.isDefined() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid.intersectsSegment(Segment(Point.Origin(), Point.Origin())) ;" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid.containsPoint(Point.Origin()) ;" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid.containsSegment(Segment(Point.Origin(), Point.Origin())) ;" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid.getCenter() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid.getFirstPrincipalSemiAxis() ;\n", + "ellipsoid.getSecondPrincipalSemiAxis() ;\n", + "ellipsoid.getThirdPrincipalSemiAxis() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid.getFirstAxis() ;\n", + "ellipsoid.getSecondAxis() ;\n", + "ellipsoid.getThirdAxis() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid.getOrientation() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid.getMatrix() ;" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [], + "source": [ + "ellipsoid.translate(numpy.array((0.0, 0.0, 0.0))) ;\n", + "ellipsoid.rotate(Geometry.Transformations.Rotations.Quaternion.Unit()) ;" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -196,7 +752,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 85, "metadata": {}, "outputs": [], "source": [ @@ -212,7 +768,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 86, "metadata": {}, "outputs": [], "source": [ @@ -228,7 +784,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 87, "metadata": {}, "outputs": [], "source": [ @@ -244,7 +800,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 88, "metadata": {}, "outputs": [], "source": [ @@ -267,7 +823,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 89, "metadata": {}, "outputs": [], "source": [ @@ -289,7 +845,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 90, "metadata": {}, "outputs": [], "source": [ @@ -298,7 +854,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 91, "metadata": {}, "outputs": [], "source": [ @@ -307,7 +863,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 92, "metadata": {}, "outputs": [], "source": [ @@ -316,7 +872,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 93, "metadata": {}, "outputs": [], "source": [ @@ -328,7 +884,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 94, "metadata": {}, "outputs": [], "source": [ @@ -338,7 +894,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 95, "metadata": {}, "outputs": [], "source": [ @@ -347,7 +903,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 96, "metadata": {}, "outputs": [], "source": [ @@ -356,7 +912,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 97, "metadata": {}, "outputs": [], "source": [ @@ -365,7 +921,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 98, "metadata": {}, "outputs": [], "source": [ @@ -377,7 +933,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 99, "metadata": {}, "outputs": [], "source": [ @@ -386,7 +942,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 100, "metadata": {}, "outputs": [], "source": [ @@ -395,7 +951,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 101, "metadata": {}, "outputs": [], "source": [ @@ -404,7 +960,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 102, "metadata": {}, "outputs": [], "source": [ @@ -413,7 +969,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 103, "metadata": {}, "outputs": [], "source": [ @@ -422,7 +978,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 104, "metadata": {}, "outputs": [], "source": [ @@ -431,7 +987,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 105, "metadata": {}, "outputs": [], "source": [ @@ -440,7 +996,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 106, "metadata": {}, "outputs": [], "source": [ @@ -449,7 +1005,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 107, "metadata": {}, "outputs": [], "source": [ @@ -465,7 +1021,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 108, "metadata": {}, "outputs": [], "source": [ @@ -523,7 +1079,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 109, "metadata": {}, "outputs": [], "source": [ diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D.cpp index 104df919..0b4a77d3 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D.cpp @@ -15,9 +15,9 @@ inline void LibraryMathematicsPy_Geometry_3D ( ) { - boost::python::object module(boost::python::handle<>(boost::python::borrowed(PyImport_AddModule("Library.Mathematics.Geometry.3D")))) ; + boost::python::object module(boost::python::handle<>(boost::python::borrowed(PyImport_AddModule("Library.Mathematics.Geometry.D3")))) ; - boost::python::scope().attr("3D") = module ; + boost::python::scope().attr("D3") = module ; boost::python::scope scope = module ; diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Ellipsoid.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Ellipsoid.cpp index 0716dd49..92ef4184 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Ellipsoid.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Ellipsoid.cpp @@ -33,7 +33,7 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Ellipso .def(self_ns::repr(self_ns::self)) .def("isDefined", &Ellipsoid::isDefined) - .def("intersects", &Ellipsoid::intersects) + .def("intersectsSegment", +[] (const Ellipsoid& anEllipsoid, const Segment& aSegment) -> bool { return anEllipsoid.intersects(aSegment) ; }) .def("containsPoint", +[] (const Ellipsoid& anEllipsoid, const Point& aPoint) -> bool { return anEllipsoid.contains(aPoint) ; }) .def("containsSegment", +[] (const Ellipsoid& anEllipsoid, const Segment& aSegment) -> bool { return anEllipsoid.contains(aSegment) ; }) diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp index be1b7be6..9f069d9d 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp @@ -22,7 +22,8 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Point ( using library::math::geom::d3::Object ; using library::math::geom::d3::objects::Point ; - scope in_Point = class_>("Point", init()) + // scope in_Point = class_>("Point", init()) // Does not work for some reason + scope in_Point = class_>("Point", init()) .def(self == self) .def(self != self) diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Segment.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Segment.cpp index 4b4ab369..aba7a9cc 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Segment.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Segment.cpp @@ -19,6 +19,7 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Segment 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::objects::Ellipsoid ; scope in_Segment = class_>("Segment", init()) @@ -30,7 +31,7 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Segment .def("isDefined", &Segment::isDefined) .def("isDegenerate", &Segment::isDegenerate) - .def("intersects", &Segment::intersects) + .def("intersectsEllipsoid", +[] (const Segment& aSegment, const Ellipsoid& anEllipsoid) -> bool { return aSegment.intersects(anEllipsoid) ; }) // .def("contains", &Segment::contains) .def("getFirstPoint", &Segment::getFirstPoint) From 8f0f7e5a298a26a01da2245241fc473020bdfcba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Mon, 27 Aug 2018 15:43:04 -0700 Subject: [PATCH 7/8] [feature] Improve tests --- .../Mathematics/Geometry/3D/Object.hpp | 4 + .../Mathematics/Geometry/3D/Objects/Point.hpp | 16 +- .../Rotations/RotationMatrix.hpp | 10 + .../Geometry/3D/Objects/Point.cpp | 1 + .../Geometry/3D/Objects/Ellipsoid.cpp | 14 +- .../Mathematics/Geometry/3D/Objects/Point.cpp | 23 +++ .../Geometry/3D/Objects/Segment.cpp | 42 ++++- .../Rotations/RotationMatrix.cpp | 12 ++ .../Geometry/3D/Objects/Ellipsoid.test.cpp | 171 +++++++++++++++++- .../Geometry/3D/Objects/Point.test.cpp | 58 +++++- .../Geometry/3D/Objects/Segment.test.cpp | 150 ++++++++++++++- .../Geometry/3D/Objects/Sphere.test.cpp | 35 +++- 12 files changed, 511 insertions(+), 25 deletions(-) diff --git a/include/Library/Mathematics/Geometry/3D/Object.hpp b/include/Library/Mathematics/Geometry/3D/Object.hpp index 86963752..e47cdfa3 100755 --- a/include/Library/Mathematics/Geometry/3D/Object.hpp +++ b/include/Library/Mathematics/Geometry/3D/Object.hpp @@ -97,6 +97,10 @@ class Object virtual Intersection computeIntersectionWith ( const Object& anObject ) const ; virtual void translate ( const Vector3d& aTranslation ) = 0 ; + + /// @brief Rotate object around its center, using passive transformation (alias) + /// + /// @param [in] aRotation Rotation quaternion virtual void rotate ( const Quaternion& aRotation ) = 0 ; diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp index 6345ee6f..61219872 100755 --- a/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp +++ b/include/Library/Mathematics/Geometry/3D/Objects/Point.hpp @@ -34,6 +34,7 @@ using library::core::types::Real ; using library::math::obj::Vector3d ; using library::math::geom::d3::Object ; +using library::math::geom::trf::rot::Quaternion ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -139,13 +140,26 @@ class Point : public Object, public Vector3d /// @brief Check if point is defined /// /// @code - /// Point(Vector3d::Zero(), 1.0).isDefined() ; // True + /// Point(0.0, 0.0, 0.0).isDefined() ; // True /// @endcode /// /// @return True if point is defined virtual bool isDefined ( ) const override ; + /// @brief Check if point is near another point + /// + /// @code + /// Point(0.0, 0.0, 0.0).isNear(Point(0.0, 0.0, 0.0), 1e-15) ; // True + /// @endcode + /// + /// @param [in] aPoint A point + /// @param [in] aTolerance A tolerance + /// @return True if point is near another point + + bool isNear ( const Point& aPoint, + const Real& aTolerance ) const ; + /// @brief Translate point /// /// @param [in] aTranslation A translation vector diff --git a/include/Library/Mathematics/Geometry/Transformations/Rotations/RotationMatrix.hpp b/include/Library/Mathematics/Geometry/Transformations/Rotations/RotationMatrix.hpp index 834ac4a9..55b8fea7 100755 --- a/include/Library/Mathematics/Geometry/Transformations/Rotations/RotationMatrix.hpp +++ b/include/Library/Mathematics/Geometry/Transformations/Rotations/RotationMatrix.hpp @@ -158,6 +158,10 @@ class RotationMatrix bool isDefined ( ) const ; + /// @brief Access underlying rotation matrix + /// + /// @return Reference to underlying rotation matrix + const Matrix3d& accessMatrix ( ) const ; /// @brief Get row at index @@ -174,6 +178,12 @@ class RotationMatrix Vector3d getColumnAt ( const Index& aColumnIndex ) const ; + /// @brief Get underlying rotation matrix + /// + /// @return Underlying rotation matrix + + Matrix3d getMatrix ( ) const ; + /// @brief Get transposed rotation matrix /// /// @code diff --git a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp index 9f069d9d..b82eae12 100755 --- a/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp +++ b/share/python/src/LibraryMathematicsPy/Geometry/3D/Objects/Point.cpp @@ -38,6 +38,7 @@ inline void LibraryMathematicsPy_Geometry_3D_Objects_Point ( .def("__repr__", +[] (const Point& aPoint) -> std::string { return aPoint.toString() ; }) .def("isDefined", &Point::isDefined) + .def("isNear", &Point::isNear) .def("translate", &Point::translate) .def("rotate", &Point::rotate) diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp index a6b8fca2..eff71dad 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.cpp @@ -72,9 +72,19 @@ bool Ellipsoid::operator == ( return false ; } - // [TBI] Check for invariants after rotation + if (center_ == anEllipsoid.center_) + { + + if ((a_ == anEllipsoid.a_) && (b_ == anEllipsoid.b_) && (c_ == anEllipsoid.c_) && (q_ == anEllipsoid.q_)) + { + return true ; + } - return (center_ == anEllipsoid.center_) && (a_ == anEllipsoid.a_) && (b_ == anEllipsoid.b_) && (c_ == anEllipsoid.c_) && (q_ == anEllipsoid.q_) ; + return this->getMatrix().isApprox(anEllipsoid.getMatrix(), Real::Epsilon()) ; + + } + + return false ; } diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp index 426c93e6..b79ba3ad 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp @@ -135,6 +135,29 @@ bool Point::isDefined ( ) return Vector3d::isDefined() ; } +bool Point::isNear ( const Point& aPoint, + 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 ; + +} + void Point::translate ( const Vector3d& aTranslation ) { diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp index ec728ebe..c54ced67 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Segment.cpp @@ -107,10 +107,40 @@ bool Segment::intersects ( return anEllipsoid.intersects(*this) ; } -// bool Segment::contains ( const Point& aPoint ) const -// { +bool Segment::contains ( const Point& aPoint ) const +{ -// } + if (!aPoint.isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Segment") ; + } + + if (this->isDegenerate()) + { + return firstPoint_ == aPoint ; + } + + const Vector3d AB = secondPoint_ - firstPoint_ ; + const Vector3d AC = aPoint - firstPoint_ ; + + if (AB.cross(AC).squaredNorm() == 0.0) // Points are aligned + { + + const Real K_AC = AB.dot(AC) ; + const Real K_AB = AB.dot(AB) ; + + return (0.0 <= K_AC) && (K_AC <= K_AB) ; // C between A and B + + } + + return false ; + +} // bool Segment::contains ( const PointSet& aPointSet ) const // { @@ -213,8 +243,10 @@ void Segment::rotate ( throw library::core::error::runtime::Undefined("Segment") ; } - firstPoint_ = aRotation * firstPoint_ ; - secondPoint_ = aRotation * secondPoint_ ; + const Point center = this->getCenter() ; + + firstPoint_ = center + aRotation * (firstPoint_ - center) ; + secondPoint_ = center + aRotation * (secondPoint_ - center) ; } diff --git a/src/Library/Mathematics/Geometry/Transformations/Rotations/RotationMatrix.cpp b/src/Library/Mathematics/Geometry/Transformations/Rotations/RotationMatrix.cpp index 4ab0c072..f8ba9a30 100644 --- a/src/Library/Mathematics/Geometry/Transformations/Rotations/RotationMatrix.cpp +++ b/src/Library/Mathematics/Geometry/Transformations/Rotations/RotationMatrix.cpp @@ -224,6 +224,18 @@ Vector3d RotationMatrix::getColumnAt ( } +Matrix3d RotationMatrix::getMatrix ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Rotation matrix") ; + } + + return matrix_ ; + +} + RotationMatrix RotationMatrix::toTransposed ( ) const { diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp index 968a0545..f92dcdfd 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Ellipsoid.test.cpp @@ -7,6 +7,8 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include #include #include @@ -50,7 +52,10 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Clone) TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, EqualToOperator) { + using library::math::geom::Angle ; using library::math::geom::d3::objects::Ellipsoid ; + using library::math::geom::trf::rot::Quaternion ; + using library::math::geom::trf::rot::RotationVector ; { @@ -67,7 +72,8 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, EqualToOperator) { - // [TBI] Check invariants after rotation + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0) == Ellipsoid({ 1.0, 2.0, 3.0 }, 5.0, 4.0, 6.0, Quaternion::RotationVector(RotationVector({ 0.0, 0.0, 1.0 }, Angle::Degrees(+90.0))))) ; + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0) == Ellipsoid({ 1.0, 2.0, 3.0 }, 5.0, 4.0, 6.0, Quaternion::RotationVector(RotationVector({ 0.0, 0.0, 1.0 }, Angle::Degrees(-90.0))))) ; } @@ -84,7 +90,10 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, EqualToOperator) TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, NotEqualToOperator) { + using library::math::geom::Angle ; using library::math::geom::d3::objects::Ellipsoid ; + using library::math::geom::trf::rot::Quaternion ; + using library::math::geom::trf::rot::RotationVector ; { @@ -101,7 +110,8 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, NotEqualToOperator) { - // [TBI] Check invariants after rotation + EXPECT_FALSE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0) != Ellipsoid({ 1.0, 2.0, 3.0 }, 5.0, 4.0, 6.0, Quaternion::RotationVector(RotationVector({ 0.0, 0.0, 1.0 }, Angle::Degrees(+90.0))))) ; + EXPECT_FALSE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0) != Ellipsoid({ 1.0, 2.0, 3.0 }, 5.0, 4.0, 6.0, Quaternion::RotationVector(RotationVector({ 0.0, 0.0, 1.0 }, Angle::Degrees(-90.0))))) ; } @@ -260,11 +270,47 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Intersects) TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Contains) { + using library::math::geom::d3::objects::Point ; using library::math::geom::d3::objects::Ellipsoid ; + // Point + { - FAIL() ; + { + + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).contains(Point(+5.0, +2.0, +3.0))) ; + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).contains(Point(-3.0, +2.0, +3.0))) ; + + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).contains(Point(+1.0, +7.0, +3.0))) ; + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).contains(Point(+1.0, -3.0, +3.0))) ; + + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).contains(Point(+1.0, +2.0, +9.0))) ; + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).contains(Point(+1.0, +2.0, -3.0))) ; + + } + + { + + EXPECT_FALSE(Ellipsoid(Point::Origin(), 4.0, 5.0, 6.0).contains(Point::Origin())) ; + + } + + { + + EXPECT_ANY_THROW(Ellipsoid::Undefined().contains(Point::Undefined())) ; + EXPECT_ANY_THROW(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).contains(Point::Undefined())) ; + EXPECT_ANY_THROW(Ellipsoid::Undefined().contains(Point(0.0, 0.0, 0.0))) ; + + } + + } + + // PointSet + + { + + // [TBI] } @@ -350,11 +396,25 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetThirdPrincipalSemiAx TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetFirstAxis) { + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::Angle ; using library::math::geom::d3::objects::Ellipsoid ; + using library::math::geom::trf::rot::Quaternion ; + using library::math::geom::trf::rot::RotationVector ; + + { + + EXPECT_EQ(Vector3d(1.0, 0.0, 0.0), Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).getFirstAxis()) ; + + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0, Quaternion::RotationVector(RotationVector({ 0.0, 0.0, 1.0 }, Angle::Degrees(45.0)))).getFirstAxis().isApprox(Vector3d(1.0, 1.0, 0.0).normalized(), Real::Epsilon())) ; + + } { - FAIL() ; + EXPECT_ANY_THROW(Ellipsoid::Undefined().getFirstAxis()) ; } @@ -363,11 +423,25 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetFirstAxis) TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetSecondAxis) { + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::Angle ; using library::math::geom::d3::objects::Ellipsoid ; + using library::math::geom::trf::rot::Quaternion ; + using library::math::geom::trf::rot::RotationVector ; { - FAIL() ; + EXPECT_EQ(Vector3d(0.0, 1.0, 0.0), Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).getSecondAxis()) ; + + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0, Quaternion::RotationVector(RotationVector({ 0.0, 0.0, 1.0 }, Angle::Degrees(45.0)))).getSecondAxis().isApprox(Vector3d(-1.0, 1.0, 0.0).normalized(), Real::Epsilon())) ; + + } + + { + + EXPECT_ANY_THROW(Ellipsoid::Undefined().getSecondAxis()) ; } @@ -376,11 +450,25 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetSecondAxis) TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetThirdAxis) { + using library::core::types::Real ; + + using library::math::obj::Vector3d ; + using library::math::geom::Angle ; using library::math::geom::d3::objects::Ellipsoid ; + using library::math::geom::trf::rot::Quaternion ; + using library::math::geom::trf::rot::RotationVector ; { - FAIL() ; + EXPECT_EQ(Vector3d(0.0, 0.0, 1.0), Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).getThirdAxis()) ; + + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0, Quaternion::RotationVector(RotationVector({ 1.0, 0.0, 0.0 }, Angle::Degrees(45.0)))).getThirdAxis().isApprox(Vector3d(0.0, -1.0, 1.0).normalized(), Real::Epsilon())) ; + + } + + { + + EXPECT_ANY_THROW(Ellipsoid::Undefined().getThirdAxis()) ; } @@ -415,11 +503,46 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetOrientation) TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetMatrix) { + using library::core::types::Real ; + + using library::math::obj::Matrix3d ; + using library::math::geom::Angle ; using library::math::geom::d3::objects::Ellipsoid ; + using library::math::geom::trf::rot::Quaternion ; + using library::math::geom::trf::rot::RotationVector ; + using library::math::geom::trf::rot::RotationMatrix ; + + { + + Matrix3d referenceEllipsoidMatrix ; + + referenceEllipsoidMatrix << 1.0 / (4.0 * 4.0), 0.0, 0.0, + 0.0, 1.0 / (5.0 * 5.0), 0.0, + 0.0, 0.0, 1.0 / (6.0 * 6.0) ; + + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).getMatrix().isApprox(referenceEllipsoidMatrix, Real::Epsilon())) ; + + } + + { + + const Matrix3d referenceRotationMatrix = RotationMatrix::RotationVector(RotationVector({ 0.0, 0.0, 1.0 }, Angle::Degrees(45.0))).getMatrix() ; + + Matrix3d referenceEllipsoidMatrix ; + + referenceEllipsoidMatrix << 1.0 / (4.0 * 4.0), 0.0, 0.0, + 0.0, 1.0 / (5.0 * 5.0), 0.0, + 0.0, 0.0, 1.0 / (6.0 * 6.0) ; + + referenceEllipsoidMatrix = referenceRotationMatrix.transpose() * referenceEllipsoidMatrix * referenceRotationMatrix ; + + EXPECT_TRUE(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0, Quaternion::RotationVector(RotationVector({ 0.0, 0.0, 1.0 }, Angle::Degrees(45.0)))).getMatrix().isApprox(referenceEllipsoidMatrix, Real::Epsilon())) ; + + } { - FAIL() ; + EXPECT_ANY_THROW(Ellipsoid::Undefined().getMatrix()) ; } @@ -428,11 +551,24 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, GetMatrix) TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Translate) { + using library::math::obj::Vector3d ; using library::math::geom::d3::objects::Ellipsoid ; { - FAIL() ; + Ellipsoid ellipsoid = { { 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0 } ; + + ellipsoid.translate({ 4.0, 5.0, 6.0 }) ; + + EXPECT_EQ(Ellipsoid({ 5.0, 7.0, 9.0 }, 4.0, 5.0, 6.0), ellipsoid) ; + + } + + { + + EXPECT_ANY_THROW(Ellipsoid::Undefined().translate(Vector3d::Undefined())) ; + EXPECT_ANY_THROW(Ellipsoid::Undefined().translate({ 0.0, 0.0, 0.0 })) ; + EXPECT_ANY_THROW(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).translate(Vector3d::Undefined())) ; } @@ -441,11 +577,28 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Translate) TEST (Library_Mathematics_Geometry_3D_Objects_Ellipsoid, Rotate) { + using library::core::types::Real ; + + using library::math::geom::Angle ; using library::math::geom::d3::objects::Ellipsoid ; + using library::math::geom::trf::rot::Quaternion ; + using library::math::geom::trf::rot::RotationVector ; + + { + + Ellipsoid ellipsoid = { { 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0 } ; + + ellipsoid.rotate(Quaternion::RotationVector(RotationVector({ 1.0, 0.0, 0.0 }, Angle::Degrees(90.0)))) ; + + EXPECT_EQ(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 6.0, 5.0), ellipsoid) ; + + } { - FAIL() ; + EXPECT_ANY_THROW(Ellipsoid::Undefined().rotate(Quaternion::Undefined())) ; + EXPECT_ANY_THROW(Ellipsoid::Undefined().rotate(Quaternion::Unit())) ; + EXPECT_ANY_THROW(Ellipsoid({ 1.0, 2.0, 3.0 }, 4.0, 5.0, 6.0).rotate(Quaternion::Undefined())) ; } diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp index 655dfabc..e97a2280 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Point.test.cpp @@ -7,6 +7,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include #include #include @@ -195,14 +196,54 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Point, IsDefined) } +TEST (Library_Mathematics_Geometry_3D_Objects_Point, IsNear) +{ + + using library::core::types::Real ; + + using library::math::geom::d3::objects::Point ; + + { + + EXPECT_TRUE(Point(0.0, 0.0, 0.0).isNear(Point(0.0, 0.0, 0.0), 0.0)) ; + EXPECT_TRUE(Point(0.0, 0.0, 0.0).isNear(Point(0.0, 0.0, 1e-15), 1e-15)) ; + + EXPECT_FALSE(Point(0.0, 0.0, 0.0).isNear(Point(0.0, 0.0, 1e-14), 1e-15)) ; + + } + + { + + EXPECT_ANY_THROW(Point::Undefined().isNear(Point::Undefined(), Real::Undefined())) ; + EXPECT_ANY_THROW(Point(0.0, 0.0, 0.0).isNear(Point::Undefined(), 1e-15)) ; + EXPECT_ANY_THROW(Point::Undefined().isNear(Point(0.0, 0.0, 0.0), 1e-15)) ; + EXPECT_ANY_THROW(Point(0.0, 0.0, 0.0).isNear(Point(0.0, 0.0, 0.0), Real::Undefined())) ; + + } + +} + TEST (Library_Mathematics_Geometry_3D_Objects_Point, Translate) { + using library::math::obj::Vector3d ; using library::math::geom::d3::objects::Point ; { - FAIL() ; + Point point = { 1.0, 2.0, 3.0 } ; + + point.translate({ 4.0, 5.0, 6.0 }) ; + + EXPECT_EQ(Point(5.0, 7.0, 9.0), point) ; + + } + + { + + EXPECT_ANY_THROW(Point::Undefined().translate(Vector3d::Undefined())) ; + EXPECT_ANY_THROW(Point::Undefined().translate({ 0.0, 0.0, 0.0 })) ; + EXPECT_ANY_THROW(Point(0.0, 0.0, 0.0).translate(Vector3d::Undefined())) ; } @@ -212,10 +253,23 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Point, Rotate) { using library::math::geom::d3::objects::Point ; + using library::math::geom::trf::rot::Quaternion ; + + { + + Point point = { 1.0, 2.0, 3.0 } ; + + point.rotate(Quaternion::XYZS(1.0, 2.0, 3.0, 4.0).normalize()) ; + + EXPECT_EQ(Point(1.0, 2.0, 3.0), point) ; + + } { - FAIL() ; + EXPECT_ANY_THROW(Point::Undefined().rotate(Quaternion::Undefined())) ; + EXPECT_ANY_THROW(Point::Undefined().rotate(Quaternion::Unit())) ; + EXPECT_ANY_THROW(Point(0.0, 0.0, 0.0).rotate(Quaternion::Undefined())) ; } diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp index 98c85271..0be430db 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Segment.test.cpp @@ -7,6 +7,8 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include #include #include @@ -163,10 +165,58 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Intersects) { using library::math::geom::d3::objects::Segment ; + using library::math::geom::d3::objects::Ellipsoid ; + + // Point { - FAIL() ; + // [TBI] + + } + + // PointSet + + { + + // [TBI] + + } + + // Segment + + { + + // [TBI] + + } + + // Sphere + + { + + // [TBI] + + } + + // Ellipsoid + + { + + { + + // See: Library_Mathematics_Geometry_3D_Objects_Ellipsoid.Intersects + + SUCCEED() ; + + } + + { + + EXPECT_ANY_THROW(Segment::Undefined().intersects(Ellipsoid::Undefined())) ; + EXPECT_ANY_THROW(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }).intersects(Ellipsoid::Undefined())) ; + + } } @@ -175,12 +225,71 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Intersects) TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Contains) { + using library::math::geom::d3::objects::Point ; using library::math::geom::d3::objects::Segment ; + // Point + + { + + { + + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }).contains(Point(0.0, 0.0, 0.0))) ; + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).contains(Point(0.0, 0.0, 0.0))) ; + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).contains(Point(0.0, 0.0, 1.0))) ; + EXPECT_TRUE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).contains(Point(0.0, 0.0, 0.5))) ; + + } + + { + + EXPECT_FALSE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }).contains(Point(0.0, 0.0, 0.1))) ; + EXPECT_FALSE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).contains(Point(0.0, 0.0, 2.0))) ; + EXPECT_FALSE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).contains(Point(0.0, 0.0, -1.0))) ; + EXPECT_FALSE(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).contains(Point(1.0, 0.0, 0.0))) ; + + } + + { + + EXPECT_ANY_THROW(Segment::Undefined().contains(Point::Undefined())) ; + EXPECT_ANY_THROW(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 }).contains(Point::Undefined())) ; + EXPECT_ANY_THROW(Segment::Undefined().contains(Point(0.0, 0.0, 0.0))) ; + + } + + } + + // PointSet + { - FAIL() ; + // [TBI] + + } + + // Segment + + { + // [TBI] + + } + + // Sphere + + { + + // [TBI] + + } + + // Ellipsoid + + { + + // [TBI] + } } @@ -262,11 +371,24 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Segment, GetLength) TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Translate) { + using library::math::obj::Vector3d ; using library::math::geom::d3::objects::Segment ; { - FAIL() ; + Segment segment = { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 } } ; + + segment.translate({ 4.0, 5.0, 6.0 }) ; + + EXPECT_EQ(Segment({ 4.0, 5.0, 6.0 }, { 4.0, 5.0, 7.0 }), segment) ; + + } + + { + + EXPECT_ANY_THROW(Segment::Undefined().translate(Vector3d::Undefined())) ; + EXPECT_ANY_THROW(Segment::Undefined().translate({ 0.0, 0.0, 0.0 })) ; + EXPECT_ANY_THROW(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).translate(Vector3d::Undefined())) ; } @@ -275,11 +397,31 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Translate) TEST (Library_Mathematics_Geometry_3D_Objects_Segment, Rotate) { + using library::core::types::Real ; + + using library::math::geom::Angle ; using library::math::geom::d3::objects::Segment ; + using library::math::geom::trf::rot::Quaternion ; + using library::math::geom::trf::rot::RotationVector ; + + { + + Segment segment = { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 } } ; + + segment.rotate(Quaternion::RotationVector(RotationVector({ 1.0, 0.0, 0.0 }, Angle::Degrees(90.0)))) ; + + const Segment referenceSegment = { { 0.0, -0.5, +0.5 }, { 0.0, +0.5, +0.5 } } ; + + EXPECT_TRUE(segment.getFirstPoint().isNear(referenceSegment.getFirstPoint(), Real::Epsilon())) ; + EXPECT_TRUE(segment.getSecondPoint().isNear(referenceSegment.getSecondPoint(), Real::Epsilon())) ; + + } { - FAIL() ; + EXPECT_ANY_THROW(Segment::Undefined().rotate(Quaternion::Undefined())) ; + EXPECT_ANY_THROW(Segment::Undefined().rotate(Quaternion::Unit())) ; + EXPECT_ANY_THROW(Segment({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).rotate(Quaternion::Undefined())) ; } diff --git a/test/Library/Mathematics/Geometry/3D/Objects/Sphere.test.cpp b/test/Library/Mathematics/Geometry/3D/Objects/Sphere.test.cpp index 13be9bfe..49bc7131 100644 --- a/test/Library/Mathematics/Geometry/3D/Objects/Sphere.test.cpp +++ b/test/Library/Mathematics/Geometry/3D/Objects/Sphere.test.cpp @@ -7,6 +7,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#include #include #include @@ -201,11 +202,24 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Sphere, GetRadius) TEST (Library_Mathematics_Geometry_3D_Objects_Sphere, Translate) { + using library::math::obj::Vector3d ; using library::math::geom::d3::objects::Sphere ; { - FAIL() ; + Sphere sphere = { { 1.0, 2.0, 3.0 }, 4.0 } ; + + sphere.translate({ 4.0, 5.0, 6.0 }) ; + + EXPECT_EQ(Sphere({ 5.0, 7.0, 9.0 }, 4.0), sphere) ; + + } + + { + + EXPECT_ANY_THROW(Sphere::Undefined().translate(Vector3d::Undefined())) ; + EXPECT_ANY_THROW(Sphere::Undefined().translate({ 0.0, 0.0, 0.0 })) ; + EXPECT_ANY_THROW(Sphere({ 1.0, 2.0, 3.0 }, 4.0).translate(Vector3d::Undefined())) ; } @@ -214,11 +228,28 @@ TEST (Library_Mathematics_Geometry_3D_Objects_Sphere, Translate) TEST (Library_Mathematics_Geometry_3D_Objects_Sphere, Rotate) { + using library::core::types::Real ; + + using library::math::geom::Angle ; using library::math::geom::d3::objects::Sphere ; + using library::math::geom::trf::rot::Quaternion ; + using library::math::geom::trf::rot::RotationVector ; + + { + + Sphere sphere = { { 1.0, 2.0, 3.0 }, 4.0 } ; + + sphere.rotate(Quaternion::RotationVector(RotationVector({ 1.0, 0.0, 0.0 }, Angle::Degrees(90.0)))) ; + + EXPECT_EQ(Sphere({ 1.0, 2.0, 3.0 }, 4.0), sphere) ; + + } { - FAIL() ; + EXPECT_ANY_THROW(Sphere::Undefined().rotate(Quaternion::Undefined())) ; + EXPECT_ANY_THROW(Sphere::Undefined().rotate(Quaternion::Unit())) ; + EXPECT_ANY_THROW(Sphere::Unit({ 1.0, 2.0, 3.0 }).rotate(Quaternion::Undefined())) ; } From 8bb65175b4217f73d98dc386a304a3c1ab68df0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Br=C3=A9mond?= Date: Mon, 27 Aug 2018 18:02:24 -0700 Subject: [PATCH 8/8] [feature] Add 2D geometry --- .../Mathematics/Geometry/2D/Object.hpp | 106 +++++ .../Mathematics/Geometry/2D/Objects/Point.hpp | 200 +++++++++ .../Geometry/2D/Objects/Polygon.hpp | 181 ++++++++ .../Mathematics/Geometry/3D/Objects/Plane.hpp | 173 ++++++++ .../Geometry/3D/Objects/Polygon.hpp | 158 +++++++ .../Geometry/3D/Objects/Pyramid.hpp | 174 ++++++++ .../Mathematics/Geometry/2D/Object.cpp | 121 +++++ .../Mathematics/Geometry/2D/Objects/Point.cpp | 195 ++++++++ .../Geometry/2D/Objects/Polygon.cpp | 374 ++++++++++++++++ .../Mathematics/Geometry/3D/Objects/Point.cpp | 2 +- .../Geometry/2D/Objects/Point.test.cpp | 279 ++++++++++++ .../Geometry/2D/Objects/Polygon.test.cpp | 415 ++++++++++++++++++ tools/.env | 2 +- tools/development/docker/Dockerfile | 6 +- 14 files changed, 2381 insertions(+), 5 deletions(-) create mode 100755 include/Library/Mathematics/Geometry/2D/Object.hpp create mode 100755 include/Library/Mathematics/Geometry/2D/Objects/Point.hpp create mode 100755 include/Library/Mathematics/Geometry/2D/Objects/Polygon.hpp create mode 100755 include/Library/Mathematics/Geometry/3D/Objects/Plane.hpp create mode 100755 include/Library/Mathematics/Geometry/3D/Objects/Polygon.hpp create mode 100755 include/Library/Mathematics/Geometry/3D/Objects/Pyramid.hpp create mode 100644 src/Library/Mathematics/Geometry/2D/Object.cpp create mode 100644 src/Library/Mathematics/Geometry/2D/Objects/Point.cpp create mode 100644 src/Library/Mathematics/Geometry/2D/Objects/Polygon.cpp create mode 100644 test/Library/Mathematics/Geometry/2D/Objects/Point.test.cpp create mode 100644 test/Library/Mathematics/Geometry/2D/Objects/Polygon.test.cpp diff --git a/include/Library/Mathematics/Geometry/2D/Object.hpp b/include/Library/Mathematics/Geometry/2D/Object.hpp new file mode 100755 index 00000000..bb45b029 --- /dev/null +++ b/include/Library/Mathematics/Geometry/2D/Object.hpp @@ -0,0 +1,106 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/2D/Object.hpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __Library_Mathematics_Geometry_2D_Object__ +#define __Library_Mathematics_Geometry_2D_Object__ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d2 +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using library::math::obj::Vector2d ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @brief 2D object + +class Object +{ + + public: + + /// @brief Default constructor + + Object ( ) = default ; + + /// @brief Destructor (pure virtual) + + virtual ~Object ( ) = 0 ; + + /// @brief Clone object (pure virtual) + /// + /// @return Pointer to cloned object + + virtual Object* clone ( ) const = 0 ; + + bool operator == ( const Object& anObject ) const ; + + bool operator != ( const Object& anObject ) const ; + + /// @brief Check if object is defined + /// + /// @return True if object is defined + + virtual bool isDefined ( ) const = 0 ; + + /// @brief Check if object intersects another object + /// + /// @code + /// Unique objectUPtr = ... ; + /// Unique anotherObjectUPtr = ... ; + /// objectUPtr->intersects(*anotherObjectUPtr) ; + /// @endcode + /// + /// @param [in] anObject An object + /// @return True if object intersects another object + + virtual bool intersects ( const Object& anObject ) const ; + + /// @brief Check if object contains another object + /// + /// @code + /// Unique objectUPtr = ... ; + /// Unique anotherObjectUPtr = ... ; + /// objectUPtr->contains(*anotherObjectUPtr) ; + /// @endcode + /// + /// @param [in] anObject An object + /// @return True if object contains another object + + virtual bool contains ( const Object& anObject ) const ; + + virtual void translate ( const Vector2d& aTranslation ) = 0 ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/include/Library/Mathematics/Geometry/2D/Objects/Point.hpp b/include/Library/Mathematics/Geometry/2D/Objects/Point.hpp new file mode 100755 index 00000000..fbb76a43 --- /dev/null +++ b/include/Library/Mathematics/Geometry/2D/Objects/Point.hpp @@ -0,0 +1,200 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/2D/Objects/Point.hpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __Library_Mathematics_Geometry_2D_Objects_Point__ +#define __Library_Mathematics_Geometry_2D_Objects_Point__ + +#include +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d2 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using library::core::types::Real ; + +using library::math::obj::Vector2d ; +using library::math::geom::d2::Object ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @brief Point +/// +/// @ref https://en.wikipedia.org/wiki/Point_(geometry) + +class Point : public Object, public Vector2d +{ + + public: + + /// @brief Constructor + /// + /// @code + /// Point point(0.0, 0.0) ; + /// @endcode + /// + /// @param [in] aFirstCoordinate A first coordinate + /// @param [in] aSecondCoordinate A second coordinate + + Point ( const Real& aFirstCoordinate, + const Real& aSecondCoordinate ) ; + + /// @brief Constructor + /// + /// @code + /// Point point({ 0.0, 0.0 }) ; + /// @endcode + /// + /// @param [in] aVector A position vector + + Point ( const Vector2d& aVector ) ; + + /// @brief Clone point + /// + /// @return Pointer to cloned point + + virtual Point* clone ( ) const override ; + + /// @brief Equal to operator + /// + /// @param [in] aPoint A point + /// @return True if points are equal + + bool operator == ( const Point& aPoint ) const ; + + /// @brief Not equal to operator + /// + /// @param [in] aPoint A point + /// @return True if points not are equal + + bool operator != ( const Point& aPoint ) const ; + + /// @brief Addition operator: translate point along vector + /// + /// @code + /// Point(0.0, 0.0) + Vector2d(0.0, 1.0) ; // [0.0, 1.0] + /// @encode + /// + /// @param [in] aVector A translation vector + /// @return A point + + Point operator + ( const Vector2d& aVector ) const ; + + /// @brief Subtraction operator: translate point along opposite vector + /// + /// @code + /// Point(0.0, 1.0) - Vector2d(0.0, 1.0) ; // [0.0, 0.0] + /// @encode + /// + /// @param [in] aVector A translation vector + /// @return A point + + Point operator - ( const Vector2d& aVector ) const ; + + /// @brief Subtraction operator: get translation vector between two points + /// + /// @code + /// Point(0.0, 1.0) - Point(0.0, 0.0) ; // [0.0, 1.0] + /// @encode + /// + /// @param [in] aPoint A point + /// @return A translation vector + + Vector2d operator - ( const Point& aPoint ) const ; + + /// @brief Output stream operator + /// + /// @code + /// std::cout << Point(0.0, 0.0) ; + /// @endcode + /// + /// @param [in] anOutputStream An output stream + /// @param [in] aPoint A point + /// @return An output stream + + friend std::ostream& operator << ( std::ostream& anOutputStream, + const Point& aPoint ) ; + + /// @brief Check if point is defined + /// + /// @code + /// Point(0.0, 0.0).isDefined() ; // True + /// @endcode + /// + /// @return True if point is defined + + virtual bool isDefined ( ) const override ; + + /// @brief Check if point is near another point + /// + /// @code + /// Point(0.0, 0.0).isNear(Point(0.0, 0.0), 1e-15) ; // True + /// @endcode + /// + /// @param [in] aPoint A point + /// @param [in] aTolerance A tolerance + /// @return True if point is near another point + + bool isNear ( const Point& aPoint, + const Real& aTolerance ) const ; + + /// @brief Translate point + /// + /// @param [in] aTranslation A translation vector + + virtual void translate ( const Vector2d& aTranslation ) override ; + + /// @brief Constructs an undefined point + /// + /// @code + /// Point point = Point::Undefined() ; // Undefined + /// @endcode + /// + /// @return Undefined point + + static Point Undefined ( ) ; + + /// @brief Constructs a point at origin + /// + /// @code + /// Point point = Point::Origin() ; // [0.0, 0.0] + /// @endcode + /// + /// @return Point at origin + + static Point Origin ( ) ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/include/Library/Mathematics/Geometry/2D/Objects/Polygon.hpp b/include/Library/Mathematics/Geometry/2D/Objects/Polygon.hpp new file mode 100755 index 00000000..9fd7c5c8 --- /dev/null +++ b/include/Library/Mathematics/Geometry/2D/Objects/Polygon.hpp @@ -0,0 +1,181 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/2D/Objects/Polygon.hpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __Library_Mathematics_Geometry_2D_Objects_Polygon__ +#define __Library_Mathematics_Geometry_2D_Objects_Polygon__ + +#include +#include + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d2 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using library::core::types::Unique ; +using library::core::ctnr::Array ; + +using library::math::geom::d2::Object ; +using library::math::geom::d2::objects::Point ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @brief Polygon +/// +/// A polygon is a plane figure that is bounded by a finite chain of straight line segments closing in a loop +/// to form a closed polygonal chain or circuit. +/// These segments are called its edges, and the points where two edges meet are the polygon's vertices. +/// +/// @ref https://en.wikipedia.org/wiki/Polygon + +class Polygon : public Object +{ + + public: + + /// @brief Constructor + /// + /// @code + /// + /// @endcode + /// + /// @param [in] anOuterRing An outer ring + /// @param [in] anInnerRingArray An array of inner rings + + Polygon ( const Array& anOuterRing, + const Array>& anInnerRingArray = Array>::Empty() ) ; + + /// @brief Copy constructor + /// + /// @param [in] aPolygon A polygon + + Polygon ( const Polygon& aPolygon ) ; + + /// @brief Destructor (virtual) + + virtual ~Polygon ( ) override ; + + /// @brief Copy assignment operator + /// + /// @param [in] aPolygon A polygon + /// @return Reference to polygon + + Polygon& operator = ( const Polygon& aPolygon ) ; + + /// @brief Clone polygon + /// + /// @return Pointer to cloned polygon + + virtual Polygon* clone ( ) const override ; + + /// @brief Equal to operator + /// + /// @code + /// + /// @endcode + /// + /// @param [in] aPolygon A polygon + /// @return True if polygons are equal + + bool operator == ( const Polygon& aPolygon ) const ; + + /// @brief Not equal to operator + /// + /// @code + /// + /// @endcode + /// + /// @param [in] aPolygon A polygon + /// @return True if polygons not are equal + + bool operator != ( const Polygon& aPolygon ) const ; + + /// @brief Output stream operator + /// + /// @code + /// std::cout << Polygon(...) ; + /// @endcode + /// + /// @param [in] anOutputStream An output stream + /// @param [in] aPolygon A polygon + /// @return An output stream + + friend std::ostream& operator << ( std::ostream& anOutputStream, + const Polygon& aPolygon ) ; + + /// @brief Check if polygon is defined + /// + /// @code + /// + /// @endcode + /// + /// @return True if polygon is defined + + virtual bool isDefined ( ) const override ; + + /// @brief Get polygon vertices + /// + /// @code + /// + /// @endcode + /// + /// @return Polygon vertices + + Array getVertices ( ) const ; + + /// @brief Translate polygon + /// + /// @param [in] aTranslation A translation vector + + virtual void translate ( const Vector2d& aTranslation ) override ; + + /// @brief Constructs an undefined polygon + /// + /// @code + /// Polygon polygon = Polygon::Undefined() ; // Undefined + /// @endcode + /// + /// @return Undefined polygon + + static Polygon Undefined ( ) ; + + private: + + class Impl ; + + Unique implUPtr_ ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Plane.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Plane.hpp new file mode 100755 index 00000000..016aed1b --- /dev/null +++ b/include/Library/Mathematics/Geometry/3D/Objects/Plane.hpp @@ -0,0 +1,173 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Plane.hpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __Library_Mathematics_Geometry_3D_Objects_Plane__ +#define __Library_Mathematics_Geometry_3D_Objects_Plane__ + +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using library::math::obj::Vector3d ; +using library::math::geom::d3::Object ; +using library::math::geom::d3::objects::Point ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @brief Plane +/// +/// A plane is a flat, two-dimensional surface that extends infinitely far. +/// +/// @ref https://en.wikipedia.org/wiki/Plane_(geometry) + +class Plane : public Object +{ + + public: + + /// @brief Constructor + /// + /// @code + /// Plane plane({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) ; + /// @endcode + /// + /// @param [in] aPoint A point + /// @param [in] aNormalVector A normal vector + + Plane ( const Point& aPoint, + const Vector3d& aNormalVector ) ; + + /// @brief Clone plane + /// + /// @return Pointer to cloned plane + + virtual Plane* clone ( ) const override ; + + /// @brief Equal to operator + /// + /// @code + /// Plane({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) == Plane({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) ; // True + /// @endcode + /// + /// @param [in] aPlane A plane + /// @return True if planes are equal + + bool operator == ( const Plane& aPlane ) const ; + + /// @brief Not equal to operator + /// + /// @code + /// Plane({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) != Plane({ 0.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0 }) ; // True + /// @endcode + /// + /// @param [in] aPlane A plane + /// @return True if planes not are equal + + bool operator != ( const Plane& aPlane ) const ; + + /// @brief Output stream operator + /// + /// @code + /// std::cout << Plane({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }) ; + /// @endcode + /// + /// @param [in] anOutputStream An output stream + /// @param [in] aPlane A plane + /// @return An output stream + + friend std::ostream& operator << ( std::ostream& anOutputStream, + const Plane& aPlane ) ; + + /// @brief Check if plane is defined + /// + /// @code + /// Plane({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).isDefined() ; // True + /// @endcode + /// + /// @return True if plane is defined + + virtual bool isDefined ( ) const override ; + + /// @brief Get plane point + /// + /// @code + /// Plane({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).getPoint() ; // [0.0, 0.0, 0.0] + /// @endcode + /// + /// @return Plane point + + Point getPoint ( ) const ; + + /// @brief Get plane normal vector + /// + /// @code + /// Plane({ 0.0, 0.0, 0.0 }, { 0.0, 0.0, 1.0 }).getNormalVector() ; // [0.0, 0.0, 1.0] + /// @endcode + /// + /// @return Plane normal vector + + Vector3d getNormalVector ( ) const ; + + /// @brief Translate plane + /// + /// @param [in] aTranslation A translation vector + + virtual void translate ( const Vector3d& aTranslation ) override ; + + /// @brief Rotate plane + /// + /// @param [in] aRotation A rotation quaternion + + virtual void rotate ( const Quaternion& aRotation ) override ; + + /// @brief Constructs an undefined plane + /// + /// @code + /// Plane plane = Plane::Undefined() ; // Undefined + /// @endcode + /// + /// @return Undefined plane + + static Plane Undefined ( ) ; + + private: + + Point point_ ; + Vector3d normal_ ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Polygon.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Polygon.hpp new file mode 100755 index 00000000..f51f1200 --- /dev/null +++ b/include/Library/Mathematics/Geometry/3D/Objects/Polygon.hpp @@ -0,0 +1,158 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Polygon.hpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __Library_Mathematics_Geometry_3D_Objects_Polygon__ +#define __Library_Mathematics_Geometry_3D_Objects_Polygon__ + +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using Polygon2d = library::math::geom::d2::objects::Polygon ; + +using library::math::geom::d3::Object ; +using library::math::geom::d3::objects::Point ; +using library::math::geom::d3::objects::Plane ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @brief Polygon +/// +/// A polygon is a plane figure that is bounded by a finite chain of straight line segments closing in a loop +/// to form a closed polygonal chain or circuit. +/// These segments are called its edges, and the points where two edges meet are the polygon's vertices. +/// +/// @ref https://en.wikipedia.org/wiki/Polygon + +class Polygon : public Object +{ + + public: + + /// @brief Constructor + /// + /// @code + /// + /// @endcode + /// + /// @param [in] aBase A polygon base + /// @param [in] anApex A polygon apex + + // Polygon ( const Polygon2d& aPolygon, + // const Point& anApex ) ; + + /// @brief Clone polygon + /// + /// @return Pointer to cloned polygon + + virtual Polygon* clone ( ) const override ; + + /// @brief Equal to operator + /// + /// @code + /// + /// @endcode + /// + /// @param [in] aPolygon A polygon + /// @return True if polygons are equal + + bool operator == ( const Polygon& aPolygon ) const ; + + /// @brief Not equal to operator + /// + /// @code + /// + /// @endcode + /// + /// @param [in] aPolygon A polygon + /// @return True if polygons not are equal + + bool operator != ( const Polygon& aPolygon ) const ; + + /// @brief Output stream operator + /// + /// @code + /// std::cout << Polygon(...) ; + /// @endcode + /// + /// @param [in] anOutputStream An output stream + /// @param [in] aPolygon A polygon + /// @return An output stream + + friend std::ostream& operator << ( std::ostream& anOutputStream, + const Polygon& aPolygon ) ; + + /// @brief Check if polygon is defined + /// + /// @code + /// + /// @endcode + /// + /// @return True if polygon is defined + + virtual bool isDefined ( ) const override ; + + /// @brief Translate polygon + /// + /// @param [in] aTranslation A translation vector + + virtual void translate ( const Vector3d& aTranslation ) override ; + + /// @brief Rotate polygon + /// + /// @param [in] aRotation A rotation quaternion + + virtual void rotate ( const Quaternion& aRotation ) override ; + + /// @brief Constructs an undefined polygon + /// + /// @code + /// Polygon polygon = Polygon::Undefined() ; // Undefined + /// @endcode + /// + /// @return Undefined polygon + + static Polygon Undefined ( ) ; + + private: + + Polygon2d polygon_ ; + // Transformation transformation_ ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/include/Library/Mathematics/Geometry/3D/Objects/Pyramid.hpp b/include/Library/Mathematics/Geometry/3D/Objects/Pyramid.hpp new file mode 100755 index 00000000..b0661a95 --- /dev/null +++ b/include/Library/Mathematics/Geometry/3D/Objects/Pyramid.hpp @@ -0,0 +1,174 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/3D/Objects/Pyramid.hpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __Library_Mathematics_Geometry_3D_Objects_Pyramid__ +#define __Library_Mathematics_Geometry_3D_Objects_Pyramid__ + +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d3 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using library::math::geom::d3::Object ; +using library::math::geom::d3::objects::Point ; +using library::math::geom::d3::objects::Polygon ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @brief Pyramid +/// +/// A pyramid is a polyhedron formed by connecting a polygonal base and a point, called the apex. +/// Each base edge and apex form a triangle, called a lateral face. +/// +/// @ref https://en.wikipedia.org/wiki/Pyramid_(geometry) + +class Pyramid : public Object +{ + + public: + + /// @brief Constructor + /// + /// @code + /// + /// @endcode + /// + /// @param [in] aBase A pyramid base + /// @param [in] anApex A pyramid apex + + Pyramid ( const Polygon& aBase, + const Point& anApex ) ; + + /// @brief Clone pyramid + /// + /// @return Pointer to cloned pyramid + + virtual Pyramid* clone ( ) const override ; + + /// @brief Equal to operator + /// + /// @code + /// + /// @endcode + /// + /// @param [in] aPyramid A pyramid + /// @return True if pyramids are equal + + bool operator == ( const Pyramid& aPyramid ) const ; + + /// @brief Not equal to operator + /// + /// @code + /// + /// @endcode + /// + /// @param [in] aPyramid A pyramid + /// @return True if pyramids not are equal + + bool operator != ( const Pyramid& aPyramid ) const ; + + /// @brief Output stream operator + /// + /// @code + /// std::cout << Pyramid(...) ; + /// @endcode + /// + /// @param [in] anOutputStream An output stream + /// @param [in] aPyramid A pyramid + /// @return An output stream + + friend std::ostream& operator << ( std::ostream& anOutputStream, + const Pyramid& aPyramid ) ; + + /// @brief Check if pyramid is defined + /// + /// @code + /// + /// @endcode + /// + /// @return True if pyramid is defined + + virtual bool isDefined ( ) const override ; + + /// @brief Get pyramid base + /// + /// @code + /// + /// @endcode + /// + /// @return Pyramid base + + Polygon getBase ( ) const ; + + /// @brief Get pyramid apex + /// + /// @code + /// + /// @endcode + /// + /// @return Pyramid apex + + Point getApex ( ) const ; + + /// @brief Translate pyramid + /// + /// @param [in] aTranslation A translation vector + + virtual void translate ( const Vector3d& aTranslation ) override ; + + /// @brief Rotate pyramid + /// + /// @param [in] aRotation A rotation quaternion + + virtual void rotate ( const Quaternion& aRotation ) override ; + + /// @brief Constructs an undefined pyramid + /// + /// @code + /// Pyramid pyramid = Pyramid::Undefined() ; // Undefined + /// @endcode + /// + /// @return Undefined pyramid + + static Pyramid Undefined ( ) ; + + private: + + Polygon base_ ; + Point apex_ ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/Library/Mathematics/Geometry/2D/Object.cpp b/src/Library/Mathematics/Geometry/2D/Object.cpp new file mode 100644 index 00000000..55db6f9c --- /dev/null +++ b/src/Library/Mathematics/Geometry/2D/Object.cpp @@ -0,0 +1,121 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/2D/Object.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d2 +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Object::~Object ( ) +{ + +} + +bool Object::operator == ( const Object& anObject ) const +{ + + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + if ((!this->isDefined()) && (!anObject.isDefined())) + { + return false ; + } + + if (typeid(*this) != typeid(anObject)) + { + return false ; + } + + if (const Point* objectPtr = dynamic_cast(this)) + { + + if (const Point* otherObjectPtr = dynamic_cast(&anObject)) + { + return (*objectPtr) == (*otherObjectPtr) ; + } + + } + + if (const Polygon* objectPtr = dynamic_cast(this)) + { + + if (const Polygon* otherObjectPtr = dynamic_cast(&anObject)) + { + return (*objectPtr) == (*otherObjectPtr) ; + } + + } + + return false ; + +} + +bool Object::operator != ( const Object& anObject ) const +{ + return !((*this) == anObject) ; +} + +bool Object::intersects ( const Object& anObject ) const +{ + + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + if (!anObject.isDefined()) + { + throw library::core::error::runtime::Undefined("Object") ; + } + + throw library::core::error::runtime::ToBeImplemented("Object :: intersects") ; + + return false ; + +} + +bool Object::contains ( const Object& anObject ) const +{ + + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + if (!anObject.isDefined()) + { + throw library::core::error::runtime::Undefined("Object") ; + } + + throw library::core::error::runtime::ToBeImplemented("Object :: contains") ; + + return false ; + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ 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 new file mode 100644 index 00000000..6bb8721d --- /dev/null +++ b/src/Library/Mathematics/Geometry/2D/Objects/Point.cpp @@ -0,0 +1,195 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/2D/Objects/Point.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d2 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Point::Point ( const Real& aFirstCoordinate, + const Real& aSecondCoordinate ) + : Object(), + Vector2d(aFirstCoordinate, aSecondCoordinate) +{ + +} + + Point::Point ( const Vector2d& aVector ) + : Object(), + Vector2d(aVector) +{ + +} + +Point* Point::clone ( ) const +{ + return new Point(*this) ; +} + +bool Point::operator == ( const Point& aPoint ) const +{ + + if ((!this->isDefined()) && (!aPoint.isDefined())) + { + return false ; + } + + return this->Vector2d::operator == (aPoint) ; + +} + +bool Point::operator != ( const Point& aPoint ) const +{ + return !((*this) == aPoint) ; +} + +Point Point::operator + ( const Vector2d& aVector ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + if (!aVector.isDefined()) + { + throw library::core::error::runtime::Undefined("Vector") ; + } + + return Point(this->Vector2d::operator + (aVector)) ; + +} + +Point Point::operator - ( const Vector2d& aVector ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + if (!aVector.isDefined()) + { + throw library::core::error::runtime::Undefined("Vector") ; + } + + return Point(this->Vector2d::operator - (aVector)) ; + +} + +Vector2d Point::operator - ( const Point& aPoint ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + if (!aPoint.isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + return this->Vector2d::operator - (aPoint) ; + +} + +std::ostream& operator << ( std::ostream& anOutputStream, + const Point& aPoint ) +{ + + library::core::utils::Print::Header(anOutputStream, "Point") ; + + library::core::utils::Print::Line(anOutputStream) << "Coordinates:" << (aPoint.isDefined() ? aPoint.toString() : "Undefined") ; + + library::core::utils::Print::Footer(anOutputStream) ; + + return anOutputStream ; + +} + +bool Point::isDefined ( ) const +{ + return Vector2d::isDefined() ; +} + +bool Point::isNear ( const Point& aPoint, + 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 ; + +} + +void Point::translate ( const Vector2d& aTranslation ) +{ + + if (!aTranslation.isDefined()) + { + throw library::core::error::runtime::Undefined("Translation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Point") ; + } + + (*this) += aTranslation ; + +} + +Point Point::Undefined ( ) +{ + return Vector2d::Undefined() ; +} + +Point Point::Origin ( ) +{ + return { 0.0, 0.0 } ; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/Library/Mathematics/Geometry/2D/Objects/Polygon.cpp b/src/Library/Mathematics/Geometry/2D/Objects/Polygon.cpp new file mode 100644 index 00000000..f470f630 --- /dev/null +++ b/src/Library/Mathematics/Geometry/2D/Objects/Polygon.cpp @@ -0,0 +1,374 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/2D/Objects/Polygon.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace library +{ +namespace math +{ +namespace geom +{ +namespace d2 +{ +namespace objects +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +using boost::geometry::model::point ; +using boost::geometry::model::polygon ; +using boost::geometry::model::ring ; +using boost::geometry::cs::cartesian ; + +using library::core::types::Index ; +using library::core::types::Size ; +using library::core::types::String ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class Polygon::Impl +{ + + public: + + Impl ( const Array& anOuterRing, + const Array>& anInnerRingArray ) ; + + ~Impl ( ) = default ; + + bool operator == ( const Polygon::Impl& aPolygon ) const ; + + bool isDefined ( ) const ; + + Size getInnerRingCount ( ) const ; + + Array getOuterRingVertices ( ) const ; + + Array getInnerRingVerticesAt ( const Index& aRingIndex ) const ; + + Array getVertices ( ) const ; + + void translate ( const Vector2d& aTranslation ) ; + + private: + + typedef point BoostPoint ; + typedef ring BoostRing ; + typedef polygon BoostPolygon ; + + Impl::BoostPolygon polygon_ ; + + static Impl::BoostPolygon BoostPolygonFromPoints ( const Array& aPointArray ) ; + +} ; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Polygon::Impl::Impl ( const Array& anOuterRing, + const Array>& anInnerRingArray ) + : polygon_(Polygon::Impl::BoostPolygonFromPoints(anOuterRing)) +{ + + for (const auto& innerRing : anInnerRingArray) // [TBM] This is temporary, should construct inline instead + { + + Polygon::Impl::BoostRing ring ; + + for (const auto& innerRingPoint : innerRing) + { + boost::geometry::append(ring, Polygon::Impl::BoostPoint(innerRingPoint.x(), innerRingPoint.y())) ; + } + + polygon_.inners().push_back(ring) ; + + } + +} + +bool Polygon::Impl::operator == ( const Polygon::Impl& aPolygon ) const +{ + return boost::geometry::equals(polygon_, aPolygon.polygon_) ; +} + +bool Polygon::Impl::isDefined ( ) const +{ + return polygon_.outer().size() >= 3 ; +} + +Size Polygon::Impl::getInnerRingCount ( ) const +{ + return polygon_.inners().size() ; +} + +Array Polygon::Impl::getOuterRingVertices ( ) const +{ + + if (polygon_.outer().size() == 0) + { + return Array::Empty() ; + } + + Array outerRingVertices = Array::Empty() ; + + for (size_t vertexIdx = 0; vertexIdx < (polygon_.outer().size() - 1); ++vertexIdx) + { + outerRingVertices.add(Point(boost::geometry::get<0>(polygon_.outer().at(vertexIdx)), boost::geometry::get<1>(polygon_.outer().at(vertexIdx)))) ; + } + + return outerRingVertices ; + +} + +Array Polygon::Impl::getInnerRingVerticesAt ( const Index& aRingIndex ) const +{ + + if (aRingIndex >= this->getInnerRingCount()) + { + throw library::core::error::RuntimeError("Inner ring index [{}] out of bounds [{}].", aRingIndex, this->getInnerRingCount()) ; + } + + if (polygon_.inners().at(aRingIndex).size() == 0) + { + return Array::Empty() ; + } + + Array innerRingVertices = Array::Empty() ; + + for (size_t vertexIdx = 0; vertexIdx < (polygon_.inners().at(aRingIndex).size() - 1); ++vertexIdx) + { + innerRingVertices.add(Point(boost::geometry::get<0>(polygon_.inners().at(aRingIndex).at(vertexIdx)), boost::geometry::get<1>(polygon_.inners().at(aRingIndex).at(vertexIdx)))) ; + } + + return innerRingVertices ; + +} + +Array Polygon::Impl::getVertices ( ) const +{ + + Array vertices = Array::Empty() ; + + for (const auto& vertex : this->getOuterRingVertices()) + { + vertices.add(vertex) ; + } + + for (Index innerRingIndex = 0; innerRingIndex < this->getInnerRingCount(); ++innerRingIndex) + { + for (const auto& vertex : this->getInnerRingVerticesAt(innerRingIndex)) + { + vertices.add(vertex) ; + } + } + + return vertices ; + +} + +void Polygon::Impl::translate ( const Vector2d& aTranslation ) +{ + + Polygon::Impl::BoostPolygon transformedPolygon ; + + boost::geometry::strategy::transform::translate_transformer translate(aTranslation.x(), aTranslation.y()) ; + + boost::geometry::transform(polygon_, transformedPolygon, translate) ; + + polygon_ = transformedPolygon ; + +} + +Polygon::Impl::BoostPolygon Polygon::Impl::BoostPolygonFromPoints ( const Array& aPointArray ) +{ + + Polygon::Impl::BoostPolygon polygon ; + + for (const auto& point : aPointArray) + { + boost::geometry::append(polygon, Polygon::Impl::BoostPoint(point(0), point(1))) ; + } + + boost::geometry::correct(polygon) ; + + return polygon ; + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Polygon::Polygon ( const Array& anOuterRing, + const Array>& anInnerRingArray ) + : Object(), + implUPtr_(std::make_unique(anOuterRing, anInnerRingArray)) +{ + +} + + Polygon::Polygon ( const Polygon& aPolygon ) + : Object(aPolygon), + implUPtr_((aPolygon.implUPtr_ != nullptr) ? new Polygon::Impl(*aPolygon.implUPtr_) : nullptr) +{ + +} + + Polygon::~Polygon ( ) +{ + +} + +Polygon& Polygon::operator = ( const Polygon& aPolygon ) +{ + + if (this != &aPolygon) + { + + Object::operator = (aPolygon) ; + + implUPtr_.reset((aPolygon.implUPtr_ != nullptr) ? new Polygon::Impl(*aPolygon.implUPtr_) : nullptr) ; + + } + + return *this ; + +} + +Polygon* Polygon::clone ( ) const +{ + return new Polygon(*this) ; +} + +bool Polygon::operator == ( const Polygon& aPolygon ) const +{ + + if ((!this->isDefined()) && (!aPolygon.isDefined())) + { + return false ; + } + + return (*implUPtr_) == (*aPolygon.implUPtr_) ; + +} + +bool Polygon::operator != ( const Polygon& aPolygon ) const +{ + return !((*this) == aPolygon) ; +} + +std::ostream& operator << ( std::ostream& anOutputStream, + const Polygon& aPolygon ) +{ + + library::core::utils::Print::Header(anOutputStream, "Polygon") ; + + library::core::utils::Print::Separator(anOutputStream, "Outer Ring") ; + + if (aPolygon.implUPtr_ != nullptr) + { + + for (const auto& point : aPolygon.implUPtr_->getOuterRingVertices()) + { + library::core::utils::Print::Line(anOutputStream) << String::Format("- {}", point.toString()) ; + } + + } + else + { + library::core::utils::Print::Line(anOutputStream) << "Undefined" ; + } + + library::core::utils::Print::Separator(anOutputStream, "Inner Rings") ; + + if (aPolygon.implUPtr_ != nullptr) + { + + for (Index innerRingIndex = 0; innerRingIndex < aPolygon.implUPtr_->getInnerRingCount(); ++innerRingIndex) + { + + library::core::utils::Print::Separator(anOutputStream, String::Format("Inner Ring @ {}", innerRingIndex)) ; + + for (const auto& point : aPolygon.implUPtr_->getInnerRingVerticesAt(innerRingIndex)) + { + library::core::utils::Print::Line(anOutputStream) << String::Format("- {}", point.toString()) ; + } + + } + + } + else + { + library::core::utils::Print::Line(anOutputStream) << "Undefined" ; + } + + library::core::utils::Print::Footer(anOutputStream) ; + + return anOutputStream ; + +} + +bool Polygon::isDefined ( ) const +{ + return (implUPtr_ != nullptr) && implUPtr_->isDefined() ; +} + +Array Polygon::getVertices ( ) const +{ + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Polygon") ; + } + + return implUPtr_->getVertices() ; + +} + +void Polygon::translate ( const Vector2d& aTranslation ) +{ + + if (!aTranslation.isDefined()) + { + throw library::core::error::runtime::Undefined("Translation") ; + } + + if (!this->isDefined()) + { + throw library::core::error::runtime::Undefined("Polygon") ; + } + + implUPtr_->translate(aTranslation) ; + +} + +Polygon Polygon::Undefined ( ) +{ + return { Array::Empty() } ; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} +} +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp index b79ba3ad..df12024a 100644 --- a/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp +++ b/src/Library/Mathematics/Geometry/3D/Objects/Point.cpp @@ -199,7 +199,7 @@ Point Point::Undefined ( ) Point Point::Origin ( ) { - return Point(0.0, 0.0, 0.0) ; + return { 0.0, 0.0, 0.0 } ; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/test/Library/Mathematics/Geometry/2D/Objects/Point.test.cpp b/test/Library/Mathematics/Geometry/2D/Objects/Point.test.cpp new file mode 100644 index 00000000..9bb3868e --- /dev/null +++ b/test/Library/Mathematics/Geometry/2D/Objects/Point.test.cpp @@ -0,0 +1,279 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/2D/Objects/Point.test.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, Constructor) +{ + + using library::math::obj::Vector2d ; + using library::math::geom::d2::objects::Point ; + + { + + EXPECT_NO_THROW(Point(1.0, 2.0)) ; + + } + + { + + EXPECT_NO_THROW(Point(Vector2d({ 1.0, 2.0 }))) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, Clone) +{ + + using library::math::geom::d2::objects::Point ; + + { + + EXPECT_NO_THROW(Point(1.0, 2.0).clone()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, AdditionOperator) +{ + + using library::math::obj::Vector2d ; + using library::math::geom::d2::objects::Point ; + + { + + EXPECT_EQ(Point(1.0, 2.0), Point(1.0, 2.0) + Vector2d(0.0, 0.0)) ; + EXPECT_EQ(Point(2.0, 2.0), Point(1.0, 2.0) + Vector2d(1.0, 0.0)) ; + + } + + { + + EXPECT_ANY_THROW(Point::Undefined() + Vector2d(0.0, 0.0)) ; + EXPECT_ANY_THROW(Point(1.0, 2.0) + Vector2d::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, SubtractionOperator) +{ + + using library::math::obj::Vector2d ; + using library::math::geom::d2::objects::Point ; + + { + + EXPECT_EQ(Point(1.0, 2.0), Point(1.0, 2.0) - Vector2d(0.0, 0.0)) ; + EXPECT_EQ(Point(0.0, 2.0), Point(1.0, 2.0) - Vector2d(1.0, 0.0)) ; + + } + + { + + EXPECT_ANY_THROW(Point::Undefined() - Vector2d(0.0, 0.0)) ; + EXPECT_ANY_THROW(Point(1.0, 2.0) - Vector2d::Undefined()) ; + + } + + { + + EXPECT_EQ(Vector2d(1.0, 2.0), Point(1.0, 2.0) - Point(0.0, 0.0)) ; + EXPECT_EQ(Vector2d(0.0, 2.0), Point(1.0, 2.0) - Point(1.0, 0.0)) ; + + } + + { + + EXPECT_ANY_THROW(Point::Undefined() - Point(0.0, 0.0)) ; + EXPECT_ANY_THROW(Point(1.0, 2.0) - Point::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, EqualToOperator) +{ + + using library::math::geom::d2::objects::Point ; + + { + + EXPECT_TRUE(Point(1.0, 2.0) == Point(1.0, 2.0)) ; + + } + + { + + EXPECT_FALSE(Point(1.0, 2.0) == Point(1.0, 3.0)) ; + + } + + { + + EXPECT_FALSE(Point(1.0, 2.0) == Point::Undefined()) ; + EXPECT_FALSE(Point::Undefined() == Point(1.0, 2.0)) ; + EXPECT_FALSE(Point::Undefined() == Point::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, NotEqualToOperator) +{ + + using library::math::geom::d2::objects::Point ; + + { + + EXPECT_TRUE(Point(1.0, 2.0) != Point(1.0, 3.0)) ; + + } + + { + + EXPECT_FALSE(Point(1.0, 2.0) != Point(1.0, 2.0)) ; + + } + + { + + EXPECT_TRUE(Point(1.0, 2.0) != Point::Undefined()) ; + EXPECT_TRUE(Point::Undefined() != Point(1.0, 2.0)) ; + EXPECT_TRUE(Point::Undefined() != Point::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, StreamOperator) +{ + + using library::math::geom::d2::objects::Point ; + + { + + testing::internal::CaptureStdout() ; + + EXPECT_NO_THROW(std::cout << Point(1.0, 2.0) << std::endl) ; + + EXPECT_FALSE(testing::internal::GetCapturedStdout().empty()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, IsDefined) +{ + + using library::math::geom::d2::objects::Point ; + + { + + EXPECT_TRUE(Point(0.0, 0.0).isDefined()) ; + EXPECT_TRUE(Point(1.0, 2.0).isDefined()) ; + + } + + { + + EXPECT_FALSE(Point::Undefined().isDefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, IsNear) +{ + + using library::core::types::Real ; + + using library::math::geom::d2::objects::Point ; + + { + + EXPECT_TRUE(Point(0.0, 0.0).isNear(Point(0.0, 0.0), 0.0)) ; + EXPECT_TRUE(Point(0.0, 0.0).isNear(Point(0.0, 1e-15), 1e-15)) ; + + EXPECT_FALSE(Point(0.0, 0.0).isNear(Point(0.0, 1e-14), 1e-15)) ; + + } + + { + + EXPECT_ANY_THROW(Point::Undefined().isNear(Point::Undefined(), Real::Undefined())) ; + EXPECT_ANY_THROW(Point(0.0, 0.0).isNear(Point::Undefined(), 1e-15)) ; + EXPECT_ANY_THROW(Point::Undefined().isNear(Point(0.0, 0.0), 1e-15)) ; + EXPECT_ANY_THROW(Point(0.0, 0.0).isNear(Point(0.0, 0.0), Real::Undefined())) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, Translate) +{ + + using library::math::obj::Vector2d ; + using library::math::geom::d2::objects::Point ; + + { + + Point point = { 1.0, 2.0 } ; + + point.translate({ 4.0, 5.0 }) ; + + EXPECT_EQ(Point(5.0, 7.0), point) ; + + } + + { + + EXPECT_ANY_THROW(Point::Undefined().translate(Vector2d::Undefined())) ; + EXPECT_ANY_THROW(Point::Undefined().translate({ 0.0, 0.0 })) ; + EXPECT_ANY_THROW(Point(0.0, 0.0).translate(Vector2d::Undefined())) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, Undefined) +{ + + using library::math::geom::d2::objects::Point ; + + { + + EXPECT_NO_THROW(Point::Undefined()) ; + EXPECT_FALSE(Point::Undefined().isDefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Point, Origin) +{ + + using library::math::geom::d2::objects::Point ; + + { + + EXPECT_NO_THROW(Point::Origin()) ; + EXPECT_EQ(Point(0.0, 0.0), Point::Origin()) ; + + } + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/test/Library/Mathematics/Geometry/2D/Objects/Polygon.test.cpp b/test/Library/Mathematics/Geometry/2D/Objects/Polygon.test.cpp new file mode 100644 index 00000000..76059086 --- /dev/null +++ b/test/Library/Mathematics/Geometry/2D/Objects/Polygon.test.cpp @@ -0,0 +1,415 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/// @project Library/Mathematics +/// @file Library/Mathematics/Geometry/2D/Objects/Polygon.test.cpp +/// @author Lucas Brémond +/// @license TBD + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST (Library_Mathematics_Geometry_2D_Objects_Polygon, Constructor) +{ + + using library::core::ctnr::Array ; + + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + { + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_NO_THROW(Polygon polygon(vertices) ;) ; + + } + + { + + const Array outerRing = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + const Array> innerRings = + { + { + { 0.0, 0.0 }, + { 0.0, 0.5 }, + { 0.5, 0.5 }, + { 0.5, 0.0 } + }, + { + { 0.0, 0.0 }, + { 0.0, 0.1 }, + { 0.1, 0.1 }, + { 0.1, 0.0 } + } + } ; + + EXPECT_NO_THROW(Polygon polygon(outerRing, innerRings) ;) ; + + } + + { + + EXPECT_NO_THROW(Polygon({ { 0.0, 0.0 }, { 0.0, 1.0 }, { 1.0, 1.0 }, { 1.0, 0.0 }})) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Polygon, Clone) +{ + + using library::core::ctnr::Array ; + + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + { + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_NO_THROW(Polygon(vertices).clone()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Polygon, EqualToOperator) +{ + + using library::core::ctnr::Array ; + + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + { + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_TRUE(Polygon(vertices) == Polygon(vertices)) ; + + } + + { + + const Array vertices_A = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + const Array vertices_B = + { + { 1.0, 0.0 }, + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 } + } ; + + EXPECT_TRUE(Polygon(vertices_A) == Polygon(vertices_B)) ; + + } + + { + + const Array vertices_A = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + const Array vertices_B = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 2.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_FALSE(Polygon(vertices_A) == Polygon(vertices_B)) ; + + } + + { + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_FALSE(Polygon(vertices) == Polygon::Undefined()) ; + EXPECT_FALSE(Polygon::Undefined() == Polygon(vertices)) ; + EXPECT_FALSE(Polygon::Undefined() == Polygon::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Polygon, NotEqualToOperator) +{ + + using library::core::ctnr::Array ; + + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + { + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_FALSE(Polygon(vertices) != Polygon(vertices)) ; + + } + + { + + const Array vertices_A = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + const Array vertices_B = + { + { 1.0, 0.0 }, + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 } + } ; + + EXPECT_FALSE(Polygon(vertices_A) != Polygon(vertices_B)) ; + + } + + { + + const Array vertices_A = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + const Array vertices_B = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 2.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_TRUE(Polygon(vertices_A) != Polygon(vertices_B)) ; + + } + + { + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_TRUE(Polygon(vertices) != Polygon::Undefined()) ; + EXPECT_TRUE(Polygon::Undefined() != Polygon(vertices)) ; + EXPECT_TRUE(Polygon::Undefined() != Polygon::Undefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Polygon, StreamOperator) +{ + + using library::core::ctnr::Array ; + + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + { + + testing::internal::CaptureStdout() ; + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_NO_THROW(std::cout << Polygon(vertices) << std::endl) ; + + EXPECT_FALSE(testing::internal::GetCapturedStdout().empty()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Polygon, IsDefined) +{ + + using library::core::ctnr::Array ; + + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + { + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_TRUE(Polygon(vertices).isDefined()) ; + + } + + { + + EXPECT_FALSE(Polygon::Undefined().isDefined()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Polygon, GetVertices) +{ + + using library::core::ctnr::Array ; + + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + { + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_EQ(vertices, Polygon(vertices).getVertices()) ; + + } + + { + + EXPECT_ANY_THROW(Polygon::Undefined().getVertices()) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Polygon, Translate) +{ + + using library::core::ctnr::Array ; + + using library::math::obj::Vector2d ; + using library::math::geom::d2::objects::Point ; + using library::math::geom::d2::objects::Polygon ; + + { + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + Polygon polygon = { vertices } ; + + polygon.translate({ 4.0, 5.0 }) ; + + EXPECT_EQ(Polygon({ { 4.0, 5.0 }, { 4.0, 6.0 }, { 5.0, 6.0 }, { 5.0, 5.0 }}), polygon) ; + + } + + { + + const Array vertices = + { + { 0.0, 0.0 }, + { 0.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, 0.0 } + } ; + + EXPECT_ANY_THROW(Polygon::Undefined().translate(Vector2d::Undefined())) ; + EXPECT_ANY_THROW(Polygon::Undefined().translate({ 0.0, 0.0 })) ; + EXPECT_ANY_THROW(Polygon(vertices).translate(Vector2d::Undefined())) ; + + } + +} + +TEST (Library_Mathematics_Geometry_2D_Objects_Polygon, Undefined) +{ + + using library::math::geom::d2::objects::Polygon ; + + { + + EXPECT_NO_THROW(Polygon::Undefined()) ; + EXPECT_FALSE(Polygon::Undefined().isDefined()) ; + + } + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/tools/.env b/tools/.env index 33dc70ff..5febf096 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.5" +image_version="0.1.6" image_name="${repository_name}/${project_name}:${image_version}" diff --git a/tools/development/docker/Dockerfile b/tools/development/docker/Dockerfile index 2554b8c3..de0b84c5 100644 --- a/tools/development/docker/Dockerfile +++ b/tools/development/docker/Dockerfile @@ -34,12 +34,12 @@ RUN mkdir /tmp/eigen \ && make install \ && rm -rf /tmp/eigen -## Library :: Core [0.1.9] +## Library :: Core [0.1.10] 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.9/library-core-0.1.9-1.x86_64-runtime.rpm \ - && wget --quiet https://github.com/open-space-collective/library-core/releases/download/0.1.9/library-core-0.1.9-1.x86_64-devel.rpm \ + && wget --quiet https://github.com/open-space-collective/library-core/releases/download/0.1.10/library-core-0.1.10-1.x86_64-runtime.rpm \ + && wget --quiet https://github.com/open-space-collective/library-core/releases/download/0.1.10/library-core-0.1.10-1.x86_64-devel.rpm \ && dnf install -y ./*.rpm \ && rm -rf /tmp/library-core \ && popd > /dev/null