Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Text fixes and some shape/free func additions #1700

Merged
merged 85 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from 84 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
c592ce8
Initial commit of better paramAt, solid and a new function check
adam-urbanczyk Sep 25, 2024
1dd7481
mypy fix
adam-urbanczyk Sep 25, 2024
3e9d30f
isSolid fix
adam-urbanczyk Sep 25, 2024
6ba8b72
Implement outerShell, innerShells
adam-urbanczyk Sep 25, 2024
44cb068
Imports cleanup
adam-urbanczyk Sep 25, 2024
bac0c7a
Typo fix
adam-urbanczyk Sep 25, 2024
12c5e0e
Make paramAt fully compatibile with Wires
adam-urbanczyk Sep 26, 2024
b820c3a
Typo fix
adam-urbanczyk Sep 26, 2024
908064b
Add check test
adam-urbanczyk Sep 26, 2024
eda0d3f
Fix orientation handling
adam-urbanczyk Sep 26, 2024
5330777
Add test
adam-urbanczyk Sep 26, 2024
151a70b
paramAt test
adam-urbanczyk Sep 27, 2024
a39a8cc
More tests
adam-urbanczyk Sep 27, 2024
c6d372e
Add orientation fix and optimize check
adam-urbanczyk Oct 1, 2024
06aa44f
Switch to miniforge
adam-urbanczyk Oct 1, 2024
de5cc76
Add missing newline
adam-urbanczyk Oct 8, 2024
a894918
Use OBB (perf) and modified frenet
adam-urbanczyk Oct 20, 2024
520afc5
Merge branch 'shape-improvements' of https://github.com/CadQuery/cadq…
adam-urbanczyk Oct 20, 2024
56d9cbe
Merge branch 'master' into shape-improvements
adam-urbanczyk Oct 20, 2024
6f3e93e
overload normalAt for parameters
adam-urbanczyk Oct 21, 2024
aabe46d
bulk normals calculation
adam-urbanczyk Oct 21, 2024
0446dcf
workaround for bad fonts
adam-urbanczyk Oct 21, 2024
8179a00
first pass at loft to vertex
adam-urbanczyk Oct 22, 2024
a3e87af
Add trim and more loft to vertex tweaks
adam-urbanczyk Oct 22, 2024
9af29a2
Some mypy fixes
adam-urbanczyk Oct 23, 2024
4e4ef16
Loft improvements and sewing fixes.
adam-urbanczyk Oct 24, 2024
2707a7d
Add loft to vertox to workplane
adam-urbanczyk Oct 24, 2024
36009e1
Add dummy kwargs for better unified codebase support (raw / CQ-editor)
adam-urbanczyk Oct 24, 2024
c7e676d
Add continuity
adam-urbanczyk Oct 24, 2024
ec7757e
Use seperate builders for loft
adam-urbanczyk Oct 27, 2024
3f96f18
Add parametrization to loft and aux spine to sweep
adam-urbanczyk Oct 27, 2024
d79f171
Add params to spline interpolation
adam-urbanczyk Oct 27, 2024
d00f113
Add missing arg
adam-urbanczyk Oct 31, 2024
64d88af
Add tol and smoothing
adam-urbanczyk Nov 1, 2024
0584b37
Fix cap handling
adam-urbanczyk Nov 7, 2024
e5ff3bc
Fix crash
adam-urbanczyk Nov 7, 2024
8410af5
Fix loft args
adam-urbanczyk Nov 7, 2024
198013e
Typo
adam-urbanczyk Nov 7, 2024
e302135
Fix test
adam-urbanczyk Nov 7, 2024
750ea3b
Fix show test
adam-urbanczyk Nov 7, 2024
bc5b987
2nd show fix
adam-urbanczyk Nov 7, 2024
3a02fe0
Some loft tests
adam-urbanczyk Nov 7, 2024
de6dd89
Logic fix
adam-urbanczyk Nov 8, 2024
4b6e84d
Add curvature calculation
adam-urbanczyk Nov 9, 2024
649f8f0
Add multimethod docstrings
adam-urbanczyk Nov 9, 2024
f60ea78
Some tests
adam-urbanczyk Nov 9, 2024
23a5c2e
Add and fix tests
adam-urbanczyk Nov 9, 2024
5040668
More tests
adam-urbanczyk Nov 9, 2024
334bc2b
Another overload
adam-urbanczyk Nov 9, 2024
452032b
Loft to vertex tests
adam-urbanczyk Nov 9, 2024
5db25e6
Imporve coverage
adam-urbanczyk Nov 9, 2024
859572b
Remove dead code
adam-urbanczyk Nov 9, 2024
a0c2f08
Readd code with better explanation
adam-urbanczyk Nov 9, 2024
57bc5ed
Better coverage
adam-urbanczyk Nov 9, 2024
938fed6
Extend vis
adam-urbanczyk Nov 9, 2024
5d2d901
Mypy fixes
adam-urbanczyk Nov 9, 2024
94b67e5
Add alpha
adam-urbanczyk Nov 9, 2024
4b227a5
Mypy fix
adam-urbanczyk Nov 9, 2024
ff3fea5
Fix vtk rotation order
adam-urbanczyk Nov 9, 2024
4af1dd1
Second vtk rot fix
adam-urbanczyk Nov 9, 2024
cc5ccfd
Merge branch 'master' into shape-improvements
adam-urbanczyk Nov 10, 2024
1fcefa4
Typo fixes
adam-urbanczyk Nov 11, 2024
e4b1dc5
Fix regression
adam-urbanczyk Nov 13, 2024
c5b9c5e
Merge branch 'master' into shape-improvements
adam-urbanczyk Nov 13, 2024
28c082d
Text, offset, solid and exportBin changes
adam-urbanczyk Nov 14, 2024
18c0acd
Binary BREP in exporters/importers
adam-urbanczyk Nov 14, 2024
556c73c
Extra tests
adam-urbanczyk Nov 14, 2024
25b71bc
Fix tests
adam-urbanczyk Nov 14, 2024
5f5a787
Add bin imp/exp test
adam-urbanczyk Nov 14, 2024
728bbd3
Blacken
adam-urbanczyk Nov 14, 2024
3a24e12
Remove one overload
adam-urbanczyk Nov 14, 2024
efba7dd
Fix dispatch
adam-urbanczyk Nov 14, 2024
c65c257
Fix test
adam-urbanczyk Nov 14, 2024
7476275
Extra vis options
adam-urbanczyk Nov 14, 2024
0b31ab6
Different error
adam-urbanczyk Nov 14, 2024
238d504
Fix/more tests
adam-urbanczyk Nov 14, 2024
9de4a1d
Better coverage
adam-urbanczyk Nov 15, 2024
67cd3f4
More tests
adam-urbanczyk Nov 15, 2024
a4e6a63
Docs text placeholder
adam-urbanczyk Nov 18, 2024
fe33f7d
Pseudo-infinite plane
adam-urbanczyk Nov 20, 2024
c2a705e
Merge branch 'shape-improvements' of https://github.com/CadQuery/cadq…
adam-urbanczyk Nov 20, 2024
eddaaa4
Add an example for text
adam-urbanczyk Nov 20, 2024
2f24f91
Black fix
adam-urbanczyk Nov 20, 2024
f7d6d95
Apply suggestions from code review
adam-urbanczyk Nov 23, 2024
feeefdd
Typo fixes
adam-urbanczyk Nov 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cadquery/occ_impl/exporters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ class ExportTypes:
VTP = "VTP"
THREEMF = "3MF"
BREP = "BREP"
BIN = "BIN"


ExportLiterals = Literal[
"STL", "STEP", "AMF", "SVG", "TJS", "DXF", "VRML", "VTP", "3MF", "BREP"
"STL", "STEP", "AMF", "SVG", "TJS", "DXF", "VRML", "VTP", "3MF", "BREP", "BIN"
]


Expand Down Expand Up @@ -128,6 +129,9 @@ def export(
elif exportType == ExportTypes.BREP:
shape.exportBrep(fname)

elif exportType == ExportTypes.BIN:
shape.exportBin(fname)

else:
raise ValueError("Unknown export type")

Expand Down
17 changes: 16 additions & 1 deletion cadquery/occ_impl/importers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class ImportTypes:
STEP = "STEP"
DXF = "DXF"
BREP = "BREP"
BIN = "BIN"


class UNITS:
Expand All @@ -23,7 +24,7 @@ class UNITS:


def importShape(
importType: Literal["STEP", "DXF", "BREP"], fileName: str, *args, **kwargs
importType: Literal["STEP", "DXF", "BREP", "BIN"], fileName: str, *args, **kwargs
) -> "cq.Workplane":
"""
Imports a file based on the type (STEP, STL, etc)
Expand All @@ -39,6 +40,8 @@ def importShape(
return importDXF(fileName, *args, **kwargs)
elif importType == ImportTypes.BREP:
return importBrep(fileName)
elif importType == ImportTypes.BIN:
return importBin(fileName)
else:
raise RuntimeError("Unsupported import type: {!r}".format(importType))

Expand All @@ -60,6 +63,18 @@ def importBrep(fileName: str) -> "cq.Workplane":
return cq.Workplane("XY").newObject([shape])


def importBin(fileName: str) -> "cq.Workplane":
"""
Loads the binary BREP file as a single shape into a cadquery Workplane.

:param fileName: The path and name of the BREP file to be imported

"""
shape = Shape.importBin(fileName)

return cq.Workplane("XY").newObject([shape])


# Loads a STEP file into a CQ.Workplane object
def importStep(fileName: str) -> "cq.Workplane":
"""
Expand Down
187 changes: 161 additions & 26 deletions cadquery/occ_impl/shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@

from OCP.LProp3d import LProp3d_CLProps

from OCP.BinTools import BinTools

from math import pi, sqrt, inf, radians, cos

import warnings
Expand Down Expand Up @@ -520,6 +522,26 @@ def importBrep(cls, f: Union[str, BytesIO]) -> "Shape":

return cls.cast(s)

def exportBin(self, f: Union[str, BytesIO]) -> bool:
"""
Export this shape to a binary BREP file.
"""

rv = BinTools.Write_s(self.wrapped, f)

return True if rv is None else rv

@classmethod
def importBin(cls, f: Union[str, BytesIO]) -> "Shape":
"""
Import shape from a binary BREP file.
"""
s = TopoDS_Shape()

BinTools.Read_s(s, f)

return cls.cast(s)

def geomType(self) -> Geoms:
"""
Gets the underlying geometry type.
Expand Down Expand Up @@ -4528,6 +4550,7 @@ def _normalize(s: Shape) -> Shape:
"""
Apply some normalizations:
- Shell with only one Face -> Face.
- Compound with only one element -> element.
"""

t = s.ShapeType()
Expand Down Expand Up @@ -4724,17 +4747,26 @@ def shell(s: Sequence[Shape], tol: float = 1e-6) -> Shape:


@multimethod
def solid(*s: Shape, tol: float = 1e-6) -> Shape:
def solid(s1: Shape, *sn: Shape, tol: float = 1e-6) -> Shape:
"""
Build solid from faces.
Build solid from faces or shells.
"""

builder = ShapeFix_Solid()

faces = [f for el in s for f in _get(el, "Face")]
rv = builder.SolidFromShell(shell(*faces, tol=tol).wrapped)
# get both Shells and Faces
s = [s1, *sn]
shells_faces = [f for el in s for f in _get(el, ("Shell", "Face"))]

return _compound_or_shape(rv)
# if no shells are present, use faces to construct them
shells = [el.wrapped for el in shells_faces if el.ShapeType() == "Shell"]
if not shells:
faces = [el for el in shells_faces]
shells = [shell(*faces, tol=tol).wrapped]

rvs = [builder.SolidFromShell(sh) for sh in shells]

return _compound_or_shape(rvs)


@solid.register
Expand Down Expand Up @@ -4922,9 +4954,10 @@ def ellipse(r1: float, r2: float) -> Shape:
)


def plane(w: float, l: float) -> Shape:
@multimethod
def plane(w: Real, l: Real) -> Shape:
"""
Construct a planar face.
Construct a finite planar face.
"""

pln_geom = gp_Pln(Vector(0, 0, 0).toPnt(), Vector(0, 0, 1).toDir())
Expand All @@ -4934,6 +4967,24 @@ def plane(w: float, l: float) -> Shape:
)


@plane.register
def plane() -> Shape:
"""
Construct an infinite planar face.

This is a crude approximation. Truly infinite faces in OCCT do not work as
expected in all contexts.
"""

INF = 1e60

pln_geom = gp_Pln(Vector(0, 0, 0).toPnt(), Vector(0, 0, 1).toDir())

return _compound_or_shape(
BRepBuilderAPI_MakeFace(pln_geom, -INF, INF, -INF, INF).Face()
)


def box(w: float, l: float, h: float) -> Shape:
"""
Construct a solid box.
Expand Down Expand Up @@ -5012,9 +5063,10 @@ def cone(d: Real, h: Real) -> Shape:
return cone(d, 0, h)


@multimethod
def text(
txt: str,
size: float,
size: Real,
font: str = "Arial",
path: Optional[str] = None,
kind: Literal["regular", "bold", "italic"] = "regular",
Expand Down Expand Up @@ -5065,7 +5117,67 @@ def text(
font_i, NCollection_Utf8String(txt), theHAlign=theHAlign, theVAlign=theVAlign
)

return clean(_compound_or_shape(rv).faces().fuse())
return clean(compound(_compound_or_shape(rv).faces()).fuse())


@text.register
def text(
txt: str,
size: Real,
spine: Shape,
planar: bool = False,
font: str = "Arial",
path: Optional[str] = None,
kind: Literal["regular", "bold", "italic"] = "regular",
halign: Literal["center", "left", "right"] = "center",
valign: Literal["center", "top", "bottom"] = "center",
) -> Shape:
"""
Create a text on a spine.
"""

spine = _get_one_wire(spine)
L = spine.Length()

rv = []
for el in text(txt, size, font, path, kind, halign, valign):
pos = el.BoundingBox().center.x

# position
rv.append(
el.moved(-pos)
.moved(rx=-90 if planar else 0, ry=-90)
.moved(spine.locationAt(pos / L))
)

return _normalize(compound(rv))


@text.register
def text(
txt: str,
size: Real,
spine: Shape,
base: Shape,
font: str = "Arial",
path: Optional[str] = None,
kind: Literal["regular", "bold", "italic"] = "regular",
halign: Literal["center", "left", "right"] = "center",
valign: Literal["center", "top", "bottom"] = "center",
) -> Shape:
"""
Create a text on a spine and a base surface.
"""

base = _get_one(base, "Face")

tmp = text(txt, size, spine, False, font, path, kind, halign, valign)

rv = []
for f in tmp.faces():
rv.append(f.project(base, f.normalAt()))

return _normalize(compound(rv))


#%% ops
Expand Down Expand Up @@ -5266,33 +5378,56 @@ def revolve(s: Shape, p: VectorLike, d: VectorLike, a: float = 360):
return _compound_or_shape(results)


def offset(s: Shape, t: float, cap=True, tol: float = 1e-6) -> Shape:
def offset(
s: Shape, t: float, cap=True, both: bool = False, tol: float = 1e-6
) -> Shape:
"""
Offset or thicken faces or shells.
"""

builder = BRepOffset_MakeOffset()
def _offset(t):

results = []
results = []

for el in _get(s, ("Face", "Shell")):
for el in _get(s, ("Face", "Shell")):

builder.Initialize(
el.wrapped,
t,
tol,
BRepOffset_Mode.BRepOffset_Skin,
False,
False,
GeomAbs_Intersection,
cap,
)
builder = BRepOffset_MakeOffset()

builder.MakeOffsetShape()
builder.Initialize(
el.wrapped,
t,
tol,
BRepOffset_Mode.BRepOffset_Skin,
False,
False,
GeomAbs_Intersection,
cap,
)

results.append(builder.Shape())
builder.MakeOffsetShape()

return _compound_or_shape(results)
results.append(builder.Shape())

return results

if both:
results_pos = _offset(t)
results_neg = _offset(-t)

results_both = [
Shape(el1) + Shape(el2) for el1, el2 in zip(results_pos, results_neg)
]

if len(results_both) == 1:
rv = results_both[0]
else:
rv = Compound.makeCompound(results_both)

else:
results = _offset(t)
rv = _compound_or_shape(results)

return rv


@multimethod
Expand Down
17 changes: 15 additions & 2 deletions cadquery/vis.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,14 @@ def _to_vtk_axs(locs: List[Location], scale: float = 0.1) -> vtkActor:
return rv


def show(*objs: Showable, scale: float = 0.2, alpha: float = 1, **kwrags: Any):
def show(
*objs: Showable,
scale: float = 0.2,
alpha: float = 1,
tolerance: float = 1e-3,
edges: bool = False,
**kwrags: Any,
):
"""
Show CQ objects using VTK.
"""
Expand All @@ -145,10 +152,16 @@ def show(*objs: Showable, scale: float = 0.2, alpha: float = 1, **kwrags: Any):
axs = _to_vtk_axs(locs, scale=scale)

# create a VTK window
win = _vtkRenderWindow(assy)
win = _vtkRenderWindow(assy, tolerance=tolerance)

win.SetWindowName("CQ viewer")

# get renderer and actor
if edges:
ren = win.GetRenderers().GetFirstRenderer()
for act in ren.GetActors():
act.GetProperty().EdgeVisibilityOn()

# rendering related settings
win.SetMultiSamples(16)
vtkMapper.SetResolveCoincidentTopologyToPolygonOffset()
Expand Down
Loading