Skip to content

Commit 3899e8f

Browse files
committed
add boundary faces option to mesh_dual
add boundary faces option to mesh_dual remove problem import
1 parent 071acf1 commit 3899e8f

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

AUTHORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@
3232
- Mattis Koh <<[email protected]>> [@mattiskoh](https://github.com/mattiskoh)
3333
- Andrea Ghensi <<[email protected]>> [@sanzoghenzo](https://github.com/sanzoghenzo)
3434
- Nizar Taha <<[email protected]>> [@nizartaha](https://github.com/nizartaha)
35+
- Gene Ting-Chun Kao <<[email protected]>> [@GeneKao](https://github.com/GeneKao)

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
* Added `Data.guid` to JSON serialization.
1919
* Added `Data.guid` to pickle state.
2020
* Added `Assembly.find_by_key` to locate parts by key.
21+
* Added `Mesh.mesh_dual` with additional option to include boundary faces.
2122

2223
### Changed
2324

src/compas/datastructures/mesh/duality.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@
33
from __future__ import division
44

55
from math import pi
6-
6+
from compas.utilities import flatten
7+
from compas.utilities import geometric_key
78

89
__all__ = ['mesh_dual']
910

1011

1112
PI2 = 2.0 * pi
1213

1314

14-
def mesh_dual(mesh, cls=None):
15+
def mesh_dual(mesh, cls=None, boundary=0):
1516
"""Construct the dual of a mesh.
1617
1718
Parameters
@@ -21,6 +22,9 @@ def mesh_dual(mesh, cls=None):
2122
cls : Type[:class:`~compas.datastructures.Mesh`], optional
2223
The type of the dual mesh.
2324
Defaults to the type of the provided mesh object.
25+
boundary: float, optional
26+
boundary mode for the dual mesh
27+
Default mode is 0, not create faces on boundaries
2428
2529
Returns
2630
-------
@@ -34,17 +38,45 @@ def mesh_dual(mesh, cls=None):
3438
dual = cls()
3539

3640
face_centroid = {face: mesh.face_centroid(face) for face in mesh.faces()}
37-
inner = list(set(mesh.vertices()) - set(mesh.vertices_on_boundary()))
41+
outer = list(flatten(mesh.vertices_on_boundaries()))
3842
vertex_xyz = {}
3943
face_vertices = {}
44+
boundary_xyz = {}
4045

41-
for vertex in inner:
46+
# safe guarded if face index is arbitrary, random, not starting from 0
47+
num_faces = max(max(list(mesh.faces())) + 1, mesh.number_of_faces())
48+
for vertex in mesh.vertices():
4249
faces = mesh.vertex_faces(vertex, ordered=True)
4350
for face in faces:
4451
if face not in vertex_xyz:
4552
vertex_xyz[face] = face_centroid[face]
4653
face_vertices[vertex] = faces
4754

55+
if not boundary:
56+
continue
57+
if vertex not in outer or len(faces) <= 1:
58+
continue
59+
60+
nbr_vertices = reversed(mesh.vertex_neighbors(vertex, ordered=True))
61+
boundary_vertices = faces
62+
63+
for nbr_vertex in nbr_vertices:
64+
65+
if mesh.is_edge_on_boundary(vertex, nbr_vertex):
66+
pt = mesh.edge_midpoint(vertex, nbr_vertex)
67+
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
72+
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)
77+
78+
face_vertices[vertex] = boundary_vertices
79+
4880
for vertex in vertex_xyz:
4981
x, y, z = vertex_xyz[vertex]
5082
dual.add_vertex(vertex, x=x, y=y, z=z)

0 commit comments

Comments
 (0)