Skip to content

Commit

Permalink
volmesh fixes plu tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tomvanmele committed Nov 8, 2024
1 parent ff02bd2 commit 25fa515
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 49 deletions.
101 changes: 52 additions & 49 deletions src/compas/datastructures/volmesh/volmesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def from_obj(cls, filepath, precision=None):

@classmethod
def from_vertices_and_cells(cls, vertices, cells):
# type: (list[list[float]], list[list[list[int]]]) -> VolMesh
# type: (list[list[float]] | dict[int, list[float]], list[list[list[int]]]) -> VolMesh
"""Construct a volmesh object from vertices and cells.
Parameters
Expand All @@ -407,11 +407,11 @@ def from_vertices_and_cells(cls, vertices, cells):
volmesh = cls()

if isinstance(vertices, Mapping):
for key, xyz in vertices.items():
for key, xyz in vertices.items(): # type: ignore
volmesh.add_vertex(key=key, attr_dict=dict(zip(("x", "y", "z"), xyz)))
else:
for x, y, z in iter(vertices):
volmesh.add_vertex(x=x, y=y, z=z)
for x, y, z in iter(vertices): # type: ignore
volmesh.add_vertex(x=x, y=y, z=z) # type: ignore

for cell in cells:
volmesh.add_cell(cell)
Expand Down Expand Up @@ -531,9 +531,9 @@ def to_obj(self, filepath, precision=None, **kwargs):
the faces to the file.
"""
meshes = [self.cell_to_mesh(cell) for cell in self.cells()]
meshes = [self.cell_to_mesh(cell) for cell in self.cells()] # type: ignore
obj = OBJ(filepath, precision=precision)
obj.write(meshes, **kwargs)
obj.write(meshes, **kwargs) # type: ignore

def to_vertices_and_cells(self):
# type: () -> tuple[list[list[float]], list[list[list[int]]]]
Expand Down Expand Up @@ -659,7 +659,7 @@ def vertex_sample(self, size=1):
:meth:`edge_sample`, :meth:`face_sample`, :meth:`cell_sample`
"""
return sample(list(self.vertices()), size)
return sample(list(self.vertices()), size) # type: ignore

def edge_sample(self, size=1):
# type: (int) -> list[tuple[int, int]]
Expand All @@ -680,7 +680,7 @@ def edge_sample(self, size=1):
:meth:`vertex_sample`, :meth:`face_sample`, :meth:`cell_sample`
"""
return sample(list(self.edges()), size)
return sample(list(self.edges()), size) # type: ignore

def face_sample(self, size=1):
# type: (int) -> list[int]
Expand All @@ -701,7 +701,7 @@ def face_sample(self, size=1):
:meth:`vertex_sample`, :meth:`edge_sample`, :meth:`cell_sample`
"""
return sample(list(self.faces()), size)
return sample(list(self.faces()), size) # type: ignore

def cell_sample(self, size=1):
# type: (int) -> list[int]
Expand All @@ -722,7 +722,7 @@ def cell_sample(self, size=1):
:meth:`vertex_sample`, :meth:`edge_sample`, :meth:`face_sample`
"""
return sample(list(self.cells()), size)
return sample(list(self.cells()), size) # type: ignore

def vertex_index(self):
# type: () -> dict[int, int]
Expand All @@ -739,7 +739,7 @@ def vertex_index(self):
:meth:`index_vertex`
"""
return {key: index for index, key in enumerate(self.vertices())}
return {key: index for index, key in enumerate(self.vertices())} # type: ignore

def index_vertex(self):
# type: () -> dict[int, int]
Expand All @@ -756,7 +756,7 @@ def index_vertex(self):
:meth:`vertex_index`
"""
return dict(enumerate(self.vertices()))
return dict(enumerate(self.vertices())) # type: ignore

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

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

# --------------------------------------------------------------------------
# Builders & Modifiers
Expand Down Expand Up @@ -1760,8 +1760,10 @@ def vertex_halffaces(self, vertex):
u = vertex
faces = []
for v in self._plane[u]:
for face in self._plane[u][v]:
if face is not None:
for w in self._plane[u][v]:
cell = self._plane[u][v][w]
if cell is not None:
face = self.cell_halfedge_face(cell, (u, v))
faces.append(face)
return faces

Expand Down Expand Up @@ -1789,7 +1791,8 @@ def vertex_cells(self, vertex):
for w in self._plane[u][v]:
cell = self._plane[u][v][w]
if cell is not None:
cells.append(cell)
if cell not in cells:
cells.append(cell)
return cells

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

