From 1bc458d5b0dfb4efd97be490addd6522f13386a1 Mon Sep 17 00:00:00 2001 From: BenPinet Date: Mon, 2 Mar 2026 16:59:58 +0100 Subject: [PATCH 01/11] feat(IspointInside): check if a point is inside a polygon --- include/geode/geometry/is_point_inside.hpp | 42 +++++++++++ src/geode/geometry/CMakeLists.txt | 2 + src/geode/geometry/is_point_inside.cpp | 84 ++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 include/geode/geometry/is_point_inside.hpp create mode 100644 src/geode/geometry/is_point_inside.cpp diff --git a/include/geode/geometry/is_point_inside.hpp b/include/geode/geometry/is_point_inside.hpp new file mode 100644 index 000000000..6892b5163 --- /dev/null +++ b/include/geode/geometry/is_point_inside.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 - 2026 Geode-solutions + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#pragma once + +#include +#include +#include + +namespace geode +{ + /*! + * Find if point is inside a polygon. + * @param[in] point The point to rotate. + * @param[in] axis Axis for the rotation (not null but not necessary + * normalized). + * @param[in] angle Rotation angle expresses in radians. + */ + [[nodiscard]] bool opengeode_geometry_api is_point_inside_polygon( + const Point2D& point, absl::Span< const Point2D > polygon_points ); + +} // namespace geode \ No newline at end of file diff --git a/src/geode/geometry/CMakeLists.txt b/src/geode/geometry/CMakeLists.txt index 973cc2456..b70775c6e 100644 --- a/src/geode/geometry/CMakeLists.txt +++ b/src/geode/geometry/CMakeLists.txt @@ -47,6 +47,7 @@ add_geode_library( "information.cpp" "intersection.cpp" "intersection_detection.cpp" + "is_point_inside.cpp" "mensuration.cpp" "nn_search.cpp" "normal_frame_transform.cpp" @@ -86,6 +87,7 @@ add_geode_library( "information.hpp" "intersection.hpp" "intersection_detection.hpp" + "is_point_inside.hpp" "mensuration.hpp" "nn_search.hpp" "normal_frame_transform.hpp" diff --git a/src/geode/geometry/is_point_inside.cpp b/src/geode/geometry/is_point_inside.cpp new file mode 100644 index 000000000..929e89eb9 --- /dev/null +++ b/src/geode/geometry/is_point_inside.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019 - 2026 Geode-solutions + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include + +#include + +namespace +{ + double is_left( const geode::Point2D& p0, + const geode::Point2D& p1, + const geode::Point2D& p2 ) + { + return ( p1.value( 0 ) - p0.value( 0 ) ) + * ( p2.value( 1 ) - p0.value( 1 ) ) + - ( p2.value( 0 ) - p0.value( 0 ) ) + * ( p1.value( 1 ) - p0.value( 1 ) ); + } +} // namespace + +namespace geode +{ + bool opengeode_geometry_api is_point_inside_polygon( + const Point2D& point, absl::Span< const Point2D > polygon_points ) + { + double widing_number{ 0 }; + DEBUG( "is_point_inside_polygon" ); + SDEBUG( point ); + for( const auto polygon_vertex : + geode::Range{ 0, polygon_points.size() } ) + { + const auto v0 = polygon_points[polygon_vertex]; + const auto next_polygon_vertex = + ( polygon_vertex + 1 ) % polygon_points.size(); + const auto v1 = polygon_points[next_polygon_vertex]; + SDEBUG( v0 ); + SDEBUG( v1 ); + if( v0.value( 1 ) <= point.value( 1 ) ) + { + if( v1.value( 1 ) > point.value( 1 ) ) + { + if( is_left( v0, v1, point ) > 0 ) + { + DEBUG( "widing_number++" ); + widing_number++; + } + } + } + else + { + if( v1.value( 1 ) <= point.value( 1 ) ) + { + if( is_left( v0, v1, point ) < 0 ) + { + DEBUG( "widing_number--" ); + widing_number--; + } + } + } + } + DEBUG( widing_number ); + return widing_number != 0; + } +} // namespace geode \ No newline at end of file From 15b4e2c0f8c1112faffde656c9d0223a322f878f Mon Sep 17 00:00:00 2001 From: Pierre Anquez Date: Mon, 2 Mar 2026 21:38:16 +0100 Subject: [PATCH 02/11] PR review --- include/geode/geometry/is_point_inside.hpp | 15 +++--- src/geode/geometry/is_point_inside.cpp | 53 ++++++++++------------ 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/include/geode/geometry/is_point_inside.hpp b/include/geode/geometry/is_point_inside.hpp index 6892b5163..a928e9a38 100644 --- a/include/geode/geometry/is_point_inside.hpp +++ b/include/geode/geometry/is_point_inside.hpp @@ -23,20 +23,23 @@ #pragma once -#include #include -#include + +namespace geode +{ + FORWARD_DECLARATION_DIMENSION_CLASS( Point ); + FORWARD_DECLARATION_DIMENSION_CLASS( Polygon ); + ALIAS_2D( Point ); + ALIAS_2D( Polygon ); +} // namespace geode namespace geode { /*! * Find if point is inside a polygon. * @param[in] point The point to rotate. - * @param[in] axis Axis for the rotation (not null but not necessary - * normalized). - * @param[in] angle Rotation angle expresses in radians. */ [[nodiscard]] bool opengeode_geometry_api is_point_inside_polygon( - const Point2D& point, absl::Span< const Point2D > polygon_points ); + const Point2D& point, const Polygon2D& polygon ); } // namespace geode \ No newline at end of file diff --git a/src/geode/geometry/is_point_inside.cpp b/src/geode/geometry/is_point_inside.cpp index 929e89eb9..ac9db7c91 100644 --- a/src/geode/geometry/is_point_inside.cpp +++ b/src/geode/geometry/is_point_inside.cpp @@ -23,62 +23,57 @@ #include -#include +#include +#include namespace { - double is_left( const geode::Point2D& p0, + bool is_left( const geode::Point2D& p0, const geode::Point2D& p1, const geode::Point2D& p2 ) { return ( p1.value( 0 ) - p0.value( 0 ) ) - * ( p2.value( 1 ) - p0.value( 1 ) ) - - ( p2.value( 0 ) - p0.value( 0 ) ) - * ( p1.value( 1 ) - p0.value( 1 ) ); + * ( p2.value( 1 ) - p0.value( 1 ) ) + - ( p2.value( 0 ) - p0.value( 0 ) ) + * ( p1.value( 1 ) - p0.value( 1 ) ) + > 0; } } // namespace namespace geode { - bool opengeode_geometry_api is_point_inside_polygon( - const Point2D& point, absl::Span< const Point2D > polygon_points ) + bool is_point_inside_polygon( + const Point2D& point, const Polygon2D& polygon ) { - double widing_number{ 0 }; - DEBUG( "is_point_inside_polygon" ); - SDEBUG( point ); - for( const auto polygon_vertex : - geode::Range{ 0, polygon_points.size() } ) + double winding_number{ 0 }; + const auto& vertices = polygon.vertices(); + for( const auto polygon_vertex : geode::Range{ polygon.nb_vertices() } ) { - const auto v0 = polygon_points[polygon_vertex]; - const auto next_polygon_vertex = - ( polygon_vertex + 1 ) % polygon_points.size(); - const auto v1 = polygon_points[next_polygon_vertex]; - SDEBUG( v0 ); - SDEBUG( v1 ); - if( v0.value( 1 ) <= point.value( 1 ) ) + const auto& v0 = vertices[polygon_vertex]; + const auto& next_polygon_vertex = + ( polygon_vertex + 1 ) % vertices.size(); + const auto& v1 = vertices[next_polygon_vertex]; + if( v0.get().value( 1 ) <= point.value( 1 ) ) { - if( v1.value( 1 ) > point.value( 1 ) ) + if( v1.get().value( 1 ) > point.value( 1 ) ) { - if( is_left( v0, v1, point ) > 0 ) + if( is_left( v0, v1, point ) ) { - DEBUG( "widing_number++" ); - widing_number++; + winding_number++; } } } else { - if( v1.value( 1 ) <= point.value( 1 ) ) + if( v1.get().value( 1 ) <= point.value( 1 ) ) { - if( is_left( v0, v1, point ) < 0 ) + if( !is_left( v0, v1, point ) ) { - DEBUG( "widing_number--" ); - widing_number--; + winding_number--; } } } } - DEBUG( widing_number ); - return widing_number != 0; + return winding_number != 0; } } // namespace geode \ No newline at end of file From 75c892c964dcd55f342db8fc5d728ae3359014ff Mon Sep 17 00:00:00 2001 From: BenPinet Date: Thu, 5 Mar 2026 17:12:17 +0100 Subject: [PATCH 03/11] fix(Distace): use dichotomic method to compute segment segment distance in case first method can't be precise enough --- src/geode/geometry/distance.cpp | 193 ++++++++++++++++++++++---------- 1 file changed, 131 insertions(+), 62 deletions(-) diff --git a/src/geode/geometry/distance.cpp b/src/geode/geometry/distance.cpp index 7472971de..7f78a82eb 100644 --- a/src/geode/geometry/distance.cpp +++ b/src/geode/geometry/distance.cpp @@ -476,79 +476,35 @@ namespace } return std::make_tuple( min_distance, point0, point1 ); } -} // namespace - -namespace geode -{ - template < index_t dimension > - double point_point_distance( - const Point< dimension >& point0, const Point< dimension >& point1 ) - { - double diff2{ 0 }; - for( const auto d : LRange{ dimension } ) - { - const auto diff = point0.value( d ) - point1.value( d ); - diff2 += diff * diff; - } - return std::sqrt( diff2 ); - } - template < index_t dimension > - double point_segment_distance( - const Point< dimension >& point, const Segment< dimension >& segment ) - { - const auto length = segment.length(); - const auto length0 = - point_point_distance( segment.vertices()[0].get(), point ); - if( length <= GLOBAL_EPSILON ) - { - return length0; - } - const auto length1 = - point_point_distance( segment.vertices()[1].get(), point ); - const auto sqr_length = length * length; - const auto sqr_length0 = length0 * length0; - const auto sqr_length1 = length1 * length1; - if( length0 >= length && length0 >= length1 - && sqr_length + sqr_length1 <= sqr_length0 ) - { // obtuse by vertex 1 - return length1; - } - if( length1 >= length && length1 >= length0 - && sqr_length + sqr_length0 <= sqr_length1 ) - { // obtuse by vertex 0 - return length0; - } - // acute angles - if( const auto distance = - compute_point_line_distance( length, length0, length1 ) ) - { - return distance.value(); - } - return std::get< 0 >( - point_segment_distance_using_projection( point, segment ) ); - } - - template < index_t dimension > - std::tuple< double, Point< dimension >, Point< dimension > > - segment_segment_distance( const Segment< dimension >& segment0, - const Segment< dimension >& segment1 ) + template < geode::index_t dimension > + std::optional< std::tuple< double, + geode::Point< dimension >, + geode::Point< dimension > > > + approximate_segment_segment_distance( + const geode::Segment< dimension >& segment0, + const geode::Segment< dimension >& segment1 ) { /* Algorithm and code found on * https://github.com/davideberly/GeometricTools/blob/master/GTE/Mathematics/DistSegmentSegment.h */ const auto P1mP0 = segment0.direction(); const auto Q1mQ0 = segment1.direction(); - const Vector< dimension > P0mQ0{ segment1.vertices()[0], + const geode::Vector< dimension > P0mQ0{ segment1.vertices()[0], segment0.vertices()[0] }; const auto a = P1mP0.dot( P1mP0 ); const auto b = P1mP0.dot( Q1mQ0 ); const auto c = Q1mQ0.dot( Q1mQ0 ); const auto d = P1mP0.dot( P0mQ0 ); const auto e = Q1mQ0.dot( P0mQ0 ); - const auto det = a * c - b * b; + const auto ac = a * c; + const auto bb = b * b; + if( std::log2( std::abs( ac ) / std::abs( ac - bb ) ) > 20 ) + { + return std::nullopt; + } + const auto det = ac - bb; double s, t, nd, bmd, bte, ctd, bpe, ate, btd; - if( det > 0 ) { bte = b * e; @@ -594,6 +550,10 @@ namespace geode } else // s > 0 { + if( std::log2( std::abs( bte ) / std::abs( bte - ctd ) ) > 20 ) + { + return std::nullopt; + } s = bte - ctd; if( s >= det ) // s >= 1 { @@ -660,6 +620,11 @@ namespace geode } else // t > 0 { + if( std::log2( std::abs( ate ) / std::abs( ate - btd ) ) + > 20 ) + { + return std::nullopt; + } t = ate - btd; if( t >= det ) // t >= 1 { @@ -766,21 +731,21 @@ namespace geode segment1.vertices()[0].get() + Q1mQ0 * t; const auto distance = point_point_distance( closest_on_segment0, closest_on_segment1 ); - if( distance < GLOBAL_EPSILON ) + if( distance < geode::GLOBAL_EPSILON ) { return std::make_tuple( distance, closest_on_segment0, closest_on_segment1 ); } const auto distance_to_closest0 = point_segment_distance( closest_on_segment0, segment1 ); - if( distance_to_closest0 < GLOBAL_EPSILON ) + if( distance_to_closest0 < geode::GLOBAL_EPSILON ) { return std::make_tuple( distance_to_closest0, closest_on_segment0, point_segment_projection( closest_on_segment0, segment1 ) ); } const auto distance_to_closest1 = point_segment_distance( closest_on_segment1, segment0 ); - if( distance_to_closest1 < GLOBAL_EPSILON ) + if( distance_to_closest1 < geode::GLOBAL_EPSILON ) { return std::make_tuple( distance_to_closest1, point_segment_projection( closest_on_segment1, segment0 ), @@ -807,6 +772,110 @@ namespace geode distance, closest_on_segment0, closest_on_segment1 ); } + template < geode::index_t dimension > + std::tuple< double, geode::Point< dimension >, geode::Point< dimension > > + dichotomic_segment_segment_distance( + const geode::Segment< dimension >& segment0, + const geode::Segment< dimension >& segment1 ) + { + auto current_point = segment0.vertices()[0].get(); + auto step = segment0.length() / 4; + auto current_distance = + geode::point_segment_distance( current_point, segment1 ); + geode::index_t nb_steps = 0; + while( step > geode::GLOBAL_EPSILON ) + { + const auto point_at_step_plus = + current_point + segment0.normalized_direction() * step; + const auto point_at_step_minus = + current_point - segment0.normalized_direction() * step; + const auto distance_plus = + geode::point_segment_distance( point_at_step_plus, segment1 ); + const auto distance_minus = + geode::point_segment_distance( point_at_step_minus, segment1 ); + if( distance_plus < current_distance ) + { + current_distance = distance_plus; + current_point = point_at_step_plus; + } + if( distance_minus < current_distance ) + { + current_distance = distance_minus; + current_point = point_at_step_minus; + } + step /= 2; + nb_steps++; + } + return std::make_tuple( + current_distance, current_point, current_point ); + } + +} // namespace + +namespace geode +{ + template < index_t dimension > + double point_point_distance( + const Point< dimension >& point0, const Point< dimension >& point1 ) + { + double diff2{ 0 }; + for( const auto d : LRange{ dimension } ) + { + const auto diff = point0.value( d ) - point1.value( d ); + diff2 += diff * diff; + } + return std::sqrt( diff2 ); + } + + template < index_t dimension > + double point_segment_distance( + const Point< dimension >& point, const Segment< dimension >& segment ) + { + const auto length = segment.length(); + const auto length0 = + point_point_distance( segment.vertices()[0].get(), point ); + if( length <= GLOBAL_EPSILON ) + { + return length0; + } + const auto length1 = + point_point_distance( segment.vertices()[1].get(), point ); + const auto sqr_length = length * length; + const auto sqr_length0 = length0 * length0; + const auto sqr_length1 = length1 * length1; + if( length0 >= length && length0 >= length1 + && sqr_length + sqr_length1 <= sqr_length0 ) + { // obtuse by vertex 1 + return length1; + } + if( length1 >= length && length1 >= length0 + && sqr_length + sqr_length0 <= sqr_length1 ) + { // obtuse by vertex 0 + return length0; + } + // acute angles + if( const auto distance = + compute_point_line_distance( length, length0, length1 ) ) + { + return distance.value(); + } + return std::get< 0 >( + point_segment_distance_using_projection( point, segment ) ); + } + + template < index_t dimension > + std::tuple< double, Point< dimension >, Point< dimension > > + segment_segment_distance( const Segment< dimension >& segment0, + const Segment< dimension >& segment1 ) + { + if( const auto approximation = + approximate_segment_segment_distance( segment0, segment1 ) ) + { + return approximation.value(); + } + return dichotomic_segment_segment_distance( segment0, segment1 ); + } + template < index_t dimension > std::tuple< double, Point< dimension >, Point< dimension > > segment_line_distance( const Segment< dimension >& segment, From 7499f7a1f6ec671bf53e03b25123b299c63560b6 Mon Sep 17 00:00:00 2001 From: BenPinet Date: Thu, 5 Mar 2026 17:14:05 +0100 Subject: [PATCH 04/11] remove debug --- src/geode/geometry/distance.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/geode/geometry/distance.cpp b/src/geode/geometry/distance.cpp index 7f78a82eb..484c1b59f 100644 --- a/src/geode/geometry/distance.cpp +++ b/src/geode/geometry/distance.cpp @@ -782,7 +782,6 @@ namespace auto step = segment0.length() / 4; auto current_distance = geode::point_segment_distance( current_point, segment1 ); - geode::index_t nb_steps = 0; while( step > geode::GLOBAL_EPSILON ) { const auto point_at_step_plus = @@ -804,7 +803,6 @@ namespace current_point = point_at_step_minus; } step /= 2; - nb_steps++; } return std::make_tuple( current_distance, current_point, current_point ); From f3652c27cba4d687a4375e8627944bed7b805866 Mon Sep 17 00:00:00 2001 From: BenPinet Date: Thu, 5 Mar 2026 17:30:10 +0100 Subject: [PATCH 05/11] pierre's comments --- src/geode/geometry/distance.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/geode/geometry/distance.cpp b/src/geode/geometry/distance.cpp index 484c1b59f..cdf0c9663 100644 --- a/src/geode/geometry/distance.cpp +++ b/src/geode/geometry/distance.cpp @@ -778,16 +778,17 @@ namespace const geode::Segment< dimension >& segment0, const geode::Segment< dimension >& segment1 ) { - auto current_point = segment0.vertices()[0].get(); + auto current_point = segment0.barycenter(); auto step = segment0.length() / 4; auto current_distance = geode::point_segment_distance( current_point, segment1 ); + const auto segment_direction = segment0.normalized_direction(); while( step > geode::GLOBAL_EPSILON ) { const auto point_at_step_plus = - current_point + segment0.normalized_direction() * step; + current_point + segment_direction * step; const auto point_at_step_minus = - current_point - segment0.normalized_direction() * step; + current_point - segment_direction * step; const auto distance_plus = geode::point_segment_distance( point_at_step_plus, segment1 ); const auto distance_minus = From 63b0c88c69974c9d2e3c907de7e04170eebfd328 Mon Sep 17 00:00:00 2001 From: BenPinet Date: Fri, 6 Mar 2026 09:53:10 +0100 Subject: [PATCH 06/11] arnaud's comment --- src/geode/geometry/distance.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/geode/geometry/distance.cpp b/src/geode/geometry/distance.cpp index cdf0c9663..f05495bcb 100644 --- a/src/geode/geometry/distance.cpp +++ b/src/geode/geometry/distance.cpp @@ -778,21 +778,25 @@ namespace const geode::Segment< dimension >& segment0, const geode::Segment< dimension >& segment1 ) { - auto current_point = segment0.barycenter(); - auto step = segment0.length() / 4; + const auto longest_segment = + ( segment0.length() > segment1.length() ) ? segment0 : segment1; + const auto shortest_segment = + ( segment0.length() < segment1.length() ) ? segment0 : segment1; + auto current_point = longest_segment.barycenter(); + auto step = longest_segment.length() / 4; auto current_distance = - geode::point_segment_distance( current_point, segment1 ); - const auto segment_direction = segment0.normalized_direction(); + geode::point_segment_distance( current_point, shortest_segment ); + const auto segment_direction = longest_segment.normalized_direction(); while( step > geode::GLOBAL_EPSILON ) { const auto point_at_step_plus = current_point + segment_direction * step; const auto point_at_step_minus = current_point - segment_direction * step; - const auto distance_plus = - geode::point_segment_distance( point_at_step_plus, segment1 ); - const auto distance_minus = - geode::point_segment_distance( point_at_step_minus, segment1 ); + const auto distance_plus = geode::point_segment_distance( + point_at_step_plus, shortest_segment ); + const auto distance_minus = geode::point_segment_distance( + point_at_step_minus, shortest_segment ); if( distance_plus < current_distance ) { current_distance = distance_plus; From 2e29255332b6889e81a3de18a95427f7d1f5a098 Mon Sep 17 00:00:00 2001 From: BenPinet Date: Fri, 6 Mar 2026 10:29:27 +0100 Subject: [PATCH 07/11] fix test --- src/geode/geometry/distance.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/geode/geometry/distance.cpp b/src/geode/geometry/distance.cpp index f05495bcb..3f26576ae 100644 --- a/src/geode/geometry/distance.cpp +++ b/src/geode/geometry/distance.cpp @@ -499,14 +499,14 @@ namespace const auto e = Q1mQ0.dot( P0mQ0 ); const auto ac = a * c; const auto bb = b * b; - if( std::log2( std::abs( ac ) / std::abs( ac - bb ) ) > 20 ) - { - return std::nullopt; - } const auto det = ac - bb; double s, t, nd, bmd, bte, ctd, bpe, ate, btd; if( det > 0 ) { + if( std::log2( std::abs( ac ) / std::abs( ac - bb ) ) > 20 ) + { + return std::nullopt; + } bte = b * e; ctd = c * d; if( bte <= ctd ) // s <= 0 From 8d22b358a15632725583a1776a853ce1f7969b6b Mon Sep 17 00:00:00 2001 From: BenPinet Date: Fri, 6 Mar 2026 10:30:36 +0100 Subject: [PATCH 08/11] fix test --- src/geode/geometry/distance.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/geode/geometry/distance.cpp b/src/geode/geometry/distance.cpp index 3f26576ae..d8594064e 100644 --- a/src/geode/geometry/distance.cpp +++ b/src/geode/geometry/distance.cpp @@ -499,14 +499,14 @@ namespace const auto e = Q1mQ0.dot( P0mQ0 ); const auto ac = a * c; const auto bb = b * b; - const auto det = ac - bb; double s, t, nd, bmd, bte, ctd, bpe, ate, btd; - if( det > 0 ) + if( ac > bb ) { if( std::log2( std::abs( ac ) / std::abs( ac - bb ) ) > 20 ) { return std::nullopt; } + const auto det = ac - bb; bte = b * e; ctd = c * d; if( bte <= ctd ) // s <= 0 From b117e006305dd43c1185654238bdab1a15e2d866 Mon Sep 17 00:00:00 2001 From: BenPinet Date: Fri, 6 Mar 2026 13:51:59 +0100 Subject: [PATCH 09/11] fix tests --- .../tests/geometry/test-py-bounding-box.py | 25 +++++++++++-------- src/geode/geometry/distance.cpp | 24 +++++++++++++++--- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/bindings/python/tests/geometry/test-py-bounding-box.py b/bindings/python/tests/geometry/test-py-bounding-box.py index aa9589ed5..9c1bb829d 100644 --- a/bindings/python/tests/geometry/test-py-bounding-box.py +++ b/bindings/python/tests/geometry/test-py-bounding-box.py @@ -22,13 +22,14 @@ import os import sys import platform + if sys.version_info >= (3, 8, 0) and platform.system() == "Windows": - for path in [x.strip() for x in os.environ['PATH'].split(';') if x]: + for path in [x.strip() for x in os.environ["PATH"].split(";") if x]: os.add_dll_directory(path) import opengeode_py_geometry as geom -if __name__ == '__main__': +if __name__ == "__main__": box = geom.BoundingBox2D() box.add_point(geom.Point2D([-1, -1])) box.add_point(geom.Point2D([1, 1])) @@ -52,29 +53,33 @@ bbox3 = geom.BoundingBox3D() bbox3.add_point(geom.Point3D([-1, -1, -1])) bbox3.add_point(geom.Point3D([1, 1, 1])) - + # Points + point0 = geom.Point3D([0, 0, 0]) + point1 = geom.Point3D([0, 0, 2]) + point2 = geom.Point3D([0, 0, -2]) # Rays - ray_inside = geom.Ray3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, 0])) + + ray_inside = geom.Ray3D(geom.Vector3D([0, 0, 1]), point0) if not bbox3.intersects_ray(ray_inside): raise ValueError("[Test] Wrong result with ray_inside") - ray_up = geom.Ray3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, 2])) + ray_up = geom.Ray3D(geom.Vector3D([0, 0, 1]), point1) if bbox3.intersects_ray(ray_up): raise ValueError("[Test] Wrong result with ray_up") - ray_down = geom.Ray3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, -2])) + ray_down = geom.Ray3D(geom.Vector3D([0, 0, 1]), point2) if not bbox3.intersects_ray(ray_down): raise ValueError("[Test] Wrong result with ray_down") # Infinite lines - line_inside = geom.InfiniteLine3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, 0])) + line_inside = geom.InfiniteLine3D(geom.Vector3D([0, 0, 1]), point0) if not bbox3.intersects_infinite_line(line_inside): raise ValueError("[Test] Wrong result with line_inside") - line_up = geom.InfiniteLine3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, 2])) + line_up = geom.InfiniteLine3D(geom.Vector3D([0, 0, 1]), point1) if not bbox3.intersects_infinite_line(line_up): raise ValueError("[Test] Wrong result with line_up") - line_down = geom.InfiniteLine3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, -2])) + line_down = geom.InfiniteLine3D(geom.Vector3D([0, 0, 1]), point2) if not bbox3.intersects_infinite_line(line_down): - raise ValueError("[Test] Wrong result with line_down") \ No newline at end of file + raise ValueError("[Test] Wrong result with line_down") diff --git a/src/geode/geometry/distance.cpp b/src/geode/geometry/distance.cpp index d8594064e..a7a8cc0bf 100644 --- a/src/geode/geometry/distance.cpp +++ b/src/geode/geometry/distance.cpp @@ -500,10 +500,14 @@ namespace const auto ac = a * c; const auto bb = b * b; double s, t, nd, bmd, bte, ctd, bpe, ate, btd; + DEBUG( ac ); + DEBUG( bb ); if( ac > bb ) { if( std::log2( std::abs( ac ) / std::abs( ac - bb ) ) > 20 ) { + DEBUG( "DET" ); + DEBUG( std::log2( std::abs( ac ) / std::abs( ac - bb ) ) ); return std::nullopt; } const auto det = ac - bb; @@ -552,6 +556,8 @@ namespace { if( std::log2( std::abs( bte ) / std::abs( bte - ctd ) ) > 20 ) { + DEBUG( + std::log2( std::abs( bte ) / std::abs( bte - ctd ) ) ); return std::nullopt; } s = bte - ctd; @@ -623,6 +629,8 @@ namespace if( std::log2( std::abs( ate ) / std::abs( ate - btd ) ) > 20 ) { + DEBUG( std::log2( + std::abs( ate ) / std::abs( ate - btd ) ) ); return std::nullopt; } t = ate - btd; @@ -782,8 +790,14 @@ namespace ( segment0.length() > segment1.length() ) ? segment0 : segment1; const auto shortest_segment = ( segment0.length() < segment1.length() ) ? segment0 : segment1; - auto current_point = longest_segment.barycenter(); - auto step = longest_segment.length() / 4; + auto current_point = + ( geode::point_segment_distance( + longest_segment.vertices()[0].get(), shortest_segment ) + < geode::point_segment_distance( + longest_segment.vertices()[1].get(), shortest_segment ) ) + ? longest_segment.vertices()[0].get() + : longest_segment.vertices()[1].get(); + auto step = longest_segment.length() / 2; auto current_distance = geode::point_segment_distance( current_point, shortest_segment ); const auto segment_direction = longest_segment.normalized_direction(); @@ -797,12 +811,14 @@ namespace point_at_step_plus, shortest_segment ); const auto distance_minus = geode::point_segment_distance( point_at_step_minus, shortest_segment ); - if( distance_plus < current_distance ) + if( distance_plus < current_distance + && current_point != longest_segment.vertices()[1].get() ) { current_distance = distance_plus; current_point = point_at_step_plus; } - if( distance_minus < current_distance ) + if( distance_minus < current_distance + && current_point != longest_segment.vertices()[0].get() ) { current_distance = distance_minus; current_point = point_at_step_minus; From 181a4edc0dfbc43140f55c94fca8d9ea0d0d2308 Mon Sep 17 00:00:00 2001 From: BenPinet <126688250+BenPinet@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:23:14 +0000 Subject: [PATCH 10/11] Apply prepare changes --- .clang-tidy | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index c5d55af02..20868d455 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -8,6 +8,7 @@ Checks: > -fuchsia*, -llvmlibc*, -llvm-header-guard, + -llvm-prefer-static-over-anonymous-namespace, -misc-no-recursion, -modernize-use-trailing-return-type, -readability-redundant-access-specifiers, @@ -15,19 +16,19 @@ Checks: > -cppcoreguidelines-avoid-const-or-ref-data-members CheckOptions: - - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic - value: '1' + - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: "1" - key: readability-identifier-length.MinimumLoopCounterNameLength value: 1 - key: readability-identifier-length.IgnoredVariableNames - value: '^[defijkptuvw]$' + value: "^[defijkptuvw]$" # More options here: https://clang.llvm.org/extra/clang-tidy/checks/readability/identifier-naming.html - key: readability-identifier-naming.NamespaceCase value: lower_case - key: readability-identifier-naming.ClassCase - value: CamelCase + value: CamelCase - key: readability-identifier-naming.StructCase - value: CamelCase + value: CamelCase - key: readability-identifier-naming.FunctionCase value: lower_case - key: readability-identifier-naming.VariableCase @@ -51,14 +52,12 @@ CheckOptions: - key: readability-identifier-naming.GlobalFunctionCase value: lower_case - key: readability-identifier-naming.MemberConstantCase - value: CamelCase + value: CamelCase - key: readability-identifier-naming.StaticConstantCase - value: lower_case + value: lower_case - key: readability-function-cognitive-complexity.Threshold value: 10 - key: readability-function-size.ParameterThreshold value: 4 - key: misc-include-cleaner.IgnoreHeaders - value: utility;cstddef;geode/.*_export\.h;geode/.*/common\.h;geode/basic/types\.h;geode/basic/assert\.h; - - + value: utility;cstddef;geode/.*_export\.h;geode/.*/common\.h;geode/basic/types\.h;geode/basic/assert\.h; From 27303374918ad9f083cfa15cb12e734e664265a4 Mon Sep 17 00:00:00 2001 From: BenPinet Date: Fri, 6 Mar 2026 14:30:11 +0100 Subject: [PATCH 11/11] wip --- src/geode/geometry/distance.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/geode/geometry/distance.cpp b/src/geode/geometry/distance.cpp index a7a8cc0bf..f368f8e1c 100644 --- a/src/geode/geometry/distance.cpp +++ b/src/geode/geometry/distance.cpp @@ -500,14 +500,10 @@ namespace const auto ac = a * c; const auto bb = b * b; double s, t, nd, bmd, bte, ctd, bpe, ate, btd; - DEBUG( ac ); - DEBUG( bb ); if( ac > bb ) { if( std::log2( std::abs( ac ) / std::abs( ac - bb ) ) > 20 ) { - DEBUG( "DET" ); - DEBUG( std::log2( std::abs( ac ) / std::abs( ac - bb ) ) ); return std::nullopt; } const auto det = ac - bb; @@ -556,8 +552,6 @@ namespace { if( std::log2( std::abs( bte ) / std::abs( bte - ctd ) ) > 20 ) { - DEBUG( - std::log2( std::abs( bte ) / std::abs( bte - ctd ) ) ); return std::nullopt; } s = bte - ctd; @@ -629,8 +623,6 @@ namespace if( std::log2( std::abs( ate ) / std::abs( ate - btd ) ) > 20 ) { - DEBUG( std::log2( - std::abs( ate ) / std::abs( ate - btd ) ) ); return std::nullopt; } t = ate - btd;