Skip to content

Commit be570bb

Browse files
Multiple additions to the func API
1 parent 0e00697 commit be570bb

File tree

1 file changed

+101
-9
lines changed

1 file changed

+101
-9
lines changed

cadquery/occ_impl/shapes.py

Lines changed: 101 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,9 @@
321321

322322
from OCP.OSD import OSD_ThreadPool
323323

324+
from OCP.Bnd import Bnd_OBB
325+
from OCP.BRepBndLib import BRepBndLib
326+
324327
from math import pi, sqrt, inf, radians, cos
325328

326329
import warnings
@@ -1432,12 +1435,12 @@ def split(self, *splitters: "Shape") -> "Shape":
14321435

14331436
return self._bool_op((self,), splitters, split_op)
14341437

1435-
def distance(self, other: "Shape") -> float:
1438+
def distance(self, other: "Shape", tol: float = 1e-6) -> float:
14361439
"""
14371440
Minimal distance between two shapes
14381441
"""
14391442

1440-
dist_calc = BRepExtrema_DistShapeShape(self.wrapped, other.wrapped)
1443+
dist_calc = BRepExtrema_DistShapeShape(self.wrapped, other.wrapped, tol)
14411444
dist_calc.SetMultiThread(True)
14421445

14431446
return dist_calc.Value()
@@ -2396,6 +2399,13 @@ def hasPCurve(self, f: "Face") -> bool:
23962399

23972400
return ShapeAnalysis_Edge().HasPCurve(self.wrapped, f.wrapped)
23982401