def halfface_adjacent_halfface(self, halfface, halfedge):
"""Return the halfface adjacent to the halfface across the halfedge.
Parameters
----------
halfface : int
The identifier of the halfface.
halfedge : tuple[int, int]
The identifier of the halfedge.
Returns
-------
int | None
The identifier of the adjacent half-face, or None if `halfedge` is on the boundary.
See Also
--------
:meth:`halfface_opposite_halfface`
Notes
-----
The adjacent face belongs a to one of the cell neighbors over faces of the initial cell.
A face and its adjacent face share two common vertices.
"""
u, v = halfedge
cell = self.halfface_cell(halfface)
nbr_halfface = self._cell[cell][v][u]
nbr_cell = self._plane[u][v][nbr_halfface]
return None if nbr_cell is None else self._cell[nbr_cell][v][u]
# def halfface_adjacent_halfface(self, halfface, halfedge):
# """Return the halfface adjacent to the halfface across the halfedge.

# Parameters
# ----------
# halfface : int
# The identifier of the halfface.
# halfedge : tuple[int, int]
# The identifier of the halfedge.

# Returns
# -------
# int | None
# The identifier of the adjacent half-face, or None if `halfedge` is on the boundary.

# See Also
# --------
# :meth:`halfface_opposite_halfface`

# Notes
# -----
# The adjacent face belongs to one of the cell neighbors over faces of the initial cell.
# A face and its adjacent face share two common vertices.

# """
# u, v = halfedge
# cell = self.halfface_cell(halfface)
# nbr_halfface = self._cell[cell][v][u]
# nbr_cell = self._plane[u][v][nbr_halfface]
# return None if nbr_cell is None else self._cell[nbr_cell][v][u]

def halfface_vertex_ancestor(self, halfface, vertex):
"""Return the vertex before the specified vertex in a specific face.
Expand Down Expand Up @@ -3282,8 +3285,8 @@ def is_halfface_on_boundary(self, halfface):
:meth:`is_vertex_on_boundary`, :meth:`is_edge_on_boundary`, :meth:`is_cell_on_boundary`
"""
u, v = self._halfface[halfface][:2]
return self._plane[v][u][halfface] is None
u, v, w = self._halfface[halfface][:3]
return self._plane[w][v][u] is None

# --------------------------------------------------------------------------
# Face Geometry
Expand Down
105 changes: 105 additions & 0 deletions tests/compas/datastructures/test_volmesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,111 @@ def test_volmesh_data():
# Samples
# ==============================================================================

# ==============================================================================
# Topology
# ==============================================================================


@pytest.mark.parametrize(
"nx,ny,nz",
[
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
],
)
def test_vertex_neighbours(nx, ny, nz):
volmesh = VolMesh.from_meshgrid(1, 1, 1, nx, ny, nz)

for vertex in volmesh.vertices():
count = len(volmesh.vertex_neighbors(vertex))

if volmesh.is_vertex_on_boundary(vertex):
assert 2 < count < 6
else:
assert count == 6


@pytest.mark.parametrize(
"nx,ny,nz",
[
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
],
)
def test_vertex_cells(nx, ny, nz):
volmesh = VolMesh.from_meshgrid(1, 1, 1, nx, ny, nz)

for vertex in volmesh.vertices():
nbrs = len(volmesh.vertex_neighbors(vertex))
cells = len(volmesh.vertex_cells(vertex))

if nbrs == 6:
assert cells == 8
elif nbrs == 5:
assert cells == 4
elif nbrs == 4:
assert cells == 2
elif nbrs == 3:
assert cells == 1


@pytest.mark.parametrize(
"nx,ny,nz",
[
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
],
)
def test_edge_cells(nx, ny, nz):
volmesh = VolMesh.from_meshgrid(1, 1, 1, nx, ny, nz)

for edge in volmesh.edges():
cells = len(volmesh.edge_cells(edge))

if volmesh.is_edge_on_boundary(edge):
assert 0 < cells < 3
else:
assert cells == 4


@pytest.mark.parametrize(
"nx,ny,nz",
[
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
],
)
def test_edge_halffaces(nx, ny, nz):
volmesh = VolMesh.from_meshgrid(1, 1, 1, nx, ny, nz)

for edge in volmesh.edges():
faces = len(volmesh.edge_halffaces(edge))

if volmesh.is_edge_on_boundary(edge):
assert 0 < faces < 3
else:
assert faces == 4


@pytest.mark.parametrize(
"nx,ny,nz",
[
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
],
)
def test_halffaces_on_boundary(nx, ny, nz):
volmesh = VolMesh.from_meshgrid(1, 1, 1, nx, ny, nz)

count = sum(volmesh.is_halfface_on_boundary(face) for face in volmesh.halffaces())
assert count == 2 * nx * ny + 2 * ny * nz + 2 * nx * nz


# ==============================================================================
# Vertex Attributes
# ==============================================================================
Expand Down

0 comments on commit 25fa515

Please sign in to comment.