mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 10:41:20 -08:00
Merge ddd236c787 into a971cbbad6
This commit is contained in:
commit
3675816ed6
7 changed files with 240 additions and 2 deletions
|
|
@ -29,7 +29,7 @@ Objects and arithmetic
|
||||||
|
|
||||||
:math:`B^2 := \lbrace` ``Sketch``, ``Rectangle``, ``Circle``, ``Ellipse``, ``Rectangle``, ``Polygon``, ``RegularPolygon``, ``Text``, ``Trapezoid``, ``SlotArc``, ``SlotCenterPoint``, ``SlotCenterToCenter``, ``SlotOverall`` :math:`\rbrace`
|
:math:`B^2 := \lbrace` ``Sketch``, ``Rectangle``, ``Circle``, ``Ellipse``, ``Rectangle``, ``Polygon``, ``RegularPolygon``, ``Text``, ``Trapezoid``, ``SlotArc``, ``SlotCenterPoint``, ``SlotCenterToCenter``, ``SlotOverall`` :math:`\rbrace`
|
||||||
|
|
||||||
:math:`B^1 := \lbrace` ``Curve``, ``Bezier``, ``FilletPolyline``, ``PolarLine``, ``Polyline``, ``Spline``, ``Helix``, ``CenterArc``, ``EllipticalCenterArc``, ``RadiusArc``, ``SagittaArc``, ``TangentArc``, ``ThreePointArc``, ``JernArc`` :math:`\rbrace`
|
:math:`B^1 := \lbrace` ``Curve``, ``Bezier``, ``FilletPolyline``, ``PolarLine``, ``Polyline``, ``Spline``, ``Helix``, ``CenterArc``, ``EllipticalCenterArc``, ``ParabolicCenterArc``, ``HyperbolicCenterArc``, ``RadiusArc``, ``SagittaArc``, ``TangentArc``, ``ThreePointArc``, ``JernArc`` :math:`\rbrace`
|
||||||
|
|
||||||
with :math:`B^3 \subset C^3, B^2 \subset C^2` and :math:`B^1 \subset C^1`
|
with :math:`B^3 \subset C^3, B^2 \subset C^2` and :math:`B^1 \subset C^1`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ Cheat Sheet
|
||||||
| :class:`~objects_curve.CenterArc`
|
| :class:`~objects_curve.CenterArc`
|
||||||
| :class:`~objects_curve.DoubleTangentArc`
|
| :class:`~objects_curve.DoubleTangentArc`
|
||||||
| :class:`~objects_curve.EllipticalCenterArc`
|
| :class:`~objects_curve.EllipticalCenterArc`
|
||||||
|
| :class:`~objects_curve.ParabolicCenterArc`
|
||||||
|
| :class:`~objects_curve.HyperbolicCenterArc`
|
||||||
| :class:`~objects_curve.FilletPolyline`
|
| :class:`~objects_curve.FilletPolyline`
|
||||||
| :class:`~objects_curve.Helix`
|
| :class:`~objects_curve.Helix`
|
||||||
| :class:`~objects_curve.IntersectingLine`
|
| :class:`~objects_curve.IntersectingLine`
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,20 @@ The following objects all can be used in BuildLine contexts. Note that
|
||||||
+++
|
+++
|
||||||
Elliptical arc defined by center, radii & angles
|
Elliptical arc defined by center, radii & angles
|
||||||
|
|
||||||
|
.. grid-item-card:: :class:`~objects_curve.ParabolicCenterArc`
|
||||||
|
|
||||||
|
.. image:: assets/parabolic_center_arc_example.svg
|
||||||
|
|
||||||
|
+++
|
||||||
|
Parabolic arc defined by vertex, focal length & angles
|
||||||
|
|
||||||
|
.. grid-item-card:: :class:`~objects_curve.HyperbolicCenterArc`
|
||||||
|
|
||||||
|
.. image:: assets/hyperbolic_center_arc_example.svg
|
||||||
|
|
||||||
|
+++
|
||||||
|
Hyperbolic arc defined by center, radii & angles
|
||||||
|
|
||||||
.. grid-item-card:: :class:`~objects_curve.FilletPolyline`
|
.. grid-item-card:: :class:`~objects_curve.FilletPolyline`
|
||||||
|
|
||||||
.. image:: assets/filletpolyline_example.svg
|
.. image:: assets/filletpolyline_example.svg
|
||||||
|
|
@ -241,6 +255,8 @@ Reference
|
||||||
.. autoclass:: CenterArc
|
.. autoclass:: CenterArc
|
||||||
.. autoclass:: DoubleTangentArc
|
.. autoclass:: DoubleTangentArc
|
||||||
.. autoclass:: EllipticalCenterArc
|
.. autoclass:: EllipticalCenterArc
|
||||||
|
.. autoclass:: ParabolicCenterArc
|
||||||
|
.. autoclass:: HyperbolicCenterArc
|
||||||
.. autoclass:: FilletPolyline
|
.. autoclass:: FilletPolyline
|
||||||
.. autoclass:: Helix
|
.. autoclass:: Helix
|
||||||
.. autoclass:: IntersectingLine
|
.. autoclass:: IntersectingLine
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,22 @@ svg.add_shape(elliptical_center_arc.line)
|
||||||
svg.add_shape(dot.moved(Location(Vector((0, 0)))))
|
svg.add_shape(dot.moved(Location(Vector((0, 0)))))
|
||||||
svg.write("assets/elliptical_center_arc_example.svg")
|
svg.write("assets/elliptical_center_arc_example.svg")
|
||||||
|
|
||||||
|
with BuildLine() as parabolic_center_arc:
|
||||||
|
ParabolicCenterArc((0, 0), 0.5, 60, 0)
|
||||||
|
s = 100 / max(*parabolic_center_arc.line.bounding_box().size)
|
||||||
|
svg = ExportSVG(scale=s)
|
||||||
|
svg.add_shape(parabolic_center_arc.line)
|
||||||
|
svg.add_shape(dot.moved(Location(Vector((0, 0)))))
|
||||||
|
svg.write("assets/parabolic_center_arc_example.svg")
|
||||||
|
|
||||||
|
with BuildLine() as hyperbolic_center_arc:
|
||||||
|
HyperbolicCenterArc((0, 0), 0.5, 1, 45, 90)
|
||||||
|
s = 100 / max(*hyperbolic_center_arc.line.bounding_box().size)
|
||||||
|
svg = ExportSVG(scale=s)
|
||||||
|
svg.add_shape(hyperbolic_center_arc.line)
|
||||||
|
svg.add_shape(dot.moved(Location(Vector((0, 0)))))
|
||||||
|
svg.write("assets/hyperbolic_center_arc_example.svg")
|
||||||
|
|
||||||
with BuildLine() as helix:
|
with BuildLine() as helix:
|
||||||
Helix(1, 3, 1)
|
Helix(1, 3, 1)
|
||||||
scene = Compound(helix.line) + Compound.make_triad(0.5)
|
scene = Compound(helix.line) + Compound.make_triad(0.5)
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,8 @@ __all__ = [
|
||||||
"DoubleTangentArc",
|
"DoubleTangentArc",
|
||||||
"EllipticalCenterArc",
|
"EllipticalCenterArc",
|
||||||
"EllipticalStartArc",
|
"EllipticalStartArc",
|
||||||
|
"ParabolicCenterArc",
|
||||||
|
"HyperbolicCenterArc",
|
||||||
"FilletPolyline",
|
"FilletPolyline",
|
||||||
"Helix",
|
"Helix",
|
||||||
"IntersectingLine",
|
"IntersectingLine",
|
||||||
|
|
|
||||||
|
|
@ -741,6 +741,117 @@ class EllipticalCenterArc(BaseEdgeObject):
|
||||||
super().__init__(curve, mode=mode)
|
super().__init__(curve, mode=mode)
|
||||||
|
|
||||||
|
|
||||||
|
class ParabolicCenterArc(BaseEdgeObject):
|
||||||
|
"""Line Object: Parabolic Center Arc
|
||||||
|
|
||||||
|
Create a parabolic arc defined by a vertex point and focal length (distance from focus to vertex).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
vertex (VectorLike): parabola vertex
|
||||||
|
focal_length (float): focal length the parabola (distance from the vertex to focus along the x-axis of plane)
|
||||||
|
start_angle (float, optional): arc start angle.
|
||||||
|
Defaults to 0.0
|
||||||
|
end_angle (float, optional): arc end angle.
|
||||||
|
Defaults to 90.0
|
||||||
|
rotation (float, optional): angle to rotate arc. Defaults to 0.0
|
||||||
|
angular_direction (AngularDirection, optional): arc direction.
|
||||||
|
Defaults to AngularDirection.COUNTER_CLOCKWISE
|
||||||
|
mode (Mode, optional): combination mode. Defaults to Mode.ADD
|
||||||
|
"""
|
||||||
|
|
||||||
|
_applies_to = [BuildLine._tag]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
vertex: VectorLike,
|
||||||
|
focal_length: float,
|
||||||
|
start_angle: float = 0.0,
|
||||||
|
end_angle: float = 90.0,
|
||||||
|
rotation: float = 0.0,
|
||||||
|
angular_direction: AngularDirection = AngularDirection.COUNTER_CLOCKWISE,
|
||||||
|
mode: Mode = Mode.ADD,
|
||||||
|
):
|
||||||
|
context: BuildLine | None = BuildLine._get_context(self)
|
||||||
|
validate_inputs(context, self)
|
||||||
|
|
||||||
|
vertex_pnt = WorkplaneList.localize(vertex)
|
||||||
|
if context is None:
|
||||||
|
parabola_workplane = Plane.XY
|
||||||
|
else:
|
||||||
|
parabola_workplane = copy_module.copy(
|
||||||
|
WorkplaneList._get_context().workplanes[0]
|
||||||
|
)
|
||||||
|
parabola_workplane.origin = vertex_pnt
|
||||||
|
curve = Edge.make_parabola(
|
||||||
|
focal_length=focal_length,
|
||||||
|
plane=parabola_workplane,
|
||||||
|
start_angle=start_angle,
|
||||||
|
end_angle=end_angle,
|
||||||
|
angular_direction=angular_direction,
|
||||||
|
).rotate(
|
||||||
|
Axis(parabola_workplane.origin, parabola_workplane.z_dir.to_dir()), rotation
|
||||||
|
)
|
||||||
|
|
||||||
|
super().__init__(curve, mode=mode)
|
||||||
|
|
||||||
|
|
||||||
|
class HyperbolicCenterArc(BaseEdgeObject):
|
||||||
|
"""Line Object: Hyperbolic Center Arc
|
||||||
|
|
||||||
|
Create a hyperbolic arc defined by a center point and focal length (distance from focus to vertex).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
center (VectorLike): hyperbola center
|
||||||
|
x_radius (float): x radius of the ellipse (along the x-axis of plane)
|
||||||
|
y_radius (float): y radius of the ellipse (along the y-axis of plane)
|
||||||
|
start_angle (float, optional): arc start angle from x-axis.
|
||||||
|
Defaults to 0.0
|
||||||
|
end_angle (float, optional): arc end angle from x-axis.
|
||||||
|
Defaults to 90.0
|
||||||
|
rotation (float, optional): angle to rotate arc. Defaults to 0.0
|
||||||
|
angular_direction (AngularDirection, optional): arc direction.
|
||||||
|
Defaults to AngularDirection.COUNTER_CLOCKWISE
|
||||||
|
mode (Mode, optional): combination mode. Defaults to Mode.ADD
|
||||||
|
"""
|
||||||
|
|
||||||
|
_applies_to = [BuildLine._tag]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
center: VectorLike,
|
||||||
|
x_radius: float,
|
||||||
|
y_radius: float,
|
||||||
|
start_angle: float = 0.0,
|
||||||
|
end_angle: float = 90.0,
|
||||||
|
rotation: float = 0.0,
|
||||||
|
angular_direction: AngularDirection = AngularDirection.COUNTER_CLOCKWISE,
|
||||||
|
mode: Mode = Mode.ADD,
|
||||||
|
):
|
||||||
|
context: BuildLine | None = BuildLine._get_context(self)
|
||||||
|
validate_inputs(context, self)
|
||||||
|
|
||||||
|
center_pnt = WorkplaneList.localize(center)
|
||||||
|
if context is None:
|
||||||
|
hyperbola_workplane = Plane.XY
|
||||||
|
else:
|
||||||
|
hyperbola_workplane = copy_module.copy(
|
||||||
|
WorkplaneList._get_context().workplanes[0]
|
||||||
|
)
|
||||||
|
hyperbola_workplane.origin = center_pnt
|
||||||
|
curve = Edge.make_hyperbola(
|
||||||
|
x_radius=x_radius,
|
||||||
|
y_radius=y_radius,
|
||||||
|
plane=hyperbola_workplane,
|
||||||
|
start_angle=start_angle,
|
||||||
|
end_angle=end_angle,
|
||||||
|
angular_direction=angular_direction,
|
||||||
|
).rotate(
|
||||||
|
Axis(hyperbola_workplane.origin, hyperbola_workplane.z_dir.to_dir()), rotation
|
||||||
|
)
|
||||||
|
|
||||||
|
super().__init__(curve, mode=mode)
|
||||||
|
|
||||||
|
|
||||||
class Helix(BaseEdgeObject):
|
class Helix(BaseEdgeObject):
|
||||||
"""Line Object: Helix
|
"""Line Object: Helix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ from OCP.BRepOffsetAPI import BRepOffsetAPI_MakeOffset
|
||||||
from OCP.BRepPrimAPI import BRepPrimAPI_MakeHalfSpace
|
from OCP.BRepPrimAPI import BRepPrimAPI_MakeHalfSpace
|
||||||
from OCP.BRepProj import BRepProj_Projection
|
from OCP.BRepProj import BRepProj_Projection
|
||||||
from OCP.BRepTools import BRepTools, BRepTools_WireExplorer
|
from OCP.BRepTools import BRepTools, BRepTools_WireExplorer
|
||||||
from OCP.GC import GC_MakeArcOfCircle, GC_MakeArcOfEllipse
|
from OCP.GC import GC_MakeArcOfCircle, GC_MakeArcOfEllipse, GC_MakeArcOfParabola, GC_MakeArcOfHyperbola
|
||||||
from OCP.GCPnts import (
|
from OCP.GCPnts import (
|
||||||
GCPnts_AbscissaPoint,
|
GCPnts_AbscissaPoint,
|
||||||
GCPnts_QuasiUniformDeflection,
|
GCPnts_QuasiUniformDeflection,
|
||||||
|
|
@ -151,6 +151,8 @@ from OCP.gp import (
|
||||||
gp_Dir,
|
gp_Dir,
|
||||||
gp_Dir2d,
|
gp_Dir2d,
|
||||||
gp_Elips,
|
gp_Elips,
|
||||||
|
gp_Parab,
|
||||||
|
gp_Hypr,
|
||||||
gp_Pln,
|
gp_Pln,
|
||||||
gp_Pnt,
|
gp_Pnt,
|
||||||
gp_Pnt2d,
|
gp_Pnt2d,
|
||||||
|
|
@ -2066,6 +2068,95 @@ class Edge(Mixin1D[TopoDS_Edge]):
|
||||||
|
|
||||||
return ellipse
|
return ellipse
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def make_parabola(
|
||||||
|
cls,
|
||||||
|
focal_length: float,
|
||||||
|
plane: Plane = Plane.XY,
|
||||||
|
start_angle: float = 0.0,
|
||||||
|
end_angle: float = 90.0,
|
||||||
|
angular_direction: AngularDirection = AngularDirection.COUNTER_CLOCKWISE,
|
||||||
|
) -> Edge:
|
||||||
|
"""make parabola
|
||||||
|
|
||||||
|
Makes an parabola centered at the origin of plane.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
focal_length (float): focal length the parabola (distance from the vertex to focus along the x-axis of plane)
|
||||||
|
plane (Plane, optional): base plane. Defaults to Plane.XY.
|
||||||
|
start_angle (float, optional): Defaults to 0.0.
|
||||||
|
end_angle (float, optional): Defaults to 90.0.
|
||||||
|
angular_direction (AngularDirection, optional): arc direction.
|
||||||
|
Defaults to AngularDirection.COUNTER_CLOCKWISE.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Edge: full or partial parabola
|
||||||
|
"""
|
||||||
|
parabola_gp = gp_Parab(plane.to_gp_ax2(), focal_length)
|
||||||
|
|
||||||
|
parabola_geom = GC_MakeArcOfParabola(
|
||||||
|
parabola_gp,
|
||||||
|
start_angle * DEG2RAD,
|
||||||
|
end_angle * DEG2RAD,
|
||||||
|
angular_direction == AngularDirection.COUNTER_CLOCKWISE,
|
||||||
|
).Value()
|
||||||
|
parabola = cls(BRepBuilderAPI_MakeEdge(parabola_geom).Edge())
|
||||||
|
|
||||||
|
return parabola
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def make_hyperbola(
|
||||||
|
cls,
|
||||||
|
x_radius: float,
|
||||||
|
y_radius: float,
|
||||||
|
plane: Plane = Plane.XY,
|
||||||
|
start_angle: float = 360.0,
|
||||||
|
end_angle: float = 360.0,
|
||||||
|
angular_direction: AngularDirection = AngularDirection.COUNTER_CLOCKWISE,
|
||||||
|
) -> Edge:
|
||||||
|
"""make hyperbola
|
||||||
|
|
||||||
|
Makes a hyperbola centered at the origin of plane.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
x_radius (float): x radius of the hyperbola (along the x-axis of plane)
|
||||||
|
y_radius (float): y radius of the hyperbola (along the y-axis of plane)
|
||||||
|
plane (Plane, optional): base plane. Defaults to Plane.XY.
|
||||||
|
start_angle (float, optional): Defaults to 360.0.
|
||||||
|
end_angle (float, optional): Defaults to 360.0.
|
||||||
|
angular_direction (AngularDirection, optional): arc direction.
|
||||||
|
Defaults to AngularDirection.COUNTER_CLOCKWISE.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Edge: full or partial hyperbola
|
||||||
|
"""
|
||||||
|
ax1 = gp_Ax1(plane.origin.to_pnt(), plane.z_dir.to_dir())
|
||||||
|
|
||||||
|
if y_radius > x_radius:
|
||||||
|
# swap x and y radius and rotate by 90° afterwards to create an ellipse
|
||||||
|
# with x_radius < y_radius
|
||||||
|
correction_angle = 90.0 * DEG2RAD
|
||||||
|
hyperbola_gp = gp_Hypr(plane.to_gp_ax2(), y_radius, x_radius).Rotated(
|
||||||
|
ax1, correction_angle
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
correction_angle = 0.0
|
||||||
|
hyperbola_gp = gp_Hypr(plane.to_gp_ax2(), x_radius, y_radius)
|
||||||
|
|
||||||
|
if start_angle == end_angle: # full hyperbola case
|
||||||
|
hyperbola = cls(BRepBuilderAPI_MakeEdge(hyperbola_gp).Edge())
|
||||||
|
else: # arc case
|
||||||
|
# take correction_angle into account
|
||||||
|
hyperbola_geom = GC_MakeArcOfHyperbola(
|
||||||
|
hyperbola_gp,
|
||||||
|
start_angle * DEG2RAD - correction_angle,
|
||||||
|
end_angle * DEG2RAD - correction_angle,
|
||||||
|
angular_direction == AngularDirection.COUNTER_CLOCKWISE,
|
||||||
|
).Value()
|
||||||
|
hyperbola = cls(BRepBuilderAPI_MakeEdge(hyperbola_geom).Edge())
|
||||||
|
|
||||||
|
return hyperbola
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def make_helix(
|
def make_helix(
|
||||||
cls,
|
cls,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue