Skip to content

Commit

Permalink
Merge pull request #39 from cemsbv/36-add-method-to-filter-cut-volume…
Browse files Browse the repository at this point in the history
…s-below-polygons

Add method to filter cut volumes below polygons.
  • Loading branch information
PabloVasconez committed Nov 21, 2023
2 parents 884dccc + d40e241 commit 5fc3a75
Showing 1 changed file with 127 additions and 0 deletions.
127 changes: 127 additions & 0 deletions src/plxcontroller/plaxis_3d_input_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,133 @@ def filter_cut_volumes_above_polygons(

return filtered_cut_volumes

def filter_cut_volumes_below_polygons(
self,
polygons: List[Polygon3D],
cut_volumes: List[PlxProxyObject] | None = None,
tol: float | None = None,
) -> List[PlxProxyObject]:
"""Filters the given cut volumes if all its vertices are located below any polygon
in the given list of polygons.
Note that if any vertex of the cut volume falls outside the projection
of a polygon in the xy plane, then the cut volume is not considered to be below
the polygon.
A cut volume is defined as any Volume or SoilVolume in Mesh, FlowConditions
and StagedConstruction tabs of the plaxis model.
Parameters
----------
polygons : List[Polygon3D]
the list of polygons.
cut_volumes : List[PlxProxyObject] | None, optional
the list of plaxis volumes to filter from.
If None is given then all the cut volumes in the model are used.
Defaults to None.
tol: float | None, optional
the allowed tolerance to compared the coordinates of the cut_volumes
and the polygons.
If None given, then the globals.ABS_TOL will be used.
Defaults to None.
Returns
-------
List[PlxProxyObject]
the filtered cut volumes.
Raises
------
TypeError
if parameters are not of the expected type.
ValueError
- if this method is not called in modes Mesh, FlowConditions and StagedConstruction.
- if any item of cut_volumes is not present in the Volumes nor SoilVolumes of the plaxis model.
- if tol is not >= 0.
"""

# Method should be only called in Mesh, FlowConditions and StagedConstruction.
if not 2 <= self.g_i.Project.Mode.value <= 4:
raise ValueError(
"Method filter_cut_volumes_above_polygons can only be called in Mesh, "
+ "FlowConditions and StagedConstruction."
)

# Validate input
if not isinstance(polygons, list):
raise TypeError(
f"Unexpected type for polygons. Expected list, but got {type(polygons)}."
)
for i, polygon in enumerate(polygons):
if not isinstance(polygon, Polygon3D):
raise TypeError(
f"Unexpected type for item {i} of polygons. Expected Polygon3D, but got {type(polygon)}."
)

if cut_volumes is not None:
if not isinstance(cut_volumes, list):
raise TypeError(
f"Unexpected type for cut_volumes. Expected list, but got {type(cut_volumes)}."
)
for i, cut_volume in enumerate(cut_volumes):
if not isinstance(cut_volume, PlxProxyObject):
raise TypeError(
f"Unexpected type for item {i} of cut_volumes. Expected PlxProxyObject, but got {type(cut_volume)}."
)
if cut_volume not in list(
set(list(self.g_i.SoilVolumes) + list(self.g_i.Volumes))
):
raise ValueError(
f"Item {i} of cut_volumes is not present in the volumes of the plaxis model."
)

if tol is not None:
if not isinstance(tol, (float, int)):
raise TypeError(
f"Unexpected type for tol. Expected float, but got {type(tol)}."
)
if not tol >= 0:
raise ValueError(f"tol must be >= 0, but got {tol}.")

# Initialize plaxis_volume list as all the volumes in the Plaxis model.
if cut_volumes is None:
cut_volumes = list(set(list(self.g_i.SoilVolumes) + list(self.g_i.Volumes)))

# Initialize tol
if tol is None:
tol = ABS_TOL

# Map convex hulls per cut volume (if any cut volume is not present in self.convex_hull_per_cut_volume)
if any(a not in self.convex_hull_per_cut_volume for a in cut_volumes):
self.map_convex_hull_per_cut_volume()

# Filter the volumes if it is above any of the polygons
filtered_cut_volumes = []
for cut_volume in cut_volumes:
# Get the convex hull corresponding to the cut volume
convex_hull = self.convex_hull_per_cut_volume[cut_volume]

# Check that all vertices of the convex hull are below
# any of the polygon. If this is the case add it to the
# filtered_cut_volumes list.
for polygon in polygons:
checks = []
for vertex in convex_hull.vertices:
projected_point = project_vertically_point_onto_polygon_3d(
point=vertex, polygon=polygon, tol=tol
)
checks.append(
isinstance(projected_point, Point3D)
and vertex.z - tol <= projected_point.z
)
if checks[-1] is False:
break
if all(checks):
filtered_cut_volumes.append(cut_volume)
break

return filtered_cut_volumes

def map_convex_hull_per_cut_volume(self) -> None:
"""Maps the convex hull for each cut volume of the Plaxis model
and stores it in the dictionary `self.convex_hull_per_cut_volume`.
Expand Down

0 comments on commit 5fc3a75

Please sign in to comment.