Changed Shape method to properties - Issue #44

This commit is contained in:
Roger Maitland 2022-11-01 14:38:53 -04:00
parent ff87637eaa
commit ea2c201192
14 changed files with 461 additions and 484 deletions

View file

@ -39,19 +39,19 @@
<polygon fill="none" stroke="black" points="656,-98 656,-362 1241,-362 1241,-98 656,-98"/>
<text text-anchor="middle" x="948.5" y="-346.8" font-family="Times,serif" font-size="14.00">BoundBox</text>
<polyline fill="none" stroke="black" points="656,-339 1241,-339 "/>
<text text-anchor="start" x="664" y="-323.8" font-family="Times,serif" font-size="14.00">wrapped</text>
<text text-anchor="start" x="664" y="-308.8" font-family="Times,serif" font-size="14.00">xlen</text>
<text text-anchor="start" x="664" y="-293.8" font-family="Times,serif" font-size="14.00">xmax</text>
<text text-anchor="start" x="664" y="-278.8" font-family="Times,serif" font-size="14.00">xmin</text>
<text text-anchor="start" x="664" y="-263.8" font-family="Times,serif" font-size="14.00">ylen</text>
<text text-anchor="start" x="664" y="-248.8" font-family="Times,serif" font-size="14.00">ymax</text>
<text text-anchor="start" x="664" y="-233.8" font-family="Times,serif" font-size="14.00">ymin</text>
<text text-anchor="start" x="664" y="-218.8" font-family="Times,serif" font-size="14.00">zlen</text>
<text text-anchor="start" x="664" y="-203.8" font-family="Times,serif" font-size="14.00">zmax</text>
<text text-anchor="start" x="664" y="-188.8" font-family="Times,serif" font-size="14.00">zmin</text>
<polyline fill="none" stroke="black" points="656,-181 1241,-181 "/>
<text text-anchor="start" x="664" y="-165.8" font-family="Times,serif" font-size="14.00">add(obj: Union[tuple[float, float, float], Vector, BoundBox], tol: float): BoundBox</text>
<text text-anchor="start" x="664" y="-150.8" font-family="Times,serif" font-size="14.00">center(): Vector</text>
<text text-anchor="start" x="664" y="-323.8" font-family="Times,serif" font-size="14.00">center</text>
<text text-anchor="start" x="664" y="-308.8" font-family="Times,serif" font-size="14.00">wrapped</text>
<text text-anchor="start" x="664" y="-293.8" font-family="Times,serif" font-size="14.00">xlen</text>
<text text-anchor="start" x="664" y="-278.8" font-family="Times,serif" font-size="14.00">xmax</text>
<text text-anchor="start" x="664" y="-263.8" font-family="Times,serif" font-size="14.00">xmin</text>
<text text-anchor="start" x="664" y="-248.8" font-family="Times,serif" font-size="14.00">ylen</text>
<text text-anchor="start" x="664" y="-233.8" font-family="Times,serif" font-size="14.00">ymax</text>
<text text-anchor="start" x="664" y="-218.8" font-family="Times,serif" font-size="14.00">ymin</text>
<text text-anchor="start" x="664" y="-203.8" font-family="Times,serif" font-size="14.00">zlen</text>
<text text-anchor="start" x="664" y="-188.8" font-family="Times,serif" font-size="14.00">zmax</text>
<text text-anchor="start" x="664" y="-173.8" font-family="Times,serif" font-size="14.00">zmin</text>
<polyline fill="none" stroke="black" points="656,-166 1241,-166 "/>
<text text-anchor="start" x="664" y="-150.8" font-family="Times,serif" font-size="14.00">add(obj: Union[tuple[float, float, float], Vector, BoundBox], tol: float): BoundBox</text>
<text text-anchor="start" x="664" y="-135.8" font-family="Times,serif" font-size="14.00">diagonal_length(): float</text>
<text text-anchor="start" x="664" y="-120.8" font-family="Times,serif" font-size="14.00">find_outside_box_2d(bb1: BoundBox, bb2): Optional[BoundBox]</text>
<text text-anchor="start" x="664" y="-105.8" font-family="Times,serif" font-size="14.00">is_inside(b2: BoundBox): bool</text>
@ -141,63 +141,63 @@
<polygon fill="none" stroke="black" points="4921,-511.5 4921,-1405.5 6026,-1405.5 6026,-511.5 4921,-511.5"/>
<text text-anchor="middle" x="5473.5" y="-1390.3" font-family="Times,serif" font-size="14.00">Shape</text>
<polyline fill="none" stroke="black" points="4921,-1382.5 6026,-1382.5 "/>
<text text-anchor="start" x="4929" y="-1367.3" font-family="Times,serif" font-size="14.00">for_construction : bool</text>
<text text-anchor="start" x="4929" y="-1352.3" font-family="Times,serif" font-size="14.00">label : str</text>
<text text-anchor="start" x="4929" y="-1337.3" font-family="Times,serif" font-size="14.00">orientation</text>
<text text-anchor="start" x="4929" y="-1322.3" font-family="Times,serif" font-size="14.00">position</text>
<text text-anchor="start" x="4929" y="-1307.3" font-family="Times,serif" font-size="14.00">wrapped</text>
<polyline fill="none" stroke="black" points="4921,-1299.5 6026,-1299.5 "/>
<text text-anchor="start" x="4929" y="-1284.3" font-family="Times,serif" font-size="14.00">area(): float</text>
<text text-anchor="start" x="4929" y="-1269.3" font-family="Times,serif" font-size="14.00">bounding_box(tolerance: float): BoundBox</text>
<text text-anchor="start" x="4929" y="-1254.3" font-family="Times,serif" font-size="14.00">cast(cls: TopoDS_Shape, obj: bool, for_construction): Shape</text>
<text text-anchor="start" x="4929" y="-1239.3" font-family="Times,serif" font-size="14.00">clean(): Shape</text>
<text text-anchor="start" x="4929" y="-1224.3" font-family="Times,serif" font-size="14.00">combined_center(objects: CenterOf, center_of): Vector</text>
<text text-anchor="start" x="4929" y="-1209.3" font-family="Times,serif" font-size="14.00">compounds(): ShapeList[&#39;Compound&#39;]</text>
<text text-anchor="start" x="4929" y="-1194.3" font-family="Times,serif" font-size="14.00">compute_mass(obj): float</text>
<text text-anchor="start" x="4929" y="-1179.3" font-family="Times,serif" font-size="14.00">copy(): Shape</text>
<text text-anchor="start" x="4929" y="-1164.3" font-family="Times,serif" font-size="14.00">cut(): Shape</text>
<text text-anchor="start" x="4929" y="-1149.3" font-family="Times,serif" font-size="14.00">distance(other: Shape): float</text>
<text text-anchor="start" x="4929" y="-1134.3" font-family="Times,serif" font-size="14.00">distances(): Iterator[float]</text>
<text text-anchor="start" x="4929" y="-1119.3" font-family="Times,serif" font-size="14.00">edges(): ShapeList[&#39;Edge&#39;]</text>
<text text-anchor="start" x="4929" y="-1104.3" font-family="Times,serif" font-size="14.00">export_brep(f: Union[str, BytesIO]): bool</text>
<text text-anchor="start" x="4929" y="-1089.3" font-family="Times,serif" font-size="14.00">export_step(file_name: str): IFSelect_ReturnStatus</text>
<text text-anchor="start" x="4929" y="-1074.3" font-family="Times,serif" font-size="14.00">export_stl(file_name: str, tolerance: float, angular_tolerance: float, ascii: bool): bool</text>
<text text-anchor="start" x="4929" y="-1059.3" font-family="Times,serif" font-size="14.00">faces(): ShapeList[&#39;Face&#39;]</text>
<text text-anchor="start" x="4929" y="-1044.3" font-family="Times,serif" font-size="14.00">faces_intersected_by_line(point: VectorLike, axis: VectorLike, tol: float, direction: Direction): ShapeList[Face]</text>
<text text-anchor="start" x="4929" y="-1029.3" font-family="Times,serif" font-size="14.00">find_intersection(point: VectorLike, direction: VectorLike): list[tuple[Vector, Vector]]</text>
<text text-anchor="start" x="4929" y="-1014.3" font-family="Times,serif" font-size="14.00">fix(): Shape</text>
<text text-anchor="start" x="4929" y="-999.3" font-family="Times,serif" font-size="14.00">fuse(): Shape</text>
<text text-anchor="start" x="4929" y="-984.3" font-family="Times,serif" font-size="14.00">geom_type(): Geoms</text>
<text text-anchor="start" x="4929" y="-969.3" font-family="Times,serif" font-size="14.00">hash_code(): int</text>
<text text-anchor="start" x="4929" y="-954.3" font-family="Times,serif" font-size="14.00">import_brep(cls: Union[str, BytesIO], f): Shape</text>
<text text-anchor="start" x="4929" y="-939.3" font-family="Times,serif" font-size="14.00">intersect(): Shape</text>
<text text-anchor="start" x="4929" y="-924.3" font-family="Times,serif" font-size="14.00">is_equal(other: Shape): bool</text>
<text text-anchor="start" x="4929" y="-909.3" font-family="Times,serif" font-size="14.00">is_null(): bool</text>
<text text-anchor="start" x="4929" y="-894.3" font-family="Times,serif" font-size="14.00">is_same(other: Shape): bool</text>
<text text-anchor="start" x="4929" y="-879.3" font-family="Times,serif" font-size="14.00">is_valid(): bool</text>
<text text-anchor="start" x="4929" y="-864.3" font-family="Times,serif" font-size="14.00">locate(loc: Location): Shape</text>
<text text-anchor="start" x="4929" y="-849.3" font-family="Times,serif" font-size="14.00">located(loc: Location): Shape</text>
<text text-anchor="start" x="4929" y="-834.3" font-family="Times,serif" font-size="14.00">location(): Location</text>
<text text-anchor="start" x="4929" y="-819.3" font-family="Times,serif" font-size="14.00">max_fillet(edge_list: Iterable[Edge], tolerance, max_iterations: int): float</text>
<text text-anchor="start" x="4929" y="-804.3" font-family="Times,serif" font-size="14.00">mesh(tolerance: float, angular_tolerance: float)</text>
<text text-anchor="start" x="4929" y="-789.3" font-family="Times,serif" font-size="14.00">mirror(mirror_plane: Plane): Shape</text>
<text text-anchor="start" x="4929" y="-774.3" font-family="Times,serif" font-size="14.00">move(loc: Location): Shape</text>
<text text-anchor="start" x="4929" y="-759.3" font-family="Times,serif" font-size="14.00">moved(loc: Location): Shape</text>
<text text-anchor="start" x="4929" y="-744.3" font-family="Times,serif" font-size="14.00">project_text(txt: str, fontsize: float, depth: float, path: Union[Wire, Edge], font: str, font_path: str, kind: FontStyle, valign: Valign, start: float): Compound</text>
<text text-anchor="start" x="4929" y="-729.3" font-family="Times,serif" font-size="14.00">rotate(axis: Axis, angle: float): Shape</text>
<text text-anchor="start" x="4929" y="-714.3" font-family="Times,serif" font-size="14.00">scale(factor: float): Shape</text>
<text text-anchor="start" x="4929" y="-699.3" font-family="Times,serif" font-size="14.00">shape_type(): Shapes</text>
<text text-anchor="start" x="4929" y="-684.3" font-family="Times,serif" font-size="14.00">shells(): ShapeList[&#39;Shell&#39;]</text>
<text text-anchor="start" x="4929" y="-669.3" font-family="Times,serif" font-size="14.00">solids(): ShapeList[&#39;Solid&#39;]</text>
<text text-anchor="start" x="4929" y="-654.3" font-family="Times,serif" font-size="14.00">split(): Shape</text>
<text text-anchor="start" x="4929" y="-639.3" font-family="Times,serif" font-size="14.00">tessellate(tolerance: float, angular_tolerance: float): Tuple[list[Vector], list[Tuple[int, int, int]]]</text>
<text text-anchor="start" x="4929" y="-624.3" font-family="Times,serif" font-size="14.00">to_vtk_poly_data(tolerance: float, angular_tolerance: float, normals: bool): vtkPolyData</text>
<text text-anchor="start" x="4929" y="-609.3" font-family="Times,serif" font-size="14.00">transform_geometry(t_matrix: Matrix): Shape</text>
<text text-anchor="start" x="4929" y="-594.3" font-family="Times,serif" font-size="14.00">transform_shape(t_matrix: Matrix): Shape</text>
<text text-anchor="start" x="4929" y="-579.3" font-family="Times,serif" font-size="14.00">transformed(rotate: VectorLike, offset: VectorLike): Shape</text>
<text text-anchor="start" x="4929" y="-564.3" font-family="Times,serif" font-size="14.00">translate(vector: VectorLike): Shape</text>
<text text-anchor="start" x="4929" y="-549.3" font-family="Times,serif" font-size="14.00">vertices(): ShapeList[&#39;Vertex&#39;]</text>
<text text-anchor="start" x="4929" y="-534.3" font-family="Times,serif" font-size="14.00">volume(): float</text>
<text text-anchor="start" x="4929" y="-1367.3" font-family="Times,serif" font-size="14.00">area</text>
<text text-anchor="start" x="4929" y="-1352.3" font-family="Times,serif" font-size="14.00">for_construction : bool</text>
<text text-anchor="start" x="4929" y="-1337.3" font-family="Times,serif" font-size="14.00">label : str</text>
<text text-anchor="start" x="4929" y="-1322.3" font-family="Times,serif" font-size="14.00">location</text>
<text text-anchor="start" x="4929" y="-1307.3" font-family="Times,serif" font-size="14.00">orientation</text>
<text text-anchor="start" x="4929" y="-1292.3" font-family="Times,serif" font-size="14.00">position</text>
<text text-anchor="start" x="4929" y="-1277.3" font-family="Times,serif" font-size="14.00">volume</text>
<text text-anchor="start" x="4929" y="-1262.3" font-family="Times,serif" font-size="14.00">wrapped</text>
<polyline fill="none" stroke="black" points="4921,-1254.5 6026,-1254.5 "/>
<text text-anchor="start" x="4929" y="-1239.3" font-family="Times,serif" font-size="14.00">bounding_box(tolerance: float): BoundBox</text>
<text text-anchor="start" x="4929" y="-1224.3" font-family="Times,serif" font-size="14.00">cast(cls: TopoDS_Shape, obj: bool, for_construction): Shape</text>
<text text-anchor="start" x="4929" y="-1209.3" font-family="Times,serif" font-size="14.00">clean(): Shape</text>
<text text-anchor="start" x="4929" y="-1194.3" font-family="Times,serif" font-size="14.00">combined_center(objects: CenterOf, center_of): Vector</text>
<text text-anchor="start" x="4929" y="-1179.3" font-family="Times,serif" font-size="14.00">compounds(): ShapeList[&#39;Compound&#39;]</text>
<text text-anchor="start" x="4929" y="-1164.3" font-family="Times,serif" font-size="14.00">compute_mass(obj): float</text>
<text text-anchor="start" x="4929" y="-1149.3" font-family="Times,serif" font-size="14.00">copy(): Shape</text>
<text text-anchor="start" x="4929" y="-1134.3" font-family="Times,serif" font-size="14.00">cut(): Shape</text>
<text text-anchor="start" x="4929" y="-1119.3" font-family="Times,serif" font-size="14.00">distance(other: Shape): float</text>
<text text-anchor="start" x="4929" y="-1104.3" font-family="Times,serif" font-size="14.00">distances(): Iterator[float]</text>
<text text-anchor="start" x="4929" y="-1089.3" font-family="Times,serif" font-size="14.00">edges(): ShapeList[&#39;Edge&#39;]</text>
<text text-anchor="start" x="4929" y="-1074.3" font-family="Times,serif" font-size="14.00">export_brep(f: Union[str, BytesIO]): bool</text>
<text text-anchor="start" x="4929" y="-1059.3" font-family="Times,serif" font-size="14.00">export_step(file_name: str): IFSelect_ReturnStatus</text>
<text text-anchor="start" x="4929" y="-1044.3" font-family="Times,serif" font-size="14.00">export_stl(file_name: str, tolerance: float, angular_tolerance: float, ascii: bool): bool</text>
<text text-anchor="start" x="4929" y="-1029.3" font-family="Times,serif" font-size="14.00">faces(): ShapeList[&#39;Face&#39;]</text>
<text text-anchor="start" x="4929" y="-1014.3" font-family="Times,serif" font-size="14.00">faces_intersected_by_line(point: VectorLike, axis: VectorLike, tol: float, direction: Direction): ShapeList[Face]</text>
<text text-anchor="start" x="4929" y="-999.3" font-family="Times,serif" font-size="14.00">find_intersection(point: VectorLike, direction: VectorLike): list[tuple[Vector, Vector]]</text>
<text text-anchor="start" x="4929" y="-984.3" font-family="Times,serif" font-size="14.00">fix(): Shape</text>
<text text-anchor="start" x="4929" y="-969.3" font-family="Times,serif" font-size="14.00">fuse(): Shape</text>
<text text-anchor="start" x="4929" y="-954.3" font-family="Times,serif" font-size="14.00">geom_type(): Geoms</text>
<text text-anchor="start" x="4929" y="-939.3" font-family="Times,serif" font-size="14.00">hash_code(): int</text>
<text text-anchor="start" x="4929" y="-924.3" font-family="Times,serif" font-size="14.00">import_brep(cls: Union[str, BytesIO], f): Shape</text>
<text text-anchor="start" x="4929" y="-909.3" font-family="Times,serif" font-size="14.00">intersect(): Shape</text>
<text text-anchor="start" x="4929" y="-894.3" font-family="Times,serif" font-size="14.00">is_equal(other: Shape): bool</text>
<text text-anchor="start" x="4929" y="-879.3" font-family="Times,serif" font-size="14.00">is_null(): bool</text>
<text text-anchor="start" x="4929" y="-864.3" font-family="Times,serif" font-size="14.00">is_same(other: Shape): bool</text>
<text text-anchor="start" x="4929" y="-849.3" font-family="Times,serif" font-size="14.00">is_valid(): bool</text>
<text text-anchor="start" x="4929" y="-834.3" font-family="Times,serif" font-size="14.00">locate(loc: Location): Shape</text>
<text text-anchor="start" x="4929" y="-819.3" font-family="Times,serif" font-size="14.00">located(loc: Location): Shape</text>
<text text-anchor="start" x="4929" y="-804.3" font-family="Times,serif" font-size="14.00">max_fillet(edge_list: Iterable[Edge], tolerance, max_iterations: int): float</text>
<text text-anchor="start" x="4929" y="-789.3" font-family="Times,serif" font-size="14.00">mesh(tolerance: float, angular_tolerance: float)</text>
<text text-anchor="start" x="4929" y="-774.3" font-family="Times,serif" font-size="14.00">mirror(mirror_plane: Plane): Shape</text>
<text text-anchor="start" x="4929" y="-759.3" font-family="Times,serif" font-size="14.00">move(loc: Location): Shape</text>
<text text-anchor="start" x="4929" y="-744.3" font-family="Times,serif" font-size="14.00">moved(loc: Location): Shape</text>
<text text-anchor="start" x="4929" y="-729.3" font-family="Times,serif" font-size="14.00">project_text(txt: str, fontsize: float, depth: float, path: Union[Wire, Edge], font: str, font_path: str, kind: FontStyle, valign: Valign, start: float): Compound</text>
<text text-anchor="start" x="4929" y="-714.3" font-family="Times,serif" font-size="14.00">rotate(axis: Axis, angle: float): Shape</text>
<text text-anchor="start" x="4929" y="-699.3" font-family="Times,serif" font-size="14.00">scale(factor: float): Shape</text>
<text text-anchor="start" x="4929" y="-684.3" font-family="Times,serif" font-size="14.00">shape_type(): Shapes</text>
<text text-anchor="start" x="4929" y="-669.3" font-family="Times,serif" font-size="14.00">shells(): ShapeList[&#39;Shell&#39;]</text>
<text text-anchor="start" x="4929" y="-654.3" font-family="Times,serif" font-size="14.00">solids(): ShapeList[&#39;Solid&#39;]</text>
<text text-anchor="start" x="4929" y="-639.3" font-family="Times,serif" font-size="14.00">split(): Shape</text>
<text text-anchor="start" x="4929" y="-624.3" font-family="Times,serif" font-size="14.00">tessellate(tolerance: float, angular_tolerance: float): Tuple[list[Vector], list[Tuple[int, int, int]]]</text>
<text text-anchor="start" x="4929" y="-609.3" font-family="Times,serif" font-size="14.00">to_vtk_poly_data(tolerance: float, angular_tolerance: float, normals: bool): vtkPolyData</text>
<text text-anchor="start" x="4929" y="-594.3" font-family="Times,serif" font-size="14.00">transform_geometry(t_matrix: Matrix): Shape</text>
<text text-anchor="start" x="4929" y="-579.3" font-family="Times,serif" font-size="14.00">transform_shape(t_matrix: Matrix): Shape</text>
<text text-anchor="start" x="4929" y="-564.3" font-family="Times,serif" font-size="14.00">transformed(rotate: VectorLike, offset: VectorLike): Shape</text>
<text text-anchor="start" x="4929" y="-549.3" font-family="Times,serif" font-size="14.00">translate(vector: VectorLike): Shape</text>
<text text-anchor="start" x="4929" y="-534.3" font-family="Times,serif" font-size="14.00">vertices(): ShapeList[&#39;Vertex&#39;]</text>
<text text-anchor="start" x="4929" y="-519.3" font-family="Times,serif" font-size="14.00">wires(): ShapeList[&#39;Wire&#39;]</text>
</g>
<!-- build123d.direct_api.Compound&#45;&gt;build123d.direct_api.Shape -->
@ -209,90 +209,93 @@
<!-- build123d.direct_api.Edge -->
<g id="node4" class="node">
<title>build123d.direct_api.Edge</title>
<polygon fill="none" stroke="black" points="5952.5,-112.5 5952.5,-347.5 7172.5,-347.5 7172.5,-112.5 5952.5,-112.5"/>
<text text-anchor="middle" x="6562.5" y="-332.3" font-family="Times,serif" font-size="14.00">Edge</text>
<polyline fill="none" stroke="black" points="5952.5,-324.5 7172.5,-324.5 "/>
<polyline fill="none" stroke="black" points="5952.5,-300.5 7172.5,-300.5 "/>
<text text-anchor="start" x="5960.5" y="-285.3" font-family="Times,serif" font-size="14.00">arc_center(): Vector</text>
<text text-anchor="start" x="5960.5" y="-270.3" font-family="Times,serif" font-size="14.00">close(): Union[Edge, Wire]</text>
<text text-anchor="start" x="5960.5" y="-255.3" font-family="Times,serif" font-size="14.00">distribute_locations(count: int, start: float, stop: float, positions_only: bool): list[Location]</text>
<text text-anchor="start" x="5960.5" y="-240.3" font-family="Times,serif" font-size="14.00">make_circle(cls: float, radius: VectorLike, pnt: VectorLike, dir: float, angle1: float, angle2, orientation): Edge</text>
<text text-anchor="start" x="5960.5" y="-225.3" font-family="Times,serif" font-size="14.00">make_ellipse(cls: float, x_radius: float, y_radius: VectorLike, pnt: VectorLike, dir: VectorLike, xdir: float, angle1: float, angle2: AngularDirection, angular_direction): Edge</text>
<text text-anchor="start" x="5960.5" y="-210.3" font-family="Times,serif" font-size="14.00">make_line(cls: VectorLike, v1: VectorLike, v2): Edge</text>
<text text-anchor="start" x="5960.5" y="-195.3" font-family="Times,serif" font-size="14.00">make_spline(cls: list[VectorLike], points: list[VectorLike], tangents: bool, periodic: list[float], parameters: bool, scale: float, tol): Edge</text>
<text text-anchor="start" x="5960.5" y="-180.3" font-family="Times,serif" font-size="14.00">make_spline_approx(cls: list[VectorLike], points: float, tol: Tuple[float, float, float], smoothing: int, min_deg: int, max_deg): Edge</text>
<text text-anchor="start" x="5960.5" y="-165.3" font-family="Times,serif" font-size="14.00">make_tangent_arc(cls: VectorLike, start: VectorLike, tangent: VectorLike, end): Edge</text>
<text text-anchor="start" x="5960.5" y="-150.3" font-family="Times,serif" font-size="14.00">make_three_point_arc(cls: VectorLike, v1: VectorLike, v2: VectorLike, v3): Edge</text>
<text text-anchor="start" x="5960.5" y="-135.3" font-family="Times,serif" font-size="14.00">project_to_shape(target_object: Shape, direction: VectorLike, center: VectorLike): list[Edge]</text>
<text text-anchor="start" x="5960.5" y="-120.3" font-family="Times,serif" font-size="14.00">to_wire(): Wire</text>
<polygon fill="none" stroke="black" points="5952.5,-120.5 5952.5,-339.5 7172.5,-339.5 7172.5,-120.5 5952.5,-120.5"/>
<text text-anchor="middle" x="6562.5" y="-324.3" font-family="Times,serif" font-size="14.00">Edge</text>
<polyline fill="none" stroke="black" points="5952.5,-316.5 7172.5,-316.5 "/>
<text text-anchor="start" x="5960.5" y="-301.3" font-family="Times,serif" font-size="14.00">arc_center</text>
<polyline fill="none" stroke="black" points="5952.5,-293.5 7172.5,-293.5 "/>
<text text-anchor="start" x="5960.5" y="-278.3" font-family="Times,serif" font-size="14.00">close(): Union[Edge, Wire]</text>
<text text-anchor="start" x="5960.5" y="-263.3" font-family="Times,serif" font-size="14.00">distribute_locations(count: int, start: float, stop: float, positions_only: bool): list[Location]</text>
<text text-anchor="start" x="5960.5" y="-248.3" font-family="Times,serif" font-size="14.00">make_circle(cls: float, radius: VectorLike, pnt: VectorLike, dir: float, angle1: float, angle2, orientation): Edge</text>
<text text-anchor="start" x="5960.5" y="-233.3" font-family="Times,serif" font-size="14.00">make_ellipse(cls: float, x_radius: float, y_radius: VectorLike, pnt: VectorLike, dir: VectorLike, xdir: float, angle1: float, angle2: AngularDirection, angular_direction): Edge</text>
<text text-anchor="start" x="5960.5" y="-218.3" font-family="Times,serif" font-size="14.00">make_line(cls: VectorLike, v1: VectorLike, v2): Edge</text>
<text text-anchor="start" x="5960.5" y="-203.3" font-family="Times,serif" font-size="14.00">make_spline(cls: list[VectorLike], points: list[VectorLike], tangents: bool, periodic: list[float], parameters: bool, scale: float, tol): Edge</text>
<text text-anchor="start" x="5960.5" y="-188.3" font-family="Times,serif" font-size="14.00">make_spline_approx(cls: list[VectorLike], points: float, tol: Tuple[float, float, float], smoothing: int, min_deg: int, max_deg): Edge</text>
<text text-anchor="start" x="5960.5" y="-173.3" font-family="Times,serif" font-size="14.00">make_tangent_arc(cls: VectorLike, start: VectorLike, tangent: VectorLike, end): Edge</text>
<text text-anchor="start" x="5960.5" y="-158.3" font-family="Times,serif" font-size="14.00">make_three_point_arc(cls: VectorLike, v1: VectorLike, v2: VectorLike, v3): Edge</text>
<text text-anchor="start" x="5960.5" y="-143.3" font-family="Times,serif" font-size="14.00">project_to_shape(target_object: Shape, direction: VectorLike, center: VectorLike): list[Edge]</text>
<text text-anchor="start" x="5960.5" y="-128.3" font-family="Times,serif" font-size="14.00">to_wire(): Wire</text>
</g>
<!-- build123d.direct_api.Mixin1D -->
<g id="node8" class="node">
<title>build123d.direct_api.Mixin1D</title>
<polygon fill="none" stroke="black" points="6656,-826 6656,-1091 7507,-1091 7507,-826 6656,-826"/>
<text text-anchor="middle" x="7081.5" y="-1075.8" font-family="Times,serif" font-size="14.00">Mixin1D</text>
<polyline fill="none" stroke="black" points="6656,-1068 7507,-1068 "/>
<polyline fill="none" stroke="black" points="6656,-1044 7507,-1044 "/>
<text text-anchor="start" x="6664" y="-1028.8" font-family="Times,serif" font-size="14.00">center(center_of: CenterOf): Vector</text>
<text text-anchor="start" x="6664" y="-1013.8" font-family="Times,serif" font-size="14.00">end_point(): Vector</text>
<text text-anchor="start" x="6664" y="-998.8" font-family="Times,serif" font-size="14.00">is_closed(): bool</text>
<text text-anchor="start" x="6664" y="-983.8" font-family="Times,serif" font-size="14.00">length(): float</text>
<text text-anchor="start" x="6664" y="-968.8" font-family="Times,serif" font-size="14.00">location_at(distance: float, position_mode: PositionMode, frame_method: FrameMethod, planar: bool): Location</text>
<text text-anchor="start" x="6664" y="-953.8" font-family="Times,serif" font-size="14.00">locations(ds: Iterable[float], position_mode: PositionMode, frame_method: FrameMethod, planar: bool): list[Location]</text>
<text text-anchor="start" x="6664" y="-938.8" font-family="Times,serif" font-size="14.00">normal(): Vector</text>
<text text-anchor="start" x="6664" y="-923.8" font-family="Times,serif" font-size="14.00">param_at(d: float): float</text>
<text text-anchor="start" x="6664" y="-908.8" font-family="Times,serif" font-size="14.00">position_at(d: float, position_mode: PositionMode): Vector</text>
<text text-anchor="start" x="6664" y="-893.8" font-family="Times,serif" font-size="14.00">positions(ds: Iterable[float], position_mode: PositionMode): list[Vector]</text>
<text text-anchor="start" x="6664" y="-878.8" font-family="Times,serif" font-size="14.00">project(face: Face, d: VectorLike, closest: bool): Union[Mixin1D, list[Mixin1D]]</text>
<text text-anchor="start" x="6664" y="-863.8" font-family="Times,serif" font-size="14.00">radius(): float</text>
<text text-anchor="start" x="6664" y="-848.8" font-family="Times,serif" font-size="14.00">start_point(): Vector</text>
<text text-anchor="start" x="6664" y="-833.8" font-family="Times,serif" font-size="14.00">tangent_at(location_param: float, position_mode: PositionMode): Vector</text>
<polygon fill="none" stroke="black" points="6656,-826.5 6656,-1090.5 7507,-1090.5 7507,-826.5 6656,-826.5"/>
<text text-anchor="middle" x="7081.5" y="-1075.3" font-family="Times,serif" font-size="14.00">Mixin1D</text>
<polyline fill="none" stroke="black" points="6656,-1067.5 7507,-1067.5 "/>
<text text-anchor="start" x="6664" y="-1052.3" font-family="Times,serif" font-size="14.00">center</text>
<text text-anchor="start" x="6664" y="-1037.3" font-family="Times,serif" font-size="14.00">center_of_mass</text>
<text text-anchor="start" x="6664" y="-1022.3" font-family="Times,serif" font-size="14.00">length</text>
<text text-anchor="start" x="6664" y="-1007.3" font-family="Times,serif" font-size="14.00">radius</text>
<polyline fill="none" stroke="black" points="6656,-999.5 7507,-999.5 "/>
<text text-anchor="start" x="6664" y="-984.3" font-family="Times,serif" font-size="14.00">end_point(): Vector</text>
<text text-anchor="start" x="6664" y="-969.3" font-family="Times,serif" font-size="14.00">is_closed(): bool</text>
<text text-anchor="start" x="6664" y="-954.3" font-family="Times,serif" font-size="14.00">location_at(distance: float, position_mode: PositionMode, frame_method: FrameMethod, planar: bool): Location</text>
<text text-anchor="start" x="6664" y="-939.3" font-family="Times,serif" font-size="14.00">locations(ds: Iterable[float], position_mode: PositionMode, frame_method: FrameMethod, planar: bool): list[Location]</text>
<text text-anchor="start" x="6664" y="-924.3" font-family="Times,serif" font-size="14.00">normal(): Vector</text>
<text text-anchor="start" x="6664" y="-909.3" font-family="Times,serif" font-size="14.00">param_at(d: float): float</text>
<text text-anchor="start" x="6664" y="-894.3" font-family="Times,serif" font-size="14.00">position_at(d: float, position_mode: PositionMode): Vector</text>
<text text-anchor="start" x="6664" y="-879.3" font-family="Times,serif" font-size="14.00">positions(ds: Iterable[float], position_mode: PositionMode): list[Vector]</text>
<text text-anchor="start" x="6664" y="-864.3" font-family="Times,serif" font-size="14.00">project(face: Face, d: VectorLike, closest: bool): Union[Mixin1D, list[Mixin1D]]</text>
<text text-anchor="start" x="6664" y="-849.3" font-family="Times,serif" font-size="14.00">start_point(): Vector</text>
<text text-anchor="start" x="6664" y="-834.3" font-family="Times,serif" font-size="14.00">tangent_at(location_param: float, position_mode: PositionMode): Vector</text>
</g>
<!-- build123d.direct_api.Edge&#45;&gt;build123d.direct_api.Mixin1D -->
<g id="edge3" class="edge">
<title>build123d.direct_api.Edge&#45;&gt;build123d.direct_api.Mixin1D</title>
<path fill="none" stroke="black" d="M6645.89,-347.72C6737.24,-475.61 6883.74,-680.67 6981.28,-817.21"/>
<polygon fill="none" stroke="black" points="6978.68,-819.59 6987.34,-825.69 6984.37,-815.52 6978.68,-819.59"/>
<path fill="none" stroke="black" d="M6640.2,-339.76C6731.28,-467.26 6882.4,-678.8 6981.98,-818.2"/>
<polygon fill="none" stroke="black" points="6979.21,-820.34 6987.87,-826.44 6984.91,-816.27 6979.21,-820.34"/>
</g>
<!-- build123d.direct_api.Edge&#45;&gt;build123d.direct_api.Shape -->
<g id="edge4" class="edge">
<title>build123d.direct_api.Edge&#45;&gt;build123d.direct_api.Shape</title>
<path fill="none" stroke="black" d="M6387.84,-347.52C6290.42,-412.51 6163.07,-497.47 6034.49,-583.25"/>
<polygon fill="none" stroke="black" points="6032.39,-580.44 6026.02,-588.9 6036.28,-586.26 6032.39,-580.44"/>
<path fill="none" stroke="black" d="M6399.76,-339.57C6300.99,-405.46 6168.5,-493.85 6034.66,-583.13"/>
<polygon fill="none" stroke="black" points="6032.63,-580.28 6026.25,-588.74 6036.52,-586.1 6032.63,-580.28"/>
</g>
<!-- build123d.direct_api.Face -->
<g id="node5" class="node">
<title>build123d.direct_api.Face</title>
<polygon fill="none" stroke="black" points="4262.5,-52.5 4262.5,-407.5 5268.5,-407.5 5268.5,-52.5 4262.5,-52.5"/>
<text text-anchor="middle" x="4765.5" y="-392.3" font-family="Times,serif" font-size="14.00">Face</text>
<polyline fill="none" stroke="black" points="4262.5,-384.5 5268.5,-384.5 "/>
<polyline fill="none" stroke="black" points="4262.5,-360.5 5268.5,-360.5 "/>
<text text-anchor="start" x="4270.5" y="-345.3" font-family="Times,serif" font-size="14.00">center(center_of: CenterOf): Vector</text>
<text text-anchor="start" x="4270.5" y="-330.3" font-family="Times,serif" font-size="14.00">chamfer_2d(d: float, vertices: Iterable[Vertex]): Face</text>
<text text-anchor="start" x="4270.5" y="-315.3" font-family="Times,serif" font-size="14.00">construct_on(cls: Face, f: Wire, outer): Face</text>
<text text-anchor="start" x="4270.5" y="-300.3" font-family="Times,serif" font-size="14.00">fillet_2d(radius: float, vertices: Iterable[Vertex]): Face</text>
<text text-anchor="start" x="4270.5" y="-285.3" font-family="Times,serif" font-size="14.00">inner_wires(): list[Wire]</text>
<text text-anchor="start" x="4270.5" y="-270.3" font-family="Times,serif" font-size="14.00">is_inside(point: VectorLike, tolerance: float): bool</text>
<text text-anchor="start" x="4270.5" y="-255.3" font-family="Times,serif" font-size="14.00">make_from_wires(cls: Wire, outer_wire: list[Wire], inner_wires): Face</text>
<text text-anchor="start" x="4270.5" y="-240.3" font-family="Times,serif" font-size="14.00">make_holes(interior_wires: list[Wire]): Face</text>
<text text-anchor="start" x="4270.5" y="-225.3" font-family="Times,serif" font-size="14.00">make_plane(cls: VectorLike, pnt: VectorLike, dir): Face</text>
<text text-anchor="start" x="4270.5" y="-210.3" font-family="Times,serif" font-size="14.00">make_rect(cls: float, width: float, height: VectorLike, pnt: VectorLike, normal): Face</text>
<text text-anchor="start" x="4270.5" y="-195.3" font-family="Times,serif" font-size="14.00">make_ruled_surface(cls: Edge, edge1: Edge, edge2): Face</text>
<text text-anchor="start" x="4270.5" y="-180.3" font-family="Times,serif" font-size="14.00">make_surface(cls: Union[Wire, list[Edge]], exterior: list[VectorLike], surface_points: list[Wire], interior_wires): Face</text>
<text text-anchor="start" x="4270.5" y="-165.3" font-family="Times,serif" font-size="14.00">make_surface_from_curves(cls, curve1, curve2): Face</text>
<text text-anchor="start" x="4270.5" y="-150.3" font-family="Times,serif" font-size="14.00">make_surface_from_points(cls: list[list[VectorLike]], points: float, tol: Tuple[float, float, float], smoothing: int, min_deg: int, max_deg): Face</text>
<text text-anchor="start" x="4270.5" y="-135.3" font-family="Times,serif" font-size="14.00">normal_at(surface_point: VectorLike): Vector</text>
<text text-anchor="start" x="4270.5" y="-120.3" font-family="Times,serif" font-size="14.00">outer_wire(): Wire</text>
<text text-anchor="start" x="4270.5" y="-105.3" font-family="Times,serif" font-size="14.00">project(other: Face, d: VectorLike): Face</text>
<text text-anchor="start" x="4270.5" y="-90.3" font-family="Times,serif" font-size="14.00">project_to_shape(target_object: Shape, direction: VectorLike, center: VectorLike, internal_face_points: list[Vector]): list[Face]</text>
<text text-anchor="start" x="4270.5" y="-75.3" font-family="Times,serif" font-size="14.00">thicken(depth: float, direction: VectorLike): Solid</text>
<text text-anchor="start" x="4270.5" y="-60.3" font-family="Times,serif" font-size="14.00">to_pln(): gp_Pln</text>
<polygon fill="none" stroke="black" points="4262.5,-45.5 4262.5,-414.5 5268.5,-414.5 5268.5,-45.5 4262.5,-45.5"/>
<text text-anchor="middle" x="4765.5" y="-399.3" font-family="Times,serif" font-size="14.00">Face</text>
<polyline fill="none" stroke="black" points="4262.5,-391.5 5268.5,-391.5 "/>
<text text-anchor="start" x="4270.5" y="-376.3" font-family="Times,serif" font-size="14.00">center</text>
<text text-anchor="start" x="4270.5" y="-361.3" font-family="Times,serif" font-size="14.00">center_of_geometry</text>
<text text-anchor="start" x="4270.5" y="-346.3" font-family="Times,serif" font-size="14.00">center_of_mass</text>
<polyline fill="none" stroke="black" points="4262.5,-338.5 5268.5,-338.5 "/>
<text text-anchor="start" x="4270.5" y="-323.3" font-family="Times,serif" font-size="14.00">chamfer_2d(d: float, vertices: Iterable[Vertex]): Face</text>
<text text-anchor="start" x="4270.5" y="-308.3" font-family="Times,serif" font-size="14.00">construct_on(cls: Face, f: Wire, outer): Face</text>
<text text-anchor="start" x="4270.5" y="-293.3" font-family="Times,serif" font-size="14.00">fillet_2d(radius: float, vertices: Iterable[Vertex]): Face</text>
<text text-anchor="start" x="4270.5" y="-278.3" font-family="Times,serif" font-size="14.00">inner_wires(): list[Wire]</text>
<text text-anchor="start" x="4270.5" y="-263.3" font-family="Times,serif" font-size="14.00">is_inside(point: VectorLike, tolerance: float): bool</text>
<text text-anchor="start" x="4270.5" y="-248.3" font-family="Times,serif" font-size="14.00">make_from_wires(cls: Wire, outer_wire: list[Wire], inner_wires): Face</text>
<text text-anchor="start" x="4270.5" y="-233.3" font-family="Times,serif" font-size="14.00">make_holes(interior_wires: list[Wire]): Face</text>
<text text-anchor="start" x="4270.5" y="-218.3" font-family="Times,serif" font-size="14.00">make_plane(cls: VectorLike, pnt: VectorLike, dir): Face</text>
<text text-anchor="start" x="4270.5" y="-203.3" font-family="Times,serif" font-size="14.00">make_rect(cls: float, width: float, height: VectorLike, pnt: VectorLike, normal): Face</text>
<text text-anchor="start" x="4270.5" y="-188.3" font-family="Times,serif" font-size="14.00">make_ruled_surface(cls: Edge, edge1: Edge, edge2): Face</text>
<text text-anchor="start" x="4270.5" y="-173.3" font-family="Times,serif" font-size="14.00">make_surface(cls: Union[Wire, list[Edge]], exterior: list[VectorLike], surface_points: list[Wire], interior_wires): Face</text>
<text text-anchor="start" x="4270.5" y="-158.3" font-family="Times,serif" font-size="14.00">make_surface_from_curves(cls, curve1, curve2): Face</text>
<text text-anchor="start" x="4270.5" y="-143.3" font-family="Times,serif" font-size="14.00">make_surface_from_points(cls: list[list[VectorLike]], points: float, tol: Tuple[float, float, float], smoothing: int, min_deg: int, max_deg): Face</text>
<text text-anchor="start" x="4270.5" y="-128.3" font-family="Times,serif" font-size="14.00">normal_at(surface_point: VectorLike): Vector</text>
<text text-anchor="start" x="4270.5" y="-113.3" font-family="Times,serif" font-size="14.00">outer_wire(): Wire</text>
<text text-anchor="start" x="4270.5" y="-98.3" font-family="Times,serif" font-size="14.00">project(other: Face, d: VectorLike): Face</text>
<text text-anchor="start" x="4270.5" y="-83.3" font-family="Times,serif" font-size="14.00">project_to_shape(target_object: Shape, direction: VectorLike, center: VectorLike, internal_face_points: list[Vector]): list[Face]</text>
<text text-anchor="start" x="4270.5" y="-68.3" font-family="Times,serif" font-size="14.00">thicken(depth: float, direction: VectorLike): Solid</text>
<text text-anchor="start" x="4270.5" y="-53.3" font-family="Times,serif" font-size="14.00">to_pln(): gp_Pln</text>
</g>
<!-- build123d.direct_api.Face&#45;&gt;build123d.direct_api.Shape -->
<g id="edge5" class="edge">
<title>build123d.direct_api.Face&#45;&gt;build123d.direct_api.Shape</title>
<path fill="none" stroke="black" d="M4937.79,-407.79C4967.22,-437.99 4998.94,-470.54 5031.73,-504.19"/>
<polygon fill="none" stroke="black" points="5029.26,-506.67 5038.75,-511.39 5034.27,-501.78 5029.26,-506.67"/>
<path fill="none" stroke="black" d="M4944.62,-414.8C4972.02,-442.91 5001.29,-472.95 5031.46,-503.91"/>
<polygon fill="none" stroke="black" points="5029.25,-506.66 5038.74,-511.38 5034.27,-501.78 5029.25,-506.66"/>
</g>
<!-- build123d.direct_api.Location -->
<g id="node6" class="node">
@ -398,37 +401,38 @@
<!-- build123d.direct_api.Solid -->
<g id="node15" class="node">
<title>build123d.direct_api.Solid</title>
<polygon fill="none" stroke="black" points="2872.5,-90 2872.5,-370 4244.5,-370 4244.5,-90 2872.5,-90"/>
<text text-anchor="middle" x="3558.5" y="-354.8" font-family="Times,serif" font-size="14.00">Solid</text>
<polyline fill="none" stroke="black" points="2872.5,-347 4244.5,-347 "/>
<polyline fill="none" stroke="black" points="2872.5,-323 4244.5,-323 "/>
<text text-anchor="start" x="2880.5" y="-307.8" font-family="Times,serif" font-size="14.00">center(center_of: CenterOf): Vector</text>
<text text-anchor="start" x="2880.5" y="-292.8" font-family="Times,serif" font-size="14.00">extrude_linear(cls: Union[Face, Wire], section: VectorLike, normal: list[Wire], inner_wires: float, taper): Solid</text>
<text text-anchor="start" x="2880.5" y="-277.8" font-family="Times,serif" font-size="14.00">extrude_linear_with_rotation(cls: Union[Face, Wire], section: VectorLike, center: VectorLike, normal: float, angle: list[Wire], inner_wires): Solid</text>
<text text-anchor="start" x="2880.5" y="-262.8" font-family="Times,serif" font-size="14.00">is_solid(obj): bool</text>
<text text-anchor="start" x="2880.5" y="-247.8" font-family="Times,serif" font-size="14.00">make_box(cls: float, length: float, width: float, height: VectorLike, pnt: VectorLike, dir): Solid</text>
<text text-anchor="start" x="2880.5" y="-232.8" font-family="Times,serif" font-size="14.00">make_cone(cls: float, radius1: float, radius2: float, height: VectorLike, pnt: VectorLike, dir: float, angle): Solid</text>
<text text-anchor="start" x="2880.5" y="-217.8" font-family="Times,serif" font-size="14.00">make_cylinder(cls: float, radius: float, height: VectorLike, pnt: VectorLike, dir: float, angle): Solid</text>
<text text-anchor="start" x="2880.5" y="-202.8" font-family="Times,serif" font-size="14.00">make_loft(cls: list[Wire], list_of_wire: bool, ruled): Solid</text>
<text text-anchor="start" x="2880.5" y="-187.8" font-family="Times,serif" font-size="14.00">make_solid(cls: Shell, shell): Solid</text>
<text text-anchor="start" x="2880.5" y="-172.8" font-family="Times,serif" font-size="14.00">make_sphere(cls: float, radius: VectorLike, pnt: VectorLike, dir: float, angle1: float, angle2: float, angle3): Shape</text>
<text text-anchor="start" x="2880.5" y="-157.8" font-family="Times,serif" font-size="14.00">make_torus(cls: float, radius1: float, radius2: VectorLike, pnt: VectorLike, dir: float, angle1: float, angle2): Solid</text>
<text text-anchor="start" x="2880.5" y="-142.8" font-family="Times,serif" font-size="14.00">make_wedge(cls: float, dx: float, dy: float, dz: float, xmin: float, zmin: float, xmax: float, zmax: VectorLike, pnt: VectorLike, dir): Solid</text>
<text text-anchor="start" x="2880.5" y="-127.8" font-family="Times,serif" font-size="14.00">revolve(cls: Union[Face, Wire], section: float, angle: Axis, axis: list[Wire], inner_wires): Solid</text>
<text text-anchor="start" x="2880.5" y="-112.8" font-family="Times,serif" font-size="14.00">sweep(cls: Union[Face, Wire], section: Union[Wire, Edge], path: list[Wire], inner_wires: bool, make_solid: bool, is_frenet: Union[Vector, Wire, Edge, None], mode: Transition, transition): Solid</text>
<text text-anchor="start" x="2880.5" y="-97.8" font-family="Times,serif" font-size="14.00">sweep_multi(cls: Iterable[Union[Wire, Face]], profiles: Union[Wire, Edge], path: bool, make_solid: bool, is_frenet: Union[Vector, Wire, Edge, None], mode): Solid</text>
<polygon fill="none" stroke="black" points="2872.5,-90.5 2872.5,-369.5 4244.5,-369.5 4244.5,-90.5 2872.5,-90.5"/>
<text text-anchor="middle" x="3558.5" y="-354.3" font-family="Times,serif" font-size="14.00">Solid</text>
<polyline fill="none" stroke="black" points="2872.5,-346.5 4244.5,-346.5 "/>
<text text-anchor="start" x="2880.5" y="-331.3" font-family="Times,serif" font-size="14.00">center</text>
<text text-anchor="start" x="2880.5" y="-316.3" font-family="Times,serif" font-size="14.00">center_of_mass</text>
<polyline fill="none" stroke="black" points="2872.5,-308.5 4244.5,-308.5 "/>
<text text-anchor="start" x="2880.5" y="-293.3" font-family="Times,serif" font-size="14.00">extrude_linear(cls: Union[Face, Wire], section: VectorLike, normal: list[Wire], inner_wires: float, taper): Solid</text>
<text text-anchor="start" x="2880.5" y="-278.3" font-family="Times,serif" font-size="14.00">extrude_linear_with_rotation(cls: Union[Face, Wire], section: VectorLike, center: VectorLike, normal: float, angle: list[Wire], inner_wires): Solid</text>
<text text-anchor="start" x="2880.5" y="-263.3" font-family="Times,serif" font-size="14.00">is_solid(obj): bool</text>
<text text-anchor="start" x="2880.5" y="-248.3" font-family="Times,serif" font-size="14.00">make_box(cls: float, length: float, width: float, height: VectorLike, pnt: VectorLike, dir): Solid</text>
<text text-anchor="start" x="2880.5" y="-233.3" font-family="Times,serif" font-size="14.00">make_cone(cls: float, radius1: float, radius2: float, height: VectorLike, pnt: VectorLike, dir: float, angle): Solid</text>
<text text-anchor="start" x="2880.5" y="-218.3" font-family="Times,serif" font-size="14.00">make_cylinder(cls: float, radius: float, height: VectorLike, pnt: VectorLike, dir: float, angle): Solid</text>
<text text-anchor="start" x="2880.5" y="-203.3" font-family="Times,serif" font-size="14.00">make_loft(cls: list[Wire], list_of_wire: bool, ruled): Solid</text>
<text text-anchor="start" x="2880.5" y="-188.3" font-family="Times,serif" font-size="14.00">make_solid(cls: Shell, shell): Solid</text>
<text text-anchor="start" x="2880.5" y="-173.3" font-family="Times,serif" font-size="14.00">make_sphere(cls: float, radius: VectorLike, pnt: VectorLike, dir: float, angle1: float, angle2: float, angle3): Shape</text>
<text text-anchor="start" x="2880.5" y="-158.3" font-family="Times,serif" font-size="14.00">make_torus(cls: float, radius1: float, radius2: VectorLike, pnt: VectorLike, dir: float, angle1: float, angle2): Solid</text>
<text text-anchor="start" x="2880.5" y="-143.3" font-family="Times,serif" font-size="14.00">make_wedge(cls: float, dx: float, dy: float, dz: float, xmin: float, zmin: float, xmax: float, zmax: VectorLike, pnt: VectorLike, dir): Solid</text>
<text text-anchor="start" x="2880.5" y="-128.3" font-family="Times,serif" font-size="14.00">revolve(cls: Union[Face, Wire], section: float, angle: Axis, axis: list[Wire], inner_wires): Solid</text>
<text text-anchor="start" x="2880.5" y="-113.3" font-family="Times,serif" font-size="14.00">sweep(cls: Union[Face, Wire], section: Union[Wire, Edge], path: list[Wire], inner_wires: bool, make_solid: bool, is_frenet: Union[Vector, Wire, Edge, None], mode: Transition, transition): Solid</text>
<text text-anchor="start" x="2880.5" y="-98.3" font-family="Times,serif" font-size="14.00">sweep_multi(cls: Iterable[Union[Wire, Face]], profiles: Union[Wire, Edge], path: bool, make_solid: bool, is_frenet: Union[Vector, Wire, Edge, None], mode): Solid</text>
</g>
<!-- build123d.direct_api.Solid&#45;&gt;build123d.direct_api.Mixin3D -->
<g id="edge8" class="edge">
<title>build123d.direct_api.Solid&#45;&gt;build123d.direct_api.Mixin3D</title>
<path fill="none" stroke="black" d="M3459.24,-370.22C3349.79,-523.72 3177.91,-764.78 3092.41,-884.7"/>
<polygon fill="none" stroke="black" points="3089.36,-882.95 3086.4,-893.12 3095.06,-887.01 3089.36,-882.95"/>
<path fill="none" stroke="black" d="M3459.54,-369.79C3350.14,-523.23 3178.08,-764.55 3092.47,-884.61"/>
<polygon fill="none" stroke="black" points="3089.41,-882.87 3086.46,-893.04 3095.11,-886.93 3089.41,-882.87"/>
</g>
<!-- build123d.direct_api.Solid&#45;&gt;build123d.direct_api.Shape -->
<g id="edge9" class="edge">
<title>build123d.direct_api.Solid&#45;&gt;build123d.direct_api.Shape</title>
<path fill="none" stroke="black" d="M3924.9,-370C4203.92,-475.86 4592.95,-623.44 4911.27,-744.21"/>
<polygon fill="none" stroke="black" points="4910.08,-747.5 4920.67,-747.77 4912.56,-740.95 4910.08,-747.5"/>
<path fill="none" stroke="black" d="M3923.77,-369.57C4202.95,-475.49 4592.74,-623.36 4911.55,-744.31"/>
<polygon fill="none" stroke="black" points="4910.37,-747.61 4920.96,-747.88 4912.85,-741.06 4910.37,-747.61"/>
</g>
<!-- build123d.direct_api.Vector -->
<g id="node16" class="node">
@ -441,18 +445,18 @@
<text text-anchor="start" x="279" y="-391.3" font-family="Times,serif" font-size="14.00">Y</text>
<text text-anchor="start" x="279" y="-376.3" font-family="Times,serif" font-size="14.00">Y</text>
<text text-anchor="start" x="279" y="-361.3" font-family="Times,serif" font-size="14.00">Z</text>
<text text-anchor="start" x="279" y="-346.3" font-family="Times,serif" font-size="14.00">vector_index : int</text>
<text text-anchor="start" x="279" y="-331.3" font-family="Times,serif" font-size="14.00">wrapped</text>
<polyline fill="none" stroke="black" points="271,-323.5 638,-323.5 "/>
<text text-anchor="start" x="279" y="-308.3" font-family="Times,serif" font-size="14.00">add(v: Vector): Vector</text>
<text text-anchor="start" x="279" y="-293.3" font-family="Times,serif" font-size="14.00">center(): Vector</text>
<text text-anchor="start" x="279" y="-278.3" font-family="Times,serif" font-size="14.00">cross(v: Vector): Vector</text>
<text text-anchor="start" x="279" y="-263.3" font-family="Times,serif" font-size="14.00">distance_to_line()</text>
<text text-anchor="start" x="279" y="-248.3" font-family="Times,serif" font-size="14.00">distance_to_plane()</text>
<text text-anchor="start" x="279" y="-233.3" font-family="Times,serif" font-size="14.00">dot(v: Vector): float</text>
<text text-anchor="start" x="279" y="-218.3" font-family="Times,serif" font-size="14.00">get_angle(v: Vector): float</text>
<text text-anchor="start" x="279" y="-203.3" font-family="Times,serif" font-size="14.00">get_signed_angle(v: Vector, normal: Vector): float</text>
<text text-anchor="start" x="279" y="-188.3" font-family="Times,serif" font-size="14.00">length(): float</text>
<text text-anchor="start" x="279" y="-346.3" font-family="Times,serif" font-size="14.00">center</text>
<text text-anchor="start" x="279" y="-331.3" font-family="Times,serif" font-size="14.00">length</text>
<text text-anchor="start" x="279" y="-316.3" font-family="Times,serif" font-size="14.00">vector_index : int</text>
<text text-anchor="start" x="279" y="-301.3" font-family="Times,serif" font-size="14.00">wrapped</text>
<polyline fill="none" stroke="black" points="271,-293.5 638,-293.5 "/>
<text text-anchor="start" x="279" y="-278.3" font-family="Times,serif" font-size="14.00">add(v: Vector): Vector</text>
<text text-anchor="start" x="279" y="-263.3" font-family="Times,serif" font-size="14.00">cross(v: Vector): Vector</text>
<text text-anchor="start" x="279" y="-248.3" font-family="Times,serif" font-size="14.00">distance_to_line()</text>
<text text-anchor="start" x="279" y="-233.3" font-family="Times,serif" font-size="14.00">distance_to_plane()</text>
<text text-anchor="start" x="279" y="-218.3" font-family="Times,serif" font-size="14.00">dot(v: Vector): float</text>
<text text-anchor="start" x="279" y="-203.3" font-family="Times,serif" font-size="14.00">get_angle(v: Vector): float</text>
<text text-anchor="start" x="279" y="-188.3" font-family="Times,serif" font-size="14.00">get_signed_angle(v: Vector, normal: Vector): float</text>
<text text-anchor="start" x="279" y="-173.3" font-family="Times,serif" font-size="14.00">multiply(scale: float): Vector</text>
<text text-anchor="start" x="279" y="-158.3" font-family="Times,serif" font-size="14.00">normalized(): Vector</text>
<text text-anchor="start" x="279" y="-143.3" font-family="Times,serif" font-size="14.00">project_to_line(line: Vector): Vector</text>
@ -545,10 +549,10 @@
<text text-anchor="start" x="5686.5" y="-271.3" font-family="Times,serif" font-size="14.00">X</text>
<text text-anchor="start" x="5686.5" y="-256.3" font-family="Times,serif" font-size="14.00">Y</text>
<text text-anchor="start" x="5686.5" y="-241.3" font-family="Times,serif" font-size="14.00">Z</text>
<text text-anchor="start" x="5686.5" y="-226.3" font-family="Times,serif" font-size="14.00">for_construction : bool</text>
<text text-anchor="start" x="5686.5" y="-211.3" font-family="Times,serif" font-size="14.00">wrapped</text>
<polyline fill="none" stroke="black" points="5678.5,-203.5 5934.5,-203.5 "/>
<text text-anchor="start" x="5686.5" y="-188.3" font-family="Times,serif" font-size="14.00">center(): Vector</text>
<text text-anchor="start" x="5686.5" y="-226.3" font-family="Times,serif" font-size="14.00">center</text>
<text text-anchor="start" x="5686.5" y="-211.3" font-family="Times,serif" font-size="14.00">for_construction : bool</text>
<text text-anchor="start" x="5686.5" y="-196.3" font-family="Times,serif" font-size="14.00">wrapped</text>
<polyline fill="none" stroke="black" points="5678.5,-188.5 5934.5,-188.5 "/>
<text text-anchor="start" x="5686.5" y="-173.3" font-family="Times,serif" font-size="14.00">to_tuple(): tuple[float, float, float]</text>
<text text-anchor="start" x="5686.5" y="-158.3" font-family="Times,serif" font-size="14.00">to_vector(): Vector</text>
</g>
@ -583,8 +587,8 @@
<!-- build123d.direct_api.Wire&#45;&gt;build123d.direct_api.Mixin1D -->
<g id="edge11" class="edge">
<title>build123d.direct_api.Wire&#45;&gt;build123d.direct_api.Mixin1D</title>
<path fill="none" stroke="black" d="M7622.8,-362.56C7505.62,-491.36 7327.75,-686.84 7208.22,-818.22"/>
<polygon fill="none" stroke="black" points="7205.29,-816.24 7201.15,-826 7210.47,-820.96 7205.29,-816.24"/>
<path fill="none" stroke="black" d="M7622.8,-362.56C7505.52,-491.46 7327.48,-687.15 7207.94,-818.53"/>
<polygon fill="none" stroke="black" points="7205.01,-816.55 7200.87,-826.3 7210.19,-821.26 7205.01,-816.55"/>
</g>
<!-- build123d.direct_api.Wire&#45;&gt;build123d.direct_api.Shape -->
<g id="edge12" class="edge">

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Before After
Before After

View file

@ -49,7 +49,7 @@ with Workplanes(Plane.XY):
x_count=exchanger_diameter // tube_diameter,
y_count=exchanger_diameter // tube_diameter,
)
if l.position.length() < bundle_diameter / 2
if l.position.length < bundle_diameter / 2
]
tube_count = len(tube_locations)
print(f"{tube_count=}")
@ -71,7 +71,7 @@ with BuildPart() as heat_exchanger:
with Locations(*tube_locations):
Circle(radius=tube_diameter / 2 - tube_wall_thickness, mode=Mode.SUBTRACT)
Extrude(amount=plate_thickness)
half_volume_before_fillet = heat_exchanger.part.volume()
half_volume_before_fillet = heat_exchanger.part.volume
# Simulate welded tubes by adding a fillet to the outside radius of the tubes
Fillet(
*heat_exchanger.edges()
@ -80,7 +80,7 @@ with BuildPart() as heat_exchanger:
.sort_by(Axis.Z, reverse=True)[2 * tube_count : 3 * tube_count],
radius=fillet_radius,
)
half_volume_after_fillet = heat_exchanger.part.volume()
half_volume_after_fillet = heat_exchanger.part.volume
Mirror(about=Plane.XY)
fillet_volume = 2 * (half_volume_after_fillet - half_volume_before_fillet)

View file

@ -574,13 +574,13 @@ class Workplanes(WorkplaneList):
plane_face = Face.make_rect(1, 1).move(obj)
self.workplanes.append(
Plane(
origin=plane_face.center(),
z_dir=plane_face.normal_at(plane_face.center()),
origin=plane_face.center,
z_dir=plane_face.normal_at(plane_face.center),
)
)
elif isinstance(obj, Face):
self.workplanes.append(
Plane(origin=obj.center(), z_dir=obj.normal_at(obj.center()))
Plane(origin=obj.center, z_dir=obj.normal_at(obj.center))
)
else:
raise ValueError(f"Workplanes does not accept {type(obj)}")

View file

@ -479,7 +479,7 @@ class Scale(Compound):
)
new_objects = []
for obj in objects:
current_location = obj.location()
current_location = obj.location
obj_at_origin = obj.located(Location(Vector()))
new_objects.append(
obj_at_origin.transform_geometry(scale_matrix).locate(current_location)

View file

@ -343,7 +343,7 @@ class Polyline(Wire):
Edge.make_line(lines_pts[i], lines_pts[i + 1])
for i in range(len(lines_pts) - 1)
]
if close and (new_edges[0] @ 0 - new_edges[-1] @ 1).length() > 1e-5:
if close and (new_edges[0] @ 0 - new_edges[-1] @ 1).length > 1e-5:
new_edges.append(Edge.make_line(new_edges[-1] @ 1, new_edges[0] @ 0))
context._add_to_context(*new_edges, mode=mode)
@ -378,7 +378,7 @@ class RadiusArc(Edge):
end = Vector(end_point)
# Calculate the sagitta from the radius
length = end.sub(start).length() / 2.0
length = end.sub(start).length / 2.0
try:
sagitta = abs(radius) - sqrt(radius**2 - length**2)
except ValueError as exception:

View file

@ -129,7 +129,7 @@ class BuildPart(Builder):
for face in new_faces:
logger.debug(
"Adding Face to pending_faces at %s",
face.location(),
face.location,
)
self.pending_faces.append(face)
self.pending_face_planes.append(face_plane)
@ -138,7 +138,7 @@ class BuildPart(Builder):
for edge in new_edges:
logger.debug(
"Adding Edge to pending_edges at %s",
edge.location(),
edge.location,
)
self.pending_edges.append(edge)
@ -469,7 +469,7 @@ class Extrude(Compound):
trim_faces = [
f
for f in trim_faces
if f.normal_at(f.center()).dot(plane.z_dir) != 0.0
if f.normal_at(f.center).dot(plane.z_dir) != 0.0
]
# Group the faces into surfaces
trim_shells = Shell.make_shell(trim_faces).shells()
@ -480,7 +480,7 @@ class Extrude(Compound):
face_directions = Vector(0, 0, 0)
for trim_face in trim_shell.faces():
face_directions = face_directions + trim_face.normal_at(
trim_face.center()
trim_face.center
)
surface_dirs.append(face_directions.get_angle(plane.z_dir))
if until == Until.NEXT:
@ -501,7 +501,7 @@ class Extrude(Compound):
for trim_object, trim_face in zip(trim_objects, trim_faces):
if not trim_object.is_valid():
warn(
message=f"Part face with area {trim_face.area()} "
message=f"Part face with area {trim_face.area} "
f"creates an invalid extrusion",
category=Warning,
)
@ -656,7 +656,7 @@ class Revolve(Compound):
for profile in profiles:
# axis origin must be on the same plane as profile
face_occt_pln = gp_Pln(
profile.center().to_pnt(), profile.normal_at(profile.center()).to_dir()
profile.center.to_pnt(), profile.normal_at(profile.center).to_dir()
)
if not face_occt_pln.Contains(axis.position.to_pnt(), 1e-5):
raise ValueError(

View file

@ -515,6 +515,7 @@ class Vector:
def to_tuple(self) -> tuple[float, float, float]:
return (self.X, self.Y, self.Z)
@property
def length(self) -> float:
return self.wrapped.Magnitude()
@ -568,6 +569,7 @@ class Vector:
def normalized(self) -> Vector:
return Vector(self.wrapped.Normalized())
@property
def center(self) -> Vector:
"""center
@ -616,7 +618,7 @@ class Vector:
Vector: Returns the projected vector.
"""
line_length = line.length()
line_length = line.length
return line * (self.dot(line) / (line_length * line_length))
@ -638,13 +640,13 @@ class Vector:
base = plane._origin
normal = plane.z_dir
return self - normal * (((self - base).dot(normal)) / normal.length() ** 2)
return self - normal * (((self - base).dot(normal)) / normal.length**2)
def __neg__(self) -> Vector:
return self * -1
def __abs__(self) -> float:
return self.length()
return self.length
def __repr__(self) -> str:
return "Vector: " + str((self.X, self.Y, self.Z))
@ -904,8 +906,9 @@ class BoundBox:
self.zmax = z_max
self.zlen = z_max - z_min
@property
def center(self) -> Vector:
"""center"""
"""Return center of the bounding box"""
return Vector(
(self.xmax + self.xmin) / 2,
(self.ymax + self.ymin) / 2,
@ -1494,31 +1497,24 @@ class Mixin1D:
return return_value
def center(self, center_of: CenterOf = CenterOf.GEOMETRY) -> Vector:
"""Center of object
@property
def center(self) -> Vector:
"""Return center along Edge/Wire"""
return self.position_at(0.5)
Return the center based on center_of
Args:
center_of (CenterOf, optional): centering option. Defaults to CenterOf.GEOMETRY.
Returns:
Vector: center
"""
if center_of == CenterOf.GEOMETRY:
middle = self.position_at(0.5)
elif center_of == CenterOf.MASS:
properties = GProp_GProps()
BRepGProp.LinearProperties_s(self.wrapped, properties)
middle = Vector(properties.CentreOfMass())
elif center_of == CenterOf.BOUNDING_BOX:
middle = self.bounding_box().center()
return middle
@property
def center_of_mass(self) -> Vector:
"""Return center of mass - which may not be on the Edge/Wire"""
properties = GProp_GProps()
BRepGProp.LinearProperties_s(self.wrapped, properties)
return Vector(properties.CentreOfMass())
@property
def length(self) -> float:
return GCPnts_AbscissaPoint.Length_s(self._geom_adaptor())
@property
def radius(self) -> float:
"""Calculate the radius.
@ -1927,6 +1923,16 @@ class Shape:
# Helps identify this solid through the use of an ID
self.label: str = ""
@property
def location(self) -> Location:
"""Get this Shape's Location"""
return Location(self.wrapped.Location())
@location.setter
def location(self, value: Location):
"""Set Shape's Location to value"""
self.wrapped.Location(value)
@property
def position(self) -> Vector:
"""Get the position component of this Shape's Location"""
@ -2272,8 +2278,7 @@ class Shape:
if center_of == CenterOf.MASS:
total_mass = sum(Shape.compute_mass(o) for o in objects)
weighted_centers = [
o.center(center_of=CenterOf.MASS).multiply(Shape.compute_mass(o))
for o in objects
o.center_of_mass.multiply(Shape.compute_mass(o)) for o in objects
]
sum_wc = weighted_centers[0]
@ -2285,7 +2290,7 @@ class Shape:
weighted_centers = []
for o in objects:
weighted_centers.append(BoundBox._from_topo_ds(o.wrapped).center())
weighted_centers.append(o.bounding_box().center)
sum_wc = weighted_centers[0]
for wc in weighted_centers[1:]:
@ -2447,6 +2452,7 @@ class Shape:
return ShapeList([Solid(i) for i in self._entities(Solid.__name__)])
@property
def area(self) -> float:
"""
@ -2461,6 +2467,7 @@ class Shape:
return properties.Mass()
@property
def volume(self) -> float:
"""
@ -2593,9 +2600,6 @@ class Shape:
return new_shape
def location(self) -> Location:
return Location(self.wrapped.Location())
def locate(self, loc: Location) -> Shape:
"""Apply a location in absolute sense to self
@ -3112,8 +3116,8 @@ class Shape:
"""
path_length = path.length()
shape_center = self.center()
path_length = path.length
shape_center = self.center
# Create text faces
text_faces = Compound.make_2d_text(
@ -3150,7 +3154,7 @@ class Shape:
projected_text = projected_faces
else:
projected_text = [
f.thicken(depth, f.center() - shape_center) for f in projected_faces
f.thicken(depth, f.center - shape_center) for f in projected_faces
]
logging.debug(f"finished projecting text sting '{txt}'")
@ -3279,7 +3283,7 @@ class ShapeList(list[T]):
result = list(
filter(
lambda o: filter_by.is_parallel(
Axis(o.center(), o.normal_at(None)), tolerance
Axis(o.center, o.normal_at(None)), tolerance
),
planar_faces,
)
@ -3335,28 +3339,28 @@ class ShapeList(list[T]):
if inclusive == (True, True):
objects = filter(
lambda o: minimum
<= axis.to_plane().to_local_coords(o).center().Z
<= axis.to_plane().to_local_coords(o).center.Z
<= maximum,
self,
)
elif inclusive == (True, False):
objects = filter(
lambda o: minimum
<= axis.to_plane().to_local_coords(o).center().Z
<= axis.to_plane().to_local_coords(o).center.Z
< maximum,
self,
)
elif inclusive == (False, True):
objects = filter(
lambda o: minimum
< axis.to_plane().to_local_coords(o).center().Z
< axis.to_plane().to_local_coords(o).center.Z
<= maximum,
self,
)
elif inclusive == (False, False):
objects = filter(
lambda o: minimum
< axis.to_plane().to_local_coords(o).center().Z
< axis.to_plane().to_local_coords(o).center.Z
< maximum,
self,
)
@ -3382,23 +3386,23 @@ class ShapeList(list[T]):
groups = {}
for obj in self:
if isinstance(group_by, Axis):
key = group_by.to_plane().to_local_coords(obj).center().Z
key = group_by.to_plane().to_local_coords(obj).center.Z
elif isinstance(group_by, SortBy):
if group_by == SortBy.LENGTH:
key = obj.length()
key = obj.length
elif group_by == SortBy.RADIUS:
key = obj.radius()
key = obj.radius
elif group_by == SortBy.DISTANCE:
key = obj.center().length()
key = obj.center.length
elif group_by == SortBy.AREA:
key = obj.area()
key = obj.area
elif group_by == SortBy.VOLUME:
key = obj.volume()
key = obj.volume
else:
raise ValueError(f"Group by {type(group_by)} unsupported")
@ -3431,7 +3435,7 @@ class ShapeList(list[T]):
if isinstance(sort_by, Axis):
objects = sorted(
self,
key=lambda o: sort_by.to_plane().to_local_coords(o).center().Z,
key=lambda o: sort_by.to_plane().to_local_coords(o).center.Z,
reverse=reverse,
)
@ -3439,31 +3443,31 @@ class ShapeList(list[T]):
if sort_by == SortBy.LENGTH:
objects = sorted(
self,
key=lambda obj: obj.length(),
key=lambda obj: obj.length,
reverse=reverse,
)
elif sort_by == SortBy.RADIUS:
objects = sorted(
self,
key=lambda obj: obj.radius(),
key=lambda obj: obj.radius,
reverse=reverse,
)
elif sort_by == SortBy.DISTANCE:
objects = sorted(
self,
key=lambda obj: obj.center().length(),
key=lambda obj: obj.center.length,
reverse=reverse,
)
elif sort_by == SortBy.AREA:
objects = sorted(
self,
key=lambda obj: obj.area(),
key=lambda obj: obj.area,
reverse=reverse,
)
elif sort_by == SortBy.VOLUME:
objects = sorted(
self,
key=lambda obj: obj.volume(),
key=lambda obj: obj.volume,
reverse=reverse,
)
@ -3639,7 +3643,7 @@ class Plane:
ValueError: if the specified x_dir is not orthogonal to the provided normal
"""
self.z_dir = Vector(z_dir)
if self.z_dir.length() == 0.0:
if self.z_dir.length == 0.0:
raise ValueError("normal should be non null")
self.z_dir = self.z_dir.normalized()
@ -3648,7 +3652,7 @@ class Plane:
ax3 = gp_Ax3(Vector(origin).to_pnt(), Vector(z_dir).to_dir())
self.x_dir = Vector(ax3.XDirection()).normalized()
else:
if Vector(x_dir).length() == 0.0:
if Vector(x_dir).length == 0.0:
raise ValueError("x_dir should be non null")
self.x_dir = Vector(x_dir).normalized()
self.y_dir = self.z_dir.cross(self.x_dir).normalized()
@ -4072,7 +4076,7 @@ class Compound(Shape, Mixin3D):
text_flat = text_flat.translate(t)
if text_path is not None:
path_length = text_path.length()
path_length = text_path.length
text_flat = Compound.make_compound(
[position_face(f) for f in text_flat.faces()]
)
@ -4209,6 +4213,7 @@ class Edge(Shape, Mixin1D):
"""Edge as Wire"""
return Wire.make_wire([self])
@property
def arc_center(self) -> Vector:
"""center of an underlying circle or ellipse geometry."""
@ -4626,33 +4631,29 @@ class Face(Shape):
return Vector(vn)
def center(self, center_of: CenterOf = CenterOf.GEOMETRY) -> Vector:
"""Center of object
@property
def center(self) -> Vector:
"""Center of geometry"""
return self.center_of_geometry
Return the center based on center_of
@property
def center_of_mass(self) -> Vector:
"""Center of mass"""
properties = GProp_GProps()
BRepGProp.SurfaceProperties_s(self.wrapped, properties)
return Vector(properties.CentreOfMass())
Args:
center_of (CenterOf, optional): centering option. Defaults to CenterOf.GEOMETRY.
@property
def center_of_geometry(self) -> Vector:
"""Center of geometry"""
u0, u1, v0, v1 = self._uv_bounds()
u = 0.5 * (u0 + u1)
v = 0.5 * (v0 + v1)
Returns:
Vector: center
"""
if center_of == CenterOf.MASS:
properties = GProp_GProps()
BRepGProp.LinearProperties_s(self.wrapped, properties)
middle = Vector(properties.CentreOfMass())
elif center_of == CenterOf.GEOMETRY:
u0, u1, v0, v1 = self._uv_bounds()
u = 0.5 * (u0 + u1)
v = 0.5 * (v0 + v1)
p = gp_Pnt()
vn = gp_Vec()
BRepGProp_Face(self.wrapped).Normal(u, v, p, vn)
middle = Vector(p)
elif center_of == CenterOf.BOUNDING_BOX:
middle = self.bounding_box().center()
return middle
p = gp_Pnt()
vn = gp_Vec()
BRepGProp_Face(self.wrapped).Normal(u, v, p, vn)
return Vector(p)
def outer_wire(self) -> Wire:
@ -5011,7 +5012,7 @@ class Face(Shape):
# Check to see if the normal needs to be flipped
adjusted_depth = depth
if direction is not None:
face_center = self.center()
face_center = self.center
face_normal = self.normal_at(face_center).normalized()
if face_normal.dot(Vector(direction).normalized()) < 0:
adjusted_depth = -depth
@ -5162,7 +5163,7 @@ class Face(Shape):
# Not sure if it's always a good idea to add an internal central point so the next
# two lines of code can be easily removed without impacting the rest
if not internal_face_points:
internal_face_points = [planar_outer_wire.center()]
internal_face_points = [planar_outer_wire.center]
if not internal_face_points:
projected_grid_points = []
@ -5297,30 +5298,21 @@ class Solid(Shape, Mixin3D):
return True
return False
def center(self, center_of: CenterOf = CenterOf.MASS) -> Vector:
"""Return center of object
@property
def center(self) -> Vector:
"""Return center of mass"""
return self.center_of_mass
Find center of object
Args:
center_of (CenterOf, optional): center option. Defaults to CenterOf.GEOMETRY.
Returns:
Vector: center
"""
if center_of == CenterOf.GEOMETRY:
raise ValueError("Center of GEOMETRY is not supported for this object")
if center_of == CenterOf.MASS:
properties = GProp_GProps()
calc_function = shape_properties_LUT[shapetype(self.wrapped)]
if calc_function:
calc_function(self.wrapped, properties)
middle = Vector(properties.CentreOfMass())
else:
raise NotImplementedError
elif center_of == CenterOf.BOUNDING_BOX:
middle = self.bounding_box(tolerance=1e-6).center
return middle
@property
def center_of_mass(self) -> Vector:
"""Return center of mass"""
properties = GProp_GProps()
calc_function = shape_properties_LUT[shapetype(self.wrapped)]
if calc_function:
calc_function(self.wrapped, properties)
return Vector(properties.CentreOfMass())
else:
raise NotImplementedError
@classmethod
def make_solid(cls, shell: Shell) -> Solid:
@ -5618,7 +5610,7 @@ class Solid(Shape, Mixin3D):
face_normal = section_face.normal_at()
d = 1 if normal.get_angle(face_normal) < 90 else -1
prism_builder = LocOpe_DPrism(
section_face.wrapped, d * normal.length(), d * taper * DEG2RAD
section_face.wrapped, d * normal.length, d * taper * DEG2RAD
)
return cls(prism_builder.Shape())
@ -5686,10 +5678,10 @@ class Solid(Shape, Mixin3D):
)[0].wrapped
# make an auxiliary spine
pitch = 360.0 / angle * normal.length()
pitch = 360.0 / angle * normal.length
radius = 1
aux_spine_w = Wire.make_helix(
pitch, normal.length(), radius, center=center, normal=normal
pitch, normal.length, radius, center=center, normal=normal
).wrapped
# extrude the outer wire
@ -5925,6 +5917,7 @@ class Vertex(Shape):
geom_point = BRep_Tool.Pnt_s(self.wrapped)
return (geom_point.X(), geom_point.Y(), geom_point.Z())
@property
def center(self) -> Vector:
"""The center of a vertex is itself!"""
return Vector(self.to_tuple())
@ -6094,8 +6087,8 @@ class Wire(Shape, Mixin1D):
sorted_edges = sorted(
unplaced_edges,
key=lambda e: min(
(target_point - e.position_at(0)).length(),
(target_point - e.position_at(1)).length(),
(target_point - e.position_at(0)).length,
(target_point - e.position_at(1)).length,
),
)
return sorted_edges[0]
@ -6206,7 +6199,7 @@ class Wire(Shape, Mixin1D):
Wire: an irregular polygon
"""
vertices = [Vector(v) for v in vertices]
if (vertices[0] - vertices[-1]).length() > TOLERANCE and close:
if (vertices[0] - vertices[-1]).length > TOLERANCE and close:
vertices.append(vertices[0])
wire_builder = BRepBuilderAPI_MakePolygon()
@ -6460,9 +6453,9 @@ class Wire(Shape, Mixin1D):
# by distance from the original planar wire
if len(output_wires) > 1:
output_wires_distances = []
planar_wire_center = self.center()
planar_wire_center = self.center
for output_wire in output_wires:
output_wire_center = output_wire.center()
output_wire_center = output_wire.center
if direction_vector is not None:
output_wire_direction = (
output_wire_center - planar_wire_center
@ -6471,12 +6464,12 @@ class Wire(Shape, Mixin1D):
output_wires_distances.append(
(
output_wire,
(output_wire_center - planar_wire_center).length(),
(output_wire_center - planar_wire_center).length,
)
)
else:
output_wires_distances.append(
(output_wire, (output_wire_center - center_point).length())
(output_wire, (output_wire_center - center_point).length)
)
output_wires_distances.sort(key=lambda x: x[1])

View file

@ -98,8 +98,8 @@ def convert_and_validate(edges: Iterable[Edge]) -> Tuple[List[Arc], List[Point]]
points.update((Point(p1.X, p1.Y), Point(p2.X, p2.Y)))
elif gt == "CIRCLE":
c = e.arc_center()
r = e.radius()
c = e.arc_center
r = e.radius
a1, a2 = e._bounds()
arcs.add(Arc(Point(c.X, c.Y), r, a1, a2))

View file

@ -108,14 +108,14 @@ class TestShapeList(unittest.TestCase):
self.assertTrue(isinstance(edges, ShapeList))
self.assertEqual(len(edges), 4)
if axis == Axis.X:
self.assertLessEqual(faces[0].center().x, faces[1].center().x)
self.assertLessEqual(edges[0].center().x, edges[-1].center().x)
self.assertLessEqual(faces[0].center.x, faces[1].center.x)
self.assertLessEqual(edges[0].center.x, edges[-1].center.x)
elif axis == Axis.Y:
self.assertLessEqual(faces[0].center().y, faces[1].center().y)
self.assertLessEqual(edges[0].center().y, edges[-1].center().y)
self.assertLessEqual(faces[0].center.y, faces[1].center.y)
self.assertLessEqual(edges[0].center.y, edges[-1].center.y)
elif axis == Axis.Z:
self.assertLessEqual(faces[0].center().z, faces[1].center().z)
self.assertLessEqual(edges[0].center().z, edges[-1].center().z)
self.assertLessEqual(faces[0].center.z, faces[1].center.z)
self.assertLessEqual(edges[0].center.z, edges[-1].center.z)
# test filter by type
with BuildPart() as test:
@ -147,26 +147,14 @@ class TestShapeList(unittest.TestCase):
self.assertTrue(isinstance(edges, ShapeList))
self.assertEqual(len(edges), 4 * sum(inclusive) + 4)
if axis == Axis.X:
self.assertLessEqual(
faces[0].center().x, faces[-1].center().x
)
self.assertLessEqual(
edges[0].center().x, edges[-1].center().x
)
self.assertLessEqual(faces[0].center.x, faces[-1].center.x)
self.assertLessEqual(edges[0].center.x, edges[-1].center.x)
elif axis == Axis.Y:
self.assertLessEqual(
faces[0].center().y, faces[-1].center().y
)
self.assertLessEqual(
edges[0].center().y, edges[-1].center().y
)
self.assertLessEqual(faces[0].center.y, faces[-1].center.y)
self.assertLessEqual(edges[0].center.y, edges[-1].center.y)
elif axis == Axis.Z:
self.assertLessEqual(
faces[0].center().z, faces[-1].center().z
)
self.assertLessEqual(
edges[0].center().z, edges[-1].center().z
)
self.assertLessEqual(faces[0].center.z, faces[-1].center.z)
self.assertLessEqual(edges[0].center.z, edges[-1].center.z)
def test_sort_by_type(self):
"""test sorting by different attributes"""
@ -174,22 +162,22 @@ class TestShapeList(unittest.TestCase):
with BuildPart() as test:
Wedge(1, 1, 1, 0, 0, 0.5, 0.5)
faces = test.faces().sort_by(SortBy.AREA)
self.assertEqual(faces[0].area(), 0.25)
self.assertEqual(faces[-1].area(), 1)
self.assertEqual(faces[0].area, 0.25)
self.assertEqual(faces[-1].area, 1)
with self.subTest(sort_by=SortBy.LENGTH):
with BuildPart() as test:
Wedge(1, 1, 1, 0, 0, 0.5, 0.5)
edges = test.edges().sort_by(SortBy.LENGTH)
self.assertEqual(edges[0].length(), 0.5)
self.assertAlmostEqual(edges[-1].length(), 1.2247448713915892, 7)
self.assertEqual(edges[0].length, 0.5)
self.assertAlmostEqual(edges[-1].length, 1.2247448713915892, 7)
with self.subTest(sort_by=SortBy.DISTANCE):
with BuildPart() as test:
Box(1, 1, 1, centered=(False, True, True))
faces = test.faces().sort_by(SortBy.DISTANCE)
self.assertAlmostEqual(faces[0].center().length(), 0, 7)
self.assertAlmostEqual(faces[-1].center().length(), 1, 7)
self.assertAlmostEqual(faces[0].center.length, 0, 7)
self.assertAlmostEqual(faces[-1].center.length, 1, 7)
with self.subTest(sort_by=SortBy.VOLUME):
with BuildPart() as test:
@ -197,36 +185,36 @@ class TestShapeList(unittest.TestCase):
with Locations((0, 0, 10)):
Box(2, 2, 2)
solids = test.solids().sort_by(SortBy.VOLUME)
self.assertAlmostEqual(solids[0].volume(), 1, 7)
self.assertAlmostEqual(solids[-1].volume(), 8, 7)
self.assertAlmostEqual(solids[0].volume, 1, 7)
self.assertAlmostEqual(solids[-1].volume, 8, 7)
with self.subTest(sort_by=SortBy.RADIUS):
with BuildPart() as test:
Cone(1, 0.5, 2)
edges = test.edges().filter_by(GeomType.CIRCLE).sort_by(SortBy.RADIUS)
self.assertEqual(edges[0].radius(), 0.5)
self.assertEqual(edges[-1].radius(), 1)
self.assertEqual(edges[0].radius, 0.5)
self.assertEqual(edges[-1].radius, 1)
with self.subTest(sort_by="X"):
with BuildPart() as test:
Box(1, 1, 1)
edges = test.edges() > Axis.X
self.assertEqual(edges[0].center().X, -0.5)
self.assertEqual(edges[-1].center().X, 0.5)
self.assertEqual(edges[0].center.X, -0.5)
self.assertEqual(edges[-1].center.X, 0.5)
with self.subTest(sort_by="Y"):
with BuildPart() as test:
Box(1, 1, 1)
edges = test.edges() > Axis.Y
self.assertEqual(edges[0].center().Y, -0.5)
self.assertEqual(edges[-1].center().Y, 0.5)
self.assertEqual(edges[0].center.Y, -0.5)
self.assertEqual(edges[-1].center.Y, 0.5)
with self.subTest(sort_by="Z"):
with BuildPart() as test:
Box(1, 1, 1)
edges = test.edges() > Axis.Z
self.assertEqual(edges[0].center().Z, -0.5)
self.assertEqual(edges[-1].center().Z, 0.5)
self.assertEqual(edges[0].center.Z, -0.5)
self.assertEqual(edges[-1].center.Z, 0.5)
def test_vertices(self):
with BuildPart() as test:

View file

@ -79,13 +79,13 @@ class AddTests(unittest.TestCase):
def test_add_to_sketch(self):
with BuildSketch() as test:
Add(Face.make_rect(10, 10))
self.assertAlmostEqual(test.sketch.area(), 100, 5)
self.assertAlmostEqual(test.sketch.area, 100, 5)
def test_add_to_part(self):
# Add Solid
with BuildPart() as test:
Add(Solid.make_box(10, 10, 10))
self.assertAlmostEqual(test.part.volume(), 1000, 5)
self.assertAlmostEqual(test.part.volume, 1000, 5)
# Add Compound
with BuildPart() as test:
Add(
@ -96,7 +96,7 @@ class AddTests(unittest.TestCase):
]
)
)
self.assertEqual(test.part.volume(), 1125, 5)
self.assertEqual(test.part.volume, 1125, 5)
# Add Wire
with BuildLine() as wire:
Polyline((0, 0, 0), (1, 1, 1), (2, 0, 0), (3, 1, 1))
@ -128,7 +128,7 @@ class TestOffset(unittest.TestCase):
Line(l @ 1, (1, 1))
Offset(amount=1)
MakeFace()
self.assertAlmostEqual(test.sketch.area(), pi * 1.25 + 3, 5)
self.assertAlmostEqual(test.sketch.area, pi * 1.25 + 3, 5)
def test_line_offset(self):
with BuildSketch() as test:
@ -137,13 +137,13 @@ class TestOffset(unittest.TestCase):
Line(l @ 1, (1, 1))
Offset(*line.line.edges(), amount=1)
MakeFace()
self.assertAlmostEqual(test.sketch.area(), pi * 1.25 + 3, 5)
self.assertAlmostEqual(test.sketch.area, pi * 1.25 + 3, 5)
def test_face_offset(self):
with BuildSketch() as test:
Rectangle(1, 1)
Offset(amount=1, kind=Kind.INTERSECTION)
self.assertAlmostEqual(test.sketch.area(), 9, 5)
self.assertAlmostEqual(test.sketch.area, 9, 5)
def test_box_offset(self):
with BuildPart() as test:
@ -152,7 +152,7 @@ class TestOffset(unittest.TestCase):
amount=1,
kind=Kind.INTERSECTION,
)
self.assertAlmostEqual(test.part.volume(), 3**3 - 1**3, 5)
self.assertAlmostEqual(test.part.volume, 3**3 - 1**3, 5)
def test_box_offset_with_opening(self):
with BuildPart() as test:
@ -162,7 +162,7 @@ class TestOffset(unittest.TestCase):
openings=test.faces() >> Axis.Z,
kind=Kind.INTERSECTION,
)
self.assertAlmostEqual(test.part.volume(), 10**3 - 8**2 * 9, 5)
self.assertAlmostEqual(test.part.volume, 10**3 - 8**2 * 9, 5)
class BoundingBoxTests(unittest.TestCase):
@ -175,7 +175,7 @@ class BoundingBoxTests(unittest.TestCase):
ears = (bb.vertices() > Axis.Y)[:-2]
with Locations(*ears):
Circle(7)
self.assertAlmostEqual(mickey.sketch.area(), 586.1521145312807, 5)
self.assertAlmostEqual(mickey.sketch.area, 586.1521145312807, 5)
"""Test Vertices"""
with BuildSketch() as test:
Rectangle(10, 10)
@ -186,11 +186,11 @@ class BoundingBoxTests(unittest.TestCase):
with BuildPart() as test:
Sphere(1)
BoundingBox(*test.solids())
self.assertAlmostEqual(test.part.volume(), 8, 5)
self.assertAlmostEqual(test.part.volume, 8, 5)
with BuildPart() as test:
Sphere(1)
BoundingBox(*test.vertices())
self.assertAlmostEqual(test.part.volume(), (4 / 3) * pi, 5)
self.assertAlmostEqual(test.part.volume, (4 / 3) * pi, 5)
def test_errors(self):
with self.assertRaises(RuntimeError):
@ -203,13 +203,13 @@ class ChamferTests(unittest.TestCase):
with BuildPart() as test:
Box(10, 10, 10)
Chamfer(*test.edges(), length=1)
self.assertLess(test.part.volume(), 1000)
self.assertLess(test.part.volume, 1000)
def test_sketch_chamfer(self):
with BuildSketch() as test:
Rectangle(10, 10)
Chamfer(*test.vertices(), length=1)
self.assertAlmostEqual(test.sketch.area(), 100 - 4 * 0.5, 5)
self.assertAlmostEqual(test.sketch.area, 100 - 4 * 0.5, 5)
with BuildSketch() as test:
with Locations((-10, 0), (10, 0)):
@ -218,7 +218,7 @@ class ChamferTests(unittest.TestCase):
*test.vertices().filter_by_position(Axis.X, minimum=0, maximum=20),
length=1
)
self.assertAlmostEqual(test.sketch.area(), 200 - 4 * 0.5, 5)
self.assertAlmostEqual(test.sketch.area, 200 - 4 * 0.5, 5)
def test_errors(self):
with self.assertRaises(RuntimeError):
@ -231,13 +231,13 @@ class FilletTests(unittest.TestCase):
with BuildPart() as test:
Box(10, 10, 10)
Fillet(*test.edges(), radius=1)
self.assertLess(test.part.volume(), 1000)
self.assertLess(test.part.volume, 1000)
def test_sketch_chamfer(self):
with BuildSketch() as test:
Rectangle(10, 10)
Fillet(*test.vertices(), radius=1)
self.assertAlmostEqual(test.sketch.area(), 100 - 4 + pi, 5)
self.assertAlmostEqual(test.sketch.area, 100 - 4 + pi, 5)
with BuildSketch() as test:
with Locations((-10, 0), (10, 0)):
@ -246,7 +246,7 @@ class FilletTests(unittest.TestCase):
*test.vertices().filter_by_position(Axis.X, minimum=0, maximum=20),
radius=1
)
self.assertAlmostEqual(test.sketch.area(), 200 - 4 + pi, 5)
self.assertAlmostEqual(test.sketch.area, 200 - 4 + pi, 5)
def test_errors(self):
with self.assertRaises(RuntimeError):
@ -260,7 +260,7 @@ class HexArrayTests(unittest.TestCase):
Rectangle(70, 70)
with HexLocations(20, 4, 3, centered=(True, True)):
Circle(5, mode=Mode.SUBTRACT)
self.assertAlmostEqual(test.sketch.area(), 70**2 - 12 * 25 * pi, 5)
self.assertAlmostEqual(test.sketch.area, 70**2 - 12 * 25 * pi, 5)
def test_error(self):
with self.assertRaises(ValueError):
@ -329,25 +329,25 @@ class ScaleTests(unittest.TestCase):
with BuildLine() as test:
Line((0, 0), (1, 0))
Scale(by=2, mode=Mode.REPLACE)
self.assertAlmostEqual(test.edges()[0].length(), 2.0, 5)
self.assertAlmostEqual(test.edges()[0].length, 2.0, 5)
def test_sketch(self):
with BuildSketch() as test:
Rectangle(1, 1)
Scale(by=2, mode=Mode.REPLACE)
self.assertAlmostEqual(test.sketch.area(), 4.0, 5)
self.assertAlmostEqual(test.sketch.area, 4.0, 5)
def test_part(self):
with BuildPart() as test:
Box(1, 1, 1)
Scale(by=(2, 2, 2), mode=Mode.REPLACE)
self.assertAlmostEqual(test.part.volume(), 8.0, 5)
self.assertAlmostEqual(test.part.volume, 8.0, 5)
def test_external_object(self):
line = Edge.make_line((0, 0), (1, 0))
with BuildLine() as test:
Scale(line, by=2)
self.assertAlmostEqual(test.edges()[0].length(), 2.0, 5)
self.assertAlmostEqual(test.edges()[0].length, 2.0, 5)
def test_error_checking(self):
with self.assertRaises(ValueError):

View file

@ -77,7 +77,7 @@ class BuildLineTests(unittest.TestCase):
TangentArc(l6 @ 1, l7 @ 0, tangent=l6 % 1)
Mirror(*outline.edges(), about=Plane.YZ)
MakeFace(*leaf.pending_edges)
self.assertAlmostEqual(leaf.sketch.area(), 0.2741600685288115, 5)
self.assertAlmostEqual(leaf.sketch.area, 0.2741600685288115, 5)
def test_three_d(self):
"""Test 3D lines with a helix"""
@ -98,7 +98,7 @@ class BuildLineTests(unittest.TestCase):
powerup @ 0,
tangents=(screw % 1, powerup % 0),
)
self.assertAlmostEqual(roller_coaster.wires()[0].length(), 678.983628932414, 5)
self.assertAlmostEqual(roller_coaster.wires()[0].length, 678.983628932414, 5)
def test_polar_line(self):
"""Test 2D and 3D polar lines"""
@ -131,16 +131,16 @@ class BuildLineTests(unittest.TestCase):
with BuildLine() as test:
Polyline((0, 0), (1, 0), (1, 1), (0, 1), close=True)
self.assertAlmostEqual(
(test.edges()[0] @ 0 - test.edges()[-1] @ 1).length(), 0, 5
(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.assertAlmostEqual(test.wires()[0].length, 4)
def test_wires_select_last(self):
with BuildLine() as test:
Line((0, 0), (0, 1))
Polyline((1, 0), (1, 1), (0, 1), (0, 0))
self.assertAlmostEqual(test.wires(Select.LAST)[0].length(), 3, 5)
self.assertAlmostEqual(test.wires(Select.LAST)[0].length, 3, 5)
def test_error_conditions(self):
"""Test error handling"""

View file

@ -103,20 +103,20 @@ class BuildPartTests(unittest.TestCase):
Box(20, 20, 20)
Sphere(10, mode=Mode.SUBTRACT)
self.assertTrue(isinstance(test._obj, Compound))
self.assertAlmostEqual(test.part.volume(), 8000 - (4000 / 3) * pi, 5)
self.assertAlmostEqual(test.part.volume, 8000 - (4000 / 3) * pi, 5)
def test_mode_intersect(self):
"""Note that a negative volume is created"""
with BuildPart() as test:
Box(20, 20, 20)
Sphere(10, mode=Mode.INTERSECT)
self.assertAlmostEqual(abs(test.part.volume()), (4000 / 3) * pi, 5)
self.assertAlmostEqual(abs(test.part.volume), (4000 / 3) * pi, 5)
def test_mode_replace(self):
with BuildPart() as test:
Box(10, 10, 10)
Sphere(10, mode=Mode.REPLACE)
self.assertAlmostEqual(test.part.volume(), (4000 / 3) * pi, 5)
self.assertAlmostEqual(test.part.volume, (4000 / 3) * pi, 5)
def test_add_pending_faces(self):
with BuildPart() as test:
@ -168,34 +168,34 @@ class TestCounterBoreHole(unittest.TestCase):
def test_fixed_depth(self):
with BuildPart() as test:
Box(10, 10, 10)
with Locations(test.faces().filter_by(Axis.Z)[-1].center()):
with Locations(test.faces().filter_by(Axis.Z)[-1].center):
CounterBoreHole(2, 3, 1, 5)
self.assertAlmostEqual(test.part.volume(), 1000 - 4 * 4 * pi - 9 * pi, 5)
self.assertAlmostEqual(test.part.volume, 1000 - 4 * 4 * pi - 9 * pi, 5)
def test_through_hole(self):
with BuildPart() as test:
Box(10, 10, 10)
with Locations(test.faces().filter_by(Axis.Z)[-1].center()):
with Locations(test.faces().filter_by(Axis.Z)[-1].center):
CounterBoreHole(2, 3, 1)
self.assertAlmostEqual(test.part.volume(), 1000 - 4 * 9 * pi - 9 * pi, 5)
self.assertAlmostEqual(test.part.volume, 1000 - 4 * 9 * pi - 9 * pi, 5)
class TestCounterSinkHole(unittest.TestCase):
def test_fixed_depth(self):
with BuildPart() as test:
Box(10, 10, 10)
with Locations(test.faces().filter_by(Axis.Z)[-1].center()):
with Locations(test.faces().filter_by(Axis.Z)[-1].center):
CounterSinkHole(2, 4, 5)
self.assertLess(test.part.volume(), 1000, 5)
self.assertGreater(test.part.volume(), 1000 - 16 * 5 * pi, 5)
self.assertLess(test.part.volume, 1000, 5)
self.assertGreater(test.part.volume, 1000 - 16 * 5 * pi, 5)
def test_through_hole(self):
with BuildPart() as test:
Box(10, 10, 10)
with Locations(test.faces().filter_by(Axis.Z)[-1].center()):
with Locations(test.faces().filter_by(Axis.Z)[-1].center):
CounterSinkHole(2, 4)
self.assertLess(test.part.volume(), 1000, 5)
self.assertGreater(test.part.volume(), 1000 - 16 * 10 * pi, 5)
self.assertLess(test.part.volume, 1000, 5)
self.assertGreater(test.part.volume, 1000 - 16 * 10 * pi, 5)
class TestExtrude(unittest.TestCase):
@ -209,14 +209,14 @@ class TestExtrude(unittest.TestCase):
with BuildSketch() as f:
Rectangle(5, 5)
Extrude(*f.sketch.faces(), amount=2.5, both=True)
self.assertAlmostEqual(test.part.volume(), 125, 5)
self.assertAlmostEqual(test.part.volume, 125, 5)
def test_extrude_both(self):
with BuildPart() as test:
with BuildSketch():
Rectangle(5, 5)
Extrude(amount=2.5, both=True)
self.assertAlmostEqual(test.part.volume(), 125, 5)
self.assertAlmostEqual(test.part.volume, 125, 5)
# def test_extrude_until(self):
# with BuildPart() as test:
@ -225,23 +225,23 @@ class TestExtrude(unittest.TestCase):
# with BuildSketch():
# Rectangle(1, 1)
# Extrude(until=Until.NEXT)
# self.assertAlmostEqual(test.part.volume(), 10**3 - 8**3 + 1**2 * 8, 5)
# self.assertAlmostEqual(test.part.volume, 10**3 - 8**3 + 1**2 * 8, 5)
class TestHole(unittest.TestCase):
def test_fixed_depth(self):
with BuildPart() as test:
Box(10, 10, 10)
with Locations(test.faces().filter_by(Axis.Z)[-1].center()):
with Locations(test.faces().filter_by(Axis.Z)[-1].center):
Hole(2, 5)
self.assertAlmostEqual(test.part.volume(), 1000 - 4 * 5 * pi, 5)
self.assertAlmostEqual(test.part.volume, 1000 - 4 * 5 * pi, 5)
def test_through_hole(self):
with BuildPart() as test:
Box(10, 10, 10)
with Locations(test.faces().filter_by(Axis.Z)[-1].center()):
with Locations(test.faces().filter_by(Axis.Z)[-1].center):
Hole(2)
self.assertAlmostEqual(test.part.volume(), 1000 - 4 * 10 * pi, 5)
self.assertAlmostEqual(test.part.volume, 1000 - 4 * 10 * pi, 5)
class TestLoft(unittest.TestCase):
@ -253,8 +253,8 @@ class TestLoft(unittest.TestCase):
with BuildSketch():
Circle(10 * sin(i * pi / slice_count) + 5)
Loft()
self.assertLess(test.part.volume(), 225 * pi * 30, 5)
self.assertGreater(test.part.volume(), 25 * pi * 30, 5)
self.assertLess(test.part.volume, 225 * pi * 30, 5)
self.assertGreater(test.part.volume, 25 * pi * 30, 5)
sections = [
Face.make_from_wires(
@ -270,8 +270,8 @@ class TestLoft(unittest.TestCase):
]
with BuildPart() as test:
Loft(*sections)
self.assertLess(test.part.volume(), 225 * pi * 30, 5)
self.assertGreater(test.part.volume(), 25 * pi * 30, 5)
self.assertLess(test.part.volume, 225 * pi * 30, 5)
self.assertGreater(test.part.volume, 25 * pi * 30, 5)
class TestRevolve(unittest.TestCase):
@ -299,8 +299,8 @@ class TestRevolve(unittest.TestCase):
)
MakeFace()
Revolve(axis=Axis.Y)
self.assertLess(test.part.volume(), 22**2 * pi * 50, 5)
self.assertGreater(test.part.volume(), 144 * pi * 50, 5)
self.assertLess(test.part.volume, 22**2 * pi * 50, 5)
self.assertGreater(test.part.volume, 144 * pi * 50, 5)
def test_revolve_with_axis(self):
with BuildPart() as test:
@ -312,8 +312,8 @@ class TestRevolve(unittest.TestCase):
l4 = Line(l3 @ 1, l1 @ 0)
MakeFace()
Revolve(axis=Axis.X)
self.assertLess(test.part.volume(), 244 * pi * 20, 5)
self.assertGreater(test.part.volume(), 100 * pi * 20, 5)
self.assertLess(test.part.volume, 244 * pi * 20, 5)
self.assertGreater(test.part.volume, 100 * pi * 20, 5)
def test_invalid_axis_origin(self):
with BuildPart():
@ -335,13 +335,13 @@ class TestSection(unittest.TestCase):
with BuildPart() as test:
Sphere(10)
Section()
self.assertAlmostEqual(test.faces()[-1].area(), 100 * pi, 5)
self.assertAlmostEqual(test.faces()[-1].area, 100 * pi, 5)
def test_custom_plane(self):
with BuildPart() as test:
Sphere(10)
Section(Plane.XZ)
self.assertAlmostEqual(test.faces().filter_by(Axis.Y)[-1].area(), 100 * pi, 5)
self.assertAlmostEqual(test.faces().filter_by(Axis.Y)[-1].area, 100 * pi, 5)
class TestSplit(unittest.TestCase):
@ -349,7 +349,7 @@ class TestSplit(unittest.TestCase):
with BuildPart() as test:
Sphere(10)
Split(keep=Keep.TOP)
self.assertAlmostEqual(test.part.volume(), (2 / 3) * 1000 * pi, 5)
self.assertAlmostEqual(test.part.volume, (2 / 3) * 1000 * pi, 5)
def test_split_both(self):
with BuildPart() as test:
@ -361,7 +361,7 @@ class TestSplit(unittest.TestCase):
with BuildPart() as test:
Sphere(10)
Split(bisect_by=Plane.YZ, keep=Keep.TOP)
self.assertAlmostEqual(test.part.volume(), (2 / 3) * 1000 * pi, 5)
self.assertAlmostEqual(test.part.volume, (2 / 3) * 1000 * pi, 5)
class TestSweep(unittest.TestCase):
@ -372,7 +372,7 @@ class TestSweep(unittest.TestCase):
with BuildSketch():
Rectangle(2, 2)
Sweep()
self.assertAlmostEqual(test.part.volume(), 40, 5)
self.assertAlmostEqual(test.part.volume, 40, 5)
def test_multi_section(self):
segment_count = 6
@ -401,7 +401,7 @@ class TestSweep(unittest.TestCase):
Fillet(*section.vertices(), radius=0.2)
# Create the handle by sweeping along the path
Sweep(multisection=True)
self.assertAlmostEqual(handle.part.volume(), 54.11246334691092, 5)
self.assertAlmostEqual(handle.part.volume, 54.11246334691092, 5)
def test_passed_parameters(self):
with BuildLine() as path:
@ -410,14 +410,14 @@ class TestSweep(unittest.TestCase):
Rectangle(2, 2)
with BuildPart() as test:
Sweep(*section.faces(), path=path.wires()[0])
self.assertAlmostEqual(test.part.volume(), 40, 5)
self.assertAlmostEqual(test.part.volume, 40, 5)
class TestTorus(unittest.TestCase):
def test_simple_torus(self):
with BuildPart() as test:
Torus(100, 10)
self.assertAlmostEqual(test.part.volume(), pi * 100 * 2 * pi * 100, 5)
self.assertAlmostEqual(test.part.volume, pi * 100 * 2 * pi * 100, 5)
if __name__ == "__main__":

View file

@ -85,13 +85,13 @@ class BuildSketchTests(unittest.TestCase):
with BuildSketch() as test:
Circle(10)
Rectangle(10, 10, centered=(False, False), mode=Mode.INTERSECT)
self.assertAlmostEqual(test.sketch.area(), 25 * pi, 5)
self.assertAlmostEqual(test.sketch.area, 25 * pi, 5)
def test_mode_replace(self):
with BuildSketch() as test:
Circle(10)
Rectangle(10, 10, centered=(False, False), mode=Mode.REPLACE)
self.assertAlmostEqual(test.sketch.area(), 100, 5)
self.assertAlmostEqual(test.sketch.area, 100, 5)
class BuildSketchExceptions(unittest.TestCase):
@ -117,7 +117,7 @@ class BuildSketchObjects(unittest.TestCase):
self.assertEqual(c.radius, 20)
self.assertEqual(c.centered, (True, True))
self.assertEqual(c.mode, Mode.ADD)
self.assertAlmostEqual(test.sketch.area(), pi * 20**2, 5)
self.assertAlmostEqual(test.sketch.area, pi * 20**2, 5)
def test_ellipse(self):
with BuildSketch() as test:
@ -127,7 +127,7 @@ class BuildSketchObjects(unittest.TestCase):
self.assertEqual(e.rotation, 0)
self.assertEqual(e.centered, (True, True))
self.assertEqual(e.mode, Mode.ADD)
self.assertAlmostEqual(test.sketch.area(), pi * 20 * 10, 5)
self.assertAlmostEqual(test.sketch.area, pi * 20 * 10, 5)
def test_polygon(self):
with BuildSketch() as test:
@ -136,7 +136,7 @@ class BuildSketchObjects(unittest.TestCase):
self.assertEqual(p.rotation, 0)
self.assertEqual(p.centered, (True, True))
self.assertEqual(p.mode, Mode.ADD)
self.assertAlmostEqual(test.sketch.area(), 0.5, 5)
self.assertAlmostEqual(test.sketch.area, 0.5, 5)
def test_rectangle(self):
with BuildSketch() as test:
@ -146,7 +146,7 @@ class BuildSketchObjects(unittest.TestCase):
self.assertEqual(r.rotation, 0)
self.assertEqual(r.centered, (True, True))
self.assertEqual(r.mode, Mode.ADD)
self.assertAlmostEqual(test.sketch.area(), 20 * 10, 5)
self.assertAlmostEqual(test.sketch.area, 20 * 10, 5)
def test_regular_polygon(self):
with BuildSketch() as test:
@ -156,7 +156,7 @@ class BuildSketchObjects(unittest.TestCase):
self.assertEqual(r.rotation, 0)
self.assertEqual(r.centered, (True, True))
self.assertEqual(r.mode, Mode.ADD)
self.assertAlmostEqual(test.sketch.area(), (3 * sqrt(3) / 2) * 2**2, 5)
self.assertAlmostEqual(test.sketch.area, (3 * sqrt(3) / 2) * 2**2, 5)
def test_slot_arc(self):
with BuildSketch() as test:
@ -167,7 +167,7 @@ class BuildSketchObjects(unittest.TestCase):
self.assertEqual(s.height, 1)
self.assertEqual(s.rotation, 45)
self.assertEqual(s.mode, Mode.ADD)
self.assertAlmostEqual(test.sketch.area(), 6.186450426893698, 5)
self.assertAlmostEqual(test.sketch.area, 6.186450426893698, 5)
def test_slot_center_point(self):
with BuildSketch() as test:
@ -177,7 +177,7 @@ class BuildSketchObjects(unittest.TestCase):
self.assertEqual(s.height, 2)
self.assertEqual(s.rotation, 0)
self.assertEqual(s.mode, Mode.ADD)
self.assertAlmostEqual(test.sketch.area(), pi + 4 * 2, 5)
self.assertAlmostEqual(test.sketch.area, pi + 4 * 2, 5)
def test_slot_center_to_center(self):
with BuildSketch() as test:
@ -186,7 +186,7 @@ class BuildSketchObjects(unittest.TestCase):
self.assertEqual(s.height, 2)
self.assertEqual(s.rotation, 0)
self.assertEqual(s.mode, Mode.ADD)
self.assertAlmostEqual(test.sketch.area(), pi + 4 * 2, 5)
self.assertAlmostEqual(test.sketch.area, pi + 4 * 2, 5)
def test_slot_overall(self):
with BuildSketch() as test:
@ -195,7 +195,7 @@ class BuildSketchObjects(unittest.TestCase):
self.assertEqual(s.height, 2)
self.assertEqual(s.rotation, 0)
self.assertEqual(s.mode, Mode.ADD)
self.assertAlmostEqual(test.sketch.area(), pi + 4 * 2, 5)
self.assertAlmostEqual(test.sketch.area, pi + 4 * 2, 5)
def test_text(self):
with BuildSketch() as test:
@ -222,7 +222,7 @@ class BuildSketchObjects(unittest.TestCase):
self.assertEqual(t.right_side_angle, 63.434948823)
self.assertEqual(t.rotation, 0)
self.assertEqual(t.mode, Mode.ADD)
self.assertAlmostEqual(test.sketch.area(), 2 * (6 + 4) / 2, 5)
self.assertAlmostEqual(test.sketch.area, 2 * (6 + 4) / 2, 5)
with self.assertRaises(ValueError):
with BuildSketch() as test:
@ -233,7 +233,7 @@ class BuildSketchObjects(unittest.TestCase):
with BuildSketch() as test:
Circle(10)
Offset(test.faces()[0], amount=1)
self.assertAlmostEqual(test.edges()[0].radius(), 11)
self.assertAlmostEqual(test.edges()[0].radius, 11)
with self.assertRaises(RuntimeError):
with BuildSketch() as test:
Offset(Location(Vector()), amount=1)
@ -243,7 +243,7 @@ class BuildSketchObjects(unittest.TestCase):
with BuildSketch() as test:
with Locations((-10, 0), (10, 0)):
Circle(1)
self.assertAlmostEqual(sum([f.area() for f in test.faces()]), 2 * pi, 5)
self.assertAlmostEqual(sum([f.area for f in test.faces()]), 2 * pi, 5)
def test_hull(self):
"""Test hull from pending edges and passed edges"""
@ -253,14 +253,14 @@ class BuildSketchObjects(unittest.TestCase):
CenterArc((1, 1.5), 0.5, 0, 360)
Line((0.0, 2), (-1, 3.0))
MakeHull()
self.assertAlmostEqual(test.sketch.area(), 7.258175622249558, 5)
self.assertAlmostEqual(test.sketch.area, 7.258175622249558, 5)
with BuildSketch() as test:
with Locations((-10, 0)):
Circle(10)
with Locations((10, 0)):
Circle(7)
MakeHull(*test.edges())
self.assertAlmostEqual(test.sketch.area(), 577.8808734698988, 5)
self.assertAlmostEqual(test.sketch.area, 577.8808734698988, 5)
if __name__ == "__main__":

View file

@ -99,15 +99,13 @@ class TestCadObjects(unittest.TestCase):
def test_edge_wrapper_center(self):
e = self._make_circle()
self.assertTupleAlmostEquals(
(1.0, 2.0, 3.0), e.center(center_of=CenterOf.MASS).to_tuple(), 3
)
self.assertTupleAlmostEquals((1.0, 2.0, 3.0), e.center_of_mass.to_tuple(), 3)
def test_edge_wrapper_ellipse_center(self):
e = self._make_ellipse()
w = Wire.make_wire([e])
self.assertTupleAlmostEquals(
(1.0, 2.0, 3.0), Face.make_from_wires(w).center().to_tuple(), 3
(1.0, 2.0, 3.0), Face.make_from_wires(w).center.to_tuple(), 3
)
def test_edge_wrapper_make_circle(self):
@ -255,7 +253,7 @@ class TestCadObjects(unittest.TestCase):
# )
# self.assertEqual(4, len(s.val().solids()))
# self.assertTupleAlmostEquals((0.0, 0.0, 0.25), s.val().center().to_tuple(), 3)
# self.assertTupleAlmostEquals((0.0, 0.0, 0.25), s.val().center.to_tuple(), 3)
def test_matrix_creation_and_access(self):
def matrix_vals(m):
@ -398,9 +396,7 @@ class TestCadObjects(unittest.TestCase):
e = Edge.make_circle(2, (1, 2, 3))
e2 = e.translate(Vector(0, 0, 1))
self.assertTupleAlmostEquals(
(1.0, 2.0, 4.0), e2.center(center_of=CenterOf.MASS).to_tuple(), 3
)
self.assertTupleAlmostEquals((1.0, 2.0, 4.0), e2.center_of_mass.to_tuple(), 3)
def test_vertices(self):
e = Shape.cast(BRepBuilderAPI_MakeEdge(gp_Pnt(0, 0, 0), gp_Pnt(1, 1, 0)).Edge())
@ -577,20 +573,20 @@ class TestCadObjects(unittest.TestCase):
# get a radius from a simple circle
e0 = Edge.make_circle(2.4)
self.assertAlmostEqual(e0.radius(), 2.4)
self.assertAlmostEqual(e0.radius, 2.4)
# radius of an arc
e1 = Edge.make_circle(1.8, pnt=(5, 6, 7), dir=(1, 1, 1), angle1=20, angle2=30)
self.assertAlmostEqual(e1.radius(), 1.8)
self.assertAlmostEqual(e1.radius, 1.8)
# test value errors
e2 = Edge.make_ellipse(10, 20)
with self.assertRaises(ValueError):
e2.radius()
e2.radius
# radius from a wire
w0 = Wire.make_circle(10, Vector(1, 2, 3), (-1, 0, 1))
self.assertAlmostEqual(w0.radius(), 10)
self.assertAlmostEqual(w0.radius, 10)
# radius from a wire with multiple edges
rad = 2.3
@ -603,7 +599,7 @@ class TestCadObjects(unittest.TestCase):
Edge.make_circle(rad, pnt, direction, 25, 230),
]
)
self.assertAlmostEqual(w1.radius(), rad)
self.assertAlmostEqual(w1.radius, rad)
# test value error from wire
w2 = Wire.make_polygon(
@ -614,7 +610,7 @@ class TestCadObjects(unittest.TestCase):
]
)
with self.assertRaises(ValueError):
w2.radius()
w2.radius
# (I think) the radius of a wire is the radius of it's first edge.
# Since this is stated in the docstring better make sure.
@ -625,21 +621,21 @@ class TestCadObjects(unittest.TestCase):
]
)
with self.assertRaises(ValueError):
no_rad.radius()
no_rad.radius
yes_rad = Wire.make_wire(
[
Edge.make_circle(1.0, angle1=90, angle2=270),
Edge.make_line(Vector(0, -1, 0), Vector(0, 1, 0)),
]
)
self.assertAlmostEqual(yes_rad.radius(), 1.0)
self.assertAlmostEqual(yes_rad.radius, 1.0)
many_rad = Wire.make_wire(
[
Edge.make_circle(1.0, angle1=0, angle2=180),
Edge.make_circle(3.0, pnt=Vector(2, 0, 0), angle1=180, angle2=359),
]
)
self.assertAlmostEqual(many_rad.radius(), 1.0)
self.assertAlmostEqual(many_rad.radius, 1.0)
class TestVector(unittest.TestCase):
@ -698,7 +694,7 @@ class TestVector(unittest.TestCase):
def test_center(self):
v = Vector(1, 1, 1)
self.assertAlmostEqual(v, v.center())
self.assertAlmostEqual(v, v.center)
# def test_to_vertex(self):
# """Verify conversion of Vector to Vertex"""
@ -773,7 +769,7 @@ class TestVector(unittest.TestCase):
decimal_places,
)
self.assertAlmostEqual(
vec.length() * math.cos(angle), vecLineProjection.length(), decimal_places
vec.length * math.cos(angle), vecLineProjection.length, decimal_places
)
def test_vector_not_implemented(self):
@ -861,17 +857,13 @@ class TestMixin1D(unittest.TestCase):
def test_center(self):
c = Edge.make_circle(1, angle1=0, angle2=180)
self.assertTupleAlmostEquals(c.center.to_tuple(), (0, 1, 0), 5)
self.assertTupleAlmostEquals(
c.center(center_of=CenterOf.GEOMETRY).to_tuple(), (0, 1, 0), 5
)
self.assertTupleAlmostEquals(
c.center(center_of=CenterOf.MASS).to_tuple(),
c.center_of_mass.to_tuple(),
(0, 0.6366197723675814, 0),
5,
)
self.assertTupleAlmostEquals(
c.center(center_of=CenterOf.BOUNDING_BOX).to_tuple(), (0, 0.5, 0), 5
)
self.assertTupleAlmostEquals(c.bounding_box().center.to_tuple(), (0, 0.5, 0), 5)
# TODO: Test after upgrade
# def test_location_at(self):
@ -886,8 +878,8 @@ class TestMixin1D(unittest.TestCase):
target = Face.make_rect(10, 10)
source = Face.make_from_wires(Wire.make_circle(1, (0, 0, 1), (0, 0, 1)))
shadow = source.project(target, d=(0, 0, -1))
self.assertTupleAlmostEquals(shadow.center().to_tuple(), (0, 0, 0), 5)
self.assertAlmostEqual(shadow.area(), math.pi, 5)
self.assertTupleAlmostEquals(shadow.center.to_tuple(), (0, 0, 0), 5)
self.assertAlmostEqual(shadow.area, math.pi, 5)
class TestMixin3D(unittest.TestCase):
@ -896,11 +888,11 @@ class TestMixin3D(unittest.TestCase):
def test_chamfer(self):
box = Solid.make_box(1, 1, 1)
chamfer_box = box.chamfer(0.1, 0.2, box.edges().sort_by(Axis.Z)[-1:])
self.assertAlmostEqual(chamfer_box.volume(), 1 - 0.01, 5)
self.assertAlmostEqual(chamfer_box.volume, 1 - 0.01, 5)
def test_shell(self):
shell_box = Solid.make_box(1, 1, 1).shell([], thickness=-0.1)
self.assertAlmostEqual(shell_box.volume(), 1 - 0.8**3, 5)
self.assertAlmostEqual(shell_box.volume, 1 - 0.8**3, 5)
with self.assertRaises(ValueError):
Solid.make_box(1, 1, 1).shell([], thickness=0.1, kind=Kind.TANGENT)
@ -914,7 +906,7 @@ class TestMixin3D(unittest.TestCase):
None, [f], additive=False
)
self.assertTrue(d.is_valid())
self.assertAlmostEqual(d.volume(), 1 - 0.5**2, 5)
self.assertAlmostEqual(d.volume, 1 - 0.5**2, 5)
# face with depth
f = Face.make_rect(0.5, 0.5)
@ -922,7 +914,7 @@ class TestMixin3D(unittest.TestCase):
None, [f], depth=0.5, thru_all=False, additive=False
)
self.assertTrue(d.is_valid())
self.assertAlmostEqual(d.volume(), 1 - 0.5**3, 5)
self.assertAlmostEqual(d.volume, 1 - 0.5**3, 5)
# face until
f = Face.make_rect(0.5, 0.5)
@ -931,7 +923,7 @@ class TestMixin3D(unittest.TestCase):
None, [f], up_to_face=limit, thru_all=False, additive=False
)
self.assertTrue(d.is_valid())
self.assertAlmostEqual(d.volume(), 1 - 0.5**3, 5)
self.assertAlmostEqual(d.volume, 1 - 0.5**3, 5)
# wire
w = Face.make_rect(0.5, 0.5).outer_wire()
@ -939,7 +931,7 @@ class TestMixin3D(unittest.TestCase):
None, [w], additive=False
)
self.assertTrue(d.is_valid())
self.assertAlmostEqual(d.volume(), 1 - 0.5**2, 5)
self.assertAlmostEqual(d.volume, 1 - 0.5**2, 5)
class TestShape(unittest.TestCase):
@ -981,17 +973,17 @@ class TestShape(unittest.TestCase):
self.assertEqual(Vertex().shape_type(), "Vertex")
def test_scale(self):
self.assertAlmostEqual(Solid.make_box(1, 1, 1).scale(2).volume(), 2**3, 5)
self.assertAlmostEqual(Solid.make_box(1, 1, 1).scale(2).volume, 2**3, 5)
def test_fuse(self):
box1 = Solid.make_box(1, 1, 1)
box2 = Solid.make_box(1, 1, 1, pnt=(1, 0, 0))
combined = box1.fuse(box2, glue=True)
self.assertTrue(combined.is_valid())
self.assertAlmostEqual(combined.volume(), 2, 5)
self.assertAlmostEqual(combined.volume, 2, 5)
fuzzy = box1.fuse(box2, tol=1e-6)
self.assertTrue(fuzzy.is_valid())
self.assertAlmostEqual(fuzzy.volume(), 2, 5)
self.assertAlmostEqual(fuzzy.volume, 2, 5)
def test_faces_intersected_by_line(self):
box = Solid.make_box(1, 1, 1, pnt=(0, 0, 1))
@ -1081,7 +1073,7 @@ class TestShape(unittest.TestCase):
predicted_location = Location(offset) * Rotation(*rotation)
located_shape = Solid.make_box(1, 1, 1).locate(predicted_location)
intersect = shape.intersect(located_shape)
self.assertAlmostEqual(intersect.volume(), 1, 5)
self.assertAlmostEqual(intersect.volume, 1, 5)
class TestShapeList(unittest.TestCase):
@ -1092,7 +1084,7 @@ class TestShapeList(unittest.TestCase):
Solid.make_cylinder(1, 1).faces().filter_by(GeomType.PLANE, reverse=True)
)
self.assertEqual(len(non_planar_faces), 1)
self.assertAlmostEqual(non_planar_faces[0].area(), 2 * math.pi, 5)
self.assertAlmostEqual(non_planar_faces[0].area, 2 * math.pi, 5)
class TestCompound(unittest.TestCase):
@ -1114,10 +1106,10 @@ class TestCompound(unittest.TestCase):
box2 = Solid.make_box(1, 1, 1, pnt=(1, 0, 0))
combined = Compound.make_compound([box1]).fuse(box2, glue=True)
self.assertTrue(combined.is_valid())
self.assertAlmostEqual(combined.volume(), 2, 5)
self.assertAlmostEqual(combined.volume, 2, 5)
fuzzy = Compound.make_compound([box1]).fuse(box2, tol=1e-6)
self.assertTrue(fuzzy.is_valid())
self.assertAlmostEqual(fuzzy.volume(), 2, 5)
self.assertAlmostEqual(fuzzy.volume, 2, 5)
# Doesn't work
# def test_remove(self):
@ -1130,16 +1122,16 @@ class TestCompound(unittest.TestCase):
class TestEdge(unittest.TestCase):
def test_close(self):
self.assertAlmostEqual(
Edge.make_circle(1, angle2=180).close().length(), math.pi + 2, 5
Edge.make_circle(1, angle2=180).close().length, math.pi + 2, 5
)
self.assertAlmostEqual(Edge.make_circle(1).close().length(), 2 * math.pi, 5)
self.assertAlmostEqual(Edge.make_circle(1).close().length, 2 * math.pi, 5)
def test_arc_center(self):
self.assertTupleAlmostEquals(
Edge.make_ellipse(2, 1).arc_center().to_tuple(), (0, 0, 0), 5
Edge.make_ellipse(2, 1).arc_center.to_tuple(), (0, 0, 0), 5
)
with self.assertRaises(ValueError):
Edge.make_line((0, 0, 0), (0, 0, 1)).arc_center()
Edge.make_line((0, 0, 0), (0, 0, 1)).arc_center
def test_spline_with_parameters(self):
spline = Edge.make_spline(
@ -1176,7 +1168,7 @@ class TestFace(unittest.TestCase):
top_edge = Edge.make_circle(radius=1, pnt=(0, 0, 1), angle2=90)
curved = Face.make_surface_from_curves(bottom_edge, top_edge)
self.assertTrue(curved.is_valid())
self.assertAlmostEqual(curved.area(), math.pi / 2, 5)
self.assertAlmostEqual(curved.area, math.pi / 2, 5)
self.assertTupleAlmostEquals(
curved.normal_at().to_tuple(), (math.sqrt(2) / 2, math.sqrt(2) / 2, 0), 5
)
@ -1185,17 +1177,17 @@ class TestFace(unittest.TestCase):
top_wire = Wire.make_circle(1, center=(0, 0, 1), normal=(0, 0, 1))
curved = Face.make_surface_from_curves(bottom_wire, top_wire)
self.assertTrue(curved.is_valid())
self.assertAlmostEqual(curved.area(), 2 * math.pi, 5)
self.assertAlmostEqual(curved.area, 2 * math.pi, 5)
def test_center(self):
test_face = Face.make_from_wires(
Wire.make_polygon([(0, 0), (1, 0), (1, 1), (0, 0)])
)
self.assertTupleAlmostEquals(
test_face.center(center_of=CenterOf.MASS).to_tuple(), (2 / 3, 1 / 3, 0), 1
test_face.center_of_mass.to_tuple(), (2 / 3, 1 / 3, 0), 1
)
self.assertTupleAlmostEquals(
test_face.center(center_of=CenterOf.BOUNDING_BOX).to_tuple(),
test_face.bounding_box().center.to_tuple(),
(0.5, 0.5, 0),
5,
)
@ -1329,8 +1321,8 @@ class TestSolid(unittest.TestCase):
base = Face.make_rect(1, 1)
pyramid = Solid.extrude_linear(base, normal=(0, 0, 1), taper=1)
self.assertLess(
pyramid.faces().sort_by(Axis.Z)[-1].area(),
pyramid.faces().sort_by(Axis.Z)[0].area(),
pyramid.faces().sort_by(Axis.Z)[-1].area,
pyramid.faces().sort_by(Axis.Z)[0].area,
)
def test_extrude_linear_with_rotation(self):
@ -1339,19 +1331,19 @@ class TestSolid(unittest.TestCase):
twist = Solid.extrude_linear_with_rotation(
base, center=(0, 0, 0), normal=(0, 0, 1), angle=45
)
self.assertAlmostEqual(twist.volume(), 1, 5)
self.assertAlmostEqual(twist.volume, 1, 5)
top = twist.faces().sort_by(Axis.Z)[-1].rotate(Axis.Z, 45)
bottom = twist.faces().sort_by(Axis.Z)[0]
self.assertAlmostEqual(top.translate((0, 0, -1)).intersect(bottom).area(), 1, 5)
self.assertAlmostEqual(top.translate((0, 0, -1)).intersect(bottom).area, 1, 5)
# Wire
base = Wire.make_rect(1, 1)
twist = Solid.extrude_linear_with_rotation(
base, center=(0, 0, 0), normal=(0, 0, 1), angle=45
)
self.assertAlmostEqual(twist.volume(), 1, 5)
self.assertAlmostEqual(twist.volume, 1, 5)
top = twist.faces().sort_by(Axis.Z)[-1].rotate(Axis.Z, 45)
bottom = twist.faces().sort_by(Axis.Z)[0]
self.assertAlmostEqual(top.translate((0, 0, -1)).intersect(bottom).area(), 1, 5)
self.assertAlmostEqual(top.translate((0, 0, -1)).intersect(bottom).area, 1, 5)
class ProjectionTests(unittest.TestCase):
@ -1443,7 +1435,7 @@ class VertexTests(unittest.TestCase):
v = Vertex(1, 1, 1)
self.assertEqual(1, v.X)
self.assertEqual(Vector, type(v.center()))
self.assertEqual(Vector, type(v.center))
with self.assertRaises(ValueError):
Vertex(Vector())
@ -1494,11 +1486,11 @@ class TestWire(unittest.TestCase):
def test_ellipse_arc(self):
full_ellipse = Wire.make_ellipse(2, 1)
half_ellipse = Wire.make_ellipse(2, 1, angle1=0, angle2=180, closed=True)
self.assertAlmostEqual(full_ellipse.area() / 2, half_ellipse.area(), 5)
self.assertAlmostEqual(full_ellipse.area / 2, half_ellipse.area, 5)
def test_conical_helix(self):
helix = Wire.make_helix(1, 4, 1, normal=(-1, 0, 0), angle=10, lefthand=True)
self.assertAlmostEqual(helix.length(), 34.102023034708374, 5)
self.assertAlmostEqual(helix.length, 34.102023034708374, 5)
def test_stitch(self):
half_ellipse1 = Wire.make_ellipse(2, 1, angle1=0, angle2=180, closed=False)
@ -1510,14 +1502,14 @@ class TestWire(unittest.TestCase):
square = Wire.make_rect(1, 1)
squaroid = square.fillet_2d(0.1, square.vertices())
self.assertAlmostEqual(
squaroid.length(), 4 * (1 - 2 * 0.1) + 2 * math.pi * 0.1, 5
squaroid.length, 4 * (1 - 2 * 0.1) + 2 * math.pi * 0.1, 5
)
def test_chamfer_2d(self):
square = Wire.make_rect(1, 1)
squaroid = square.chamfer_2d(0.1, square.vertices())
self.assertAlmostEqual(
squaroid.length(), 4 * (1 - 2 * 0.1 + 0.1 * math.sqrt(2)), 5
squaroid.length, 4 * (1 - 2 * 0.1 + 0.1 * math.sqrt(2)), 5
)
@ -1527,8 +1519,8 @@ class TestFunctions(unittest.TestCase):
rectangle_edges = Face.make_rect(2, 1, pnt=(5, 0)).edges()
wires = edges_to_wires(square_edges + rectangle_edges)
self.assertEqual(len(wires), 2)
self.assertAlmostEqual(wires[0].length(), 4, 5)
self.assertAlmostEqual(wires[1].length(), 6, 5)
self.assertAlmostEqual(wires[0].length, 4, 5)
self.assertAlmostEqual(wires[1].length, 6, 5)
if __name__ == "__main__":