mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
Changing base types Issue #792
This commit is contained in:
parent
e06337a0e8
commit
60b244442d
2 changed files with 78 additions and 43 deletions
|
|
@ -40,35 +40,55 @@ from build123d.geometry import Axis, Plane, Vector, VectorLike, TOLERANCE
|
|||
from build123d.topology import Edge, Face, Wire, Curve
|
||||
|
||||
|
||||
class BaseLineObject(Wire):
|
||||
"""BaseLineObject
|
||||
|
||||
Base class for all BuildLine objects
|
||||
def _add_curve_to_context(curve, mode: Mode):
|
||||
"""Helper function to add a curve to the context.
|
||||
|
||||
Args:
|
||||
curve (Union[Edge,Wire]): edge to create
|
||||
curve (Union[Wire, Edge]): curve to add to the context (either a Wire or an Edge).
|
||||
mode (Mode): combination mode.
|
||||
"""
|
||||
context: BuildLine = BuildLine._get_context(log=False)
|
||||
|
||||
if context is not None and isinstance(context, BuildLine):
|
||||
if isinstance(curve, Wire):
|
||||
context._add_to_context(*curve.edges(), mode=mode)
|
||||
elif isinstance(curve, Edge):
|
||||
context._add_to_context(curve, mode=mode)
|
||||
|
||||
|
||||
class BaseLineObject(Wire):
|
||||
"""BaseLineObject specialized for Wire.
|
||||
|
||||
Args:
|
||||
curve (Wire): wire to create.
|
||||
mode (Mode, optional): combination mode. Defaults to Mode.ADD.
|
||||
"""
|
||||
|
||||
_applies_to = [BuildLine._tag]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
curve: Union[Edge, Wire],
|
||||
mode: Mode = Mode.ADD,
|
||||
):
|
||||
context: BuildLine = BuildLine._get_context(self, log=False)
|
||||
|
||||
if context is not None and isinstance(context, BuildLine):
|
||||
context._add_to_context(*curve.edges(), mode=mode)
|
||||
|
||||
if isinstance(curve, Edge):
|
||||
super().__init__(Wire([curve]).wrapped)
|
||||
else:
|
||||
def __init__(self, curve: Wire, mode: Mode = Mode.ADD):
|
||||
# Use the helper function to handle adding the curve to the context
|
||||
_add_curve_to_context(curve, mode)
|
||||
super().__init__(curve.wrapped)
|
||||
|
||||
|
||||
class Bezier(BaseLineObject):
|
||||
class BaseEdgeObject(Edge):
|
||||
"""BaseEdgeObject specialized for Edge.
|
||||
|
||||
Args:
|
||||
curve (Edge): edge to create.
|
||||
mode (Mode, optional): combination mode. Defaults to Mode.ADD.
|
||||
"""
|
||||
|
||||
_applies_to = [BuildLine._tag]
|
||||
|
||||
def __init__(self, curve: Edge, mode: Mode = Mode.ADD):
|
||||
# Use the helper function to handle adding the curve to the context
|
||||
_add_curve_to_context(curve, mode)
|
||||
super().__init__(curve.wrapped)
|
||||
|
||||
|
||||
class Bezier(BaseEdgeObject):
|
||||
"""Line Object: Bezier Curve
|
||||
|
||||
Create a rational (with weights) or non-rational bezier curve. The first and last
|
||||
|
|
@ -99,7 +119,7 @@ class Bezier(BaseLineObject):
|
|||
super().__init__(curve, mode=mode)
|
||||
|
||||
|
||||
class CenterArc(BaseLineObject):
|
||||
class CenterArc(BaseEdgeObject):
|
||||
"""Line Object: Center Arc
|
||||
|
||||
Add center arc to the line.
|
||||
|
|
@ -150,7 +170,7 @@ class CenterArc(BaseLineObject):
|
|||
super().__init__(arc, mode=mode)
|
||||
|
||||
|
||||
class DoubleTangentArc(BaseLineObject):
|
||||
class DoubleTangentArc(BaseEdgeObject):
|
||||
"""Line Object: Double Tangent Arc
|
||||
|
||||
Create an arc defined by a point/tangent pair and another line which the other end
|
||||
|
|
@ -249,7 +269,7 @@ class DoubleTangentArc(BaseLineObject):
|
|||
super().__init__(double.wire(), mode=mode)
|
||||
|
||||
|
||||
class EllipticalStartArc(BaseLineObject):
|
||||
class EllipticalStartArc(BaseEdgeObject):
|
||||
"""Line Object: Elliptical Start Arc
|
||||
|
||||
Makes an arc of an ellipse from the start point.
|
||||
|
|
@ -355,7 +375,7 @@ class EllipticalStartArc(BaseLineObject):
|
|||
# context: BuildLine = BuildLine._get_context(self)
|
||||
|
||||
|
||||
class EllipticalCenterArc(BaseLineObject):
|
||||
class EllipticalCenterArc(BaseEdgeObject):
|
||||
"""Line Object: Elliptical Center Arc
|
||||
|
||||
Makes an arc of an ellipse from a center point.
|
||||
|
|
@ -409,7 +429,7 @@ class EllipticalCenterArc(BaseLineObject):
|
|||
super().__init__(curve, mode=mode)
|
||||
|
||||
|
||||
class Helix(BaseLineObject):
|
||||
class Helix(BaseEdgeObject):
|
||||
"""Line Object: Helix
|
||||
|
||||
Add a helix to the line.
|
||||
|
|
@ -545,7 +565,7 @@ class FilletPolyline(BaseLineObject):
|
|||
super().__init__(new_wire, mode=mode)
|
||||
|
||||
|
||||
class JernArc(BaseLineObject):
|
||||
class JernArc(BaseEdgeObject):
|
||||
"""JernArc
|
||||
|
||||
Circular tangent arc with given radius and arc_size
|
||||
|
|
@ -605,7 +625,7 @@ class JernArc(BaseLineObject):
|
|||
super().__init__(arc, mode=mode)
|
||||
|
||||
|
||||
class Line(BaseLineObject):
|
||||
class Line(BaseEdgeObject):
|
||||
"""Line Object: Line
|
||||
|
||||
Add a straight line defined by two end points.
|
||||
|
|
@ -638,7 +658,7 @@ class Line(BaseLineObject):
|
|||
super().__init__(new_edge, mode=mode)
|
||||
|
||||
|
||||
class IntersectingLine(BaseLineObject):
|
||||
class IntersectingLine(BaseEdgeObject):
|
||||
"""Intersecting Line Object: Line
|
||||
|
||||
Add a straight line that intersects another line at a given parameter and angle.
|
||||
|
|
@ -679,7 +699,7 @@ class IntersectingLine(BaseLineObject):
|
|||
super().__init__(new_edge, mode=mode)
|
||||
|
||||
|
||||
class PolarLine(BaseLineObject):
|
||||
class PolarLine(BaseEdgeObject):
|
||||
"""Line Object: Polar Line
|
||||
|
||||
Add line defined by a start point, length and angle.
|
||||
|
|
@ -780,7 +800,7 @@ class Polyline(BaseLineObject):
|
|||
super().__init__(Wire.combine(new_edges)[0], mode=mode)
|
||||
|
||||
|
||||
class RadiusArc(BaseLineObject):
|
||||
class RadiusArc(BaseEdgeObject):
|
||||
"""Line Object: Radius Arc
|
||||
|
||||
Add an arc defined by two end points and a radius
|
||||
|
|
@ -832,7 +852,7 @@ class RadiusArc(BaseLineObject):
|
|||
super().__init__(arc, mode=mode)
|
||||
|
||||
|
||||
class SagittaArc(BaseLineObject):
|
||||
class SagittaArc(BaseEdgeObject):
|
||||
"""Line Object: Sagitta Arc
|
||||
|
||||
Add an arc defined by two points and the height of the arc (sagitta).
|
||||
|
|
@ -874,7 +894,7 @@ class SagittaArc(BaseLineObject):
|
|||
super().__init__(arc, mode=mode)
|
||||
|
||||
|
||||
class Spline(BaseLineObject):
|
||||
class Spline(BaseEdgeObject):
|
||||
"""Line Object: Spline
|
||||
|
||||
Add a spline through the provided points optionally constrained by tangents.
|
||||
|
|
@ -932,7 +952,7 @@ class Spline(BaseLineObject):
|
|||
super().__init__(spline, mode=mode)
|
||||
|
||||
|
||||
class TangentArc(BaseLineObject):
|
||||
class TangentArc(BaseEdgeObject):
|
||||
"""Line Object: Tangent Arc
|
||||
|
||||
Add an arc defined by two points and a tangent.
|
||||
|
|
@ -974,7 +994,7 @@ class TangentArc(BaseLineObject):
|
|||
super().__init__(arc, mode=mode)
|
||||
|
||||
|
||||
class ThreePointArc(BaseLineObject):
|
||||
class ThreePointArc(BaseEdgeObject):
|
||||
"""Line Object: Three Point Arc
|
||||
|
||||
Add an arc generated by three points.
|
||||
|
|
|
|||
|
|
@ -104,8 +104,9 @@ class BuildLineTests(unittest.TestCase):
|
|||
pts = [(0, 0), (20, 20), (40, 0), (0, -40), (-60, 0), (0, 100), (100, 0)]
|
||||
wts = [1.0, 1.0, 2.0, 3.0, 4.0, 2.0, 1.0]
|
||||
with BuildLine() as bz:
|
||||
Bezier(*pts, weights=wts)
|
||||
b1 = Bezier(*pts, weights=wts)
|
||||
self.assertAlmostEqual(bz.wires()[0].length, 225.86389406824566, 5)
|
||||
self.assertTrue(isinstance(b1, Edge))
|
||||
|
||||
def test_double_tangent_arc(self):
|
||||
l1 = Line((10, 0), (30, 20))
|
||||
|
|
@ -140,6 +141,7 @@ class BuildLineTests(unittest.TestCase):
|
|||
l9 = EllipticalCenterArc((15, 0), 10, 5, start_angle=90, end_angle=270)
|
||||
l10 = DoubleTangentArc((0, 0, 0), (1, 0, 0), l9, keep=Keep.BOTH)
|
||||
self.assertEqual(len(l10.edges()), 2)
|
||||
self.assertTrue(isinstance(l10, Edge))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
DoubleTangentArc((0, 0, 0), (0, 0, 1), l9)
|
||||
|
|
@ -168,6 +170,7 @@ class BuildLineTests(unittest.TestCase):
|
|||
self.assertGreaterEqual(bbox.min.Y, 0)
|
||||
self.assertLessEqual(bbox.max.X, 10)
|
||||
self.assertLessEqual(bbox.max.Y, 5)
|
||||
self.assertTrue(isinstance(e1, Edge))
|
||||
|
||||
def test_filletpolyline(self):
|
||||
with BuildLine(Plane.YZ):
|
||||
|
|
@ -185,6 +188,7 @@ class BuildLineTests(unittest.TestCase):
|
|||
self.assertEqual(len(p.edges()), 8)
|
||||
self.assertEqual(len(p.edges().filter_by(GeomType.CIRCLE)), 4)
|
||||
self.assertEqual(len(p.edges().filter_by(GeomType.LINE)), 4)
|
||||
self.assertTrue(isinstance(p, Wire))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
FilletPolyline((0, 0), radius=0.1)
|
||||
|
|
@ -200,6 +204,7 @@ class BuildLineTests(unittest.TestCase):
|
|||
l3 = Line((0, 0), (10, 10))
|
||||
l4 = IntersectingLine((0, 10), (1, -1), l3)
|
||||
self.assertTupleAlmostEquals((l4 @ 1).to_tuple(), (5, 5, 0), 5)
|
||||
self.assertTrue(isinstance(l4, Edge))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
IntersectingLine((0, 10), (1, 1), l3)
|
||||
|
|
@ -209,18 +214,20 @@ class BuildLineTests(unittest.TestCase):
|
|||
j1 = JernArc((1, 0), (0, 1), 1, 90)
|
||||
self.assertTupleAlmostEquals((jern.line @ 1).to_tuple(), (0, 1, 0), 5)
|
||||
self.assertAlmostEqual(j1.radius, 1)
|
||||
self.assertAlmostEqual(j1.length, pi/2)
|
||||
self.assertAlmostEqual(j1.length, pi / 2)
|
||||
|
||||
with BuildLine(Plane.XY.offset(1)) as offset_l:
|
||||
off1 = JernArc((1, 0), (0, 1), 1, 90)
|
||||
self.assertTupleAlmostEquals((offset_l.line @ 1).to_tuple(), (0, 1, 1), 5)
|
||||
self.assertAlmostEqual(off1.radius, 1)
|
||||
self.assertAlmostEqual(off1.length, pi/2)
|
||||
self.assertAlmostEqual(off1.length, pi / 2)
|
||||
|
||||
plane_iso = Plane(origin=(0, 0, 0), x_dir=(1, 1, 0), z_dir=(1, -1, 1))
|
||||
with BuildLine(plane_iso) as iso_l:
|
||||
iso1 = JernArc((0, 0), (0, 1), 1, 180)
|
||||
self.assertTupleAlmostEquals((iso_l.line @ 1).to_tuple(), (-sqrt(2), -sqrt(2), 0), 5)
|
||||
self.assertTupleAlmostEquals(
|
||||
(iso_l.line @ 1).to_tuple(), (-sqrt(2), -sqrt(2), 0), 5
|
||||
)
|
||||
self.assertAlmostEqual(iso1.radius, 1)
|
||||
self.assertAlmostEqual(iso1.length, pi)
|
||||
|
||||
|
|
@ -229,13 +236,14 @@ class BuildLineTests(unittest.TestCase):
|
|||
l2 = JernArc(start=(0, 0, 0), tangent=(1, 0, 0), radius=1, arc_size=300)
|
||||
self.assertTrue(l1.is_closed)
|
||||
self.assertFalse(l2.is_closed)
|
||||
circle_face = Face(l1)
|
||||
circle_face = Face(Wire([l1]))
|
||||
self.assertAlmostEqual(circle_face.area, pi, 5)
|
||||
self.assertTupleAlmostEquals(circle_face.center().to_tuple(), (0, 1, 0), 5)
|
||||
self.assertTupleAlmostEquals(l1.vertex().to_tuple(), l2.start.to_tuple(), 5)
|
||||
|
||||
l1 = JernArc((0, 0), (1, 0), 1, 90)
|
||||
self.assertTupleAlmostEquals((l1 @ 1).to_tuple(), (1, 1, 0), 5)
|
||||
self.assertTrue(isinstance(l1, Edge))
|
||||
|
||||
def test_polar_line(self):
|
||||
"""Test 2D and 3D polar lines"""
|
||||
|
|
@ -267,6 +275,7 @@ class BuildLineTests(unittest.TestCase):
|
|||
|
||||
l1 = PolarLine((0, 0), 10, direction=(1, 1))
|
||||
self.assertTupleAlmostEquals((l1 @ 1).to_tuple(), (10, 10, 0), 5)
|
||||
self.assertTrue(isinstance(l1, Edge))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
PolarLine((0, 0), 1)
|
||||
|
|
@ -274,8 +283,9 @@ class BuildLineTests(unittest.TestCase):
|
|||
def test_spline(self):
|
||||
"""Test spline with no tangents"""
|
||||
with BuildLine() as test:
|
||||
Spline((0, 0), (1, 1), (2, 0))
|
||||
s1 = Spline((0, 0), (1, 1), (2, 0))
|
||||
self.assertTupleAlmostEquals((test.edges()[0] @ 1).to_tuple(), (2, 0, 0), 5)
|
||||
self.assertTrue(isinstance(s1, Edge))
|
||||
|
||||
def test_radius_arc(self):
|
||||
"""Test center arc as arc and circle"""
|
||||
|
|
@ -304,9 +314,12 @@ class BuildLineTests(unittest.TestCase):
|
|||
self.assertAlmostEqual(arc4.length, 2 * r * pi * 0.6, 6)
|
||||
self.assertGreater(arc4.bounding_box().max.X, c.bounding_box().max.X)
|
||||
|
||||
self.assertTrue(isinstance(arc1, Edge))
|
||||
|
||||
def test_sagitta_arc(self):
|
||||
l1 = SagittaArc((0, 0), (1, 0), 0.1)
|
||||
self.assertAlmostEqual((l1 @ 0.5).Y, 0.1, 5)
|
||||
self.assertTrue(isinstance(l1, Edge))
|
||||
|
||||
def test_center_arc(self):
|
||||
"""Test center arc as arc and circle"""
|
||||
|
|
@ -327,18 +340,20 @@ class BuildLineTests(unittest.TestCase):
|
|||
self.assertTupleAlmostEquals((arc.edges()[0] @ 0.5).to_tuple(), (0, 0, 0), 5)
|
||||
|
||||
arc = CenterArc((-100, 0), 100, 0, 360)
|
||||
self.assertTrue(Face(arc.wires()[0]).is_coplanar(Plane.XY))
|
||||
self.assertTrue(Face(Wire([arc])).is_coplanar(Plane.XY))
|
||||
self.assertTupleAlmostEquals(arc.bounding_box().max, (0, 100, 0), 5)
|
||||
self.assertTrue(isinstance(arc, Edge))
|
||||
|
||||
def test_polyline(self):
|
||||
"""Test edge generation and close"""
|
||||
with BuildLine() as test:
|
||||
Polyline((0, 0), (1, 0), (1, 1), (0, 1), close=True)
|
||||
p1 = Polyline((0, 0), (1, 0), (1, 1), (0, 1), close=True)
|
||||
self.assertAlmostEqual(
|
||||
(test.edges()[0] @ 0 - test.edges()[-1] @ 1).length, 0, 5
|
||||
)
|
||||
self.assertEqual(len(test.edges()), 4)
|
||||
self.assertAlmostEqual(test.wires()[0].length, 4)
|
||||
self.assertTrue(isinstance(p1, Wire))
|
||||
|
||||
def test_polyline_with_list(self):
|
||||
"""Test edge generation and close"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue