Skip to content

Commit 25fa515

Browse files
committed
volmesh fixes plu tests
1 parent ff02bd2 commit 25fa515

File tree

2 files changed

+157
-49
lines changed

2 files changed

+157
-49
lines changed

src/compas/datastructures/volmesh/volmesh.py

Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ def from_obj(cls, filepath, precision=None):
383383

384384
@classmethod
385385
def from_vertices_and_cells(cls, vertices, cells):
386-
# type: (list[list[float]], list[list[list[int]]]) -> VolMesh
386+
# type: (list[list[float]] | dict[int, list[float]], list[list[list[int]]]) -> VolMesh
387387
"""Construct a volmesh object from vertices and cells.
388388
389389
Parameters
@@ -407,11 +407,11 @@ def from_vertices_and_cells(cls, vertices, cells):
407407
volmesh = cls()
408408

409409
if isinstance(vertices, Mapping):
410-
for key, xyz in vertices.items():
410+
for key, xyz in vertices.items(): # type: ignore
411411
volmesh.add_vertex(key=key, attr_dict=dict(zip(("x", "y", "z"), xyz)))
412412
else:
413-
for x, y, z in iter(vertices):
414-
volmesh.add_vertex(x=x, y=y, z=z)
413+
for x, y, z in iter(vertices): # type: ignore
414+
volmesh.add_vertex(x=x, y=y, z=z) # type: ignore
415415

416416
for cell in cells:
417417
volmesh.add_cell(cell)
@@ -531,9 +531,9 @@ def to_obj(self, filepath, precision=None, **kwargs):
531531
the faces to the file.
532532
533533
"""
534-
meshes = [self.cell_to_mesh(cell) for cell in self.cells()]
534+
meshes = [self.cell_to_mesh(cell) for cell in self.cells()] # type: ignore
535535
obj = OBJ(filepath, precision=precision)
536-
obj.write(meshes, **kwargs)
536+
obj.write(meshes, **kwargs) # type: ignore
537537

538538
def to_vertices_and_cells(self):
539539
# type: () -> tuple[list[list[float]], list[list[list[int]]]]
@@ -659,7 +659,7 @@ def vertex_sample(self, size=1):
659659
:meth:`edge_sample`, :meth:`face_sample`, :meth:`cell_sample`
660660
661661
"""
662-
return sample(list(self.vertices()), size)
662+
return sample(list(self.vertices()), size) # type: ignore
663663

664664
def edge_sample(self, size=1):
665665
# type: (int) -> list[tuple[int, int]]
@@ -680,7 +680,7 @@ def edge_sample(self, size=1):
680680
:meth:`vertex_sample`, :meth:`face_sample`, :meth:`cell_sample`
681681
682682
"""
683-
return sample(list(self.edges()), size)
683+
return sample(list(self.edges()), size) # type: ignore
684684

685685
def face_sample(self, size=1):
686686
# type: (int) -> list[int]
@@ -701,7 +701,7 @@ def face_sample(self, size=1):
701701
:meth:`vertex_sample`, :meth:`edge_sample`, :meth:`cell_sample`
702702
703703
"""
704-
return sample(list(self.faces()), size)
704+
return sample(list(self.faces()), size) # type: ignore
705705

706706
def cell_sample(self, size=1):
707707
# type: (int) -> list[int]
@@ -722,7 +722,7 @@ def cell_sample(self, size=1):
722722
:meth:`vertex_sample`, :meth:`edge_sample`, :meth:`face_sample`
723723
724724
"""
725-
return sample(list(self.cells()), size)
725+
return sample(list(self.cells()), size) # type: ignore
726726

727727
def vertex_index(self):
728728
# type: () -> dict[int, int]
@@ -739,7 +739,7 @@ def vertex_index(self):
739739
:meth:`index_vertex`
740740
741741
"""
742-
return {key: index for index, key in enumerate(self.vertices())}
742+
return {key: index for index, key in enumerate(self.vertices())} # type: ignore
743743

744744
def index_vertex(self):
745745
# type: () -> dict[int, int]
@@ -756,7 +756,7 @@ def index_vertex(self):
756756
:meth:`vertex_index`
757757
758758
"""
759-
return dict(enumerate(self.vertices()))
759+
return dict(enumerate(self.vertices())) # type: ignore
760760

