Skip to content

Commit

Permalink
Issue: #19 Additional adapter functions for Ray and Plane
Browse files Browse the repository at this point in the history
  • Loading branch information
attcs committed Mar 3, 2024
1 parent 0c83795 commit c3ee48d
Show file tree
Hide file tree
Showing 12 changed files with 694 additions and 317 deletions.
157 changes: 103 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ What is the Octree and what is good for? https://en.wikipedia.org/wiki/Octree
* Tested compilers: MSVC 2022, Clang 12.0.0, GCC 11.3

## Attached adapters
* Default: `std::array` based `PointND`, `BoundingBoxND`
* Default: `std::array` based structures (`PointND`, `VectorND`, `BoundingBoxND`, `RayND`, `PlaneND`)
* Eigen: `Eigen::OctreePoint3d`, `::OctreePointC3d`, `::OctreeBox3d`, `::OctreeBoxC3d`, etc. (adaptor.eigen.h)
* Unreal Engine: `FOctreePoint`, `FOctreePointC`, `FOctreeBox`, `FOctreeBoxC`, etc. (adaptor.unreal.h)
* `struct{x,y,z}`: (adaptor.xyz.h)
Expand All @@ -72,46 +72,64 @@ What is the Octree and what is good for? https://en.wikipedia.org/wiki/Octree
```C++
/// Default geometrical base elements

using Point2D = OrthoTree::PointND<2>;
using Point3D = OrthoTree::PointND<3>;
using BoundingBox2D = OrthoTree::BoundingBoxND<2>;
using BoundingBox3D = OrthoTree::BoundingBoxND<3>;
using BaseGeometryType = double;
using Vector1D = OrthoTree::VectorND<1, BaseGeometryType>;
using Vector2D = OrthoTree::VectorND<2, BaseGeometryType>;
using Vector3D = OrthoTree::VectorND<3, BaseGeometryType>;
using Point1D = OrthoTree::PointND<1, BaseGeometryType>;
using Point2D = OrthoTree::PointND<2, BaseGeometryType>;
using Point3D = OrthoTree::PointND<3, BaseGeometryType>;
using BoundingBox1D = OrthoTree::BoundingBoxND<1, BaseGeometryType>;
using BoundingBox2D = OrthoTree::BoundingBoxND<2, BaseGeometryType>;
using BoundingBox3D = OrthoTree::BoundingBoxND<3, BaseGeometryType>;
using Ray2D = OrthoTree::RayND<2, BaseGeometryType>;
using Ray3D = OrthoTree::RayND<3, BaseGeometryType>;
using Plane2D = OrthoTree::PlaneND<2, BaseGeometryType>;
using Plane3D = OrthoTree::PlaneND<3, BaseGeometryType>;


/// Core types

// Quadtree for points (2D)
using QuadtreePoint = TreePointND<2>;
// Quadtree for points
using QuadtreePoint = TreePointND<2, BaseGeometryType>;

// Quadtree for bounding boxes (2D)
using QuadtreeBox = TreeBoxND<2>;
// Quadtree for bounding boxes
using QuadtreeBox = TreeBoxND<2, 2, BaseGeometryType>;

// Octree for points (3D)
using OctreePoint = TreePointND<3>;
// Octree for points
using OctreePoint = TreePointND<3, BaseGeometryType>;

// Octree for bounding boxes (3D)
using OctreeBox = TreeBoxND<3>;
// Octree for bounding boxes
using OctreeBox = TreeBoxND<3, 2, BaseGeometryType>;

// Hexatree for points (4D)
using HexatreePoint = TreePointND<4>;

// ...
using TreePoint16D = TreePointND<16>;
// Hexatree for points
using HexatreePoint = TreePointND<4, BaseGeometryType>;

// Hexatree for bounding boxes
using HexatreeBox = TreeBoxND<4, 2, BaseGeometryType>;

// NTrees for higher dimensions
using TreePoint16D = TreePointND<16, BaseGeometryType>;
using TreeBox16D = TreeBoxND<16, 2, BaseGeometryType>;


/// Container types

// Quadtree for points (2D)
using QuadtreePointC = TreePointContainerND<2>;
// Quadtree for points
using QuadtreePointC = TreePointContainerND<2, BaseGeometryType>;

// Quadtree for bounding boxes (2D)
using QuadtreeBoxC = TreeBoxContainerND<2>;
// Quadtree for bounding boxes
template<uint32_t SPLIT_DEPTH_INCREASEMENT = 2>
using QuadtreeBoxCs = TreeBoxContainerND<2, SPLIT_DEPTH_INCREASEMENT, BaseGeometryType>;
using QuadtreeBoxC = TreeBoxContainerND<2, 2, BaseGeometryType>;

// Octree for points (3D)
using OctreePointC = TreePointContainerND<3>;
// Octree for points
using OctreePointC = TreePointContainerND<3, BaseGeometryType>;

// Octree for bounding boxes (3D)
using OctreeBoxC = TreeBoxContainerND<3>;
// Octree for bounding boxes
template<uint32_t SPLIT_DEPTH_INCREASEMENT = 2>
using OctreeBoxCs = TreeBoxContainerND<3, 2, BaseGeometryType>;
using OctreeBoxC = TreeBoxContainerND<3, 2, BaseGeometryType>;
```

## Basic examples
Expand Down Expand Up @@ -252,49 +270,80 @@ For more examples, see the unit tests.

## Adapting Octree/Quadtree to user-defined Point / Bounding box objects
```C++
// User-defined geometrical objects

struct Point2DCustom { float x; float y; };
using BoundingBox2DCustom = std::array<Point2DCustom, 2>;
// User-defined geometrical objects

struct MyPoint2D { float x; float y; };
using MyBox2D = std::array<MyPoint2D, 2>;
using MyRay2D = std::array<MyPoint2D, 2>;
struct MyPlane2D { float OrigoDistance; MyPoint2D Normal; };

// Adaptor
// Adaptor

struct AdaptorBasicsCustom
struct AdaptorBasicsCustom
{
static float GetPointC(MyPoint2D const& pt, OrthoTree::dim_t i)
{
static inline float& point_comp(Point2DCustom& pt, OrthoTree::dim_type iDimension)
switch (i)
{
switch (iDimension)
{
case 0: return pt.x;
case 1: return pt.y;
default: assert(false); return pt.x;
}
case 0: return pt.x;
case 1: return pt.y;
default: assert(false); return pt.x;
}
}

static constexpr float point_comp_c(Point2DCustom const& pt, OrthoTree::dim_type iDimension)
static void SetPointC(MyPoint2D& pt, OrthoTree::dim_t i, float v)
{
switch (i)
{
switch (iDimension)
{
case 0: return pt.x;
case 1: return pt.y;
default: assert(false); return pt.x;
}
case 0: pt.x = v; break;
case 1: pt.y = v; break;
default: assert(false);
}
}

static void SetBoxMinC(MyBox2D& box, dim_t i, float v) { SetPointC(box[0], i, v); }
static void SetBoxMaxC(MyBox2D& box, dim_t i, float v) { SetPointC(box[1], i, v); }
static float GetBoxMinC(MyBox2D const& box, dim_t i) { return GetPointC(box[0], i); }
static float GetBoxMaxC(MyBox2D const& box, dim_t i) { return GetPointC(box[1], i); }

static MyPoint2D const& GetRayDirection(MyRay2D const& ray) { return ray[1]; }
static MyPoint2D const& GetRayOrigin(MyRay2D const& ray) { return ray[0]; }

static MyPoint2D const& GetPlaneNormal(MyPlane2D const& plane) { return plane.Normal; }
static float GetPlaneOrigoDistance(MyPlane2D const& plane) { return plane.OrigoDistance; }
};

static inline Point2DCustom& box_min(BoundingBox2DCustom& box) { return box[0]; }
static inline Point2DCustom& box_max(BoundingBox2DCustom& box) { return box[1]; }
static constexpr Point2DCustom const& box_min_c(BoundingBox2DCustom const& box) { return box[0]; }
static constexpr Point2DCustom const& box_max_c(BoundingBox2DCustom const& box) { return box[1]; }
};

using AdaptorCustom = OrthoTree::AdaptorGeneralBase<2, Point2DCustom, BoundingBox2DCustom, AdaptorBasicsCustom, float>;
using AdaptorCustom = OrthoTree::AdaptorGeneralBase<
2,
MyPoint2D,
MyBox2D,
MyRay2D,
MyPlane2D,
float,
AdaptorBasicsCustom>;


// Tailored Quadtree objects

using QuadtreePointCustom = OrthoTree::OrthoTreePoint<2, Point2DCustom, BoundingBox2DCustom, AdaptorCustom, float>;
using QuadtreeBoxCustom = OrthoTree::OrthoTreeBoundingBox<2, Point2DCustom, BoundingBox2DCustom, AdaptorCustom, float>;
using QuadtreePointCustom = OrthoTree::OrthoTreePoint<
2,
MyPoint2D,
MyBox2D,
MyRay2D,
MyPlane2D,
float,
AdaptorCustom>;

using QuadtreeBoxCustom = OrthoTree::OrthoTreeBoundingBox<
2,
MyPoint2D,
MyBox2D,
MyRay2D,
MyPlane2D,
float,
2,
AdaptorCustom>;
```

## Benchmarks
Expand Down
39 changes: 34 additions & 5 deletions adaptor.eigen.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ SOFTWARE.
*/

#include "octree.h"
#include <Eigen/Dense>
#include <Eigen/Geometry>

