Skip to content

Commit a084f03

Browse files
authored
Merge pull request #1038 from GeneKao/feature/dualmesh_boundary
add boundary faces option to mesh_dual
2 parents 071acf1 + 31b0c40 commit a084f03

File tree

3 files changed

+56
-3
lines changed

3 files changed

+56
-3
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
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2626
* Fixed bug in `compas.robots.Configuration`.
2727
* Rebuild part index after deserialization in `Assembly`.
2828
* Fixed bug in `compas.artists.colordict.ColorDict`.
29+
* Change `Mesh.mesh_dual` with option of including the boundary.
2930

3031
### Removed
3132

src/compas/datastructures/mesh/duality.py

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

55
from math import pi
6-
6+
from compas.utilities import flatten
77

88
__all__ = ['mesh_dual']
99

1010

1111
PI2 = 2.0 * pi
1212

1313

14-
def mesh_dual(mesh, cls=None):
14+
def mesh_dual(mesh, cls=None, include_boundary=False):
1515
"""Construct the dual of a mesh.
1616
1717
Parameters
@@ -21,20 +21,36 @@ def mesh_dual(mesh, cls=None):
2121
cls : Type[:class:`~compas.datastructures.Mesh`], optional
2222
The type of the dual mesh.
2323
Defaults to the type of the provided mesh object.
24+
include_boundary: bool, optional
25+
Whether to include boundary faces for the dual mesh
26+
If True, create faces on boundaries including all original mesh boundary vertices.
2427
2528
Returns
2629
-------
2730
:class:`~compas.datastructures.Mesh`
2831
The dual mesh object.
2932
33+
Examples
34+
--------
35+
>>> import compas
36+
>>> from compas.datastructures import Mesh
37+
>>> mesh = Mesh.from_obj(compas.get('faces.obj'))
38+
>>> mesh.delete_face(11)
39+
>>> mesh.delete_face(6)
40+
>>> mesh.delete_face(7)
41+
>>> mesh.quads_to_triangles()
42+
>>> mesh = mesh.subdivide('corner')
43+
>>> dual = mesh.dual(include_boundary=True)
44+
3045
"""
3146
if not cls:
3247
cls = type(mesh)
3348

3449
dual = cls()
3550

3651
face_centroid = {face: mesh.face_centroid(face) for face in mesh.faces()}
37-
inner = list(set(mesh.vertices()) - set(mesh.vertices_on_boundary()))
52+
outer = set(flatten(mesh.vertices_on_boundaries()))
53+
inner = list(set(mesh.vertices()) - outer)
3854
vertex_xyz = {}
3955
face_vertices = {}
4056

@@ -52,4 +68,39 @@ def mesh_dual(mesh, cls=None):
5268
for face in face_vertices:
5369
dual.add_face(face_vertices[face], fkey=face)
5470

71+
if not include_boundary:
72+
return dual
73+
74+
for boundary in mesh.faces_on_boundaries():
75+
for face in boundary:
76+
if not dual.has_vertex(face):
77+
x, y, z = face_centroid[face]
78+
dual.add_vertex(key=face, x=x, y=y, z=z)
79+
80+
edge_vertex = {}
81+
for boundary in mesh.edges_on_boundaries():
82+
for u, v in boundary:
83+
x, y, z = mesh.edge_midpoint(u, v)
84+
edge_vertex[u, v] = edge_vertex[v, u] = dual.add_vertex(x=x, y=y, z=z)
85+
86+
vertex_vertex = {}
87+
for boundary in mesh.vertices_on_boundaries():
88+
if boundary[0] == boundary[-1]:
89+
boundary = boundary[:-1]
90+
for vertex in boundary:
91+
x, y, z = mesh.vertex_coordinates(vertex)
92+
vertex_vertex[vertex] = dual.add_vertex(x=x, y=y, z=z)
93+
94+
for boundary in mesh.vertices_on_boundaries():
95+
if boundary[0] == boundary[-1]:
96+
boundary = boundary[:-1]
97+
for vertex in boundary:
98+
vertices = [vertex_vertex[vertex]]
99+
nbrs = mesh.vertex_neighbors(vertex, ordered=True)[::-1]
100+
vertices.append(edge_vertex[vertex, nbrs[0]])
101+
for nbr in nbrs[:-1]:
102+
vertices.append(mesh.halfedge_face(vertex, nbr))
103+
vertices.append(edge_vertex[vertex, nbrs[-1]])
104+
dual.add_face(vertices[::-1])
105+
55106
return dual

0 commit comments

Comments
 (0)