diff --git a/include/geode/mesh/helpers/ray_tracing.hpp b/include/geode/mesh/helpers/ray_tracing.hpp index d8ccf6a01..9ee7fdbf1 100644 --- a/include/geode/mesh/helpers/ray_tracing.hpp +++ b/include/geode/mesh/helpers/ray_tracing.hpp @@ -48,6 +48,8 @@ namespace geode { class opengeode_mesh_api RayTracing2D { + OPENGEODE_DISABLE_COPY( RayTracing2D ); + public: struct EdgeDistance { @@ -60,7 +62,7 @@ namespace geode : edge{ edge_in }, distance{ distance_in }, position{ position_in }, - point{ std::move( point_in ) } + point{ point_in } { } @@ -84,8 +86,9 @@ namespace geode const InfiniteLine2D& infinite_line ); RayTracing2D( const EdgedCurve2D& mesh, const Point2D& origin, - const OwnerSegment2D& segment ); + OwnerSegment2D segment ); RayTracing2D( RayTracing2D&& other ) noexcept; + RayTracing2D& operator=( RayTracing2D&& other ) noexcept; ~RayTracing2D(); [[nodiscard]] std::optional< EdgeDistance > closest_edge() const; @@ -103,6 +106,8 @@ namespace geode class opengeode_mesh_api RayTracing3D { + OPENGEODE_DISABLE_COPY( RayTracing3D ); + public: struct PolygonDistance { @@ -115,7 +120,7 @@ namespace geode : polygon{ polygon_in }, distance{ distance_in }, position{ position_in }, - point{ std::move( point_in ) } + point{ point_in } { } @@ -139,8 +144,9 @@ namespace geode const InfiniteLine3D& infinite_line ); RayTracing3D( const SurfaceMesh3D& mesh, const Point3D& origin, - const OwnerSegment3D& segment ); + OwnerSegment3D segment ); RayTracing3D( RayTracing3D&& other ) noexcept; + RayTracing3D& operator=( RayTracing3D&& other ) noexcept; ~RayTracing3D(); [[nodiscard]] std::optional< PolygonDistance > closest_polygon() const; diff --git a/src/geode/mesh/helpers/ray_tracing.cpp b/src/geode/mesh/helpers/ray_tracing.cpp index cdd73a3ec..94231ed49 100644 --- a/src/geode/mesh/helpers/ray_tracing.cpp +++ b/src/geode/mesh/helpers/ray_tracing.cpp @@ -46,7 +46,7 @@ namespace auto bbox_with_line = bbox; bbox_with_line.add_point( line.origin() ); const auto diagonal = bbox_with_line.diagonal(); - return line.origin() - line.direction() * diagonal.length(); + return line.origin() - ( line.direction() * diagonal.length() ); } template < geode::index_t dimension, typename Line > @@ -56,7 +56,7 @@ namespace auto bbox_with_line = bbox; bbox_with_line.add_point( line.origin() ); const auto diagonal = bbox_with_line.diagonal(); - return line.origin() + line.direction() * diagonal.length(); + return line.origin() + ( line.direction() * diagonal.length() ); } bool test_vertex_mode( const geode::EdgedCurve2D& mesh, @@ -258,8 +258,8 @@ namespace geode Impl( const EdgedCurve2D& mesh, const Point2D& origin, - const OwnerSegment2D& segment ) - : mesh_( mesh ), origin_( origin ), segment_{ segment } + OwnerSegment2D segment ) + : mesh_( mesh ), origin_( origin ), segment_{ std::move( segment ) } { } @@ -330,9 +330,8 @@ namespace geode { distance *= -1.; } - std::lock_guard< std::mutex > lock{ mutex_ }; - results_.emplace_back( edge_id, distance, result.second, - std::move( intersection_result ) ); + results_.emplace_back( + edge_id, distance, result.second, intersection_result ); } return false; } @@ -359,7 +358,6 @@ namespace geode OwnerSegment2D segment_; mutable std::vector< EdgeDistance > results_; mutable bool are_results_sorted_{ false }; - std::mutex mutex_; }; RayTracing2D::RayTracing2D( @@ -377,13 +375,15 @@ namespace geode RayTracing2D::RayTracing2D( const EdgedCurve2D& mesh, const Point2D& origin, - const OwnerSegment2D& segment ) - : impl_{ mesh, origin, segment } + OwnerSegment2D segment ) + : impl_{ mesh, origin, std::move( segment ) } { } RayTracing2D::RayTracing2D( RayTracing2D&& ) noexcept = default; + RayTracing2D& RayTracing2D::operator=( RayTracing2D&& ) noexcept = default; + RayTracing2D::~RayTracing2D() = default; std::optional< RayTracing2D::EdgeDistance > @@ -448,8 +448,8 @@ namespace geode Impl( const SurfaceMesh3D& mesh, const Point3D& origin, - const OwnerSegment3D& segment ) - : mesh_( mesh ), origin_( origin ), segment_{ segment } + OwnerSegment3D segment ) + : mesh_( mesh ), origin_( origin ), segment_{ std::move( segment ) } { } @@ -493,14 +493,14 @@ namespace geode bool compute( index_t polygon_id ) { - const auto& p0 = + const auto& point0 = mesh_.point( mesh_.polygon_vertex( { polygon_id, 0 } ) ); - for( const auto e : + for( const auto edge : LRange{ 1, mesh_.nb_polygon_edges( polygon_id ) - 1 } ) { const auto edge_vertices = - mesh_.polygon_edge_vertices( { polygon_id, e } ); - const Triangle3D triangle{ p0, + mesh_.polygon_edge_vertices( { polygon_id, edge } ); + const Triangle3D triangle{ point0, mesh_.point( edge_vertices.front() ), mesh_.point( edge_vertices.back() ) }; const auto result = segment_triangle_intersection_detection( @@ -521,38 +521,43 @@ namespace geode { distance *= -1.; } - std::lock_guard< std::mutex > lock{ mutex_ }; results_.emplace_back( polygon_id, distance, result.second, - std::move( intersection_result ) ); + intersection_result ); break; } - for( const auto e2 : LRange{ 3 } ) + for( const auto edge2 : LRange{ 3 } ) { - auto [ray_edge_distance, point, _] = - segment_segment_distance( Segment3D{ segment_ }, - { triangle.vertices()[e2].get(), - triangle.vertices()[( e2 + 1 ) % 3].get() } ); + auto [ray_edge_distance, ray_point, + _] = segment_segment_distance( Segment3D{ segment_ }, + { triangle.vertices()[edge2].get(), + triangle.vertices()[( edge2 + 1 ) % 3].get() } ); if( ray_edge_distance > GLOBAL_EPSILON ) { continue; } - if( Vector3D{ origin_, point }.dot( segment_.direction() ) - < 0 ) + const Vector3D origin_target{ origin_, ray_point }; + auto distance = origin_target.length(); + if( origin_target.dot( segment_.direction() ) < 0 ) { - ray_edge_distance *= -1.; + distance *= -1.; } - std::lock_guard< std::mutex > lock{ mutex_ }; - results_.emplace_back( polygon_id, ray_edge_distance, - result.second, std::move( point ) ); + results_.emplace_back( + polygon_id, distance, result.second, ray_point ); } - const auto [distance, __, triangle_point] = + const auto [triangle_distance, ray_point, _] = segment_triangle_distance( segment_, triangle ); - if( distance < GLOBAL_EPSILON ) + if( triangle_distance > GLOBAL_EPSILON ) { - std::lock_guard< std::mutex > lock{ mutex_ }; - results_.emplace_back( - polygon_id, distance, result.second, triangle_point ); + continue; } + const Vector3D origin_target{ origin_, ray_point }; + auto distance = origin_target.length(); + if( origin_target.dot( segment_.direction() ) < 0 ) + { + distance *= -1.; + } + results_.emplace_back( + polygon_id, distance, result.second, ray_point ); break; } return false; @@ -581,7 +586,6 @@ namespace geode OwnerSegment3D segment_; mutable std::vector< PolygonDistance > results_; mutable bool are_results_sorted_{ false }; - std::mutex mutex_; }; RayTracing3D::RayTracing3D( @@ -599,13 +603,15 @@ namespace geode RayTracing3D::RayTracing3D( const SurfaceMesh3D& mesh, const Point3D& origin, - const OwnerSegment3D& segment ) - : impl_{ mesh, origin, segment } + OwnerSegment3D segment ) + : impl_{ mesh, origin, std::move( segment ) } { } RayTracing3D::RayTracing3D( RayTracing3D&& ) noexcept = default; + RayTracing3D& RayTracing3D::operator=( RayTracing3D&& ) noexcept = default; + RayTracing3D::~RayTracing3D() = default; std::optional< RayTracing3D::PolygonDistance > diff --git a/tests/mesh/test-ray-tracing.cpp b/tests/mesh/test-ray-tracing.cpp index ba551bac3..f2b788566 100644 --- a/tests/mesh/test-ray-tracing.cpp +++ b/tests/mesh/test-ray-tracing.cpp @@ -34,96 +34,99 @@ #include -void test_ray_inside() +namespace { - geode::Logger::info( "Test ray inside" ); - auto mesh = geode::SurfaceMesh3D::create(); - auto builder = geode::SurfaceMeshBuilder3D::create( *mesh ); - builder->create_point( geode::Point3D{ { -1, -1, 1 } } ); - builder->create_point( geode::Point3D{ { 1, -1, 1 } } ); - builder->create_point( geode::Point3D{ { 0, 1, 1 } } ); - builder->create_point( geode::Point3D{ { -1, -1, 2 } } ); - builder->create_point( geode::Point3D{ { 1, -1, 2 } } ); - builder->create_point( geode::Point3D{ { 0, 1, 2 } } ); - builder->create_polygon( { 0, 1, 2 } ); - builder->create_polygon( { 3, 4, 5 } ); + void test_ray_inside() + { + geode::Logger::info( "Test ray inside" ); + auto mesh = geode::SurfaceMesh3D::create(); + auto builder = geode::SurfaceMeshBuilder3D::create( *mesh ); + builder->create_point( geode::Point3D{ { -1, -1, 1 } } ); + builder->create_point( geode::Point3D{ { 1, -1, 1 } } ); + builder->create_point( geode::Point3D{ { 0, 1, 1 } } ); + builder->create_point( geode::Point3D{ { -1, -1, 2 } } ); + builder->create_point( geode::Point3D{ { 1, -1, 2 } } ); + builder->create_point( geode::Point3D{ { 0, 1, 2 } } ); + builder->create_polygon( { 0, 1, 2 } ); + builder->create_polygon( { 3, 4, 5 } ); - const auto aabb = geode::create_aabb_tree( *mesh ); - const geode::Vector3D direction{ { 0, 0, 1 } }; - const geode::Point3D origin{ { 0, 0, 0 } }; - const geode::Ray3D ray{ direction, origin }; - geode::RayTracing3D tracing{ *mesh, aabb.bounding_box(), ray }; - aabb.compute_ray_element_bbox_intersections( ray, tracing ); - const auto result = tracing.closest_polygon(); - geode::OpenGeodeMeshException::test( - result.has_value(), "Ray inside no result" ); - geode::OpenGeodeMeshException::test( - result->polygon == 0, "Ray inside wrong polygon" ); - geode::OpenGeodeMeshException::test( - result->distance == 1, "Ray inside wrong distance" ); -} + const auto aabb = geode::create_aabb_tree( *mesh ); + const geode::Vector3D direction{ { 0, 0, 1 } }; + const geode::Point3D origin{ { 0, 0, 0 } }; + const geode::Ray3D ray{ direction, origin }; + geode::RayTracing3D tracing{ *mesh, aabb.bounding_box(), ray }; + aabb.compute_ray_element_bbox_intersections( ray, tracing ); + const auto result = tracing.closest_polygon(); + geode::OpenGeodeMeshException::test( + result.has_value(), "Ray inside no result" ); + geode::OpenGeodeMeshException::test( + result->polygon == 0, "Ray inside wrong polygon" ); + geode::OpenGeodeMeshException::test( + result->distance == 1, "Ray inside wrong distance" ); + } -void test_ray_edge() -{ - geode::Logger::info( "Test ray edge" ); - auto mesh = geode::SurfaceMesh3D::create(); - auto builder = geode::SurfaceMeshBuilder3D::create( *mesh ); - builder->create_point( geode::Point3D{ { 1, -1, 0 } } ); - builder->create_point( geode::Point3D{ { 1, 1, 0 } } ); - builder->create_point( geode::Point3D{ { 1, 0, -1 } } ); - builder->create_point( geode::Point3D{ { 1, 0, 3 } } ); - builder->create_polygon( { 0, 1, 2 } ); - builder->create_polygon( { 1, 0, 3 } ); - builder->compute_polygon_adjacencies(); + void test_ray_edge() + { + geode::Logger::info( "Test ray edge" ); + auto mesh = geode::SurfaceMesh3D::create(); + auto builder = geode::SurfaceMeshBuilder3D::create( *mesh ); + builder->create_point( geode::Point3D{ { 1, -1, 0 } } ); + builder->create_point( geode::Point3D{ { 1, 1, 0 } } ); + builder->create_point( geode::Point3D{ { 1, 0, -1 } } ); + builder->create_point( geode::Point3D{ { 1, 0, 3 } } ); + builder->create_polygon( { 0, 1, 2 } ); + builder->create_polygon( { 1, 0, 3 } ); + builder->compute_polygon_adjacencies(); - const auto aabb = geode::create_aabb_tree( *mesh ); - const geode::Vector3D direction{ { 1, 0, 0 } }; - const geode::Point3D origin{ { 0, 0, 1 } }; - const geode::Ray3D ray{ direction, origin }; - geode::RayTracing3D tracing{ *mesh, aabb.bounding_box(), ray }; - aabb.compute_ray_element_bbox_intersections( ray, tracing ); - const auto result = tracing.closest_polygon(); - geode::OpenGeodeMeshException::test( - result.has_value(), "Ray edge no result" ); - geode::OpenGeodeMeshException::test( - result->polygon == 1, "Ray edge wrong polygon" ); - geode::OpenGeodeMeshException::test( - result->distance == 1, "Ray edge wrong distance" ); - geode::OpenGeodeMeshException::test( - tracing.all_intersections().size() == 1, - "Wrong size for ray tracing result for case edge" ); -} + const auto aabb = geode::create_aabb_tree( *mesh ); + const geode::Vector3D direction{ { 1, 0, 0 } }; + const geode::Point3D origin{ { 0, 0, 1 } }; + const geode::Ray3D ray{ direction, origin }; + geode::RayTracing3D tracing{ *mesh, aabb.bounding_box(), ray }; + aabb.compute_ray_element_bbox_intersections( ray, tracing ); + const auto result = tracing.closest_polygon(); + geode::OpenGeodeMeshException::test( + result.has_value(), "Ray edge no result" ); + geode::OpenGeodeMeshException::test( + result->polygon == 1, "Ray edge wrong polygon" ); + geode::OpenGeodeMeshException::test( + result->distance == 1, "Ray edge wrong distance" ); + geode::OpenGeodeMeshException::test( + tracing.all_intersections().size() == 1, + "Wrong size for ray tracing result for case edge" ); + } -void test_ray_parallel() -{ - geode::Logger::info( "Test ray parallel" ); - auto mesh = geode::SurfaceMesh3D::create(); - auto builder = geode::SurfaceMeshBuilder3D::create( *mesh ); - builder->create_point( geode::Point3D{ { -1, -1, 0 } } ); - builder->create_point( geode::Point3D{ { -1, 1, 0 } } ); - builder->create_point( geode::Point3D{ { -2, 0, 0 } } ); - builder->create_polygon( { 0, 1, 2 } ); - const auto aabb = geode::create_aabb_tree( *mesh ); - const geode::Vector3D direction{ { -1, 0, 0 } }; - const geode::Point3D origin{ { 0, 0, 0 } }; - const geode::Ray3D ray{ direction, origin }; - geode::RayTracing3D tracing{ *mesh, aabb.bounding_box(), ray }; - aabb.compute_ray_element_bbox_intersections( ray, tracing ); - const auto result = tracing.closest_polygon(); - geode::OpenGeodeMeshException::test( - result.has_value(), "Ray edge no result" ); - geode::OpenGeodeMeshException::test( - result->polygon == 0, "Ray edge wrong polygon" ); - geode::OpenGeodeMeshException::test( - result->distance == 0, "Ray edge wrong distance" ); -} + void test_ray_parallel() + { + geode::Logger::info( "Test ray parallel" ); + auto mesh = geode::SurfaceMesh3D::create(); + auto builder = geode::SurfaceMeshBuilder3D::create( *mesh ); + builder->create_point( geode::Point3D{ { -1, -1, 0 } } ); + builder->create_point( geode::Point3D{ { -1, 1, 0 } } ); + builder->create_point( geode::Point3D{ { -2, 0, 0 } } ); + builder->create_polygon( { 0, 1, 2 } ); + const auto aabb = geode::create_aabb_tree( *mesh ); + const geode::Vector3D direction{ { -1, 0, 0 } }; + const geode::Point3D origin{ { 0, 0, 0 } }; + const geode::Ray3D ray{ direction, origin }; + geode::RayTracing3D tracing{ *mesh, aabb.bounding_box(), ray }; + aabb.compute_ray_element_bbox_intersections( ray, tracing ); + const auto result = tracing.closest_polygon(); + geode::OpenGeodeMeshException::test( + result.has_value(), "Ray edge no result" ); + geode::OpenGeodeMeshException::test( + result->polygon == 0, "Ray edge wrong polygon" ); + geode::OpenGeodeMeshException::test( + result->distance == 1, "Ray edge wrong distance" ); + } -void test() -{ - geode::OpenGeodeMeshLibrary::initialize(); - test_ray_inside(); - test_ray_edge(); - test_ray_parallel(); -} + void test() + { + geode::OpenGeodeMeshLibrary::initialize(); + test_ray_inside(); + test_ray_edge(); + test_ray_parallel(); + } +} // namespace OPENGEODE_TEST( "ray-tracing" ) \ No newline at end of file