Skip to content

Commit 33e5fa3

Browse files
ADD subdivision and triangulation and types_std
1 parent 8866521 commit 33e5fa3

38 files changed

+1289
-163
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ function(add_nanobind_module module_name source_file)
225225
endfunction()
226226

227227
# Add new modules here
228+
add_nanobind_module(types_std src/types_std.cpp)
228229
add_nanobind_module(booleans_ext src/booleans.cpp)
229230
add_nanobind_module(meshing_ext src/meshing.cpp)
230231
add_nanobind_module(intersections_ext src/intersections.cpp)
@@ -233,4 +234,7 @@ add_nanobind_module(reconstruction_ext src/reconstruction.cpp)
233234
add_nanobind_module(skeletonization_ext src/skeletonization.cpp)
234235
add_nanobind_module(slicer_ext src/slicer.cpp)
235236
add_nanobind_module(straight_skeleton_2_ext src/straight_skeleton_2.cpp)
237+
add_nanobind_module(triangulation_ext src/triangulation.cpp)
238+
add_nanobind_module(subdivision_ext src/subdivision.cpp)
239+
236240

docs/examples/example_reconstruction_pointset_smoothing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def reconstruction_pointset_smoothing():
1717
ply_file_path = Path(__file__).parent.parent.parent / "data" / "box.ply"
1818
original_points = Pointcloud.from_ply(ply_file_path)
1919

20-
smoothed_points = pointset_smoothing(original_points, 1000, 3)
20+
smoothed_points = pointset_smoothing(original_points, 100, 3)
2121

2222
return Pointcloud(original_points), Pointcloud(smoothed_points)
2323

docs/examples/example_straight_skeleton_2_interior_straight_skeleton_with_holes.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from compas.geometry import Point
21
from compas.geometry import Polygon
32
from compas_viewer import Viewer
43
from line_profiler import profile
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from compas.geometry import Box
2+
from compas.geometry import Polyhedron
3+
from compas.geometry import Translation
4+
from compas_viewer import Viewer
5+
from line_profiler import profile
6+
7+
from compas_cgal.subdivision import mesh_subdivide_catmull_clark
8+
from compas_cgal.subdivision import mesh_subdivide_loop
9+
from compas_cgal.subdivision import mesh_subdivide_sqrt3
10+
11+
12+
@profile
13+
def main():
14+
"""Subdivide a mesh using different subdivision algorithms."""
15+
16+
# ==============================================================================
17+
# Input geometry
18+
# ==============================================================================
19+
20+
box = Box.from_diagonal(([0, 0, 0], [1, 1, 1]))
21+
22+
V0, F0 = box.to_vertices_and_faces(triangulated=False)
23+
V1, F1 = box.to_vertices_and_faces(triangulated=False)
24+
V2, F2 = box.to_vertices_and_faces(triangulated=True)
25+
V3, F3 = box.to_vertices_and_faces(triangulated=True)
26+
27+
# ==============================================================================
28+
# Compute
29+
# ==============================================================================
30+
31+
V4, F4 = mesh_subdivide_catmull_clark((V1, F1), 3)
32+
V5, F5 = mesh_subdivide_loop((V2, F2), 3)
33+
V6, F6 = mesh_subdivide_sqrt3((V3, F3), 3)
34+
35+
S2 = Polyhedron(V0, F0)
36+
S4 = Polyhedron(V4.tolist(), F4.tolist())
37+
S6 = Polyhedron(V5.tolist(), F5.tolist())
38+
S8 = Polyhedron(V6.tolist(), F6.tolist())
39+
40+
S2.transform(Translation.from_vector([1, 0, 0]))
41+
S4.transform(Translation.from_vector([2, 0, 0]))
42+
S6.transform(Translation.from_vector([3, 0, 0]))
43+
S8.transform(Translation.from_vector([4, 0, 0]))
44+
45+
# ==============================================================================
46+
# Visualize
47+
# ==============================================================================
48+
49+
return S2, S4, S6, S8
50+
51+
52+
S2, S4, S6, S8 = main()
53+
54+
55+
# ==============================================================================
56+
# Visualize
57+
# ==============================================================================
58+
59+
viewer = Viewer()
60+
61+
viewer.renderer.camera.target = [3, 1, 0.5]
62+
viewer.renderer.camera.position = [5, -2, 0.5]
63+
64+
viewer.scene.add(S2.to_mesh(), show_points=False)
65+
viewer.scene.add(S4.to_mesh(), show_points=False)
66+
viewer.scene.add(S6.to_mesh(), show_points=False)
67+
viewer.scene.add(S8.to_mesh(), show_points=False)
68+
69+
viewer.show()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Mesh Subdivision
2+
================
3+
4+
This example demonstrates different mesh subdivision schemes available in COMPAS CGAL.
5+
6+
Key Features:
7+
8+
* Catmull-Clark subdivision for quad meshes
9+
* Loop subdivision for triangle meshes
10+
* √3 (sqrt3) subdivision for triangle meshes
11+
* Side-by-side comparison of different subdivision methods
12+
13+
.. figure:: /_images/example_subdivision.png
14+
:figclass: figure
15+
:class: figure-img img-fluid
16+
17+
.. literalinclude:: example_subdivision.py
18+
:language: python
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from compas.datastructures import Mesh
2+
from compas.geometry import Polygon
3+
from compas.geometry import Translation
4+
from compas_viewer import Viewer
5+
from line_profiler import profile
6+
7+
from compas_cgal.triangulation import conforming_delaunay_triangulation
8+
from compas_cgal.triangulation import refined_delaunay_mesh
9+
10+
11+
@profile
12+
def main():
13+
"""Triangulate a mesh with holes."""
14+
15+
boundary = Polygon.from_sides_and_radius_xy(64, 4)
16+
17+
hole = Polygon.from_sides_and_radius_xy(128, 1)
18+
19+
hole1 = hole.transformed(Translation.from_vector([2, 0, 0]))
20+
hole2 = hole.transformed(Translation.from_vector([-2, 0, 0]))
21+
hole3 = hole.transformed(Translation.from_vector([0, 2, 0]))
22+
hole4 = hole.transformed(Translation.from_vector([0, -2, 0]))
23+
24+
holes = [hole1, hole2, hole3, hole4]
25+
26+
V, F = conforming_delaunay_triangulation(
27+
boundary,
28+
holes=holes,
29+
)
30+
31+
cdt = Mesh.from_vertices_and_faces(V, F)
32+
33+
V, F = refined_delaunay_mesh(
34+
boundary,
35+
holes=holes,
36+
maxlength=0.5,
37+
is_optimized=True,
38+
)
39+
40+
rdm = Mesh.from_vertices_and_faces(V, F)
41+
42+
return cdt, rdm
43+
44+
45+
cdt, rdm = main()
46+
47+
# ==============================================================================
48+
# Visualize
49+
# ==============================================================================
50+
51+
viewer = Viewer()
52+
53+
viewer.renderer.camera.target = [0, 0, 0]
54+
viewer.renderer.camera.position = [0, -1, 13]
55+
56+
viewer.scene.add(cdt.transformed(Translation.from_vector([-5, 0, 0])))
57+
viewer.scene.add(rdm.transformed(Translation.from_vector([+5, 0, 0])))
58+
59+
viewer.show()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Mesh Triangulation
2+
==================
3+
4+
This example demonstrates how to perform constrained and refined Delaunay triangulation using COMPAS CGAL.
5+
6+
Key Features:
7+
8+
* Creating polygonal boundary and holes
9+
* Conforming Delaunay triangulation
10+
* Refined Delaunay meshing with size constraints
11+
* Side-by-side visualization of different triangulation methods
12+
13+
.. figure:: /_images/example_triangulation.png
14+
:figclass: figure
15+
:class: figure-img img-fluid
16+
17+
.. literalinclude:: example_triangulation.py
18+
:language: python

