Draft: Support new-style Draft texts in TechDraw

This commit is contained in:
Yorik van Havre
2018-06-01 11:05:15 -03:00
parent 5ea0e9aee0
commit 693d66eb7e
2 changed files with 76 additions and 59 deletions

View File

@@ -253,7 +253,7 @@ def ungroup(obj):
g = grp.Group
g.remove(obj)
grp.Group = g
def autogroup(obj):
"adds a given object to the autogroup, if applicable"
if FreeCAD.GuiUp:
@@ -357,7 +357,7 @@ def shapify(obj):
def getGroupContents(objectslist,walls=False,addgroups=False,spaces=False):
'''getGroupContents(objectlist,[walls,addgroups]): if any object of the given list
is a group, its content is appened to the list, which is returned. If walls is True,
walls and structures are also scanned for included windows or rebars. If addgroups
walls and structures are also scanned for included windows or rebars. If addgroups
is true, the group itself is also included in the list.'''
def getWindows(obj):
l = []
@@ -1159,9 +1159,9 @@ def makeArray(baseobject,arg1,arg2,arg3,arg4=None,arg5=None,arg6=None,name="Arra
makeArray(object,center,totalangle,totalnum,[name]) for polar array: Creates an array
of the given object
with, in case of rectangular array, xnum of iterations in the x direction
at xvector distance between iterations, same for y direction with yvector and ynum,
same for z direction with zvector and znum. In case of polar array, center is a vector,
totalangle is the angle to cover (in degrees) and totalnum is the number of objects,
at xvector distance between iterations, same for y direction with yvector and ynum,
same for z direction with zvector and znum. In case of polar array, center is a vector,
totalangle is the angle to cover (in degrees) and totalnum is the number of objects,
including the original. The result is a parametric Draft Array.'''
if not FreeCAD.ActiveDocument:
FreeCAD.Console.PrintError("No active document. Aborting\n")
@@ -1400,7 +1400,7 @@ def move(objectslist,vector,copy=False):
newobj.End = obj.End.add(vector)
newobj.Dimline = obj.Dimline.add(vector)
else:
if copy and obj.isDerivedFrom("Mesh::Feature"):
if copy and obj.isDerivedFrom("Mesh::Feature"):
print("Mesh copy not supported at the moment") # TODO
newobj = obj
if "Placement" in obj.PropertiesList:
@@ -1416,19 +1416,19 @@ def move(objectslist,vector,copy=False):
if copy and getParam("selectBaseObjects",False):
select(objectslist)
else:
select(newobjlist)
select(newobjlist)
if len(newobjlist) == 1: return newobjlist[0]
return newobjlist
def array(objectslist,arg1,arg2,arg3,arg4=None,arg5=None,arg6=None):
'''array(objectslist,xvector,yvector,xnum,ynum) for rectangular array,
'''array(objectslist,xvector,yvector,xnum,ynum) for rectangular array,
array(objectslist,xvector,yvector,zvector,xnum,ynum,znum) for rectangular array,
or array(objectslist,center,totalangle,totalnum) for polar array: Creates an array
of the objects contained in list (that can be an object or a list of objects)
with, in case of rectangular array, xnum of iterations in the x direction
at xvector distance between iterations, and same for y and z directions with yvector
and ynum and zvector and znum. In case of polar array, center is a vector, totalangle
is the angle to cover (in degrees) and totalnum is the number of objects, including
and ynum and zvector and znum. In case of polar array, center is a vector, totalangle
is the angle to cover (in degrees) and totalnum is the number of objects, including
the original.
This function creates an array of independent objects. Use makeArray() to create a
@@ -1609,7 +1609,7 @@ def scale(objectslist,delta=Vector(1,1,1),center=Vector(0,0,0),copy=False,legacy
newobj.ViewObject.FontSize = factor
d = obj.Position.sub(center)
newobj.Position = center.add(Vector(d.x*delta.x,d.y*delta.y,d.z*delta.z))
if copy:
if copy:
formatObject(newobj,obj)
newobjlist.append(newobj)
if copy and getParam("selectBaseObjects",False):
@@ -2274,6 +2274,16 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
return svg
def getText(color,fontsize,fontname,angle,base,text,linespacing=0.5,align="center",flip=True):
if isinstance(angle,FreeCAD.Rotation):
if not plane:
angle = angle.Angle
else:
if plane.axis.getAngle(angle.Axis) < 0.001:
angle = angle.Angle
elif abs(plane.axis.getAngle(angle.Axis)-math.pi) < 0.001:
return "" # text is perpendicular to view, so it shouldn't appear
else:
angle = 0 #TODO maybe there is something better to do here?
if not isinstance(text,list):
text = text.split("\n")
if align.lower() == "center":
@@ -2487,16 +2497,22 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
tbase = getProj(prx.tbase)
svg += getText(stroke,fontsize,obj.ViewObject.FontName,tangle,tbase,prx.string)
elif getType(obj) == "Annotation":
elif getType(obj) in ["Annotation","DraftText"]:
"returns an svg representation of a document annotation"
if not obj.ViewObject:
print ("export of texts to SVG is only available in GUI mode")
else:
n = obj.ViewObject.FontName
a = obj.ViewObject.Rotation.getValueAs("rad")
t = obj.LabelText
if getType(obj) == "Annotation":
p = getProj(obj.Position)
r = obj.ViewObject.Rotation.getValueAs("rad")
t = obj.LabelText
else: # DraftText
p = getProj(obj.Placement.Base)
r = obj.Placement.Rotation
t = obj.Text
j = obj.ViewObject.Justification
svg += getText(stroke,fontsize,n,a,getProj(obj.Position),t,linespacing,j)
svg += getText(stroke,fontsize,n,r,p,t,linespacing,j)
elif getType(obj) == "Axis":
"returns the SVG representation of an Arch Axis system"
@@ -2551,7 +2567,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
if len(f.Edges) == 1:
if isinstance(f.Edges[0].Curve,Part.Circle):
svg += getCircle(f.Edges[0])
elif getType(obj) == "Rebar":
fill = "none"
lstyle = getLineStyle()
@@ -2645,7 +2661,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
angle = -DraftVecUtils.angle(p2.sub(p1))
arrowsize = obj.ViewObject.ArrowSize.Value/pointratio
svg += getArrow(obj.ViewObject.ArrowType,p2,arrowsize,stroke,linewidth,angle)
# techdraw expects bottom-to-top coordinates
if techdraw:
svg = '<g transform ="scale(1,-1)">'+svg+'</g>'
@@ -2744,23 +2760,23 @@ def makeShape2DView(baseobj,projectionVector=None,facenumbers=[]):
def makeSketch(objectslist,autoconstraints=False,addTo=None,
delete=False,name="Sketch",radiusPrecision=-1):
'''makeSketch(objectslist,[autoconstraints],[addTo],[delete],[name],[radiusPrecision]):
'''makeSketch(objectslist,[autoconstraints],[addTo],[delete],[name],[radiusPrecision]):
Makes a Sketch objectslist with the given Draft objects.
Makes a Sketch objectslist with the given Draft objects.
* objectlist: can be single or list of objects of Draft type objects,
Part::Feature, Part.Shape, or mix of them.
* autoconstraints(False): if True, constraints will be automatically added to
wire nodes, rectangles and circles.
wire nodes, rectangles and circles.
* addTo(None) : if set to an existing sketch, geometry will be added to it
instead of creating a new one.
* delete(False): if True, the original object will be deleted.
* delete(False): if True, the original object will be deleted.
If set to a string 'all' the object and all its linked object will be
deleted
* name('Sketch'): the name for the new sketch object
* radiusPrecision(-1): If <0, disable radius constraint. If =0, add indiviaul
@@ -6084,7 +6100,7 @@ class _Clone(_DraftObject):
obj.addProperty("App::PropertyVector","Scale","Draft",QT_TRANSLATE_NOOP("App::Property","The scale factor of this clone"))
obj.addProperty("App::PropertyBool","Fuse","Draft",QT_TRANSLATE_NOOP("App::Property","If this clones several objects, this specifies if the result is a fusion or a compound"))
obj.Scale = Vector(1,1,1)
def join(self,obj,shapes):
if len(shapes) < 2:
return shapes[0]
@@ -6214,7 +6230,7 @@ class _ViewProviderDraftArray(_ViewProviderDraft):
def getIcon(self):
return ":/icons/Draft_Array.svg"
def resetColors(self, vobj):
colors = []
if vobj.Object.Base:
@@ -6550,9 +6566,9 @@ class _ViewProviderVisGroup:
class WorkingPlaneProxy:
"The Draft working plane proxy object"
def __init__(self,obj):
obj.Proxy = self
obj.addProperty("App::PropertyPlacement","Placement","Base",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
@@ -6615,11 +6631,11 @@ class ViewProviderWorkingPlaneProxy:
def claimChildren(self):
return []
def doubleClicked(self,vobj):
FreeCADGui.runCommand("Draft_SelectPlane")
return True
def setupContextMenu(self,vobj,menu):
from PySide import QtCore,QtGui
action1 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_SelectPlane.svg"),"Write camera position",menu)
@@ -6628,7 +6644,7 @@ class ViewProviderWorkingPlaneProxy:
action2 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_SelectPlane.svg"),"Write objects state",menu)
QtCore.QObject.connect(action2,QtCore.SIGNAL("triggered()"),self.writeState)
menu.addAction(action2)
def writeCamera(self):
if hasattr(self,"Object"):
from pivy import coin
@@ -6647,7 +6663,7 @@ class ViewProviderWorkingPlaneProxy:
cdata.append(n.heightAngle.getValue())
cdata.append(1.0) # perspective camera
self.Object.ViewObject.ViewData = cdata
def writeState(self):
if hasattr(self,"Object"):
FreeCAD.Console.PrintMessage(QT_TRANSLATE_NOOP("Draft","Writing objects shown/hidden state")+"\n")
@@ -6787,9 +6803,9 @@ def makeLabel(targetpoint=None,target=None,direction=None,distance=None,labeltyp
class DraftLabel:
"The Draft Label object"
def __init__(self,obj):
obj.Proxy = self
obj.addProperty("App::PropertyPlacement","Placement","Base",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))
@@ -6988,7 +7004,7 @@ class ViewProviderDraftLabel:
self.text2d.string.setValues([l.encode("utf8") for l in obj.Text if l])
self.text3d.string.setValues([l.encode("utf8") for l in obj.Text if l])
self.onChanged(obj.ViewObject,"TextAlignment")
def getTextSize(self,vobj):
from pivy import coin
if vobj.DisplayMode == "3D text":
@@ -7081,9 +7097,9 @@ class ViewProviderDraftLabel:
class DraftText:
"The Draft Text object"
def __init__(self,obj):
obj.Proxy = self
obj.addProperty("App::PropertyPlacement","Placement","Base",QT_TRANSLATE_NOOP("App::Property","The placement of this object"))

View File

@@ -436,7 +436,7 @@ class SelectPlane(DraftTool):
self.finish()
except:
pass
def getCenterPoint(self,x,y,z):
if not self.ui.isCenterPlane:
return "0,0,0"
@@ -503,7 +503,7 @@ class SelectPlane(DraftTool):
def redraw3DView():
"""redraw3DView(): forces a redraw of 3d view."""
try:
FreeCADGui.ActiveDocument.ActiveView.redraw()
FreeCADGui.ActiveDocument.ActiveView.redraw()
except AttributeError as err:
pass
@@ -1811,6 +1811,7 @@ class Text(Creator):
self.commit(translate("draft","Create Text"),
['text = Draft.makeText('+tx+',point='+DraftVecUtils.toString(self.node[0])+')',
'Draft.autogroup(text)'])
FreeCAD.ActiveDocument.recompute()
self.finish(cont=True)
@@ -1889,7 +1890,7 @@ class Dimension(Creator):
self.setFromSelection()
msg(translate("draft", "Pick first point:")+"\n")
FreeCADGui.draftToolBar.show()
def setFromSelection(self):
"If we already have selected geometry, fill the nodes accordingly"
sel = FreeCADGui.Selection.getSelectionEx()
@@ -2158,7 +2159,7 @@ class Dimension(Creator):
elif (len(self.node) == 2) and self.cont:
self.node.append(self.cont)
self.createObject()
if not self.cont:
if not self.cont:
self.finish()
elif (len(self.node) == 3):
# for unlinked arc mode:
@@ -2168,7 +2169,7 @@ class Dimension(Creator):
# cen = self.node[0].add(v)
# self.node = [self.node[0],self.node[1],cen]
self.createObject()
if not self.cont:
if not self.cont:
self.finish()
elif self.angledata:
self.node.append(self.point)
@@ -2184,7 +2185,7 @@ class Dimension(Creator):
self.dimtrack.on()
elif (len(self.node) == 3):
self.createObject()
if not self.cont:
if not self.cont:
self.finish()
class ShapeString(Creator):
@@ -2837,7 +2838,7 @@ class Offset(Modifier):
d = DraftVecUtils.toString(self.dvec)
copymode = False
occmode = self.ui.occOffset.isChecked()
if self.ui.isCopy.isChecked():
if self.ui.isCopy.isChecked():
copymode = True
FreeCADGui.addModule("Draft")
self.commit(translate("draft","Offset"),
@@ -2864,9 +2865,9 @@ class Stretch(Modifier):
self.call = self.view.addEventCallback("SoEvent",selectObject)
else:
self.proceed()
def proceed(self):
if self.call:
if self.call:
self.view.removeEventCallback("SoEvent",self.call)
self.sel = FreeCADGui.Selection.getSelection()
if self.ui and self.sel:
@@ -3497,7 +3498,7 @@ class Trimex(Modifier):
self.doc.commitTransaction()
self.doc.recompute()
for g in self.ghost: g.off()
def trimObjects(self,objectslist):
"attempts to trim two objects together"
import Part
@@ -3563,7 +3564,7 @@ class Trimex(Modifier):
else:
obj.FirstAngle = ang
self.doc.recompute()
def finish(self,closed=False):
Modifier.finish(self)
@@ -3984,7 +3985,7 @@ class Edit(Modifier):
self.obj.ViewObject.NodeSize = 1
self.obj.ViewObject.ShowNodes = True
for p in self.obj.Nodes:
if self.pl:
if self.pl:
p = self.pl.multVec(p)
self.editpoints.append(p)
elif Draft.getType(self.obj) == "PanelCut":
@@ -4066,7 +4067,7 @@ class Edit(Modifier):
# commented out the following line to disable updating
# the object during edit, otherwise it confuses the snapper
#self.update(self.trackers[self.editing].get())
redraw3DView()
redraw3DView()
elif arg["Type"] == "SoMouseButtonEvent":
if (arg["State"] == "DOWN") and (arg["Button"] == "BUTTON1"):
self.ui.redraw()
@@ -4237,7 +4238,7 @@ class Edit(Modifier):
else:
self.obj.Group[self.editing-1].Placement.Base = self.invpl.multVec(v)
try:
FreeCADGui.ActiveDocument.ActiveView.redraw()
FreeCADGui.ActiveDocument.ActiveView.redraw()
except AttributeError as err:
pass
@@ -5231,7 +5232,7 @@ class SetAutoGroup():
self.labels = ["None"]
for g in gn:
o = FreeCAD.ActiveDocument.getObject(g)
if o:
if o:
self.labels.append(o.Label)
self.ui.sourceCmd = self
self.ui.popupMenu(self.labels)
@@ -5293,7 +5294,7 @@ class Draft_Label(Creator):
self.call = self.view.addEventCallback("SoEvent",self.action)
msg(translate("draft", "Pick target point:")+"\n")
self.ui.isCopy.hide()
def setmode(self,i):
self.labeltype = ["Custom","Name","Label","Position","Length","Area","Volume","Tag","Material"][i]
Draft.setParam("labeltype",self.labeltype)
@@ -5302,7 +5303,7 @@ class Draft_Label(Creator):
if self.ghost:
self.ghost.finalize()
Creator.finish(self)
def create(self):
if len(self.node) == 3:
targetpoint = self.node[0]
@@ -5350,7 +5351,7 @@ class Draft_Label(Creator):
self.finish()
elif arg["Type"] == "SoLocation2Event":
if hasattr(FreeCADGui,"Snapper"):
FreeCADGui.Snapper.affinity = None # don't keep affinity
FreeCADGui.Snapper.affinity = None # don't keep affinity
if len(self.node) == 2:
setMod(arg,MODCONSTRAIN,True)
self.point,ctrlPoint,info = getPoint(self,arg)
@@ -5422,13 +5423,13 @@ class Draft_AddConstruction():
for obj in FreeCADGui.Selection.getSelection():
grp.addObject(obj)
obrep = obj.ViewObject
if "TextColor" in obrep.PropertiesList:
if "TextColor" in obrep.PropertiesList:
obrep.TextColor = col
if "PointColor" in obrep.PropertiesList:
if "PointColor" in obrep.PropertiesList:
obrep.PointColor = col
if "LineColor" in obrep.PropertiesList:
if "LineColor" in obrep.PropertiesList:
obrep.LineColor = col
if "ShapeColor" in obrep.PropertiesList:
if "ShapeColor" in obrep.PropertiesList:
obrep.ShapeColor = col
if hasattr(obrep,"Transparency"):
obrep.Transparency = 80