2402+
def reversed(self) -> "Edge":
2403+
"""
2404+
Return a reversed version of self.
2405+
"""
2406+
2407+
return self.__class__(self.wrapped.Reversed())
2408+
23992409
@classmethod
24002410
def makeCircle(
24012411
cls,
@@ -5466,6 +5476,10 @@ def shell(
54665476
return shell(*s, tol=tol, manifold=manifold, ctx=ctx, history=history)
54675477

54685478

5479+
# add an alias
5480+
sew = shell
5481+
5482+
54695483
@multimethod
54705484
def solid(
54715485
s1: Shape, *sn: Shape, tol: float = 1e-6, history: Optional[ShapeHistory] = None,
@@ -5842,7 +5856,7 @@ def text(
58425856
font_i, NCollection_Utf8String(txt), theHAlign=theHAlign, theVAlign=theVAlign
58435857
)
58445858

5845-
return clean(compound(_compound_or_shape(rv).faces()).fuse())
5859+
return clean(compound(_compound_or_shape(rv).Faces()).fuse())
58465860

58475861

58485862
@text.register
@@ -5865,7 +5879,7 @@ def text(
58655879
L = spine.Length()
58665880

58675881
rv = []
5868-
for el in text(txt, size, font, path, kind, halign, valign):
5882+
for el in text(txt, size, font, path, kind, halign, valign).Faces():
58695883
pos = el.BoundingBox().center.x
58705884

58715885
# position
@@ -5899,7 +5913,7 @@ def text(
58995913
tmp = text(txt, size, spine, False, font, path, kind, halign, valign)
59005914

59015915
rv = []
5902-
for f in tmp.faces():
5916+
for f in tmp.Faces():
59035917
rv.append(f.project(base, f.normalAt()))
59045918

59055919
return _normalize(compound(rv))
@@ -6170,7 +6184,7 @@ def chamfer(s: Shape, e: Shape, d: float) -> Shape:
61706184
return _compound_or_shape(builder.Shape())
61716185

61726186

6173-
def extrude(s: Shape, d: VectorLike) -> Shape:
6187+
def extrude(s: Shape, d: VectorLike, both: bool = False) -> Shape:
61746188
"""
61756189
Extrude a shape.
61766190
"""
@@ -6179,7 +6193,11 @@ def extrude(s: Shape, d: VectorLike) -> Shape:
61796193

61806194
for el in _get(s, ("Vertex", "Edge", "Wire", "Face")):
61816195

6182-
builder = BRepPrimAPI_MakePrism(el.wrapped, Vector(d).wrapped)
6196+
if both:
6197+
builder = BRepPrimAPI_MakePrism(el.moved(-d).wrapped, 2 * Vector(d).wrapped)
6198+
else:
6199+
builder = BRepPrimAPI_MakePrism(el.wrapped, Vector(d).wrapped)
6200+
61836201
builder.Build()
61846202

61856203
results.append(builder.Shape())
@@ -6257,6 +6275,30 @@ def _offset(t):
62576275
return rv
62586276

62596277

6278+
def offset2D(
6279+
s: Shape, t: float, kind: Literal["arc", "intersection", "tangent"] = "arc"
6280+
) -> Shape:
6281+
"""
6282+
2D Offset edges, wires or faces.
6283+
"""
6284+
6285+
kind_dict = {
6286+
"arc": GeomAbs_JoinType.GeomAbs_Arc,
6287+
"intersection": GeomAbs_JoinType.GeomAbs_Intersection,
6288+
"tangent": GeomAbs_JoinType.GeomAbs_Tangent,
6289+
}
6290+
6291+
bldr = BRepOffsetAPI_MakeOffset()
6292+
bldr.Init(kind_dict[kind])
6293+
6294+
for el in _get_wires(s):
6295+
bldr.AddWire(el.wrapped)
6296+
6297+
bldr.Perform(t)
6298+
6299+
return _compound_or_shape(bldr.Shape())
6300+
6301+
62606302
@multimethod
62616303
def sweep(
62626304
s: Shape, path: Shape, aux: Optional[Shape] = None, cap: bool = False
@@ -6500,6 +6542,7 @@ def loft(
65006542
return loft(s, cap, ruled, continuity, parametrization, degree, compat)
65016543

65026544

6545+
@multimethod
65036546
def project(
65046547
s: Shape,
65056548
base: Shape,
@@ -6523,6 +6566,26 @@ def project(
65236566
return _compound_or_shape(bldr.Projection())
65246567

65256568

6569+
@project.register
6570+
def project(
6571+
s: Shape, base: Shape, direction: VectorLike,
6572+
):
6573+
"""
6574+
Project s onto base using cylindrical projection.
6575+
"""
6576+
6577+
results = []
6578+
6579+
for el in _get_wires(s):
6580+
bldr = BRepProj_Projection(el.wrapped, base.wrapped, Vector(direction).toDir())
6581+
6582+
while bldr.More():
6583+
results.append(_compound_or_shape(bldr.Current()))
6584+
bldr.Next()
6585+
6586+
return _normalize(compound(results))
6587+
6588+
65266589
#%% diagnotics
65276590

65286591

@@ -6575,7 +6638,7 @@ def isSubshape(s1: Shape, s2: Shape) -> bool:
65756638
#%% properties
65766639

65776640

6578-
def closest(s1: Shape, s2: Shape) -> Tuple[Vector, Vector]:
6641+
def closest(s1: Shape, s2: Shape, tol: float = 1e-6) -> Tuple[Vector, Vector]:
65796642
"""
65806643
Closest points between two shapes.
65816644
"""
@@ -6587,7 +6650,36 @@ def closest(s1: Shape, s2: Shape) -> Tuple[Vector, Vector]:
65876650
ext.LoadS1(s1.wrapped)
65886651
ext.LoadS2(s2.wrapped)
65896652

6653+
ext.SetDeflection(tol)
6654+
import OCP
6655+
6656+
ext.SetAlgo(OCP.Extrema.Extrema_ExtAlgo.Extrema_ExtAlgo_Grad)
6657+
65906658
# perform
6591-
assert ext.Perform()
6659+
ext.Perform()
65926660

65936661
return Vector(ext.PointOnShape1(1)), Vector(ext.PointOnShape2(1))
6662+
6663+
6664+
def obb(s: Shape) -> Shape:
6665+
6666+
# construct the OBB
6667+
bbox = Bnd_OBB()
6668+
BRepBndLib.AddOBB_s(
6669+
s.wrapped, bbox, theIsTriangulationUsed=False, theIsOptimal=True
6670+
)
6671+
6672+
# convert to a shape
6673+
center = Vector(bbox.Center())
6674+
xdir = Vector(bbox.XDirection())
6675+
ydir = Vector(bbox.YDirection())
6676+
zdir = Vector(bbox.ZDirection())
6677+
6678+
dx = bbox.XHSize()
6679+
dy = bbox.YHSize()
6680+
dz = bbox.ZHSize()
6681+
6682+
ax = gp_Ax2(center.toPnt(), zdir.toDir(), xdir.toDir())
6683+
ax.SetLocation((center - dx * xdir - dy * ydir - dz * zdir).toPnt())
6684+
6685+
return Shape.cast(BRepPrimAPI_MakeBox(ax, 2.0 * dx, 2.0 * dy, 2.0 * dz).Shape())

0 commit comments

Comments
 (0)