Skip to content

Commit

Permalink
Merge pull request #1326 from compas-dev/fix-unify-cycles
Browse files Browse the repository at this point in the history
Fix unify cycles
  • Loading branch information
tomvanmele committed Apr 22, 2024
2 parents 2d5514f + 056a048 commit a584b06
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 38 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Changed `compas.scene.Scene` to inherent from `compas.datastructrues.Tree`.
* Changed `compas.scene.SceneObject` to inherent from `compas.datastructrues.TreeNode`.
* Changed `compas.geoemetry._core.predicates_3` bug fix in `is_coplanar` while loop when there are 4 points.
* Changed to implementation of `Mesh.unify_cycles` to use the corresponding function of `compas.topology.orientation`.
* Fixed bug in `compas.topology.orientation.unify_cycles`.
* Fixed bug in `Mesh.thickened`.

### Removed

Expand Down
65 changes: 30 additions & 35 deletions src/compas/datastructures/mesh/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@
from compas.utilities import window

from compas.topology import breadth_first_traverse
from compas.topology import face_adjacency
from compas.topology import connected_components
from compas.topology import unify_cycles

from compas.datastructures.datastructure import Datastructure
from compas.datastructures.attributes import VertexAttributeView
Expand Down Expand Up @@ -2953,42 +2953,25 @@ def unify_cycles(self, root=None):
The mesh is modified in place.
"""

def unify(node, nbr):
# find the common edge
for u, v in self.face_halfedges(nbr):
if u in self.face[node] and v in self.face[node]:
# node and nbr have edge u-v in common
i = self.face[node].index(u)
j = self.face[node].index(v)
if i == j - 1 or (j == 0 and u == self.face[node][-1]):
# if the traversal of a neighboring halfedge
# is in the same direction
# flip the neighbor
self.face[nbr][:] = self.face[nbr][::-1]
return

if root is None:
root = self.face_sample(size=1)[0]

vertex_index = {}
index_vertex = {}
for index, vertex in enumerate(self.vertices()):
vertex_index[vertex] = index
index_vertex[index] = vertex
index_face = {index: face for index, face in enumerate(self.faces())}
points = self.vertices_attributes("xyz")
faces = [self.face_vertices(face) for face in self.faces()]

adj = face_adjacency(points, faces)
adjacency = {}
for face in adj:
adjacency[index_face[face]] = [index_face[nbr] for nbr in adj[face]]

visited = breadth_first_traverse(adjacency, root, unify)
vertices = self.vertices_attributes("xyz")
faces = [[vertex_index[vertex] for vertex in self.face_vertices(face)] for face in self.faces()]

if len(list(visited)) != self.number_of_faces():
raise Exception("Not all faces were visited.")
unify_cycles(vertices, faces)

self.halfedge = {key: {} for key in self.vertices()}
for fkey in self.faces():
for u, v in self.face_halfedges(fkey):
self.halfedge[u][v] = fkey
for index, vertices in enumerate(faces):
face = index_face[index]
vertices = [index_vertex[vertex] for vertex in vertices]
self.face[face] = vertices
for u, v in pairwise(vertices + vertices[:1]):
self.halfedge[u][v] = face
if u not in self.halfedge[v]:
self.halfedge[v][u] = None

Expand Down Expand Up @@ -4413,6 +4396,11 @@ def face_flatness(self, fkey, maxdev=0.02):
float
The flatness.
Raises
------
Exception
If the face has more than 4 vertices.
Notes
-----
Flatness is computed as the ratio of the distance between the diagonals
Expand All @@ -4426,6 +4414,12 @@ def face_flatness(self, fkey, maxdev=0.02):
"""
vertices = self.face_vertices(fkey)
f = len(vertices)

if f == 3:
return 0.0
if f > 4:
raise Exception("Computing face flatness for faces with more than 4 vertices is not supported.")

points = self.vertices_attributes("xyz", keys=vertices) or []
lengths = [distance_point_point(a, b) for a, b in pairwise(points + points[:1])]
length = sum(lengths) / f
Expand Down Expand Up @@ -5075,8 +5069,8 @@ def thickened(self, thickness=1.0, both=True):
raise ValueError("Thickness should be a positive number.")

if both:
mesh_top = self.offset(+0.5 * thickness)
mesh_bottom = self.offset(-0.5 * thickness)
mesh_top = self.offset(+0.5 * thickness) # type: Mesh
mesh_bottom = self.offset(-0.5 * thickness) # type: Mesh
else:
mesh_top = self.offset(thickness)
mesh_bottom = self.copy()
Expand All @@ -5085,7 +5079,8 @@ def thickened(self, thickness=1.0, both=True):
mesh_bottom.flip_cycles()

# join parts
thickened_mesh = mesh_top.join(mesh_bottom)
thickened_mesh = mesh_top.copy() # type: Mesh
thickened_mesh.join(mesh_bottom)

# close boundaries
n = thickened_mesh.number_of_vertices() / 2
Expand Down
8 changes: 5 additions & 3 deletions src/compas/topology/orientation.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def _face_adjacency(vertices, faces, nmax=10, radius=10.0):
found.add(nbr)
break

adjacency[face] = nbrs
adjacency[index] = nbrs

return adjacency

Expand All @@ -98,8 +98,10 @@ def face_adjacency(points, faces):
Parameters
----------
mesh : :class:`compas.datastructures.Mesh`
A mesh object.
points : list[point]
The vertex locations of the faces.
faces : list[list[int]]
The faces defined as list of indices in the points list.
Returns
-------
Expand Down

0 comments on commit a584b06

Please sign in to comment.