mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-15 15:20:37 -08:00
topology: operations_generic: tests: geom_type() now returns GeomType enum
This commit is contained in:
parent
d7c6c014f8
commit
355a53f52e
5 changed files with 40 additions and 85 deletions
|
|
@ -38,7 +38,7 @@ from build123d.build_common import (
|
|||
flatten_sequence,
|
||||
validate_inputs,
|
||||
)
|
||||
from build123d.build_enums import Keep, Kind, Mode, Side, Transition
|
||||
from build123d.build_enums import Keep, Kind, Mode, Side, Transition, GeomType
|
||||
from build123d.build_line import BuildLine
|
||||
from build123d.build_part import BuildPart
|
||||
from build123d.build_sketch import BuildSketch
|
||||
|
|
@ -619,7 +619,7 @@ def offset(
|
|||
pass
|
||||
new_faces.append(Face(outer_wire, inner_wires))
|
||||
if edges:
|
||||
if len(edges) == 1 and edges[0].geom_type() == "LINE":
|
||||
if len(edges) == 1 and edges[0].geom_type() == GeomType.LINE:
|
||||
new_wires = [
|
||||
Wire(
|
||||
[
|
||||
|
|
|
|||
|
|
@ -328,19 +328,8 @@ downcast_LUT = {
|
|||
ta.TopAbs_COMPOUND: TopoDS.Compound_s,
|
||||
ta.TopAbs_COMPSOLID: TopoDS.CompSolid_s,
|
||||
}
|
||||
geom_LUT = {
|
||||
ta.TopAbs_VERTEX: "Vertex",
|
||||
ta.TopAbs_EDGE: BRepAdaptor_Curve,
|
||||
ta.TopAbs_WIRE: "Wire",
|
||||
ta.TopAbs_FACE: BRepAdaptor_Surface,
|
||||
ta.TopAbs_SHELL: "Shell",
|
||||
ta.TopAbs_SOLID: "Solid",
|
||||
ta.TopAbs_COMPOUND: "Compound",
|
||||
ta.TopAbs_COMPSOLID: "Compound",
|
||||
}
|
||||
|
||||
|
||||
geom_LUT_FACE = {
|
||||
geom_LUT_FACE: Dict[ga.GeomAbs_SurfaceType, GeomType] = {
|
||||
ga.GeomAbs_Plane: GeomType.PLANE,
|
||||
ga.GeomAbs_Cylinder: GeomType.CYLINDER,
|
||||
ga.GeomAbs_Cone: GeomType.CONE,
|
||||
|
|
@ -354,7 +343,7 @@ geom_LUT_FACE = {
|
|||
ga.GeomAbs_OtherSurface: GeomType.OTHER,
|
||||
}
|
||||
|
||||
geom_LUT_EDGE = {
|
||||
geom_LUT_EDGE: Dict[ga.GeomAbs_CurveType, GeomType] = {
|
||||
ga.GeomAbs_Line: GeomType.LINE,
|
||||
ga.GeomAbs_Circle: GeomType.CIRCLE,
|
||||
ga.GeomAbs_Ellipse: GeomType.ELLIPSE,
|
||||
|
|
@ -367,29 +356,6 @@ geom_LUT_EDGE = {
|
|||
}
|
||||
|
||||
Shapes = Literal["Vertex", "Edge", "Wire", "Face", "Shell", "Solid", "Compound"]
|
||||
Geoms = Literal[
|
||||
"Vertex",
|
||||
"Wire",
|
||||
"Shell",
|
||||
"Solid",
|
||||
"Compound",
|
||||
GeomType.PLANE,
|
||||
GeomType.CYLINDER,
|
||||
GeomType.CONE,
|
||||
GeomType.SPHERE,
|
||||
GeomType.TORUS,
|
||||
GeomType.BEZIER,
|
||||
GeomType.BSPLINE,
|
||||
GeomType.REVOLUTION,
|
||||
GeomType.EXTRUSION,
|
||||
GeomType.OFFSET,
|
||||
GeomType.OTHER,
|
||||
GeomType.LINE,
|
||||
GeomType.CIRCLE,
|
||||
GeomType.ELLIPSE,
|
||||
GeomType.HYPERBOLA,
|
||||
GeomType.PARABOLA,
|
||||
]
|
||||
|
||||
|
||||
def tuplify(obj: Any, dim: int) -> tuple:
|
||||
|
|
@ -512,10 +478,10 @@ class Mixin1D:
|
|||
curve = self._geom_adaptor()
|
||||
gtype = self.geom_type()
|
||||
|
||||
if gtype == "CIRCLE":
|
||||
if gtype == GeomType.CIRCLE:
|
||||
circ = curve.Circle()
|
||||
return_value = Vector(circ.Axis().Direction())
|
||||
elif gtype == "ELLIPSE":
|
||||
elif gtype == GeomType.ELLIPSE:
|
||||
ell = curve.Ellipse()
|
||||
return_value = Vector(ell.Axis().Direction())
|
||||
else:
|
||||
|
|
@ -576,7 +542,7 @@ class Mixin1D:
|
|||
result = None
|
||||
# Are they all co-axial - if so, select one of the infinite planes
|
||||
all_edges: list[Edge] = [e for l in all_lines for e in l.edges()]
|
||||
if all([e.geom_type() == "LINE" for e in all_edges]):
|
||||
if all([e.geom_type() == GeomType.LINE for e in all_edges]):
|
||||
as_axis = [Axis(e @ 0, e % 0) for e in all_edges]
|
||||
if all([a0.is_coaxial(a1) for a0, a1 in combinations(as_axis, 2)]):
|
||||
origin = as_axis[0].position
|
||||
|
|
@ -595,7 +561,7 @@ class Mixin1D:
|
|||
all_lines = normal_lines + shortened_lines
|
||||
|
||||
for line in all_lines:
|
||||
num_points = 2 if line.geom_type() == "LINE" else 8
|
||||
num_points = 2 if line.geom_type() == GeomType.LINE else 8
|
||||
points.extend(
|
||||
[line.position_at(i / (num_points - 1)) for i in range(num_points)]
|
||||
)
|
||||
|
|
@ -868,7 +834,7 @@ class Mixin1D:
|
|||
edges_to_keep = [[], [], []]
|
||||
i = 0
|
||||
for edge in offset_edges:
|
||||
if edge.geom_type() == "CIRCLE" and (
|
||||
if edge.geom_type() == GeomType.CIRCLE and (
|
||||
edge.arc_center == line.position_at(0)
|
||||
or edge.arc_center == line.position_at(1)
|
||||
):
|
||||
|
|
@ -1876,39 +1842,25 @@ class Shape(NodeMixin):
|
|||
|
||||
return True if return_value is None else return_value
|
||||
|
||||
def geom_type(self) -> Geoms:
|
||||
def geom_type(self) -> GeomType:
|
||||
"""Gets the underlying geometry type.
|
||||
|
||||
Implementations can return any values desired, but the values the user
|
||||
uses in type filters should correspond to these.
|
||||
|
||||
The return values depend on the type of the shape:
|
||||
|
||||
| Vertex: always Vertex
|
||||
| Edge: LINE, ARC, CIRCLE, SPLINE
|
||||
| Face: PLANE, SPHERE, CONE
|
||||
| Solid: Solid
|
||||
| Shell: Shell
|
||||
| Compound: Compound
|
||||
| Wire: Wire
|
||||
|
||||
Args:
|
||||
|
||||
Returns:
|
||||
A string according to the geometry type
|
||||
|
||||
"""
|
||||
|
||||
topo_abs: Any = geom_LUT[shapetype(self.wrapped)]
|
||||
shape: TopAbs_ShapeEnum = shapetype(self.wrapped)
|
||||
|
||||
if isinstance(topo_abs, str):
|
||||
return_value = topo_abs
|
||||
elif topo_abs is BRepAdaptor_Curve:
|
||||
return_value = geom_LUT_EDGE[topo_abs(self.wrapped).GetType()]
|
||||
if shape is ta.TopAbs_EDGE:
|
||||
geom = geom_LUT_EDGE[BRepAdaptor_Curve(self.wrapped).GetType()]
|
||||
elif shape is ta.TopAbs_FACE:
|
||||
geom = geom_LUT_FACE[BRepAdaptor_Surface(self.wrapped).GetType()]
|
||||
else:
|
||||
return_value = geom_LUT_FACE[topo_abs(self.wrapped).GetType()]
|
||||
geom = GeomType.OTHER
|
||||
|
||||
return tcast(Geoms, return_value)
|
||||
return geom
|
||||
|
||||
def hash_code(self) -> int:
|
||||
"""Returns a hashed value denoting this shape. It is computed from the
|
||||
|
|
@ -3312,9 +3264,9 @@ class ShapeList(list[T]):
|
|||
# could be moved out maybe?
|
||||
def axis_parallel_predicate(axis: Axis, tolerance: float):
|
||||
def pred(shape: Shape):
|
||||
if isinstance(shape, Face) and shape.geom_type() == "PLANE":
|
||||
if isinstance(shape, Face) and shape.geom_type() == GeomType.PLANE:
|
||||
shape_axis = Axis(shape.center(), shape.normal_at(None))
|
||||
elif isinstance(shape, Edge) and shape.geom_type() == "LINE":
|
||||
elif isinstance(shape, Edge) and shape.geom_type() == GeomType.LINE:
|
||||
shape_axis = Axis(shape.position_at(0), shape.tangent_at(0))
|
||||
else:
|
||||
return False
|
||||
|
|
@ -3327,7 +3279,7 @@ class ShapeList(list[T]):
|
|||
plane_xyz = plane.z_dir.wrapped.XYZ()
|
||||
|
||||
def pred(shape: Shape):
|
||||
if isinstance(shape, Face) and shape.geom_type() == "PLANE":
|
||||
if isinstance(shape, Face) and shape.geom_type() == GeomType.PLANE:
|
||||
shape_axis = Axis(shape.center(), shape.normal_at(None))
|
||||
return plane_axis.is_parallel(shape_axis, tolerance)
|
||||
if isinstance(shape, Wire):
|
||||
|
|
@ -4408,9 +4360,9 @@ class Edge(Mixin1D, Shape):
|
|||
geom_type = self.geom_type()
|
||||
geom_adaptor = self._geom_adaptor()
|
||||
|
||||
if geom_type == "CIRCLE":
|
||||
if geom_type == GeomType.CIRCLE:
|
||||
return_value = Vector(geom_adaptor.Circle().Position().Location())
|
||||
elif geom_type == "ELLIPSE":
|
||||
elif geom_type == GeomType.ELLIPSE:
|
||||
return_value = Vector(geom_adaptor.Ellipse().Position().Location())
|
||||
else:
|
||||
raise ValueError(f"{geom_type} has no arc center")
|
||||
|
|
@ -4433,7 +4385,7 @@ class Edge(Mixin1D, Shape):
|
|||
"""
|
||||
angle = angle % 360 # angle needs to always be positive 0..360
|
||||
|
||||
if self.geom_type() == "LINE":
|
||||
if self.geom_type() == GeomType.LINE:
|
||||
if self.tangent_angle_at(0) == angle:
|
||||
u_values = [0]
|
||||
else:
|
||||
|
|
@ -5130,7 +5082,7 @@ class Edge(Mixin1D, Shape):
|
|||
|
||||
def to_axis(self) -> Axis:
|
||||
"""Translate a linear Edge to an Axis"""
|
||||
if self.geom_type() != "LINE":
|
||||
if self.geom_type() != GeomType.LINE:
|
||||
raise ValueError("to_axis is only valid for linear Edges")
|
||||
return Axis(self.position_at(0), self.position_at(1) - self.position_at(0))
|
||||
|
||||
|
|
@ -5225,7 +5177,7 @@ class Face(Shape):
|
|||
def length(self) -> float:
|
||||
"""length of planar face"""
|
||||
result = None
|
||||
if self.geom_type() == "PLANE":
|
||||
if self.geom_type() == GeomType.PLANE:
|
||||
# Reposition on Plane.XY
|
||||
flat_face = Plane(self).to_local_coords(self)
|
||||
face_vertices = flat_face.vertices().sort_by(Axis.X)
|
||||
|
|
@ -5241,7 +5193,7 @@ class Face(Shape):
|
|||
def width(self) -> float:
|
||||
"""width of planar face"""
|
||||
result = None
|
||||
if self.geom_type() == "PLANE":
|
||||
if self.geom_type() == GeomType.PLANE:
|
||||
# Reposition on Plane.XY
|
||||
flat_face = Plane(self).to_local_coords(self)
|
||||
face_vertices = flat_face.vertices().sort_by(Axis.Y)
|
||||
|
|
@ -5252,10 +5204,10 @@ class Face(Shape):
|
|||
def geometry(self) -> str:
|
||||
"""geometry of planar face"""
|
||||
result = None
|
||||
if self.geom_type() == "PLANE":
|
||||
if self.geom_type() == GeomType.PLANE:
|
||||
flat_face = Plane(self).to_local_coords(self)
|
||||
flat_face_edges = flat_face.edges()
|
||||
if all([e.geom_type() == "LINE" for e in flat_face_edges]):
|
||||
if all([e.geom_type() == GeomType.LINE for e in flat_face_edges]):
|
||||
flat_face_vertices = flat_face.vertices()
|
||||
result = "POLYGON"
|
||||
if len(flat_face_edges) == 4:
|
||||
|
|
@ -5373,7 +5325,7 @@ class Face(Shape):
|
|||
Vector: center
|
||||
"""
|
||||
if (center_of == CenterOf.MASS) or (
|
||||
center_of == CenterOf.GEOMETRY and self.geom_type() == "PLANE"
|
||||
center_of == CenterOf.GEOMETRY and self.geom_type() == GeomType.PLANE
|
||||
):
|
||||
properties = GProp_GProps()
|
||||
BRepGProp.SurfaceProperties_s(self.wrapped, properties)
|
||||
|
|
@ -6767,7 +6719,9 @@ class Solid(Mixin3D, Shape):
|
|||
clip_faces = [
|
||||
f
|
||||
for f in faces
|
||||
if not (f.geom_type() == "PLANE" and f.normal_at().dot(direction) == 0.0)
|
||||
if not (
|
||||
f.geom_type() == GeomType.PLANE and f.normal_at().dot(direction) == 0.0
|
||||
)
|
||||
]
|
||||
if not clip_faces:
|
||||
raise ValueError("provided face does not intersect target_object")
|
||||
|
|
|
|||
|
|
@ -486,7 +486,7 @@ class MirrorTests(unittest.TestCase):
|
|||
revolve(axis=Axis.Z)
|
||||
mirror(about=Plane.XY)
|
||||
construction_face = p.faces().sort_by(Axis.Z)[0]
|
||||
self.assertEqual(construction_face.geom_type(), "PLANE")
|
||||
self.assertEqual(construction_face.geom_type(), GeomType.PLANE)
|
||||
|
||||
|
||||
class OffsetTests(unittest.TestCase):
|
||||
|
|
|
|||
|
|
@ -1269,7 +1269,7 @@ class TestFace(DirectApiTestCase):
|
|||
interior_wires=[hole],
|
||||
)
|
||||
self.assertTrue(surface.is_valid())
|
||||
self.assertEqual(surface.geom_type(), "BSPLINE")
|
||||
self.assertEqual(surface.geom_type(), GeomType.BSPLINE)
|
||||
bbox = surface.bounding_box()
|
||||
self.assertVectorAlmostEquals(bbox.min, (-50.5, -24.5, -5.113393280136395), 5)
|
||||
self.assertVectorAlmostEquals(bbox.max, (50.5, 24.5, 0), 5)
|
||||
|
|
@ -1961,12 +1961,12 @@ class TestMixin1D(DirectApiTestCase):
|
|||
# base_edge = Edge.make_circle(10, start_angle=40, end_angle=50)
|
||||
# self.assertTrue(isinstance(offset_edge, Edge))
|
||||
# offset_edge = base_edge.offset_2d(2, side=Side.RIGHT, closed=False)
|
||||
# self.assertTrue(offset_edge.geom_type() == "CIRCLE")
|
||||
# self.assertTrue(offset_edge.geom_type() == GeomType.CIRCLE)
|
||||
# self.assertAlmostEqual(offset_edge.radius, 12, 5)
|
||||
# base_edge = Edge.make_line((0, 1), (1, 10))
|
||||
# offset_edge = base_edge.offset_2d(2, side=Side.RIGHT, closed=False)
|
||||
# self.assertTrue(isinstance(offset_edge, Edge))
|
||||
# self.assertTrue(offset_edge.geom_type() == "LINE")
|
||||
# self.assertTrue(offset_edge.geom_type() == GeomType.LINE)
|
||||
# self.assertAlmostEqual(offset_edge.position_at(0).X, 3)
|
||||
|
||||
def test_common_plane(self):
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from build123d import (
|
|||
)
|
||||
from build123d.importers import import_svg_as_buildline_code, import_brep, import_svg
|
||||
from build123d.exporters import ExportSVG
|
||||
from build123d.build_enums import GeomType
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
|
|
@ -34,11 +35,11 @@ class ImportSVG(unittest.TestCase):
|
|||
test_obj: BuildLine = ex_locals[builder_name]
|
||||
found = 0
|
||||
for edge in test_obj.edges():
|
||||
if edge.geom_type() == "BEZIER":
|
||||
if edge.geom_type() == GeomType.ELLIPSE:
|
||||
found += 1
|
||||
elif edge.geom_type() == "LINE":
|
||||
elif edge.geom_type() == GeomType.LINE:
|
||||
found += 1
|
||||
elif edge.geom_type() == "ELLIPSE":
|
||||
elif edge.geom_type() == GeomType.ELLIPSE:
|
||||
found += 1
|
||||
self.assertEqual(found, 4)
|
||||
os.remove("test.svg")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue