Subclassed all the new objects

This commit is contained in:
Roger Maitland 2022-07-03 14:23:49 -04:00
parent 366b7a38f8
commit 6446cb8dbc
2 changed files with 297 additions and 0 deletions

273
build1d_super.py Normal file
View file

@ -0,0 +1,273 @@
from math import pi, sin, cos, radians, sqrt
from typing import Union, Iterable, Sequence, Callable
from enum import Enum, auto
from abc import ABC, abstractmethod
import cadquery as cq
from cadquery.hull import find_hull
from cadquery import (
Edge,
Face,
Wire,
Vector,
Shape,
Location,
Vertex,
Compound,
Solid,
Plane,
)
from cadquery.occ_impl.shapes import VectorLike, Real
import cq_warehouse.extensions
from build123d_common import *
from build2d import Build2D
from build3d import Build3D
class Build1D:
@property
def working_line(self) -> Wire:
return Wire.assembleEdges(self.edge_list)
def __init__(self, mode: Mode = Mode.ADDITION):
self.edge_list = []
self.tags: dict[str, Edge] = {}
self.mode = mode
def __enter__(self):
if "context_stack" in globals():
context_stack.append(self)
else:
globals()["context_stack"] = [self]
return self
def __exit__(self, exception_type, exception_value, traceback):
# if self.parent is not None:
# self.parent.add(*self.edge_list, mode=self.mode)
if "context_stack" in globals():
context_stack.pop()
if context_stack:
context_stack[-1].add(*self.edge_list, mode=self.mode)
def edges(self) -> list[Edge]:
return self.edge_list
def vertices(self) -> list[Vertex]:
vertex_list = []
for e in self.edge_list:
vertex_list.extend(e.Vertices())
return list(set(vertex_list))
@staticmethod
def add_to_context(*edges: Edge, mode: Mode = Mode.ADDITION):
if "context_stack" in globals() and mode != Mode.PRIVATE:
if context_stack: # Stack isn't empty
for edge in edges:
edge.forConstruction = mode == Mode.CONSTRUCTION
if not isinstance(edge, Edge):
raise ValueError("Build1D.add only accepts edges")
context_stack[-1].edge_list.append(edge)
class Line(Edge):
def __init__(self, *pts: VectorLike, mode: Mode = Mode.ADDITION):
if len(pts) != 2:
raise ValueError("Line requires two pts")
lines_pts = [Vector(p) for p in pts]
new_edge = Edge.makeLine(lines_pts[0], lines_pts[1])
Build1D.add_to_context(new_edge, mode=mode)
super().__init__(new_edge.wrapped)
class Polyline(Wire):
def __init__(self, *pts: VectorLike, mode: Mode = Mode.ADDITION):
if len(pts) < 3:
raise ValueError("polyline requires three or more pts")
lines_pts = [Vector(p) for p in pts]
new_edges = [
Edge.makeLine(lines_pts[i], lines_pts[i + 1])
for i in range(len(lines_pts) - 1)
]
Build1D.add_to_context(*new_edges, mode=mode)
super().__init__(Wire.assembleEdges(new_edges).wrapped)
class Spline(Edge):
def __init__(
self,
*pts: VectorLike,
tangents: Iterable[VectorLike] = None,
tangent_scalars: Iterable[float] = None,
periodic: bool = False,
mode: Mode = Mode.ADDITION,
):
spline_pts = [Vector(pt) for pt in pts]
if tangents:
spline_tangents = [Vector(tangent) for tangent in tangents]
else:
spline_tangents = None
if tangents and not tangent_scalars:
scalars = [1.0] * len(tangents)
else:
scalars = tangent_scalars
spline = Edge.makeSpline(
[p if isinstance(p, Vector) else Vector(*p) for p in spline_pts],
tangents=[
t * s if isinstance(t, Vector) else Vector(*t) * s
for t, s in zip(spline_tangents, scalars)
]
if spline_tangents
else None,
periodic=periodic,
scale=tangent_scalars is None,
)
Build1D.add_to_context(spline, mode=mode)
super().__init__(spline.wrapped)
class CenterArc(Edge):
def __init__(
self,
center: VectorLike,
radius: float,
start_angle: float,
arc_size: float,
mode: Mode = Mode.ADDITION,
):
if abs(arc_size) >= 360:
arc = Edge.makeCircle(
radius,
center,
angle1=start_angle,
angle2=start_angle,
orientation=arc_size > 0,
)
else:
p0 = center
p1 = p0 + radius * Vector(
cos(radians(start_angle)), sin(radians(start_angle))
)
p2 = p0 + radius * Vector(
cos(radians(start_angle + arc_size / 2)),
sin(radians(start_angle + arc_size / 2)),
)
p3 = p0 + radius * Vector(
cos(radians(start_angle + arc_size)),
sin(radians(start_angle + arc_size)),
)
arc = Edge.makeThreePointArc(p1, p2, p3)
Build1D.add_to_context(arc, mode=mode)
super().__init__(arc.wrapped)
class ThreePointArc(Edge):
def __init__(self, *pts: VectorLike, mode: Mode = Mode.ADDITION):
if len(pts) != 3:
raise ValueError("ThreePointArc requires three points")
points = [Vector(p) for p in pts]
arc = Edge.makeThreePointArc(*points)
Build1D.add_to_context(arc, mode=mode)
super().__init__(arc.wrapped)
class TangentArc(Edge):
def __init__(
self,
*pts: VectorLike,
tangent: VectorLike,
tangent_from_first: bool = True,
mode: Mode = Mode.ADDITION,
):
arc_pts = [Vector(p) for p in pts]
if len(arc_pts) != 2:
raise ValueError("tangent_arc requires two points")
arc_tangent = Vector(tangent)
point_indices = (0, -1) if tangent_from_first else (-1, 0)
arc = Edge.makeTangentArc(
arc_pts[point_indices[0]], arc_tangent, arc_pts[point_indices[1]]
)
Build1D.add_to_context(arc, mode=mode)
super().__init__(arc.wrapped)
class RadiusArc(Edge):
def __init__(
self,
start_point: VectorLike,
end_point: VectorLike,
radius: float,
mode: Mode = Mode.ADDITION,
):
start = Vector(start_point)
end = Vector(end_point)
# Calculate the sagitta from the radius
length = end.sub(start).Length / 2.0
try:
sagitta = abs(radius) - sqrt(radius**2 - length**2)
except ValueError:
raise ValueError("Arc radius is not large enough to reach the end point.")
# Return a sagitta arc
if radius > 0:
arc = SagittaArc(start, end, sagitta, mode=Mode.PRIVATE)
else:
arc = SagittaArc(start, end, -sagitta, mode=Mode.PRIVATE)
Build1D.add_to_context(arc, mode=mode)
super().__init__(arc.wrapped)
class SagittaArc(Edge):
def __init__(
self,
start_point: VectorLike,
end_point: VectorLike,
sagitta: float,
mode: Mode = Mode.ADDITION,
):
start = Vector(start_point)
end = Vector(end_point)
mid_point = (end + start) * 0.5
sagitta_vector = (end - start).normalized() * abs(sagitta)
if sagitta > 0:
sagitta_vector.x, sagitta_vector.y = (
-sagitta_vector.y,
sagitta_vector.x,
) # Rotate sagitta_vector +90 deg
else:
sagitta_vector.x, sagitta_vector.y = (
sagitta_vector.y,
-sagitta_vector.x,
) # Rotate sagitta_vector -90 deg
sag_point = mid_point + sagitta_vector
arc = ThreePointArc(start, sag_point, end, mode=Mode.PRIVATE)
Build1D.add_to_context(arc, mode=mode)
super().__init__(arc.wrapped)
class MirrorX:
def __init__(self, *edges: Edge, mode: Mode = Mode.ADDITION):
mirrored_edges = Plane.named("XY").mirrorInPlane(edges, axis="X")
Build1D.add_to_context(*mirrored_edges, mode=mode)
class MirrorY:
def __init__(self, *edges: Edge, mode: Mode = Mode.ADDITION):
mirrored_edges = Plane.named("XY").mirrorInPlane(edges, axis="Y")
Build1D.add_to_context(*mirrored_edges, mode=mode)

