Skip to content

Commit

Permalink
Refactored shape extractors to avoid class references Issue #788
Browse files Browse the repository at this point in the history
  • Loading branch information
gumyr committed Nov 20, 2024
1 parent e82b20a commit 52e43d5
Showing 1 changed file with 57 additions and 99 deletions.
156 changes: 57 additions & 99 deletions src/build123d/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -2243,144 +2243,102 @@ def get_top_level_shapes(self) -> ShapeList[Shape]:

return ShapeList(first_level_shapes)

@staticmethod
def _get_shape_list(shape: Shape, entity_type: str) -> ShapeList:
"""Helper to extract entities of a specific type from a shape."""
if shape.wrapped is None:
return ShapeList()
shape_list = ShapeList([Shape.cast(i) for i in shape._entities(entity_type)])
for item in shape_list:
item.topo_parent = shape
return shape_list

@staticmethod
def _get_single_shape(shape: Shape, entity_type: str) -> Shape:
"""Helper to extract a single entity of a specific type from a shape,
with a warning if count != 1."""
shape_list = Shape._get_shape_list(shape, entity_type)
entity_count = len(shape_list)
if entity_count != 1:
warnings.warn(
f"Found {entity_count} {entity_type.lower()}s, returning first",
stacklevel=2,
)
return shape_list[0] if shape_list else None

def vertices(self) -> ShapeList[Vertex]:
"""vertices - all the vertices in this Shape"""
if self.wrapped is None:
return ShapeList()
vertex_list = ShapeList(
[Vertex(downcast(i)) for i in self._entities(Vertex.__name__)]
)
for vertex in vertex_list:
vertex.topo_parent = self
return vertex_list
return Shape._get_shape_list(self, "Vertex")

def vertex(self) -> Vertex:
"""Return the Vertex"""
vertices = self.vertices()
vertex_count = len(vertices)
if vertex_count != 1:
warnings.warn(
f"Found {vertex_count} vertices, returning first", stacklevel=2
)
return vertices[0]
return Shape._get_single_shape(self, "Vertex")

def edges(self) -> ShapeList[Edge]:
"""edges - all the edges in this Shape"""
if self.wrapped is None:
return ShapeList()
edge_list = ShapeList(
[
Edge(i)
for i in self._entities(Edge.__name__)
if not BRep_Tool.Degenerated_s(TopoDS.Edge_s(i))
]
edge_list = Shape._get_shape_list(self, "Edge")
return edge_list.filter_by(
lambda e: BRep_Tool.Degenerated_s(e.wrapped), reverse=True
)
for edge in edge_list:
edge.topo_parent = self
return edge_list

def edge(self) -> Edge:
"""Return the Edge"""
edges = self.edges()
edge_count = len(edges)
if edge_count != 1:
warnings.warn(
f"Found {edge_count} edges, returning first",
stacklevel=2,
)
return edges[0]

def compounds(self) -> ShapeList[Compound]:
"""compounds - all the compounds in this Shape"""
if self.wrapped is None:
return ShapeList()
if isinstance(self, Compound):
# pylint: disable=not-an-iterable
sub_compounds = [c for c in self if isinstance(c, Compound)]
sub_compounds.append(self)
else:
sub_compounds = []
return ShapeList(sub_compounds)

def compound(self) -> Compound:
"""Return the Compound"""
compounds = self.compounds()
compound_count = len(compounds)
if compound_count != 1:
warnings.warn(
f"Found {compound_count} compounds, returning first",
stacklevel=2,
)
return compounds[0]
return Shape._get_single_shape(self, "Edge")

def wires(self) -> ShapeList[Wire]:
"""wires - all the wires in this Shape"""
if self.wrapped is None:
return ShapeList()
return ShapeList([Wire(i) for i in self._entities(Wire.__name__)])
return Shape._get_shape_list(self, "Wire")

def wire(self) -> Wire:
"""Return the Wire"""
wires = self.wires()
wire_count = len(wires)
if wire_count != 1:
warnings.warn(
f"Found {wire_count} wires, returning first",
stacklevel=2,
)
return wires[0]
return Shape._get_single_shape(self, "Wire")

def faces(self) -> ShapeList[Face]:
"""faces - all the faces in this Shape"""
if self.wrapped is None:
return ShapeList()
face_list = ShapeList([Face(i) for i in self._entities(Face.__name__)])
for face in face_list:
face.topo_parent = self
return face_list
return Shape._get_shape_list(self, "Face")

def face(self) -> Face:
"""Return the Face"""
faces = self.faces()
face_count = len(faces)
if face_count != 1:
msg = f"Found {face_count} faces, returning first"
warnings.warn(msg, stacklevel=2)
return faces[0]
return Shape._get_single_shape(self, "Face")

def shells(self) -> ShapeList[Shell]:
"""shells - all the shells in this Shape"""
if self.wrapped is None:
return ShapeList()
return ShapeList([Shell(i) for i in self._entities(Shell.__name__)])
return Shape._get_shape_list(self, "Shell")

def shell(self) -> Shell:
"""Return the Shell"""
shells = self.shells()
shell_count = len(shells)
if shell_count != 1:
warnings.warn(
f"Found {shell_count} shells, returning first",
stacklevel=2,
)
return shells[0]
return Shape._get_single_shape(self, "Shell")

def solids(self) -> ShapeList[Solid]:
"""solids - all the solids in this Shape"""
if self.wrapped is None:
return ShapeList()
return ShapeList([Solid(i) for i in self._entities(Solid.__name__)])
return Shape._get_shape_list(self, "Solid")

def solid(self) -> Solid:
"""Return the Solid"""
solids = self.solids()
solid_count = len(solids)
if solid_count != 1:
return Shape._get_single_shape(self, "Solid")

def compounds(self) -> ShapeList[Compound]:
"""compounds - all the compounds in this Shape"""
if self.wrapped is None:
return ShapeList()
if isinstance(self.wrapped, TopoDS_Compound):
# pylint: disable=not-an-iterable
sub_compounds = [c for c in self if isinstance(c.wrapped, TopoDS_Compound)]
sub_compounds.append(self)
else:
sub_compounds = []
return ShapeList(sub_compounds)

def compound(self) -> Compound:
"""Return the Compound"""
shape_list = self.compounds()
entity_count = len(shape_list)
if entity_count != 1:
warnings.warn(
f"Found {solid_count} solids, returning first",
f"Found {entity_count} compounds, returning first",
stacklevel=2,
)
return solids[0]
return shape_list[0] if shape_list else None

@property
def area(self) -> float:
Expand Down

0 comments on commit 52e43d5

Please sign in to comment.