Skip to content

Commit 5f9a19a

Browse files
committed
improve the code to deal with some corner cases
1 parent 3899e8f commit 5f9a19a

File tree

1 file changed

+59
-18
lines changed

1 file changed

+59
-18
lines changed

src/compas/datastructures/mesh/duality.py

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from math import pi
66
from compas.utilities import flatten
7-
from compas.utilities import geometric_key
87

98
__all__ = ['mesh_dual']
109

@@ -24,24 +23,41 @@ def mesh_dual(mesh, cls=None, boundary=0):
2423
Defaults to the type of the provided mesh object.
2524
boundary: float, optional
2625
boundary mode for the dual mesh
27-
Default mode is 0, not create faces on boundaries
26+
Default mode is 0, not create faces on boundaries.
27+
1, create faces on mesh edges, not include original mesh boundary vertices.
28+
2. create faces on mesh edges and include original mesh boundary vertices on the corner.
29+
3. create faces on mesh edges and include all original mesh boundary vertices.
2830
2931
Returns
3032
-------
3133
:class:`~compas.datastructures.Mesh`
3234
The dual mesh object.
3335
36+
Examples
37+
--------
38+
>>> from compas.datastructures import Mesh
39+
>>> mesh = Mesh.from_obj(compas.get('faces.obj'))
40+
>>> mesh.delete_face(11)
41+
>>> mesh.delete_face(6)
42+
>>> mesh.delete_face(7)
43+
>>> mesh.quads_to_triangles()
44+
>>> mesh = mesh.subdivide('corner')
45+
>>> dual = mesh.dual(boundary=3)
46+
3447
"""
3548
if not cls:
3649
cls = type(mesh)
3750

3851
dual = cls()
3952

53+
mesh.unify_cycles()
54+
mesh.flip_cycles()
55+
4056
face_centroid = {face: mesh.face_centroid(face) for face in mesh.faces()}
4157
outer = list(flatten(mesh.vertices_on_boundaries()))
4258
vertex_xyz = {}
4359
face_vertices = {}
44-
boundary_xyz = {}
60+
edge_vertex = {}
4561

4662
# safe guarded if face index is arbitrary, random, not starting from 0
4763
num_faces = max(max(list(mesh.faces())) + 1, mesh.number_of_faces())
@@ -54,28 +70,53 @@ def mesh_dual(mesh, cls=None, boundary=0):
5470

5571
if not boundary:
5672
continue
57-
if vertex not in outer or len(faces) <= 1:
73+
74+
if boundary > 3:
75+
raise ValueError("edge mode from 0 to 3!")
76+
77+
if vertex not in outer or len(faces) < 1:
5878
continue
5979

60-
nbr_vertices = reversed(mesh.vertex_neighbors(vertex, ordered=True))
61-
boundary_vertices = faces
80+
boundary_fids = faces[:]
81+
current_face = vertex
82+
corner_count = 0
83+
edge_count = 0
84+
85+
for nbr_vertex in reversed(mesh.vertex_neighbors(vertex, ordered=True)):
86+
87+
if not mesh.is_edge_on_boundary(vertex, nbr_vertex):
88+
continue
89+
pt = mesh.edge_midpoint(vertex, nbr_vertex)
90+
91+
if num_faces not in vertex_xyz and len(faces) == 1 and corner_count == 0 and (boundary == 2 or boundary == 3):
92+
vertex_xyz[num_faces] = mesh.vertex_coordinates(vertex)
93+
current_face = num_faces
94+
num_faces += 1
95+
corner_count += 1
96+
97+
if num_faces not in vertex_xyz and len(faces) != 1 and edge_count == 0 and boundary == 3:
98+
vertex_xyz[num_faces] = mesh.vertex_coordinates(vertex)
99+
current_face = num_faces
100+
num_faces += 1
101+
edge_count += 1
62102

63-
for nbr_vertex in nbr_vertices:
103+
if num_faces not in vertex_xyz and ((vertex, nbr_vertex) not in edge_vertex and
104+
(nbr_vertex, vertex) not in edge_vertex):
64105

65-
if mesh.is_edge_on_boundary(vertex, nbr_vertex):
66-
pt = mesh.edge_midpoint(vertex, nbr_vertex)
106+
vertex_xyz[num_faces] = pt
107+
edge_vertex[vertex, nbr_vertex] = edge_vertex[nbr_vertex, vertex] = num_faces
108+
boundary_fids.append(num_faces)
109+
num_faces += 1
110+
else:
111+
boundary_fids.append(edge_vertex[vertex, nbr_vertex])
67112

68-
if geometric_key(pt) not in boundary_xyz and num_faces not in vertex_xyz:
69-
vertex_xyz[num_faces] = pt
70-
boundary_xyz[geometric_key(pt)] = num_faces
71-
num_faces += 1
113+
if vertex in outer and len(faces) == 1 and (boundary == 2 or boundary == 3):
114+
boundary_fids.insert(len(faces) + 1, current_face)
72115

73-
if geometric_key(pt) in boundary_xyz:
74-
boundary_vertices.append(boundary_xyz[geometric_key(pt)])
75-
else:
76-
boundary_vertices.append(num_faces)
116+
if vertex in outer and len(faces) != 1 and boundary == 3:
117+
boundary_fids.insert(len(faces) + 1, current_face)
77118

78-
face_vertices[vertex] = boundary_vertices
119+
face_vertices[vertex] = boundary_fids
79120

80121
for vertex in vertex_xyz:
81122
x, y, z = vertex_xyz[vertex]

0 commit comments

Comments
 (0)