Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
53 changes: 53 additions & 0 deletions cadquery/cq.py
Original file line number Diff line number Diff line change
Expand Up @@ -2268,6 +2268,20 @@ def _combineWithBase(self, obj):
r = baseSolid.fuse(obj)

return self.newObject([r])

def _cutFromBase(self, obj):
"""
Cuts the provided object from the base solid, if one can be found.
:param obj:
:return: a new object that represents the result of combining the base object with obj,
or obj if one could not be found
"""
baseSolid = self.findSolid(searchParents=True)
r = obj
if baseSolid is not None:
r = baseSolid.cut(obj)

return self.newObject([r])

def combine(self, clean=True):
"""
Expand Down Expand Up @@ -2770,6 +2784,45 @@ def clean(self):
raise AttributeError(
"%s object doesn't support `clean()` method!" % obj.ShapeType())
return self.newObject(cleanObjects)

def text(self, txt, fontsize, distance, cut=True, combine=False, clean=True,
font="Arial", kind='regular'):
"""
Create a 3D text

:param str txt: text to be rendered
:param distance: the distance to extrude, normal to the workplane plane
:type distance: float, negative means opposite the normal direction
:param float fontsize: size of the font
:param boolean cut: True to cut the resulting solid from the parent solids if found.
:param boolean combine: True to combine the resulting solid with parent solids if found.
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape
:param str font: fontname (default: Arial)
:param str kind: font type (default: Normal)
:return: a CQ object with the resulting solid selected.

extrude always *adds* material to a part.

The returned object is always a CQ object, and depends on wither combine is True, and
whether a context solid is already defined:

* if combine is False, the new value is pushed onto the stack.
* if combine is true, the value is combined with the context solid if it exists,
and the resulting solid becomes the new context solid.

"""
r = Compound.makeText(txt,fontsize,distance,font=font,kind=kind,
position=self.plane)

if cut:
newS = self._cutFromBase(r)
elif combine:
newS = self._combineWithBase(r)
else:
newS = self.newObject([r])
if clean:
newS = newS.clean()
return newS

def _repr_html_(self):
"""
Expand Down
25 changes: 24 additions & 1 deletion cadquery/occ_impl/shapes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from cadquery import Vector, BoundBox
from cadquery import Vector, BoundBox, Plane

import OCC.Core.TopAbs as ta # Tolopolgy type enum
import OCC.Core.GeomAbs as ga # Geometry type enum
Expand Down Expand Up @@ -106,6 +106,11 @@

from OCC.BRepCheck import BRepCheck_Analyzer

from OCC.Core.Addons import (text_to_brep,
Font_FA_Regular,
Font_FA_Italic,
Font_FA_Bold)

from math import pi, sqrt

TOLERANCE = 1e-6
Expand Down Expand Up @@ -1451,6 +1456,24 @@ def makeCompound(cls, listOfShapes):
comp_builder.Add(comp, s.wrapped)

return cls(comp)

@classmethod
def makeText(cls, text, size, height, font="Arial", kind='regular',
position=Plane.XY()):
"""
Create a 3D text
"""

font_kind = {'regular' : Font_FA_Regular,
'bold' : Font_FA_Bold,
'italic' : Font_FA_Italic}[kind]

text_flat = Shape(text_to_brep(text, font, font_kind, size, False))
vecNormal = text_flat.Faces()[0].normalAt()*height

text_3d = BRepPrimAPI_MakePrism(text_flat.wrapped, vecNormal.wrapped)

return cls(text_3d.Shape()).transformShape(position.rG)

# TODO this is likely not needed if sing PythonOCC.Core.correclty but we will see

Expand Down
24 changes: 24 additions & 0 deletions tests/TestCadQuery.py
Original file line number Diff line number Diff line change
Expand Up @@ -1800,3 +1800,27 @@ def testClose(self):

# The obj1 shape shall have the same volume as the obj2 shape.
self.assertAlmostEqual(obj1.val().Volume(), obj2.val().Volume())

def testText(self):

box = Workplane("XY" ).box(4, 4, 0.5)

obj1 = box.faces('>Z').workplane().text('CQ 2.0',0.5,-.05,cut=True)

#combined object should have smaller volume
self.assertGreater(box.val().Volume(),obj1.val().Volume())

obj2 = box.faces('>Z').workplane()\
.text('CQ 2.0',0.5,.05,cut=False,combine=True)

#combined object should have bigger volume
self.assertLess(box.val().Volume(),obj2.val().Volume())

#verify that the number of top faces is correct (NB: this is font specific)
self.assertEqual(len(obj2.faces('>Z').vals()),5)

obj3 = box.faces('>Z').workplane()\
.text('CQ 2.0',0.5,.05,cut=False,combine=False)

#verify that the number of solids is correct
self.assertEqual(len(obj3.solids().vals()),5)