namespace OrthoTree
Expand All @@ -37,6 +38,8 @@ namespace OrthoTree
{
using VectorType_ = Matrix<Scalar_, AmbientDim_, 1>;
using AlignedBox_ = AlignedBox<Scalar_, AmbientDim_>;
using Ray_ = ParametrizedLine<Scalar_, AmbientDim_>;
using Plane_ = Hyperplane<Scalar_, AmbientDim_>;

static constexpr Scalar_ GetPointC(VectorType_ const& point, dim_t dimensionID) noexcept { return point(dimensionID); }
static constexpr void SetPointC(VectorType_& point, dim_t dimensionID, Scalar_ value) noexcept { point(dimensionID) = value; }
Expand All @@ -45,6 +48,12 @@ namespace OrthoTree
static constexpr Scalar_ GetBoxMaxC(AlignedBox_ const& box, dim_t dimensionID) { return box.max()(dimensionID); }
static constexpr void SetBoxMinC(AlignedBox_& box, dim_t dimensionID, Scalar_ value) { box.min()(dimensionID) = value; }
static constexpr void SetBoxMaxC(AlignedBox_& box, dim_t dimensionID, Scalar_ value) { box.max()(dimensionID) = value; }

static constexpr VectorType_ const& GetRayDirection(Ray_ const& ray) noexcept { return ray.direction(); }
static constexpr VectorType_ const& GetRayOrigin(Ray_ const& ray) noexcept { return ray.origin(); }

static constexpr VectorType_ GetPlaneNormal(Plane_ const& plane) noexcept { return plane.normal(); }
static constexpr Scalar_ GetPlaneOrigoDistance(Plane_ const& plane) noexcept { return -plane.offset(); }
};

template<typename Scalar_, int AmbientDim_>
Expand All @@ -53,8 +62,10 @@ namespace OrthoTree
using Base = EigenAdaptorBasics<Scalar_, AmbientDim_>;
using VectorType_ = Base::VectorType_;
using AlignedBox_ = Base::AlignedBox_;
using Ray_ = ParametrizedLine<Scalar_, AmbientDim_>;
using Plane_ = Hyperplane<Scalar_, AmbientDim_>;

static_assert(AdaptorBasicsConcept<Base, VectorType_, AlignedBox_, Scalar_>);
static_assert(AdaptorBasicsConcept<Base, VectorType_, AlignedBox_, Ray_, Plane_, Scalar_>);

static constexpr Scalar_ Size2(VectorType_ const& v) noexcept { return v.squaredNorm(); }

Expand Down Expand Up @@ -177,6 +188,11 @@ namespace OrthoTree
return rMin < 0 ? rMax : rMin;
}

static constexpr std::optional<double> IsRayHit(AlignedBox_ const& box, Ray_ const& ray, Scalar_ tolerance) noexcept
{
return IsRayHit(box, Base::GetRayOrigin(ray), Base::GetRayDirection(ray), tolerance);
}

// Get point-Hyperplane relation (Plane equation: dotProduct(planeNormal, point) = distanceOfOrigo)
static constexpr PlaneRelation GetPointPlaneRelation(
VectorType_ const& point, Scalar_ distanceOfOrigo, VectorType_ const& planeNormal, Scalar_ tolerance) noexcept
Expand Down Expand Up @@ -237,12 +253,25 @@ namespace Eigen

// Basic OrthoTree types
template<typename Scalar_, int AmbientDim_>
using EigenOrthoTreePoint =
OrthoTreePoint<AmbientDim_, Matrix<Scalar_, AmbientDim_, 1>, AlignedBox<Scalar_, AmbientDim_>, EigenAdaptorGeneralBase<Scalar_, AmbientDim_>, Scalar_>;
using EigenOrthoTreePoint = OrthoTreePoint<
AmbientDim_,
Matrix<Scalar_, AmbientDim_, 1>,
AlignedBox<Scalar_, AmbientDim_>,
ParametrizedLine<Scalar_, AmbientDim_>,
Hyperplane<Scalar_, AmbientDim_>,
Scalar_,
EigenAdaptorGeneralBase<Scalar_, AmbientDim_>>;

template<typename Scalar_, int AmbientDim_, uint32_t SPLIT_DEPTH_INCREASEMENT = 2>
using EigenOrthoTreeBox =
OrthoTreeBoundingBox<AmbientDim_, Matrix<Scalar_, AmbientDim_, 1>, AlignedBox<Scalar_, AmbientDim_>, EigenAdaptorGeneralBase<Scalar_, AmbientDim_>, Scalar_, SPLIT_DEPTH_INCREASEMENT>;
using EigenOrthoTreeBox = OrthoTreeBoundingBox<
AmbientDim_,
Matrix<Scalar_, AmbientDim_, 1>,
AlignedBox<Scalar_, AmbientDim_>,
ParametrizedLine<Scalar_, AmbientDim_>,
Hyperplane<Scalar_, AmbientDim_>,
Scalar_,
SPLIT_DEPTH_INCREASEMENT,
EigenAdaptorGeneralBase<Scalar_, AmbientDim_>>;

template<typename Scalar_, int AmbientDim_>
using OrthoTreeContainerPointC = OrthoTreeContainerPoint<EigenOrthoTreePoint<Scalar_, AmbientDim_>, Matrix<Scalar_, AmbientDim_, 1>>;
Expand Down
Loading

0 comments on commit c3ee48d

Please sign in to comment.