761761
def vertex_gkey(self, precision=None):
762762
# type: (int | None) -> dict[int, str]
@@ -781,7 +781,7 @@ def vertex_gkey(self, precision=None):
781781
"""
782782
gkey = TOL.geometric_key
783783
xyz = self.vertex_coordinates
784-
return {vertex: gkey(xyz(vertex), precision) for vertex in self.vertices()}
784+
return {vertex: gkey(xyz(vertex), precision) for vertex in self.vertices()} # type: ignore
785785

786786
def gkey_vertex(self, precision=None):
787787
# type: (int | None) -> dict[str, int]
@@ -806,7 +806,7 @@ def gkey_vertex(self, precision=None):
806806
"""
807807
gkey = TOL.geometric_key
808808
xyz = self.vertex_coordinates
809-
return {gkey(xyz(vertex), precision): vertex for vertex in self.vertices()}
809+
return {gkey(xyz(vertex), precision): vertex for vertex in self.vertices()} # type: ignore
810810

811811
# --------------------------------------------------------------------------
812812
# Builders & Modifiers
@@ -1760,8 +1760,10 @@ def vertex_halffaces(self, vertex):
17601760
u = vertex
17611761
faces = []
17621762
for v in self._plane[u]:
1763-
for face in self._plane[u][v]:
1764-
if face is not None:
1763+
for w in self._plane[u][v]:
1764+
cell = self._plane[u][v][w]
1765+
if cell is not None:
1766+
face = self.cell_halfedge_face(cell, (u, v))
17651767
faces.append(face)
17661768
return faces
17671769

@@ -1789,7 +1791,8 @@ def vertex_cells(self, vertex):
17891791
for w in self._plane[u][v]:
17901792
cell = self._plane[u][v][w]
17911793
if cell is not None:
1792-
cells.append(cell)
1794+
if cell not in cells:
1795+
cells.append(cell)
17931796
return cells
17941797

17951798
def is_vertex_on_boundary(self, vertex):
@@ -3108,36 +3111,36 @@ def halfface_opposite_halfface(self, halfface):
31083111
nbr = self._plane[w][v][u]
31093112
return None if nbr is None else self._cell[nbr][w][v]
31103113

3111-
def halfface_adjacent_halfface(self, halfface, halfedge):
3112-
"""Return the halfface adjacent to the halfface across the halfedge.
3113-
3114-
Parameters
3115-
----------
3116-
halfface : int
3117-
The identifier of the halfface.
3118-
halfedge : tuple[int, int]
3119-
The identifier of the halfedge.
3120-
3121-
Returns
3122-
-------
3123-
int | None
3124-
The identifier of the adjacent half-face, or None if `halfedge` is on the boundary.
3125-
3126-
See Also
3127-
--------
3128-
:meth:`halfface_opposite_halfface`
3129-
3130-
Notes
3131-
-----
3132-
The adjacent face belongs a to one of the cell neighbors over faces of the initial cell.
3133-
A face and its adjacent face share two common vertices.
3134-
3135-
"""
3136-
u, v = halfedge
3137-
cell = self.halfface_cell(halfface)
3138-
nbr_halfface = self._cell[cell][v][u]
3139-
nbr_cell = self._plane[u][v][nbr_halfface]
3140-
return None if nbr_cell is None else self._cell[nbr_cell][v][u]
3114+
# def halfface_adjacent_halfface(self, halfface, halfedge):
3115+
# """Return the halfface adjacent to the halfface across the halfedge.
3116+
3117+
# Parameters
3118+
# ----------
3119+
# halfface : int
3120+
# The identifier of the halfface.
3121+
# halfedge : tuple[int, int]
3122+
# The identifier of the halfedge.
3123+
3124+
# Returns
3125+
# -------
3126+
# int | None
3127+
# The identifier of the adjacent half-face, or None if `halfedge` is on the boundary.
3128+
3129+
# See Also
3130+
# --------
3131+
# :meth:`halfface_opposite_halfface`
3132+
3133+
# Notes
3134+
# -----
3135+
# The adjacent face belongs to one of the cell neighbors over faces of the initial cell.
3136+
# A face and its adjacent face share two common vertices.
3137+
3138+
# """
3139+
# u, v = halfedge
3140+
# cell = self.halfface_cell(halfface)
3141+
# nbr_halfface = self._cell[cell][v][u]
3142+
# nbr_cell = self._plane[u][v][nbr_halfface]
3143+
# return None if nbr_cell is None else self._cell[nbr_cell][v][u]
31413144

