diff --git a/bindings/python/src/OpenSpaceToolkitMathematicsPy/Geometry/3D/Object/Composite.cpp b/bindings/python/src/OpenSpaceToolkitMathematicsPy/Geometry/3D/Object/Composite.cpp index 367bdc74..6d6f9227 100644 --- a/bindings/python/src/OpenSpaceToolkitMathematicsPy/Geometry/3D/Object/Composite.cpp +++ b/bindings/python/src/OpenSpaceToolkitMathematicsPy/Geometry/3D/Object/Composite.cpp @@ -4,6 +4,7 @@ #include #include +#include inline void OpenSpaceToolkitMathematicsPy_Geometry_3D_Object_Composite(pybind11::module& aModule) { @@ -26,6 +27,7 @@ inline void OpenSpaceToolkitMathematicsPy_Geometry_3D_Object_Composite(pybind11: using ostk::mathematics::geometry::d3::object::Ellipsoid; using ostk::mathematics::geometry::d3::object::Cuboid; using ostk::mathematics::geometry::d3::object::Pyramid; + using ostk::mathematics::geometry::d3::object::Cone; using ostk::mathematics::geometry::d3::object::Composite; using ostk::mathematics::geometry::d3::Intersection; using ostk::mathematics::geometry::d3::transformation::rotation::Quaternion; @@ -123,6 +125,13 @@ inline void OpenSpaceToolkitMathematicsPy_Geometry_3D_Object_Composite(pybind11: return aComposite.is(); } ) + .def( + "is_cone", + +[](const Composite& aComposite) -> bool + { + return aComposite.is(); + } + ) .def( "is_composite", +[](const Composite& aComposite) -> bool @@ -213,6 +222,13 @@ inline void OpenSpaceToolkitMathematicsPy_Geometry_3D_Object_Composite(pybind11: return aComposite.as(); } ) + .def( + "as_cone", + +[](const Composite& aComposite) -> Cone + { + return aComposite.as(); + } + ) .def( "as_composite", +[](const Composite& aComposite) -> Composite diff --git a/bindings/python/test/geometry/d3/object/test_composite.py b/bindings/python/test/geometry/d3/object/test_composite.py index bb138ebc..84baf1d3 100644 --- a/bindings/python/test/geometry/d3/object/test_composite.py +++ b/bindings/python/test/geometry/d3/object/test_composite.py @@ -2,142 +2,261 @@ import pytest -import ostk.mathematics as mathematics +import numpy as np +from ostk.mathematics.geometry import Angle +from ostk.mathematics.geometry.d2.object import Point as Point2d +from ostk.mathematics.geometry.d2.object import Polygon as Polygon2d +from ostk.mathematics.geometry.d3 import Object as Object +from ostk.mathematics.geometry.d3.object import Composite as Composite +from ostk.mathematics.geometry.d3.object import Point +from ostk.mathematics.geometry.d3.object import PointSet +from ostk.mathematics.geometry.d3.object import Line +from ostk.mathematics.geometry.d3.object import Ray +from ostk.mathematics.geometry.d3.object import Segment +from ostk.mathematics.geometry.d3.object import LineString +from ostk.mathematics.geometry.d3.object import Polygon +from ostk.mathematics.geometry.d3.object import Plane +from ostk.mathematics.geometry.d3.object import Sphere +from ostk.mathematics.geometry.d3.object import Ellipsoid +from ostk.mathematics.geometry.d3.object import Pyramid +from ostk.mathematics.geometry.d3.object import Cone -Point2d = mathematics.geometry.d2.object.Point -Polygon2d = mathematics.geometry.d2.object.Polygon -Object = mathematics.geometry.d3.Object -Composite = mathematics.geometry.d3.object.Composite -Point3d = mathematics.geometry.d3.object.Point -Segment = mathematics.geometry.d3.object.Segment -Polygon3d = mathematics.geometry.d3.object.Polygon +@pytest.fixture +def point() -> Point: + return Point(1.0, 2.0, 1.0) -def test_geometry_d3_object_composite_constructor(): - point_1: Point3d = Point3d(1.0, 2.0, 1.0) - point_2: Point3d = Point3d(1.0, 1.0, 1.0) - segment: Segment = Segment(point_1, point_2) +@pytest.fixture +def point_set(point: Point) -> PointSet: + return PointSet([point]) - composite_1 = Composite(segment) - - assert composite_1 is not None - assert isinstance(composite_1, Composite) - assert composite_1.is_defined() - - point_3: Point2d = Point2d(-1.0, 1.0) - point_4: Point2d = Point2d(1.0, 1.0) - point_5: Point2d = Point2d(1.0, -1.0) - point_6: Point2d = Point2d(-1.0, -1.0) - point_7: Point3d = Point3d(1.0, 1.0, 1.0) - vector_1 = (1.0, 0.0, 0.0) - vector_2 = (0.0, 1.0, 0.0) - polygon2d: Polygon2d = Polygon2d([point_3, point_4, point_5, point_6]) - polygon3d: Polygon3d = Polygon3d(polygon2d, point_7, vector_1, vector_2) +@pytest.fixture +def direction() -> np.ndarray: + return np.array([1.0, 0.0, 0.0]) - composite_2: Composite = Composite(polygon3d) - assert composite_2 is not None - assert isinstance(composite_2, Composite) - assert composite_2.is_defined() +@pytest.fixture +def line(point: Point, direction: np.ndarray) -> Line: + return Line(point, direction) -def test_geometry_d3_object_composite_empty(): - composite: Composite = Composite.empty() +@pytest.fixture +def ray(point: Point, direction: np.ndarray) -> Ray: + return Ray(point, direction) - assert composite is not None - assert isinstance(composite, Composite) - assert isinstance(composite, Object) - assert composite.is_defined() - assert composite.is_empty() +@pytest.fixture +def segment(): + point_1: Point = Point(1.0, 2.0, 1.0) + point_2: Point = Point(1.0, 1.0, 1.0) + return Segment(point_1, point_2) -def test_geometry_d3_object_composite_comparators(): - point_1: Point3d = Point3d(1.0, 2.0, 1.0) - point_2: Point3d = Point3d(1.0, 1.0, 1.0) - point_3: Point3d = Point3d(1.0, 4.0, 1.0) - segment_1: Segment = Segment(point_1, point_2) - segment_2: Segment = Segment(point_1, point_3) - segment_3: Segment = Segment(point_2, point_1) +@pytest.fixture +def line_string() -> LineString: + point_1: Point = Point(1.0, 2.0, 1.0) + point_2: Point = Point(1.0, 1.0, 1.0) + return LineString([point_1, point_2]) - composite_1 = Composite(segment_1) - composite_2 = Composite(segment_2) - composite_3 = Composite(segment_3) - assert composite_1 == composite_3 - assert composite_1 != composite_2 - assert composite_2 != composite_3 +@pytest.fixture +def polygon2d() -> Polygon2d: + point_1: Point2d = Point2d(-1.0, 1.0) + point_2: Point2d = Point2d(1.0, 1.0) + point_3: Point2d = Point2d(1.0, -1.0) + point_4: Point2d = Point2d(-1.0, -1.0) + return Polygon2d([point_1, point_2, point_3, point_4]) -def tes_geometry_d3_object_composite_addition_operator(): - point_1: Point3d = Point3d(1.0, 2.0, 1.0) - point_2: Point3d = Point3d(1.0, 1.0, 1.0) - point_3: Point3d = Point3d(1.0, 4.0, 1.0) +@pytest.fixture +def polygon(point: Point, polygon2d: Polygon2d) -> Polygon: + vector_1 = (1.0, 0.0, 0.0) + vector_2 = (0.0, 1.0, 0.0) + return Polygon(polygon2d, point, vector_1, vector_2) - segment_1: Segment = Segment(point_1, point_2) - segment_2: Segment = Segment(point_1, point_3) - composite_1 = Composite(segment_1) - composite_2 = Composite(segment_2) +@pytest.fixture +def plane(point: Point, direction: np.ndarray) -> Plane: + return Plane(point, direction) - composite_3 = composite_1 + composite_2 - assert composite_3 is not None - assert isinstance(composite_3, Composite) - assert composite_3.is_defined() - assert composite_3.get_object_count() == 2 +@pytest.fixture +def sphere(point: Point) -> Sphere: + return Sphere(point, 1.0) - with pytest.raises(RuntimeError): - composite = Composite.undefined() + composite_1 - with pytest.raises(RuntimeError): - composite = composite_1 + Composite.undefined() +@pytest.fixture +def ellipsoid(point: Point) -> Ellipsoid: + return Ellipsoid(point, 1.0, 1.0, 1.0) - composite_3 += composite_1 - assert isinstance(composite_3, Composite) - assert composite_3.is_defined() - assert composite_3.get_object_count() == 3 +@pytest.fixture +def pyramid(polygon: Polygon, point: Point) -> Pyramid: + return Pyramid(polygon, point) - with pytest.raises(RuntimeError): - composite_3 += Composite.undefined() +@pytest.fixture +def cone(point: Point, direction: np.ndarray) -> Cone: + return Cone(point, direction, Angle.degrees(5.0)) -def test_geometry_d3_object_composite_access_object_at(): - point_1: Point3d = Point3d(1.0, 2.0, 1.0) - point_2: Point3d = Point3d(1.0, 1.0, 1.0) - segment: Segment = Segment(point_1, point_2) +@pytest.fixture +def composite_with_polygon(segment: Segment, polygon: Polygon) -> Composite: composite_1 = Composite(segment) - - object = composite_1.access_object_at(0) - - assert object is not None - assert isinstance(object, Object) - assert isinstance(object, Segment) - - point_3: Point2d = Point2d(-1.0, 1.0) - point_4: Point2d = Point2d(1.0, 1.0) - point_5: Point2d = Point2d(1.0, -1.0) - point_6: Point2d = Point2d(-1.0, -1.0) - point_7: Point3d = Point3d(1.0, 1.0, 1.0) - vector_1 = (1.0, 0.0, 0.0) - vector_2 = (0.0, 1.0, 0.0) - - polygon2d: Polygon2d = Polygon2d([point_3, point_4, point_5, point_6]) - polygon3d: Polygon3d = Polygon3d(polygon2d, point_7, vector_1, vector_2) - composite_2: Composite = Composite(polygon3d) - - composite_3 = composite_1 + composite_2 - - object_1 = composite_3.access_object_at(0) - object_2 = composite_3.access_object_at(1) - - assert object_1 == segment - assert object_2 == polygon3d - - with pytest.raises(RuntimeError): - composite_3.access_object_at(2) + return composite_1 + Composite(polygon) + + +class Test3DComposite: + @pytest.mark.parametrize( + "geometry_name", + [ + ("point"), + ("point_set"), + ("line"), + ("ray"), + ("segment"), + ("line_string"), + ("polygon"), + ("plane"), + ("sphere"), + ("ellipsoid"), + ("pyramid"), + ("cone"), + ], + ) + def test_geometry_d3_object_composite_constructor(self, geometry_name: str, request): + geometry = request.getfixturevalue(geometry_name) + composite: Composite = Composite(geometry) + + assert composite is not None + assert isinstance(composite, Composite) + assert composite.is_defined() + + def test_geometry_d3_object_composite_empty(self): + composite: Composite = Composite.empty() + + assert composite is not None + assert isinstance(composite, Composite) + assert isinstance(composite, Object) + assert composite.is_defined() + assert composite.is_empty() + + def test_geometry_d3_object_composite_comparators(self): + point_1: Point = Point(1.0, 2.0, 1.0) + point_2: Point = Point(1.0, 1.0, 1.0) + point_3: Point = Point(1.0, 4.0, 1.0) + + segment_1: Segment = Segment(point_1, point_2) + segment_2: Segment = Segment(point_1, point_3) + segment_3: Segment = Segment(point_2, point_1) + + composite_1 = Composite(segment_1) + composite_2 = Composite(segment_2) + composite_3 = Composite(segment_3) + + assert composite_1 == composite_3 + assert composite_1 != composite_2 + assert composite_2 != composite_3 + + def tes_geometry_d3_object_composite_addition_operator(self): + point_1: Point = Point(1.0, 2.0, 1.0) + point_2: Point = Point(1.0, 1.0, 1.0) + point_3: Point = Point(1.0, 4.0, 1.0) + + segment_1: Segment = Segment(point_1, point_2) + segment_2: Segment = Segment(point_1, point_3) + + composite_1 = Composite(segment_1) + composite_2 = Composite(segment_2) + + composite_3 = composite_1 + composite_2 + + assert composite_3 is not None + assert isinstance(composite_3, Composite) + assert composite_3.is_defined() + assert composite_3.get_object_count() == 2 + + with pytest.raises(RuntimeError): + composite = Composite.undefined() + composite_1 + + with pytest.raises(RuntimeError): + composite = composite_1 + Composite.undefined() + + composite_3 += composite_1 + + assert isinstance(composite_3, Composite) + assert composite_3.is_defined() + assert composite_3.get_object_count() == 3 + + with pytest.raises(RuntimeError): + composite_3 += Composite.undefined() + + def test_geometry_d3_object_composite_access_object_at( + self, + composite_with_polygon: Composite, + ): + object: Object = composite_with_polygon.access_object_at(0) + + assert object is not None + assert isinstance(object, Object) + assert isinstance(object, Segment) + + object_2: Object = composite_with_polygon.access_object_at(1) + + assert object_2 is not None + assert isinstance(object_2, Object) + assert isinstance(object_2, Polygon) + + with pytest.raises(RuntimeError): + composite_with_polygon.access_object_at(2) + + @pytest.mark.parametrize( + "geometry_name", + [ + ("point"), + ("point_set"), + ("line"), + ("ray"), + ("segment"), + ("line_string"), + ("polygon"), + ("plane"), + ("sphere"), + ("ellipsoid"), + ("pyramid"), + ("cone"), + ], + ) + def test_geometry_d3_object_composite_is(self, geometry_name: str, request): + geometry = request.getfixturevalue(geometry_name) + composite: Composite = Composite(geometry) + + assert composite.is_defined() + assert getattr(composite, f"is_{geometry_name}")() + + @pytest.mark.parametrize( + "geometry_name", + [ + ("point"), + ("point_set"), + ("line"), + ("ray"), + ("segment"), + ("line_string"), + ("polygon"), + ("plane"), + ("sphere"), + ("ellipsoid"), + ("pyramid"), + ("cone"), + ], + ) + def test_geometry_d3_object_composite_as(self, geometry_name: str, request): + geometry = request.getfixturevalue(geometry_name) + composite: Composite = Composite(geometry) + + assert composite.is_defined() + assert getattr(composite, f"as_{geometry_name}")().is_defined() diff --git a/bindings/python/test/geometry/d3/object/test_point.py b/bindings/python/test/geometry/d3/object/test_point.py index bf511c19..0f40ef53 100644 --- a/bindings/python/test/geometry/d3/object/test_point.py +++ b/bindings/python/test/geometry/d3/object/test_point.py @@ -8,9 +8,6 @@ import ostk.mathematics as mathematics -from ostk.core.type import String - - Object = mathematics.geometry.d3.Object Point = mathematics.geometry.d3.object.Point Transformation = mathematics.geometry.d3.Transformation