Reformatted with black 24.2.0

This commit is contained in:
gumyr 2024-02-22 11:27:01 -05:00
parent 82d5f7a8c1
commit 2e81b9d5df
43 changed files with 261 additions and 157 deletions

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby challenge 23-T-24 CURVED SUPPORT Too Tall Toby challenge 23-T-24 CURVED SUPPORT
""" """
from math import sin, cos, tan, radians from math import sin, cos, tan, radians
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby Party Pack 01-01 Bearing Bracket Too Tall Toby Party Pack 01-01 Bearing Bracket
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby Party Pack 01-02 Post Cap Too Tall Toby Party Pack 01-02 Post Cap
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby Party Pack 01-03 C Clamp Base Too Tall Toby Party Pack 01-03 C Clamp Base
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby Party Pack 01-04 Angle Bracket Too Tall Toby Party Pack 01-04 Angle Bracket
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby Party Pack 01-05 Paste Sleeve Too Tall Toby Party Pack 01-05 Paste Sleeve
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby Party Pack 01-06 Bearing Jig Too Tall Toby Party Pack 01-06 Bearing Jig
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby Party Pack 01-07 Flanged Hub Too Tall Toby Party Pack 01-07 Flanged Hub
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby Party Pack 01-08 Tie Plate Too Tall Toby Party Pack 01-08 Tie Plate
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby Party Pack 01-09 Corner Tie Too Tall Toby Party Pack 01-09 Corner Tie
""" """
from math import sqrt from math import sqrt
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,6 +1,7 @@
""" """
Too Tall Toby Party Pack 01-10 Light Cap Too Tall Toby Party Pack 01-10 Light Cap
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -26,6 +26,7 @@ license:
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
""" """
from build123d import * from build123d import *

View file

@ -26,6 +26,7 @@ license:
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
""" """
from build123d import * from build123d import *

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
from build123d import * from build123d import *
exporter = ExportSVG(scale=1) exporter = ExportSVG(scale=1)

View file

@ -24,6 +24,7 @@ license:
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
""" """
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -24,6 +24,7 @@ license:
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
""" """
# [import] # [import]
from build123d import * from build123d import *
from ocp_vscode import * from ocp_vscode import *

View file

@ -1,4 +1,5 @@
"""scm version""" """scm version"""
import os.path as pth import os.path as pth
try: try:

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
from __future__ import annotations from __future__ import annotations
from typing import Union from typing import Union

View file

@ -28,6 +28,7 @@ license:
limitations under the License. limitations under the License.
""" """
from __future__ import annotations from __future__ import annotations
from typing import Union from typing import Union

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
from __future__ import annotations from __future__ import annotations
from typing import Union from typing import Union

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
from dataclasses import dataclass from dataclasses import dataclass
from datetime import date from datetime import date
from math import copysign, floor, gcd, log2, pi from math import copysign, floor, gcd, log2, pi
@ -177,6 +178,7 @@ class Draft:
Defaults to 2.0. Defaults to 2.0.
""" """
# pylint: disable=too-many-instance-attributes # pylint: disable=too-many-instance-attributes
# Class Attributes # Class Attributes

View file

@ -26,7 +26,6 @@ license:
""" """
# pylint has trouble with the OCP imports # pylint has trouble with the OCP imports
# pylint: disable=no-name-in-module, import-error # pylint: disable=no-name-in-module, import-error
# pylint: disable=too-many-lines # pylint: disable=too-many-lines

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
# pylint has trouble with the OCP imports # pylint has trouble with the OCP imports
# pylint: disable=no-name-in-module, import-error # pylint: disable=no-name-in-module, import-error

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
from __future__ import annotations from __future__ import annotations
from math import inf from math import inf

View file

@ -22,6 +22,7 @@ license:
limitations under the License. limitations under the License.
""" """
# pylint: disable=no-name-in-module # pylint: disable=no-name-in-module
from json import dumps from json import dumps
from typing import Any, Dict, List from typing import Any, Dict, List
@ -220,12 +221,14 @@ def display(shape: Any) -> Javascript:
if not hasattr(shape, "wrapped"): # Is a "Shape" if not hasattr(shape, "wrapped"): # Is a "Shape"
raise ValueError(f"Type {type(shape)} is not supported") raise ValueError(f"Type {type(shape)} is not supported")
payload.append({ payload.append(
{
"shape": to_vtkpoly_string(shape), "shape": to_vtkpoly_string(shape),
"color": DEFAULT_COLOR, "color": DEFAULT_COLOR,
"position": [0, 0, 0], "position": [0, 0, 0],
"orientation": [0, 0, 0], "orientation": [0, 0, 0],
}) }
)
code = TEMPLATE.format(data=dumps(payload), element="element", ratio=0.5) code = TEMPLATE.format(data=dumps(payload), element="element", ratio=0.5)
return Javascript(code) return Javascript(code)

View file

@ -78,6 +78,7 @@ license:
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
""" """
# pylint has trouble with the OCP imports # pylint has trouble with the OCP imports
# pylint: disable=no-name-in-module, import-error # pylint: disable=no-name-in-module, import-error
import copy import copy

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
from __future__ import annotations from __future__ import annotations
import copy import copy
@ -814,12 +815,14 @@ class Spline(BaseLineObject):
spline = Edge.make_spline( spline = Edge.make_spline(
[p if isinstance(p, Vector) else Vector(*p) for p in spline_pts], [p if isinstance(p, Vector) else Vector(*p) for p in spline_pts],
tangents=[ tangents=(
[
t * s if isinstance(t, Vector) else Vector(*t) * s t * s if isinstance(t, Vector) else Vector(*t) * s
for t, s in zip(spline_tangents, scalars) for t, s in zip(spline_tangents, scalars)
] ]
if spline_tangents if spline_tangents
else None, else None
),
periodic=periodic, periodic=periodic,
scale=tangent_scalars is None, scale=tangent_scalars is None,
) )

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
from __future__ import annotations from __future__ import annotations
from math import radians, tan from math import radians, tan

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
from __future__ import annotations from __future__ import annotations
import trianglesolver import trianglesolver

View file

@ -26,6 +26,7 @@ license:
limitations under the License. limitations under the License.
""" """
import copy import copy
import logging import logging
from math import radians, tan, isclose from math import radians, tan, isclose

View file

@ -16,9 +16,12 @@ from typing import Callable, Collection, Optional, cast
from build123d import Location, Shape from build123d import Location, Shape
def _pack2d(objects: Collection[object],
def _pack2d(
objects: Collection[object],
width_fn: Callable[[object], float], width_fn: Callable[[object], float],
length_fn: Callable[[object], float]) -> Collection[tuple[float,float]]: length_fn: Callable[[object], float],
) -> Collection[tuple[float, float]]:
"""Takes an iterable of objects to pack into a square(ish) 2D """Takes an iterable of objects to pack into a square(ish) 2D
arrangement, and return a list of (x,y) locations to place each to arrangement, and return a list of (x,y) locations to place each to
achieve the packing. achieve the packing.
@ -69,23 +72,40 @@ def _pack2d(objects: Collection[object],
def grow_right(w, h): def grow_right(w, h):
nonlocal root nonlocal root
root = _Node(used=True, x=0, y=0, w=root.w+w, h=root.h, root = _Node(
down=root, right=_Node(x=root.w, w=w, h=root.h)) used=True,
x=0,
y=0,
w=root.w + w,
h=root.h,
down=root,
right=_Node(x=root.w, w=w, h=root.h),
)
node = find_node(root, w, h) node = find_node(root, w, h)
assert node, "Failed to grow right! root: {root}, w: {w}, h: {h}" assert node, "Failed to grow right! root: {root}, w: {w}, h: {h}"
return split_node(node, w, h) return split_node(node, w, h)
def grow_down(w, h): def grow_down(w, h):
nonlocal root nonlocal root
root = _Node(used=True, x=0, y=0, w=root.w, h=root.h+h, root = _Node(
down=_Node(y=root.h, w=root.w, h=h), right=root) used=True,
x=0,
y=0,
w=root.w,
h=root.h + h,
down=_Node(y=root.h, w=root.w, h=h),
right=root,
)
node = find_node(root, w, h) node = find_node(root, w, h)
assert node, "Failed to grow down! root: {root}, w: {w}, h: {h}" assert node, "Failed to grow down! root: {root}, w: {w}, h: {h}"
return split_node(node, w, h) return split_node(node, w, h)
assert len(objects) > 0 assert len(objects) > 0
sorted_objects = sorted([(i, width_fn(o), length_fn(o)) for (i, o) in enumerate(objects)], sorted_objects = sorted(
key=lambda d: min(d[1], d[2]), reverse=True) [(i, width_fn(o), length_fn(o)) for (i, o) in enumerate(objects)],
key=lambda d: min(d[1], d[2]),
reverse=True,
)
sorted_objects = sorted(sorted_objects, key=lambda d: max(d[1], d[2]), reverse=True) sorted_objects = sorted(sorted_objects, key=lambda d: max(d[1], d[2]), reverse=True)
root = _Node(False, w=sorted_objects[0][1], h=sorted_objects[0][2]) root = _Node(False, w=sorted_objects[0][1], h=sorted_objects[0][2])
translations = [] translations = []
@ -98,13 +118,15 @@ def _pack2d(objects: Collection[object],
translations.append((o[0], node.x, node.y)) translations.append((o[0], node.x, node.y))
return [(t[1], t[2]) for t in sorted(translations, key=lambda t: t[0])] return [(t[1], t[2]) for t in sorted(translations, key=lambda t: t[0])]
def pack(objects: Collection[Shape], padding: float) -> Collection[Shape]: def pack(objects: Collection[Shape], padding: float) -> Collection[Shape]:
"""Pack objects in a squarish area in Plane.XY.""" """Pack objects in a squarish area in Plane.XY."""
bounding_boxes = {o: o.bounding_box().size + (padding, padding) for o in objects} bounding_boxes = {o: o.bounding_box().size + (padding, padding) for o in objects}
translations = _pack2d( translations = _pack2d(
objects, objects,
width_fn=lambda o: bounding_boxes[cast(Shape, o)].X, width_fn=lambda o: bounding_boxes[cast(Shape, o)].X,
length_fn=lambda o: bounding_boxes[cast(Shape, o)].Y) length_fn=lambda o: bounding_boxes[cast(Shape, o)].Y,
)
translated = [ translated = [
Location((t[0] - o.bounding_box().min.X, t[1] - o.bounding_box().min.Y, 0)) * o Location((t[0] - o.bounding_box().min.X, t[1] - o.bounding_box().min.Y, 0)) * o
for (o, t) in zip(objects, translations) for (o, t) in zip(objects, translations)
@ -118,8 +140,11 @@ def pack(objects: Collection[Shape], padding: float) -> Collection[Shape]:
max_x = min(bb1.max.X, bb2.max.X) max_x = min(bb1.max.X, bb2.max.X)
max_y = min(bb1.max.Y, bb2.max.Y) max_y = min(bb1.max.Y, bb2.max.Y)
return max_x > min_x and max_y > min_y return max_x > min_x and max_y > min_y
bb = [t.bounding_box() for t in translated] bb = [t.bounding_box() for t in translated]
for (i, bb_i) in enumerate(bb): for i, bb_i in enumerate(bb):
for (j, bb_j) in enumerate(bb[i+1:]): for j, bb_j in enumerate(bb[i + 1 :]):
assert not _overlapping(bb_i, bb_j), f"Objects at indexes {i} and {j} overlap!" assert not _overlapping(
bb_i, bb_j
), f"Objects at indexes {i} and {j} overlap!"
return translated return translated

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
# pylint has trouble with the OCP imports # pylint has trouble with the OCP imports
# pylint: disable=no-name-in-module, import-error # pylint: disable=no-name-in-module, import-error

View file

@ -563,9 +563,9 @@ class Mixin1D:
for line in all_lines: for line in all_lines:
num_points = 2 if line.geom_type == GeomType.LINE else 8 num_points = 2 if line.geom_type == GeomType.LINE else 8
points.extend([ points.extend(
line.position_at(i / (num_points - 1)) for i in range(num_points) [line.position_at(i / (num_points - 1)) for i in range(num_points)]
]) )
points = list(set(points)) # unique points points = list(set(points)) # unique points
extreme_areas = {} extreme_areas = {}
for subset in combinations(points, 3): for subset in combinations(points, 3):
@ -2068,9 +2068,9 @@ class Shape(NodeMixin):
def vertices(self) -> ShapeList[Vertex]: def vertices(self) -> ShapeList[Vertex]:
"""vertices - all the vertices in this Shape""" """vertices - all the vertices in this Shape"""
vertex_list = ShapeList([ vertex_list = ShapeList(
Vertex(downcast(i)) for i in self._entities(Vertex.__name__) [Vertex(downcast(i)) for i in self._entities(Vertex.__name__)]
]) )
for vertex in vertex_list: for vertex in vertex_list:
vertex.topo_parent = self vertex.topo_parent = self
return vertex_list return vertex_list
@ -2085,11 +2085,13 @@ class Shape(NodeMixin):
def edges(self) -> ShapeList[Edge]: def edges(self) -> ShapeList[Edge]:
"""edges - all the edges in this Shape""" """edges - all the edges in this Shape"""
edge_list = ShapeList([ edge_list = ShapeList(
[
Edge(i) Edge(i)
for i in self._entities(Edge.__name__) for i in self._entities(Edge.__name__)
if not BRep_Tool.Degenerated_s(TopoDS.Edge_s(i)) if not BRep_Tool.Degenerated_s(TopoDS.Edge_s(i))
]) ]
)
for edge in edge_list: for edge in edge_list:
edge.topo_parent = self edge.topo_parent = self
return edge_list return edge_list
@ -2637,10 +2639,12 @@ class Shape(NodeMixin):
distance = axis.position.to_pnt().SquareDistance(inter_pt) distance = axis.position.to_pnt().SquareDistance(inter_pt)
faces_dist.append(( faces_dist.append(
(
intersect_maker.Face(), intersect_maker.Face(),
abs(distance), abs(distance),
)) # will sort all intersected faces by distance whatever the direction is )
) # will sort all intersected faces by distance whatever the direction is
intersect_maker.Next() intersect_maker.Next()
@ -2950,11 +2954,13 @@ class Shape(NodeMixin):
inter_pt = intersect_maker.Pnt() inter_pt = intersect_maker.Pnt()
# Calculate distance along axis # Calculate distance along axis
distance = axis.to_plane().to_local_coords(Vector(inter_pt)).Z distance = axis.to_plane().to_local_coords(Vector(inter_pt)).Z
intersections.append(( intersections.append(
(
Face(intersect_maker.Face()), Face(intersect_maker.Face()),
Vector(inter_pt), Vector(inter_pt),
distance, distance,
)) )
)
intersect_maker.Next() intersect_maker.Next()
intersections.sort(key=lambda x: x[2]) intersections.sort(key=lambda x: x[2])
@ -3713,12 +3719,12 @@ class GroupBy(Generic[T, K]):
def _repr_pretty_(self, p, cycle=False): def _repr_pretty_(self, p, cycle=False):
if cycle: if cycle:
p.text('(...)') p.text("(...)")
else: else:
with p.group(1, '[', ']'): with p.group(1, "[", "]"):
for idx, item in enumerate(self): for idx, item in enumerate(self):
if idx: if idx:
p.text(',') p.text(",")
p.breakable() p.breakable()
p.pretty(item) p.pretty(item)
@ -3807,7 +3813,8 @@ class Compound(Mixin3D, Shape):
) * (7 - l_a) ) * (7 - l_a)
unknown_args = ", ".join( unknown_args = ", ".join(
set(kwargs.keys()).difference([ set(kwargs.keys()).difference(
[
"shapes", "shapes",
"obj", "obj",
"label", "label",
@ -3816,7 +3823,8 @@ class Compound(Mixin3D, Shape):
"joints", "joints",
"parent", "parent",
"children", "children",
]) ]
)
) )
if unknown_args: if unknown_args:
raise ValueError(f"Unexpected argument(s) {unknown_args}") raise ValueError(f"Unexpected argument(s) {unknown_args}")
@ -3939,9 +3947,9 @@ class Compound(Mixin3D, Shape):
"""Method call after detaching from `parent`.""" """Method call after detaching from `parent`."""
logger.debug("Removing parent of %s (%s)", self.label, parent.label) logger.debug("Removing parent of %s (%s)", self.label, parent.label)
if parent.children: if parent.children:
parent.wrapped = Compound._make_compound([ parent.wrapped = Compound._make_compound(
c.wrapped for c in parent.children [c.wrapped for c in parent.children]
]) )
else: else:
parent.wrapped = None parent.wrapped = None
@ -5162,14 +5170,16 @@ class Face(Shape):
) )
unknown_args = ", ".join( unknown_args = ", ".join(
set(kwargs.keys()).difference([ set(kwargs.keys()).difference(
[
"outer_wire", "outer_wire",
"inner_wires", "inner_wires",
"obj", "obj",
"label", "label",
"color", "color",
"parent", "parent",
]) ]
)
) )
if unknown_args: if unknown_args:
raise ValueError(f"Unexpected argument(s) {unknown_args}") raise ValueError(f"Unexpected argument(s) {unknown_args}")
@ -5233,16 +5243,18 @@ class Face(Shape):
if len(flat_face_edges) == 4: if len(flat_face_edges) == 4:
edge_pairs = [] edge_pairs = []
for vertex in flat_face_vertices: for vertex in flat_face_vertices:
edge_pairs.append([ edge_pairs.append(
e for e in flat_face_edges if vertex in e.vertices() [e for e in flat_face_edges if vertex in e.vertices()]
]) )
edge_pair_directions = [ edge_pair_directions = [
[edge.tangent_at(0) for edge in pair] for pair in edge_pairs [edge.tangent_at(0) for edge in pair] for pair in edge_pairs
] ]
if all([ if all(
[
edge_directions[0].get_angle(edge_directions[1]) == 90 edge_directions[0].get_angle(edge_directions[1]) == 90
for edge_directions in edge_pair_directions for edge_directions in edge_pair_directions
]): ]
):
result = "RECTANGLE" result = "RECTANGLE"
if len(flat_face_edges.group_by(SortBy.LENGTH)) == 1: if len(flat_face_edges.group_by(SortBy.LENGTH)) == 1:
result = "SQUARE" result = "SQUARE"
@ -5721,9 +5733,9 @@ class Face(Shape):
) )
if isinstance(exterior, Wire): if isinstance(exterior, Wire):
outside_edges = exterior.edges() outside_edges = exterior.edges()
elif isinstance(exterior, Iterable) and all([ elif isinstance(exterior, Iterable) and all(
isinstance(o, Edge) for o in exterior [isinstance(o, Edge) for o in exterior]
]): ):
outside_edges = exterior outside_edges = exterior
else: else:
raise ValueError("exterior must be a Wire or list of Edges") raise ValueError("exterior must be a Wire or list of Edges")
@ -6104,14 +6116,16 @@ class Shell(Shape):
faces, label, color, parent = args[:4] + (None,) * (4 - l_a) faces, label, color, parent = args[:4] + (None,) * (4 - l_a)
unknown_args = ", ".join( unknown_args = ", ".join(
set(kwargs.keys()).difference([ set(kwargs.keys()).difference(
[
"face", "face",
"faces", "faces",
"obj", "obj",
"label", "label",
"color", "color",
"parent", "parent",
]) ]
)
) )
if unknown_args: if unknown_args:
raise ValueError(f"Unexpected argument(s) {unknown_args}") raise ValueError(f"Unexpected argument(s) {unknown_args}")
@ -6246,7 +6260,8 @@ class Solid(Mixin3D, Shape):
) )
unknown_args = ", ".join( unknown_args = ", ".join(
set(kwargs.keys()).difference([ set(kwargs.keys()).difference(
[
"shell", "shell",
"obj", "obj",
"label", "label",
@ -6254,7 +6269,8 @@ class Solid(Mixin3D, Shape):
"material", "material",
"joints", "joints",
"parent", "parent",
]) ]
)
) )
if unknown_args: if unknown_args:
raise ValueError(f"Unexpected argument(s) {unknown_args}") raise ValueError(f"Unexpected argument(s) {unknown_args}")
@ -6673,9 +6689,9 @@ class Solid(Mixin3D, Shape):
# make an auxiliary spine # make an auxiliary spine
pitch = 360.0 / angle * normal.length pitch = 360.0 / angle * normal.length
aux_spine_w = Wire([ aux_spine_w = Wire(
Edge.make_helix(pitch, normal.length, 1, center=center, normal=normal) [Edge.make_helix(pitch, normal.length, 1, center=center, normal=normal)]
]).wrapped ).wrapped
# extrude the outer wire # extrude the outer wire
outer_solid = extrude_aux_spine( outer_solid = extrude_aux_spine(
@ -7270,7 +7286,8 @@ class Wire(Mixin1D, Shape):
edges, sequenced, label, color, parent = args[:5] + (None,) * (5 - l_a) edges, sequenced, label, color, parent = args[:5] + (None,) * (5 - l_a)
unknown_args = ", ".join( unknown_args = ", ".join(
set(kwargs.keys()).difference([ set(kwargs.keys()).difference(
[
"curve", "curve",
"wire", "wire",
"edge", "edge",
@ -7280,7 +7297,8 @@ class Wire(Mixin1D, Shape):
"label", "label",
"color", "color",
"parent", "parent",
]) ]
)
) )
if unknown_args: if unknown_args:
raise ValueError(f"Unexpected argument(s) {unknown_args}") raise ValueError(f"Unexpected argument(s) {unknown_args}")
@ -7492,10 +7510,12 @@ class Wire(Mixin1D, Shape):
# Select the wire containing the start and end points # Select the wire containing the start and end points
wire_segments = edges_to_wires(modified_edges + unmodified_edges) wire_segments = edges_to_wires(modified_edges + unmodified_edges)
trimmed_wire = filter( trimmed_wire = filter(
lambda w: all([ lambda w: all(
[
w.distance_to(p) <= TOLERANCE w.distance_to(p) <= TOLERANCE
for p in [trim_start_point, trim_end_point] for p in [trim_start_point, trim_end_point]
]), ]
),
wire_segments, wire_segments,
) )
try: try:
@ -7833,10 +7853,12 @@ class Wire(Mixin1D, Shape):
trim_points[edge1] = [simplice[1]] trim_points[edge1] = [simplice[1]]
else: else:
trim_points[edge1].append(simplice[1]) trim_points[edge1].append(simplice[1])
connecting_edge_data.append(( connecting_edge_data.append(
(
(edge0, points_lookup[simplice[0]][1], simplice[0]), (edge0, points_lookup[simplice[0]][1], simplice[0]),
(edge1, points_lookup[simplice[1]][1], simplice[1]), (edge1, points_lookup[simplice[1]][1], simplice[1]),
)) )
)
# Look for connecting edges within an edge # Look for connecting edges within an edge
elif abs(simplice[0] - simplice[1]) != 1: elif abs(simplice[0] - simplice[1]) != 1:
start_pnt = min(simplice.tolist()) start_pnt = min(simplice.tolist())
@ -7845,10 +7867,12 @@ class Wire(Mixin1D, Shape):
trim_points[edge0] = [start_pnt, end_pnt] trim_points[edge0] = [start_pnt, end_pnt]
else: else:
trim_points[edge0].extend([start_pnt, end_pnt]) trim_points[edge0].extend([start_pnt, end_pnt])
connecting_edge_data.append(( connecting_edge_data.append(
(
(edge0, points_lookup[start_pnt][1], start_pnt), (edge0, points_lookup[start_pnt][1], start_pnt),
(edge0, points_lookup[end_pnt][1], end_pnt), (edge0, points_lookup[end_pnt][1], end_pnt),
)) )
)
trim_data = {} trim_data = {}
for edge, points in trim_points.items(): for edge, points in trim_points.items():
@ -7956,15 +7980,19 @@ class Wire(Mixin1D, Shape):
output_wire_center - planar_wire_center output_wire_center - planar_wire_center
).normalized() ).normalized()
if output_wire_direction.dot(direction_vector) >= 0: if output_wire_direction.dot(direction_vector) >= 0:
output_wires_distances.append(( output_wires_distances.append(
(
output_wire, output_wire,
(output_wire_center - planar_wire_center).length, (output_wire_center - planar_wire_center).length,
)) )
)
else: else:
output_wires_distances.append(( output_wires_distances.append(
(
output_wire, output_wire,
(output_wire_center - center_point).length, (output_wire_center - center_point).length,
)) )
)
output_wires_distances.sort(key=lambda x: x[1]) output_wires_distances.sort(key=lambda x: x[1])
logger.debug( logger.debug(

View file

@ -1,6 +1,7 @@
""" """
Export a version string. Export a version string.
""" """
try: try:
try: try:
from ._dev.scm_version import version # pylint: disable=unused-import from ._dev.scm_version import version # pylint: disable=unused-import

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
import unittest import unittest
from math import pi from math import pi
from build123d import * from build123d import *

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
import unittest import unittest
from build123d import * from build123d import *

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
import unittest import unittest
from math import pi, sqrt from math import pi, sqrt
from build123d import * from build123d import *

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
import unittest import unittest
from math import sqrt, pi from math import sqrt, pi
from build123d import * from build123d import *

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
import unittest import unittest
from math import pi, sin from math import pi, sin
from build123d import * from build123d import *
@ -470,9 +471,7 @@ class TestThicken(unittest.TestCase):
non_planar = Sphere(1).faces()[0] non_planar = Sphere(1).faces()[0]
outer_sphere = thicken(non_planar, amount=0.1) outer_sphere = thicken(non_planar, amount=0.1)
self.assertAlmostEqual( self.assertAlmostEqual(outer_sphere.volume, (4 / 3) * pi * (1.1**3 - 1**3), 5)
outer_sphere.volume, (4 / 3) * pi * (1.1**3 - 1**3), 5
)
class TestTorus(unittest.TestCase): class TestTorus(unittest.TestCase):

View file

@ -3008,7 +3008,9 @@ class TestShapeList(DirectApiTestCase):
" [<build123d.topology.Edge object at 0x000001277FC86F90>," " [<build123d.topology.Edge object at 0x000001277FC86F90>,"
" <build123d.topology.Edge object at 0x000001277F6E1CD0>]]" " <build123d.topology.Edge object at 0x000001277F6E1CD0>]]"
) )
self.assertDunderReprEqual(repr(nonagon.edges().group_by(Axis.X)),expected_repr) self.assertDunderReprEqual(
repr(nonagon.edges().group_by(Axis.X)), expected_repr
)
f = io.StringIO() f = io.StringIO()
p = pretty.PrettyPrinter(f) p = pretty.PrettyPrinter(f)