31423145
def halfface_vertex_ancestor(self, halfface, vertex):
31433146
"""Return the vertex before the specified vertex in a specific face.
@@ -3282,8 +3285,8 @@ def is_halfface_on_boundary(self, halfface):
32823285
:meth:`is_vertex_on_boundary`, :meth:`is_edge_on_boundary`, :meth:`is_cell_on_boundary`
32833286
32843287
"""
3285-
u, v = self._halfface[halfface][:2]
3286-
return self._plane[v][u][halfface] is None
3288+
u, v, w = self._halfface[halfface][:3]
3289+
return self._plane[w][v][u] is None
32873290

32883291
# --------------------------------------------------------------------------
32893292
# Face Geometry

tests/compas/datastructures/test_volmesh.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,111 @@ def test_volmesh_data():
7272
# Samples
7373
# ==============================================================================
7474

75+
# ==============================================================================
76+
# Topology
77+
# ==============================================================================
78+
79+
80+
@pytest.mark.parametrize(
81+
"nx,ny,nz",
82+
[
83+
[1, 1, 1],
84+
[2, 2, 2],
85+
[3, 3, 3],
86+
],
87+
)
88+
def test_vertex_neighbours(nx, ny, nz):
89+
volmesh = VolMesh.from_meshgrid(1, 1, 1, nx, ny, nz)
90+
91+
for vertex in volmesh.vertices():
92+
count = len(volmesh.vertex_neighbors(vertex))
93+
94+
if volmesh.is_vertex_on_boundary(vertex):
95+
assert 2 < count < 6
96+
else:
97+
assert count == 6
98+
99+
100+
@pytest.mark.parametrize(
101+
"nx,ny,nz",
102+
[
103+
[1, 1, 1],
104+
[2, 2, 2],
105+
[3, 3, 3],
106+
],
107+
)
108+
def test_vertex_cells(nx, ny, nz):
109+
volmesh = VolMesh.from_meshgrid(1, 1, 1, nx, ny, nz)
110+
111+
for vertex in volmesh.vertices():
112+
nbrs = len(volmesh.vertex_neighbors(vertex))
113+
cells = len(volmesh.vertex_cells(vertex))
114+
115+
if nbrs == 6:
116+
assert cells == 8
117+
elif nbrs == 5:
118+
assert cells == 4
119+
elif nbrs == 4:
120+
assert cells == 2
121+
elif nbrs == 3:
122+
assert cells == 1
123+
124+
125+
@pytest.mark.parametrize(
126+
"nx,ny,nz",
127+
[
128+
[1, 1, 1],
129+
[2, 2, 2],
130+
[3, 3, 3],
131+
],
132+
)
133+
def test_edge_cells(nx, ny, nz):
134+
volmesh = VolMesh.from_meshgrid(1, 1, 1, nx, ny, nz)
135+
136+
for edge in volmesh.edges():
137+
cells = len(volmesh.edge_cells(edge))
138+
139+
if volmesh.is_edge_on_boundary(edge):
140+
assert 0 < cells < 3
141+
else:
142+
assert cells == 4
143+
144+
145+
@pytest.mark.parametrize(
146+
"nx,ny,nz",
147+
[
148+
[1, 1, 1],
149+
[2, 2, 2],
150+
[3, 3, 3],
151+
],
152+
)
153+
def test_edge_halffaces(nx, ny, nz):
154+
volmesh = VolMesh.from_meshgrid(1, 1, 1, nx, ny, nz)
155+
156+
for edge in volmesh.edges():
157+
faces = len(volmesh.edge_halffaces(edge))
158+
159+
if volmesh.is_edge_on_boundary(edge):
160+
assert 0 < faces < 3
161+
else:
162+
assert faces == 4
163+
164+
165+
@pytest.mark.parametrize(
166+
"nx,ny,nz",
167+
[
168+
[1, 1, 1],
169+
[2, 2, 2],
170+
[3, 3, 3],
171+
],
172+
)
173+
def test_halffaces_on_boundary(nx, ny, nz):
174+
volmesh = VolMesh.from_meshgrid(1, 1, 1, nx, ny, nz)
175+
176+
count = sum(volmesh.is_halfface_on_boundary(face) for face in volmesh.halffaces())
177+
assert count == 2 * nx * ny + 2 * ny * nz + 2 * nx * nz
178+
179+
75180
# ==============================================================================
76181
# Vertex Attributes
77182
# ==============================================================================

0 commit comments

Comments
 (0)