mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-15 15:20:37 -08:00
Vase example, Workplanes, new filters
This commit is contained in:
parent
1721b2e536
commit
cf5f140d02
6 changed files with 151 additions and 10 deletions
|
|
@ -65,7 +65,7 @@ with BuildPart(workplane=Plane.named("XZ")) as rail:
|
|||
)
|
||||
FilletSketch(*outside_vertices, radius=fillet + thickness)
|
||||
Extrude(rail_length)
|
||||
WorkplanesFromFaces(rail.faces().filter_by_normal(Axis.Z)[-1], replace=True)
|
||||
WorkplanesFromFaces(rail.faces().filter_by_axis(Axis.Z)[-1], replace=True)
|
||||
with BuildSketch() as slots:
|
||||
RectangularArrayToSketch(0, slot_pitch, 1, rail_length // slot_pitch - 1)
|
||||
SlotOverall(slot_length, slot_width, rotation=90)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ with BuildPart() as pillow_block:
|
|||
Rectangle(width, height)
|
||||
FilletSketch(*plan.vertices(), radius=5)
|
||||
Extrude(thickness)
|
||||
WorkplanesFromFaces(pillow_block.faces().filter_by_normal(Axis.Z)[-1])
|
||||
WorkplanesFromFaces(pillow_block.faces().filter_by_axis(Axis.Z)[-1])
|
||||
CounterBoreHole(bearing_axle_radius, bearing_radius, bearing_thickness)
|
||||
RectangularArrayToPart(width - 2 * padding, height - 2 * padding, 2, 2)
|
||||
CounterBoreHole(screw_shaft_radius, screw_head_radius, screw_head_height)
|
||||
|
|
|
|||
67
examples/vase.py
Normal file
67
examples/vase.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
"""
|
||||
|
||||
name: vase.py
|
||||
by: Gumyr
|
||||
date: July 15th 2022
|
||||
|
||||
desc:
|
||||
|
||||
This example demonstrates revolving a sketch, shelling and selecting edges
|
||||
by position range and type for fillets.
|
||||
|
||||
license:
|
||||
|
||||
Copyright 2022 Gumyr
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
from cadquery import Vector
|
||||
from build123d.build123d_common import *
|
||||
from build123d.build_line import *
|
||||
from build123d.build_sketch import *
|
||||
from build123d.build_part import *
|
||||
|
||||
with BuildPart() as vase:
|
||||
with BuildSketch() as profile:
|
||||
with BuildLine() as outline:
|
||||
l1 = Line((0, 0), (12, 0))
|
||||
l2 = RadiusArc(l1 @ 1, (15, 20), 50)
|
||||
l3 = Spline(l2 @ 1, (22, 40), (20, 50), tangents=(l2 % 1, (-0.75, 1)))
|
||||
l4 = RadiusArc(l3 @ 1, l3 @ 1 + Vector(0, 5), 5)
|
||||
l5 = Spline(
|
||||
l4 @ 1,
|
||||
l4 @ 1 + Vector(2.5, 2.5),
|
||||
l4 @ 1 + Vector(0, 5),
|
||||
tangents=(l4 % 1, (-1, 0)),
|
||||
)
|
||||
Polyline(
|
||||
l5 @ 1,
|
||||
l5 @ 1 + Vector(0, 1),
|
||||
(0, (l5 @ 1).y + 1),
|
||||
l1 @ 0,
|
||||
)
|
||||
BuildFace()
|
||||
Revolve()
|
||||
Shell(vase.faces().filter_by_axis(Axis.Y)[-1], thickness=-1)
|
||||
top_edges = (
|
||||
vase.edges().filter_by_position(Axis.Y, 60, 62).filter_by_type(Type.CIRCLE)
|
||||
)
|
||||
# debug(top_edges)
|
||||
FilletPart(*top_edges, radius=0.25)
|
||||
FilletPart(vase.edges().sort_by(SortBy.Y)[0], radius=0.5)
|
||||
|
||||
|
||||
if "show_object" in locals():
|
||||
# show_object(outline.line, name="outline")
|
||||
# show_object(profile.sketch, name="profile")
|
||||
show_object(vase.part, name="vase")
|
||||
|
|
@ -32,7 +32,7 @@ license:
|
|||
from math import radians
|
||||
from typing import Union
|
||||
from enum import Enum, auto
|
||||
from cadquery import Edge, Wire, Vector, Location
|
||||
from cadquery import Edge, Wire, Vector, Location, Face
|
||||
from OCP.gp import gp_Pnt, gp_Ax1, gp_Dir, gp_Trsf
|
||||
import cq_warehouse.extensions
|
||||
|
||||
|
|
@ -139,6 +139,25 @@ class SortBy(Enum):
|
|||
DISTANCE = auto()
|
||||
|
||||
|
||||
class Type(Enum):
|
||||
PLANE = auto()
|
||||
CYLINDER = auto()
|
||||
CONE = auto()
|
||||
SPHERE = auto()
|
||||
TORUS = auto()
|
||||
BEZIER = auto()
|
||||
BSPLINE = auto()
|
||||
REVOLUTION = auto()
|
||||
EXTRUSION = auto()
|
||||
OFFSET = auto()
|
||||
LINE = auto()
|
||||
CIRCLE = auto()
|
||||
ELLIPSE = auto()
|
||||
HYPERBOLA = auto()
|
||||
PARABOLA = auto()
|
||||
OTHER = auto()
|
||||
|
||||
|
||||
#
|
||||
# DirectAPI Classes
|
||||
#
|
||||
|
|
@ -171,11 +190,42 @@ class ShapeList(list):
|
|||
def __init_subclass__(cls) -> None:
|
||||
return super().__init_subclass__()
|
||||
|
||||
def filter_by_normal(self, axis: Axis):
|
||||
result = filter(
|
||||
lambda o: o.normalAt(o.Center()) == Vector(*ShapeList.axis_map[axis][0])
|
||||
or o.normalAt(o.Center()) == Vector(*ShapeList.axis_map[axis][1]),
|
||||
self,
|
||||
def filter_by_axis(self, axis: Axis, tolerance=1e-5):
|
||||
|
||||
planar_faces = filter(
|
||||
lambda o: isinstance(o, Face) and o.geomType() == "PLANE", self
|
||||
)
|
||||
linear_edges = filter(
|
||||
lambda o: isinstance(o, Edge) and o.geomType() == "LINE", self
|
||||
)
|
||||
|
||||
result = []
|
||||
|
||||
result = list(
|
||||
filter(
|
||||
lambda o: (
|
||||
o.normalAt(None) - Vector(*ShapeList.axis_map[axis][0])
|
||||
).Length
|
||||
<= tolerance
|
||||
or (o.normalAt(None) - Vector(*ShapeList.axis_map[axis][1])).Length
|
||||
<= tolerance,
|
||||
planar_faces,
|
||||
)
|
||||
)
|
||||
result.extend(
|
||||
list(
|
||||
filter(
|
||||
lambda o: (
|
||||
o.tangentAt(None) - Vector(*ShapeList.axis_map[axis][0])
|
||||
).Length
|
||||
<= tolerance
|
||||
or (
|
||||
o.tangentAt(o.Center()) - Vector(*ShapeList.axis_map[axis][1])
|
||||
).Length
|
||||
<= tolerance,
|
||||
linear_edges,
|
||||
)
|
||||
)
|
||||
)
|
||||
if axis == Axis.X:
|
||||
result = sorted(result, key=lambda obj: obj.Center().x)
|
||||
|
|
@ -223,6 +273,13 @@ class ShapeList(list):
|
|||
|
||||
return ShapeList(result)
|
||||
|
||||
def filter_by_type(
|
||||
self,
|
||||
type: Type,
|
||||
):
|
||||
result = filter(lambda o: o.geomType() == type.name, self)
|
||||
return ShapeList(result)
|
||||
|
||||
def sort_by(self, sort_by: SortBy = SortBy.Z, reverse: bool = False):
|
||||
|
||||
if sort_by == SortBy.X:
|
||||
|
|
|
|||
|
|
@ -827,6 +827,21 @@ class Sweep(Compound):
|
|||
super().__init__(Compound.makeCompound(new_solids).wrapped)
|
||||
|
||||
|
||||
class Workplanes:
|
||||
"""Part Operation: Workplanes
|
||||
|
||||
Create workplanes from the given sequence of planes, optionally replacing existing
|
||||
workplanes.
|
||||
|
||||
Args:
|
||||
planes (Plane): sequence of planes to use as workplanes.
|
||||
replace (bool, optional): replace existing workplanes. Defaults to True.
|
||||
"""
|
||||
|
||||
def __init__(self, *planes: Plane, replace=True):
|
||||
BuildPart._get_context()._workplane(*planes, replace=replace)
|
||||
|
||||
|
||||
class WorkplanesFromFaces:
|
||||
"""Part Operation: Workplanes from Faces
|
||||
|
||||
|
|
|
|||
|
|
@ -277,7 +277,8 @@ class BuildFace:
|
|||
"""
|
||||
|
||||
def __init__(self, *edges: Edge, mode: Mode = Mode.ADD):
|
||||
pending_face = Face.makeFromWires(Wire.combine(edges)[0])
|
||||
outer_edges = edges if edges else BuildSketch._get_context().pending_edges
|
||||
pending_face = Face.makeFromWires(Wire.combine(outer_edges)[0])
|
||||
BuildSketch._add_to_context(pending_face, mode)
|
||||
BuildSketch._get_context().pending_edges = []
|
||||
|
||||
|
|
@ -293,7 +294,8 @@ class BuildHull:
|
|||
"""
|
||||
|
||||
def __init__(self, *edges: Edge, mode: Mode = Mode.ADD):
|
||||
pending_face = find_hull(edges)
|
||||
hull_edges = edges if edges else BuildSketch._get_context().pending_edges
|
||||
pending_face = find_hull(hull_edges)
|
||||
BuildSketch._add_to_context(pending_face, mode)
|
||||
BuildSketch._get_context().pending_edges = []
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue