Vase example, Workplanes, new filters

This commit is contained in:
Roger Maitland 2022-07-15 11:19:44 -04:00
parent 1721b2e536
commit cf5f140d02
6 changed files with 151 additions and 10 deletions

View file

@ -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)

View file

@ -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
View 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")

View file

@ -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:

View file

@ -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

View file

@ -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 = []