Skip to content

Commit 195591d

Browse files
authored
feat(Intersections): inspect intersection between TriangulatedSurfaces and EdgedCurves (#54)
1 parent a915eb5 commit 195591d

File tree

13 files changed

+850
-1
lines changed

13 files changed

+850
-1
lines changed

bindings/python/src/inspector/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ add_geode_python_binding(
3636
"degeneration/surface_degeneration.h"
3737
"degeneration/component_meshes_degeneration.h"
3838
"intersections/surface_intersections.h"
39+
"intersections/surface_curve_intersections.h"
3940
"intersections/model_intersections.h"
4041
"manifold/surface_edge_manifold.h"
4142
"manifold/surface_vertex_manifold.h"

bindings/python/src/inspector/inspector.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "degeneration/surface_degeneration.h"
4444

4545
#include "intersections/model_intersections.h"
46+
#include "intersections/surface_curve_intersections.h"
4647
#include "intersections/surface_intersections.h"
4748

4849
#include "manifold/brep_meshes_manifold.h"
@@ -96,6 +97,7 @@ PYBIND11_MODULE( opengeode_inspector_py_inspector, module )
9697
geode::define_surface_degeneration( module );
9798
geode::define_models_meshes_degeneration( module );
9899
geode::define_surface_intersections( module );
100+
geode::define_surface_curve_intersections( module );
99101
geode::define_model_intersections( module );
100102
geode::define_surface_edge_manifold( module );
101103
geode::define_surface_vertex_manifold( module );
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2019 - 2023 Geode-solutions
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*
22+
*/
23+
24+
#include <geode/mesh/core/edged_curve.h>
25+
#include <geode/mesh/core/surface_mesh.h>
26+
27+
#include <geode/inspector/criterion/intersections/surface_curve_intersections.h>
28+
29+
#define PYTHON_SURFACE_CURVE_INTERSECTIONS( dimension ) \
30+
const auto name##dimension = \
31+
"SurfaceCurveIntersections" + std::to_string( dimension ) + "D"; \
32+
pybind11::class_< SurfaceCurveIntersections##dimension##D >( \
33+
module, name##dimension.c_str() ) \
34+
.def( pybind11::init< const SurfaceMesh< dimension >&, \
35+
const EdgedCurve< dimension >& >() ) \
36+
.def( pybind11::init< const SurfaceMesh< dimension >&, \
37+
const EdgedCurve< dimension >&, bool >() ) \
38+
.def( "meshes_have_intersections", \
39+
&SurfaceCurveIntersections##dimension##D:: \
40+
meshes_have_intersections ) \
41+
.def( "nb_intersecting_elements_pair", \
42+
&SurfaceCurveIntersections##dimension##D:: \
43+
nb_intersecting_elements_pair ) \
44+
.def( "intersecting_elements", \
45+
&SurfaceCurveIntersections##dimension##D::intersecting_elements )
46+
47+
namespace geode
48+
{
49+
void define_surface_curve_intersections( pybind11::module& module )
50+
{
51+
PYTHON_SURFACE_CURVE_INTERSECTIONS( 2 );
52+
PYTHON_SURFACE_CURVE_INTERSECTIONS( 3 );
53+
}
54+
} // namespace geode

bindings/python/tests/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ add_geode_python_test(
8484
${PROJECT_NAME}::py_inspector
8585
)
8686

87+
add_geode_python_test(
88+
SOURCE "test-py-surface-curve-intersections.py"
89+
DEPENDENCIES
90+
${PROJECT_NAME}::py_inspector
91+
)
92+
8793
add_geode_python_test(
8894
SOURCE "test-py-surface-manifold.py"
8995
DEPENDENCIES
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (c) 2019 - 2023 Geode-solutions
3+
#
4+
# Permission is hereby granted, free of charge, to any person obtaining a copy
5+
# of this software and associated documentation files (the "Software"), to deal
6+
# in the Software without restriction, including without limitation the rights
7+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
# copies of the Software, and to permit persons to whom the Software is
9+
# furnished to do so, subject to the following conditions:
10+
#
11+
# The above copyright notice and this permission notice shall be included in
12+
# all copies or substantial portions of the Software.
13+
#
14+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
# SOFTWARE.
21+
22+
import os
23+
import sys
24+
import platform
25+
if sys.version_info >= (3, 8, 0) and platform.system() == "Windows":
26+
for path in [x.strip() for x in os.environ['PATH'].split(';') if x]:
27+
os.add_dll_directory(path)
28+
29+
import opengeode as geode
30+
import opengeode_inspector_py_inspector as inspector
31+
32+
def check_intersections2D():
33+
surface = geode.TriangulatedSurface2D.create()
34+
builder = geode.TriangulatedSurfaceBuilder2D.create( surface )
35+
builder.create_vertices( 5 )
36+
builder.set_point( 0, geode.Point2D( [ 0., 0. ] ) )
37+
builder.set_point( 1, geode.Point2D( [ 3., -1. ] ) )
38+
builder.set_point( 2, geode.Point2D( [ 3., 3. ] ) )
39+
builder.set_point( 3, geode.Point2D( [ 0., -3. ] ) )
40+
builder.set_point( 4, geode.Point2D( [ 3., -3. ] ) )
41+
builder.create_triangle( [ 0, 1, 2 ] )
42+
builder.create_triangle( [ 0, 1, 3 ] )
43+
builder.create_triangle( [ 1, 3, 4 ] )
44+
builder.set_polygon_adjacent( geode.PolygonEdge( 0, 0 ), 1 )
45+
builder.set_polygon_adjacent( geode.PolygonEdge( 1, 0 ), 0 )
46+
builder.set_polygon_adjacent( geode.PolygonEdge( 1, 1 ), 2 )
47+
builder.set_polygon_adjacent( geode.PolygonEdge( 2, 0 ), 1 )
48+
49+
curve = geode.EdgedCurve2D.create()
50+
builder_curve = geode.EdgedCurveBuilder2D.create( curve )
51+
builder_curve.create_vertices( 8 )
52+
builder_curve.set_point( 0, geode.Point2D( [ 5., 0. ] ) )
53+
builder_curve.set_point( 1, geode.Point2D( [ 3., 0. ] ) )
54+
builder_curve.set_point( 2, geode.Point2D( [ 2., 0. ] ) )
55+
builder_curve.set_point( 3, geode.Point2D( [ 1., 0. ] ) )
56+
builder_curve.set_point( 4, geode.Point2D( [ -1., 0. ] ) )
57+
builder_curve.set_point( 5, geode.Point2D( [ 0., -3. ] ) )
58+
builder_curve.set_point( 6, geode.Point2D( [ 3., -3. ] ) )
59+
builder_curve.set_point( 7, geode.Point2D( [ 1.5, -2. ] ) )
60+
builder_curve.create_edge_with_vertices( 0, 1 )
61+
builder_curve.create_edge_with_vertices( 1, 2 )
62+
builder_curve.create_edge_with_vertices( 2, 3 )
63+
builder_curve.create_edge_with_vertices( 3, 4 )
64+
builder_curve.create_edge_with_vertices( 4, 5 )
65+
builder_curve.create_edge_with_vertices( 5, 6 )
66+
builder_curve.create_edge_with_vertices( 6, 7 )
67+
68+
intersections_inspector = inspector.SurfaceCurveIntersections2D( surface, curve )
69+
if not intersections_inspector.meshes_have_intersections():
70+
raise ValueError( "[Test] 2D Surface and Curve should have intersections." )
71+
if not intersections_inspector.nb_intersecting_elements_pair() == 7:
72+
raise ValueError( "[Test] 2D Surface and Curve should have 7 intersecting elements pair." )
73+
74+
def check_intersections3D():
75+
surface = geode.TriangulatedSurface3D.create()
76+
builder = geode.TriangulatedSurfaceBuilder3D.create( surface )
77+
builder.create_vertices( 5 )
78+
builder.set_point( 0, geode.Point3D( [ 0., 0., 0 ] ) )
79+
builder.set_point( 1, geode.Point3D( [ 3., -1., 0 ] ) )
80+
builder.set_point( 2, geode.Point3D( [ 3., 3., 0 ] ) )
81+
builder.set_point( 3, geode.Point3D( [ 0., -3., 0 ] ) )
82+
builder.set_point( 4, geode.Point3D( [ 3., -3., 0 ] ) )
83+
builder.create_triangle( [ 0, 1, 2 ] )
84+
builder.create_triangle( [ 0, 1, 3 ] )
85+
builder.create_triangle( [ 1, 3, 4 ] )
86+
builder.set_polygon_adjacent( geode.PolygonEdge( 0, 0 ), 1 )
87+
builder.set_polygon_adjacent( geode.PolygonEdge( 1, 0 ), 0 )
88+
builder.set_polygon_adjacent( geode.PolygonEdge( 1, 1 ), 2 )
89+
builder.set_polygon_adjacent( geode.PolygonEdge( 2, 0 ), 1 )
90+
91+
curve = geode.EdgedCurve3D.create()
92+
builder_curve = geode.EdgedCurveBuilder3D.create( curve )
93+
builder_curve.create_vertices( 9 )
94+
builder_curve.set_point( 0, geode.Point3D( [ 5., 0., 1 ] ) )
95+
builder_curve.set_point( 1, geode.Point3D( [ 3., 0., 0 ] ) )
96+
builder_curve.set_point( 2, geode.Point3D( [ 2., 0., 0 ] ) )
97+
builder_curve.set_point( 3, geode.Point3D( [ 1., 0., 0 ] ) )
98+
builder_curve.set_point( 4, geode.Point3D( [ -1., 0., 0 ] ) )
99+
builder_curve.set_point( 5, geode.Point3D( [ 0., -3., 0 ] ) )
100+
builder_curve.set_point( 6, geode.Point3D( [ 3., -3., 0 ] ) )
101+
builder_curve.set_point( 7, geode.Point3D( [ 1.5, -2., 2 ] ) )
102+
builder_curve.set_point( 8, geode.Point3D( [ 2, -2., -2 ] ) )
103+
builder_curve.create_edge_with_vertices( 0, 1 )
104+
builder_curve.create_edge_with_vertices( 1, 2 )
105+
builder_curve.create_edge_with_vertices( 2, 3 )
106+
builder_curve.create_edge_with_vertices( 3, 4 )
107+
builder_curve.create_edge_with_vertices( 4, 5 )
108+
builder_curve.create_edge_with_vertices( 5, 6 )
109+
builder_curve.create_edge_with_vertices( 6, 7 )
110+
builder_curve.create_edge_with_vertices( 7, 8 )
111+
112+
intersections_inspector = inspector.SurfaceCurveIntersections3D(surface, curve )
113+
if not intersections_inspector.meshes_have_intersections():
114+
raise ValueError( "[Test] 3D Surface and Curve should have intersections." )
115+
if not intersections_inspector.nb_intersecting_elements_pair() == 6:
116+
raise ValueError( "[Test] 3D Surface and Curve should have 6 intersecting elements pair." )
117+
118+
if __name__ == '__main__':
119+
inspector.OpenGeodeInspectorInspector.initialize()
120+
check_intersections2D()
121+
check_intersections3D()
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) 2019 - 2023 Geode-solutions
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*
22+
*/
23+
24+
#pragma once
25+
26+
#include <absl/types/span.h>
27+
28+
#include <geode/basic/pimpl.h>
29+
30+
#include <geode/inspector/common.h>
31+
32+
namespace geode
33+
{
34+
FORWARD_DECLARATION_DIMENSION_CLASS( SurfaceMesh );
35+
FORWARD_DECLARATION_DIMENSION_CLASS( EdgedCurve );
36+
} // namespace geode
37+
38+
namespace geode
39+
{
40+
/*!
41+
* Class for inspecting the intersections of SurfaceMeshes
42+
*/
43+
template < index_t dimension >
44+
class opengeode_inspector_inspector_api SurfaceCurveIntersections
45+
{
46+
OPENGEODE_DISABLE_COPY( SurfaceCurveIntersections );
47+
48+
public:
49+
SurfaceCurveIntersections( const SurfaceMesh< dimension >& surface,
50+
const EdgedCurve< dimension >& curve );
51+
52+
SurfaceCurveIntersections( const SurfaceMesh< dimension >& mesh,
53+
const EdgedCurve< dimension >& curve,
54+
bool verbose );
55+
56+
~SurfaceCurveIntersections();
57+
58+
bool meshes_have_intersections() const;
59+
60+
index_t nb_intersecting_elements_pair() const;
61+
62+
/* Returns all pairs of intersecting triangles and edges.
63+
* First element of each pair is a triangle index in the SurfaceMesh,
64+
* second element of each pair is an edge index in the EdgedCurve.
65+
*/
66+
std::vector< std::pair< index_t, index_t > >
67+
intersecting_elements() const;
68+
69+
private:
70+
IMPLEMENTATION_MEMBER( impl_ );
71+
};
72+
ALIAS_2D_AND_3D( SurfaceCurveIntersections );
73+
} // namespace geode

src/bin/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,16 @@ add_geode_binary(
131131
OpenGeode-IO::mesh
132132
${PROJECT_NAME}::inspector
133133
)
134+
135+
add_geode_binary(
136+
SOURCE "geode-inspector-surface-curve-intersections.cpp"
137+
DEPENDENCIES
138+
Async++
139+
absl::flags
140+
absl::flags_parse
141+
absl::flags_usage
142+
OpenGeode::basic
143+
OpenGeode::mesh
144+
OpenGeode-IO::mesh
145+
${PROJECT_NAME}::inspector
146+
)

0 commit comments

Comments
 (0)