24
build1d_super_test.py Normal file
View file

@ -0,0 +1,24 @@
from cadquery import Vector
from build123d_common import *
from build1d_super import *
with Build1D() as ml:
l1 = Polyline((0.0000, 0.0771), (0.0187, 0.0771), (0.0094, 0.2569))
print(f"{type(l1)=}")
l2 = Polyline((0.0325, 0.2773), (0.2115, 0.2458), (0.1873, 0.3125))
RadiusArc(l1 @ 1, l2 @ 0, 0.0271)
l3 = Polyline((0.1915, 0.3277), (0.3875, 0.4865), (0.3433, 0.5071))
TangentArc(l2 @ 1, l3 @ 0, tangent=l2 % 1)
l4 = Polyline((0.3362, 0.5235), (0.375, 0.6427), (0.2621, 0.6188))
SagittaArc(l3 @ 1, l4 @ 0, 0.003)
l5 = Polyline((0.2469, 0.6267), (0.225, 0.6781), (0.1369, 0.5835))
ThreePointArc(l4 @ 1, (l4 @ 1 + l5 @ 0) * 0.5 + Vector(-0.002, -0.002), l5 @ 0)
l6 = Polyline((0.1138, 0.5954), (0.1562, 0.8146), (0.0881, 0.7752))
Spline(l5 @ 1, l6 @ 0, tangents=(l5 % 1, l6 % 0), tangent_scalars=(2, 2))
l7 = Line((0.0692, 0.7808), (0.0000, 0.9167))
TangentArc(l6 @ 1, l7 @ 0, tangent=l6 % 1)
MirrorY(*ml.edges())
if "show_object" in locals():
show_object(ml.edge_list, "maple leaf")