Skip to content

Commit b43d06f

Browse files
author
pv
committed
ADD remesh_dual
1 parent 48e1347 commit b43d06f

File tree

5 files changed

+531
-9
lines changed

5 files changed

+531
-9
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818

1919
### Added
2020

21+
* Added `compas_cgal.meshing.mesh_remesh_dual`.
22+
2123
### Changed
2224

2325
### Removed

docs/examples/example_meshing.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@
1010
from compas.geometry import transform_points_numpy
1111
from compas_viewer import Viewer
1212

13-
from compas_cgal.meshing import mesh_remesh
14-
13+
from compas_cgal.meshing import mesh_remesh, mesh_remesh_dual
14+
from compas_cgal import _types_std # noqa: F401
1515

1616
def main():
1717
"""Remesh a bunny mesh that is loaded from .ply file."""
1818

1919
FILE = Path(__file__).parent.parent.parent / "data" / "Bunny.ply"
20+
2021
bunny = Mesh.from_ply(FILE)
22+
#bunny = Mesh.from_meshgrid(1,10,1,10)
23+
bunny.quads_to_triangles()
2124
bunny.remove_unused_vertices()
2225

2326
centroid = bunny.vertex_point(0)
@@ -32,14 +35,22 @@ def main():
3235
V0, F0 = bunny.to_vertices_and_faces()
3336
V1 = transform_points_numpy(V0, R * S * T)
3437

35-
V1, F1 = mesh_remesh((V0, F0), 0.3, 10)
36-
V1 = transform_points_numpy(V1, Translation.from_vector([20, 0, 0]))
38+
39+
edge_length = 0.005
40+
iterations = 10
41+
V1, F1 = mesh_remesh((V0, F0), edge_length, iterations)
42+
V1 = transform_points_numpy(V1, Translation.from_vector([0.15, 0, 0]))
3743
mesh = Mesh.from_vertices_and_faces(V1, F1)
44+
45+
46+
V1, F1 = mesh_remesh_dual((V0, F0), edge_length, iterations, 3.14, True)
47+
V1 = transform_points_numpy(V1, Translation.from_vector([0.3, 0, 0]))
48+
dual = Mesh.from_vertices_and_faces(V1, F1)
3849

39-
return bunny, mesh
50+
return bunny, mesh, dual
4051

4152

42-
bunny, mesh = main()
53+
bunny, mesh, dual = main()
4354

4455

4556
# ==============================================================================
@@ -49,9 +60,10 @@ def main():
4960
viewer = Viewer(width=1600, height=900)
5061

5162
viewer.renderer.camera.target = [0, 0, 0]
52-
viewer.renderer.camera.position = [0, -25, 10]
63+
viewer.renderer.camera.position = [0, -0.25, 0.10]
5364

5465
viewer.scene.add(bunny, show_points=False)
5566
viewer.scene.add(mesh, show_points=False)
67+
viewer.scene.add(dual, show_points=True)
5668

5769
viewer.show()

src/compas_cgal/meshing.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,63 @@ def mesh_remesh(
5252
V = np.asarray(V, dtype=np.float64, order="C")
5353
F = np.asarray(F, dtype=np.int32, order="C")
5454
return _meshing.remesh(V, F, target_edge_length, number_of_iterations)
55+
56+
57+
def mesh_remesh_dual(
58+
mesh: VerticesFaces,
59+
target_edge_length: float,
60+
number_of_iterations: int = 10,
61+
angle_radians: float = 0.0,
62+
circumcenter: bool = True,
63+
) -> tuple[np.ndarray, list[list[int]]]:
64+
"""Create a dual mesh from a triangular mesh with variable-length faces.
65+
66+
Parameters
67+
----------
68+
mesh : :attr:`compas_cgal.types.VerticesFaces`
69+
The mesh to create a dual from.
70+
target_edge_length : float
71+
The target edge length for primal mesh remeshing before dual creation.
72+
number_of_iterations : int, optional
73+
Number of remeshing iterations for the primal mesh.
74+
angle_radians : double, optional
75+
Angle limit in radians for boundary vertices to remove.
76+
circumcenter : bool, optional
77+
Whether to use the circumcenter of the triangle instead of the centroid.
78+
79+
Returns
80+
-------
81+
tuple
82+
A tuple containing:
83+
- Dual mesh vertices as an Nx3 numpy array.
84+
- Variable-length faces as a list of lists of vertex indices.
85+
86+
Notes
87+
-----
88+
This dual mesh implementation includes proper boundary handling by:
89+
1. Creating vertices at face centroids of the primal mesh
90+
2. Creating additional vertices at boundary edge midpoints
91+
3. Creating proper connections for boundary edges
92+
93+
Examples
94+
--------
95+
>>> from compas.datastructures import Mesh
96+
>>> from compas_cgal.meshing import mesh_remesh_dual
97+
98+
>>> # Create a simple quad mesh
99+
>>> mesh = Mesh.from_vertices_and_faces([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]], [[0, 1, 2, 3]])
100+
>>> vertices, faces = mesh.to_vertices_and_faces()
101+
102+
>>> # Create its dual mesh with variable-length faces
103+
>>> V, F = mesh_remesh_dual((vertices, faces), 0.1)
104+
>>> dual_mesh = Mesh.from_vertices_and_faces(V, [])
105+
>>> # Add the variable-length faces to the mesh
106+
>>> for face in F:
107+
... dual_mesh.add_face(face)
108+
109+
"""
110+
V, F = mesh
111+
V = np.asarray(V, dtype=np.float64, order="C")
112+
F = np.asarray(F, dtype=np.int32, order="C")
113+
vertices, var_faces = _meshing.remesh_dual(V, F, target_edge_length, number_of_iterations, angle_radians, circumcenter)
114+
return vertices, var_faces

0 commit comments

Comments
 (0)