Merge pull request #106 from CadQuery/adam-urbanczyk-text-rendering

Support for text rendering
This commit is contained in:
Adam Urbańczyk
2019-02-22 08:52:38 +01:00
committed by GitHub
3 changed files with 101 additions and 1 deletions

View File

@ -2268,6 +2268,20 @@ class Workplane(CQ):
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):
"""
@ -2770,6 +2784,45 @@ class Workplane(CQ):
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):
"""

View File

@ -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
@ -106,6 +106,11 @@ from OCC.LocOpe import LocOpe_DPrism
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
@ -1451,6 +1456,24 @@ class Compound(Shape, Mixin3D):
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

View File

@ -1800,3 +1800,27 @@ class TestCadQuery(BaseTest):
# 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)