View file

@ -25,6 +25,7 @@ license:
limitations under the License. limitations under the License.
""" """
import math import math
import unittest import unittest
from datetime import date from datetime import date
@ -101,7 +102,6 @@ def create_test_sketch() -> tuple[Sketch, Sketch, Sketch]:
class TestClassInstantiation(unittest.TestCase): class TestClassInstantiation(unittest.TestCase):
"""Test Draft class instantiation""" """Test Draft class instantiation"""
def test_draft_instantiation(self): def test_draft_instantiation(self):

View file

@ -26,6 +26,7 @@ license:
limitations under the License. limitations under the License.
""" """
import copy import copy
import unittest import unittest

View file

@ -7,6 +7,7 @@ date: November 9th 2023
desc: Unit tests for the build123d pack module desc: Unit tests for the build123d pack module
""" """
import operator import operator
import random import random
import unittest import unittest
@ -14,8 +15,10 @@ from functools import reduce
from build123d import * from build123d import *
class TestPack(unittest.TestCase): class TestPack(unittest.TestCase):
"""Tests for the pack helper.""" """Tests for the pack helper."""
def test_simple(self): def test_simple(self):
"""Test pack with hand-picked data against expected output.""" """Test pack with hand-picked data against expected output."""
packed = pack([Box(10, 2, 1), Box(1, 5, 1), Box(1, 5, 1)], padding=1) packed = pack([Box(10, 2, 1), Box(1, 5, 1), Box(1, 5, 1)], padding=1)
@ -27,32 +30,39 @@ class TestPack(unittest.TestCase):
"[bbox: 0.0 <= x <= 10.0, 0.0 <= y <= 2.0, -0.5 <= z <= 0.5," "[bbox: 0.0 <= x <= 10.0, 0.0 <= y <= 2.0, -0.5 <= z <= 0.5,"
" bbox: 0.0 <= x <= 1.0, 3.0 <= y <= 8.0, -0.5 <= z <= 0.5," " bbox: 0.0 <= x <= 1.0, 3.0 <= y <= 8.0, -0.5 <= z <= 0.5,"
" bbox: 2.0 <= x <= 3.0, 3.0 <= y <= 8.0, -0.5 <= z <= 0.5]", " bbox: 2.0 <= x <= 3.0, 3.0 <= y <= 8.0, -0.5 <= z <= 0.5]",
str([p.bounding_box() for p in packed])) str([p.bounding_box() for p in packed]),
)
def test_random_boxes(self): def test_random_boxes(self):
"""Test pack with larger (and randomized) inputs.""" """Test pack with larger (and randomized) inputs."""
random.seed(123456) random.seed(123456)
# 50 is an arbitrary number that is large enough to exercise # 50 is an arbitrary number that is large enough to exercise
# different aspects of the packer while still completing quickly. # different aspects of the packer while still completing quickly.
test_boxes = [Box(random.randint(1, 20), random.randint(1, 20), 1) test_boxes = [
for _ in range(50)] Box(random.randint(1, 20), random.randint(1, 20), 1) for _ in range(50)
]
# Not raising in this call shows successfull non-overlap. # Not raising in this call shows successfull non-overlap.
packed = pack(test_boxes, 1) packed = pack(test_boxes, 1)
self.assertEqual( self.assertEqual(
"bbox: 0.0 <= x <= 94.0, 0.0 <= y <= 86.0, -0.5 <= z <= 0.5", "bbox: 0.0 <= x <= 94.0, 0.0 <= y <= 86.0, -0.5 <= z <= 0.5",
str((Part() + packed).bounding_box())) str((Part() + packed).bounding_box()),
)
def test_random_slots(self): def test_random_slots(self):
"""Test pack for 2D objects.""" """Test pack for 2D objects."""
random.seed(123456) random.seed(123456)
# 50 is an arbitrary number that is large enough to exercise # 50 is an arbitrary number that is large enough to exercise
# different aspects of the packer while still completing quickly. # different aspects of the packer while still completing quickly.
inputs = [SlotOverall(random.randint(1,20), random.randint(1,20)) for _ in range(50)] inputs = [
SlotOverall(random.randint(1, 20), random.randint(1, 20)) for _ in range(50)
]
# Not raising in this call shows successfull non-overlap. # Not raising in this call shows successfull non-overlap.
packed = pack(inputs, 1) packed = pack(inputs, 1)
self.assertEqual( self.assertEqual(
"bbox: 0.0 <= x <= 124.0, 0.0 <= y <= 105.0, 0.0 <= z <= 0.0", "bbox: 0.0 <= x <= 124.0, 0.0 <= y <= 105.0, 0.0 <= z <= 0.0",
str((Sketch() + packed).bounding_box())) str((Sketch() + packed).bounding_box()),
)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()