src/compas_cgal/intersections.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from compas.plugins import plugin
33

44
from compas_cgal import intersections_ext
5+
from compas_cgal import types_std
56

67
from .types import PolylinesNumpy
78
from .types import VerticesFaces
@@ -48,6 +49,6 @@ def intersection_mesh_mesh(
4849
VB = np.asarray(VB, dtype=np.float64, order="C")
4950
FB = np.asarray(FB, dtype=np.int32, order="C")
5051

51-
pointsets: intersections_ext.VectorRowMatrixXd = intersections_ext.intersection_mesh_mesh(VA, FA, VB, FB)
52+
pointsets: types_std.VectorRowMatrixXd = intersections_ext.intersection_mesh_mesh(VA, FA, VB, FB)
5253

5354
return pointsets

src/compas_cgal/measure.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from compas.plugins import plugin
44

55
from compas_cgal import measure_ext
6+
from compas_cgal import types_std
67

78
from .types import VerticesFaces
89

@@ -76,6 +77,6 @@ def mesh_centroid(mesh: VerticesFaces) -> list[float]:
7677
V, F = mesh
7778
V = np.asarray(V, dtype=np.float64, order="C")
7879
F = np.asarray(F, dtype=np.int32, order="C")
79-
vector_of_double: measure_ext.VectorDouble = measure_ext.centroid(V, F)
80+
vector_of_double: types_std.VectorDouble = measure_ext.centroid(V, F)
8081
point = Point(*vector_of_double)
8182
return point

src/compas_cgal/skeletonization.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from compas.plugins import plugin
33

44
from compas_cgal import skeletonization_ext
5+
from compas_cgal import types_std # noqa: F401
56

67
from .types import PolylinesNumpySkeleton
78
from .types import VerticesFaces

0 commit comments

Comments
 (0)