FreeCAD/src/Mod/Draft/importDXF.py
2013-04-18 13:48:49 -03:00

1510 lines
58 KiB
Python

# -*- coding: utf8 -*-
#***************************************************************************
#* *
#* Copyright (c) 2009 Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (GPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
#* GNU Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
__title__="FreeCAD Draft Workbench - DXF importer/exporter"
__author__ = "Yorik van Havre <yorik@uncreated.net>"
__url__ = ["http://yorik.orgfree.com","http://free-cad.sourceforge.net"]
'''
This script uses a DXF-parsing library created by Stani,
Kitsu and Migius for Blender
imports:
line, polylines, lwpolylines, arcs, circles, texts,
mtexts, layers (as groups), colors
exports:
lines, polylines, lwpolylines, circles, arcs,
texts, colors,layers (from groups)
'''
import FreeCAD, os, Part, math, re, string, Mesh, Draft, DraftVecUtils, DraftGeomUtils
from draftlibs import dxfColorMap, dxfLibrary
from draftlibs.dxfReader import readDXF
from Draft import _Dimension, _ViewProviderDimension
from FreeCAD import Vector
try: import FreeCADGui
except: gui = False
else: gui = True
try: draftui = FreeCADGui.draftToolBar
except: draftui = None
if open.__module__ == '__builtin__':
pythonopen = open # to distinguish python built-in open function from the one declared here
def prec():
"returns the current Draft precision level"
return Draft.getParam("precision")
def decodeName(name):
"decodes encoded strings"
try:
decodedName = (name.decode("utf8"))
except UnicodeDecodeError:
try:
decodedName = (name.decode("latin1"))
except UnicodeDecodeError:
print "dxf: error: couldn't determine character encoding"
decodedName = name
return decodedName
def deformat(text):
"removes weird formats in texts and wipes UTF characters"
# remove ACAD string formatation
#t = re.sub('{([^!}]([^}]|\n)*)}', '', text)
t = text.strip("{}")
t = re.sub("\\\.*?;","",t)
# replace UTF codes
t = re.sub("\\\\U\+00e9","e",t)
t = re.sub("\\\\U\+00e1","a",t)
t = re.sub("\\\\U\+00e7","c",t)
t = re.sub("\\\\U\+00e3","a",t)
t = re.sub("\\\\U\+00e0","a",t)
t = re.sub("\\\\U\+00c1","A",t)
t = re.sub("\\\\U\+00ea","e",t)
# replace non-UTF chars
t = re.sub("ã","a",t)
t = re.sub("ç","c",t)
t = re.sub("õ","o",t)
t = re.sub("à","a",t)
t = re.sub("á","a",t)
t = re.sub("â","a",t)
t = re.sub("é","e",t)
t = re.sub("è","e",t)
t = re.sub("ê","e",t)
t = re.sub("í","i",t)
t = re.sub("Á","A",t)
t = re.sub("À","A",t)
t = re.sub("É","E",t)
t = re.sub("È","E",t)
# replace degrees, diameters chars
t = re.sub('%%d','°',t)
t = re.sub('%%c','Ø',t)
return t
def locateLayer(wantedLayer):
"returns layer group and creates it if needed"
wantedLayerName = decodeName(wantedLayer)
for l in layers:
if wantedLayerName==l.Label:
return l
newLayer = doc.addObject("App::DocumentObjectGroup",wantedLayer)
newLayer.Label = wantedLayerName
layers.append(newLayer)
return newLayer
def getdimheight(style):
"returns the dimension text height from the given dimstyle"
for t in drawing.tables.data:
if t.name == 'dimstyle':
for a in t.data:
if hasattr(a,"type"):
if a.type == "dimstyle":
if rawValue(a,2) == style:
return rawValue(a,140)
return None
def calcBulge(v1,bulge,v2):
'''
calculates intermediary vertex for curved segments.
algorithm from http://www.afralisp.net/lisp/Bulges1.htm
'''
chord = v2.sub(v1)
sagitta = (bulge * chord.Length)/2
startpoint = v1.add(DraftVecUtils.scale(chord,0.5))
perp = chord.cross(Vector(0,0,1))
if not DraftVecUtils.isNull(perp): perp.normalize()
endpoint = DraftVecUtils.scale(perp,sagitta)
return startpoint.add(endpoint)
def getGroup(ob,exportList):
"checks if the object is part of a group"
for i in exportList:
if (i.Type == "App::DocumentObjectGroup"):
for j in i.Group:
if (j == ob):
return i.Label
return "0"
def getACI(ob,text=False):
"gets the ACI color closest to the objects color"
if not gui: return 0
else:
if text:
col=ob.ViewObject.TextColor
else:
col=ob.ViewObject.LineColor
aci=[0,442]
for i in range (255,-1,-1):
ref=dxfColorMap.color_map[i]
dist=((ref[0]-col[0])**2 + (ref[1]-col[1])**2 + (ref[2]-col[2])**2)
if (dist <= aci[1]): aci=[i,dist]
return aci[0]
def rawValue(entity,code):
"returns the value of a DXF code in an entity section"
value = None
for pair in entity.data:
if pair[0] == code:
value = pair[1]
return value
def getMultiplePoints(entity):
"scans the given entity for multiple points (paths, leaders, etc)"
pts = []
for d in entity.data:
if d[0] == 10:
pts.append([d[1]])
elif d[0] in [20,30]:
pts[-1].append(d[1])
pts.reverse()
points = []
for p in pts:
if len(p) == 3:
points.append(Vector(p[0],p[1],p[2]))
else:
points.append(Vector(p[0],p[1],0))
return points
class fcformat:
"this contains everything related to color/lineweight formatting"
def __init__(self,drawing):
self.dxf = drawing
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
self.paramtext = params.GetBool("dxftext")
self.paramstarblocks = params.GetBool("dxfstarblocks")
self.dxflayout = params.GetBool("dxflayouts")
self.paramstyle = params.GetInt("dxfstyle")
self.join = params.GetBool("joingeometry")
self.makeBlocks = params.GetBool("groupLayers")
self.stdSize = params.GetBool("dxfStdSize")
self.importDxfHatches = params.GetBool("importDxfHatches")
self.renderPolylineWidth = params.GetBool("renderPolylineWidth")
bparams = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View")
if self.paramstyle > 1:
# checking if FreeCAD background is dark or bright
if bparams.GetBool("Gradient"):
c1 = bparams.GetUnsigned("BackgroundColor2")
c2 = bparams.GetUnsigned("BackgroundColor3")
r1 = float((c1>>24)&0xFF)
g1 = float((c1>>16)&0xFF)
b1 = float((c1>>8)&0xFF)
r2 = float((c2>>24)&0xFF)
g2 = float((c2>>16)&0xFF)
b2 = float((c2>>8)&0xFF)
v1 = FreeCAD.Vector(r1,g1,b1)
v2 = FreeCAD.Vector(r2,g2,b2)
v = v2.sub(v1)
v = DraftVecUtils.scale(v,0.5)
cv = v1.add(v)
else:
c1 = bparams.GetUnsigned("BackgroundColor")
r1 = float((c1>>24)&0xFF)
g1 = float((c1>>16)&0xFF)
b1 = float((c1>>8)&0xFF)
cv = FreeCAD.Vector(r1,g1,b1)
value = cv.x*.3 + cv.y*.59 + cv.z*.11
if value < 128: self.brightbg = False
else:
self.brightbg = True
if gui and draftui:
r = float(draftui.color.red()/255.0)
g = float(draftui.color.green()/255.0)
b = float(draftui.color.blue()/255.0)
self.lw = float(draftui.linewidth)
else:
self.lw = float(params.GetInt("linewidth"))
c = params.GetUnsigned("color")
r = float(((c>>24)&0xFF)/255)
g = float(((c>>16)&0xFF)/255)
b = float(((c>>8)&0xFF)/255)
self.col = (r,g,b,0.0)
if self.paramstyle == 3:
parammappingfile = params.GetString("dxfmappingfile")
self.table = self.buildTable(parammappingfile)
def buildTable(self,tablefile):
"builds a table for converting colors into linewidths"
try: f = pythonopen(tablefile)
except ValueError:
print "error: ",tablefile, " not found"
return None
table = {}
header = len(f.readline().split("\t"))
if header == 15:
for l in f:
s = l.split("\t")
if "Color_" in s[0]:
index = int(s[0].split("_")[1])
if s[1] == "(Object)": color = "object"
else:
c = s[2].split(",")
color = [float(c[0])/255,float(c[1])/255,float(c[2])/255]
if (color == [0.0,0.0,0.0]) and (not self.brightbg):
color = [1.0,1.0,1.0]
if s[2] == "(Object)": width = "object"
else: width = float(s[10])*10
table[index]=[color,width]
elif header == 3:
for l in f:
s = l.split("\t")
index = int(s[0])
c = string.replace(s[1],'"','')
c = c.split(",")
color = [float(c[0])/255,float(c[1])/255,float(c[2])/255]
width = float(s[2])
table[index]=[color,width]
for i in range(256):
if not i in table.keys():
table[i]=["object","object"]
else:
print "error building mapping table: file format not recognized"
table = None
print table
return table
def formatObject(self,obj,dxfobj=None):
"applies color and linetype to objects"
if self.paramstyle == 0:
if hasattr(obj.ViewObject,"TextColor"):
obj.ViewObject.TextColor = (0.0,0.0,0.0)
elif self.paramstyle == 1:
if hasattr(obj.ViewObject,"TextColor"):
obj.ViewObject.TextColor = self.col
else:
obj.ViewObject.LineColor = self.col
obj.ViewObject.LineWidth = self.lw
elif (self.paramstyle == 2) and dxfobj:
if hasattr(obj.ViewObject,"TextColor"):
if dxfobj.color_index == 256: cm = self.getGroupColor(dxfobj)[:3]
else: cm = dxfColorMap.color_map[dxfobj.color_index]
obj.ViewObject.TextColor = (cm[0],cm[1],cm[2])
else:
if dxfobj.color_index == 256: cm = self.getGroupColor(dxfobj)
elif (dxfobj.color_index == 7) and self.brightbg: cm = [0.0,0.0,0.0]
else: cm = dxfColorMap.color_map[dxfobj.color_index]
obj.ViewObject.LineColor = (cm[0],cm[1],cm[2],0.0)
obj.ViewObject.LineWidth = self.lw
elif (self.paramstyle == 3) and dxfobj:
if hasattr(obj.ViewObject,"TextColor"):
cm = table[dxfobj.color_index][0]
wm = table[dxfobj.color_index][1]
obj.ViewObject.TextColor = (cm[0],cm[1],cm[2])
else:
if dxfobj.color_index == 256:
cm = self.table[self.getGroupColor(dxfobj,index=True)][0]
wm = self.table[self.getGroupColor(dxfobj,index=True)][1]
else:
cm = self.table[dxfobj.color_index][0]
wm = self.table[dxfobj.color_index][1]
if cm == "object": cm = self.getGroupColor(dxfobj)
else: obj.ViewObject.LineColor = (cm[0],cm[1],cm[2],0.0)
if wm == "object": wm = self.lw
else: obj.ViewObject.LineWidth = wm
def getGroupColor(self,dxfobj,index=False):
"get color of bylayer stuff"
name = dxfobj.layer
for table in self.dxf.tables.get_type("table"):
if table.name == "layer":
for l in table.get_type("layer"):
if l.name == name:
if index: return l.color
else:
if (l.color == 7) and self.brightbg: return [0.0,0.0,0.0]
else: return dxfColorMap.color_map[l.color]
def vec(pt):
"returns a rounded Vector from a dxf point"
return FreeCAD.Vector(round(pt[0],prec()),round(pt[1],prec()),round(pt[2],prec()))
def drawLine(line,shapemode=False):
"returns a Part shape from a dxf line"
if (len(line.points) > 1):
v1=vec(line.points[0])
v2=vec(line.points[1])
if not DraftVecUtils.equals(v1,v2):
try:
if (fmt.paramstyle >= 4) and (not shapemode):
return Draft.makeWire([v1,v2])
else:
return Part.Line(v1,v2).toShape()
except:
warn(line)
return None
def drawPolyline(polyline,shapemode=False,num=None):
"returns a Part shape from a dxf polyline"
if (len(polyline.points) > 1):
edges = []
curves = False
verts = []
for p in range(len(polyline.points)-1):
p1 = polyline.points[p]
p2 = polyline.points[p+1]
v1 = vec(p1)
v2 = vec(p2)
verts.append(v1)
if not DraftVecUtils.equals(v1,v2):
if polyline.points[p].bulge:
curves = True
cv = calcBulge(v1,polyline.points[p].bulge,v2)
if DraftVecUtils.isColinear([v1,cv,v2]):
try: edges.append(Part.Line(v1,v2).toShape())
except: warn(polyline,num)
else:
try: edges.append(Part.Arc(v1,cv,v2).toShape())
except: warn(polyline,num)
else:
try: edges.append(Part.Line(v1,v2).toShape())
except: warn(polyline,num)
verts.append(v2)
if polyline.closed:
p1 = polyline.points[len(polyline.points)-1]
p2 = polyline.points[0]
v1 = vec(p1)
v2 = vec(p2)
cv = calcBulge(v1,polyline.points[-1].bulge,v2)
if not DraftVecUtils.equals(v1,v2):
if DraftVecUtils.isColinear([v1,cv,v2]):
try:
edges.append(Part.Line(v1,v2).toShape())
except:
warn(polyline,num)
else:
try:
edges.append(Part.Arc(v1,cv,v2).toShape())
except:
warn(polyline,num)
if edges:
try:
width = rawValue(polyline,43)
if width and fmt.renderPolylineWidth:
w = Part.Wire(edges)
w1 = w.makeOffset(width/2)
if polyline.closed:
w2 = w.makeOffset(-width/2)
w1 = Part.Face(w1)
w2 = Part.Face(w2)
if w1.BoundBox.DiagonalLength > w2.BoundBox.DiagonalLength:
return w1.cut(w2)
else:
return w2.cut(w1)
else:
return Part.Face(w1)
elif (fmt.paramstyle >= 4) and (not curves) and (not shapemode):
ob = Draft.makeWire(verts)
ob.Closed = polyline.closed
return ob
else:
if polyline.closed:
w = Part.Wire(edges)
return(Part.Face(w))
else:
return Part.Wire(edges)
except:
warn(polyline,num)
return None
def drawArc(arc,shapemode=False):
"returns a Part shape from a dxf arc"
v=vec(arc.loc)
firstangle=round(arc.start_angle,prec())
lastangle=round(arc.end_angle,prec())
circle=Part.Circle()
circle.Center=v
circle.Radius=round(arc.radius,prec())
try:
if (fmt.paramstyle >= 4) and (not shapemode):
pl = FreeCAD.Placement()
pl.move(v)
return Draft.makeCircle(arc.radius,pl,False,firstangle,lastangle)
else:
return circle.toShape(math.radians(firstangle),math.radians(lastangle))
except:
warn(arc)
return None
def drawCircle(circle,shapemode=False):
"returns a Part shape from a dxf circle"
v = vec(circle.loc)
curve = Part.Circle()
curve.Radius = round(circle.radius,prec())
curve.Center = v
try:
if (fmt.paramstyle >= 4) and (not shapemode):
pl = FreeCAD.Placement()
pl.move(v)
return Draft.makeCircle(circle.radius,pl)
else:
return curve.toShape()
except:
warn(circle)
return None
def drawFace(face):
"returns a Part face from a list of points"
pl = []
for p in face.points:
pl.append(vec(p))
p1 = face.points[0]
pl.append(vec(p1))
try:
pol = Part.makePolygon(pl)
return Part.Face(pol)
except:
warn(face)
return None
def drawMesh(mesh):
"returns a Mesh from a dxf mesh"
md = []
if mesh.flags == 16:
pts = mesh.points
udim = rawValue(mesh,71)
vdim = rawValue(mesh,72)
for u in range(udim-1):
for v in range(vdim-1):
b = u+v*udim
p1 = pts[b]
p2 = pts[b+1]
p3 = pts[b+udim]
p4 = pts[b+udim+1]
md.append([p1,p2,p4])
md.append([p1,p4,p3])
elif mesh.flags == 64:
pts = []
fcs = []
for p in mesh.points:
if p.flags == 192:
pts.append(p)
elif p.flags == 128:
fcs.append(p)
for f in fcs:
p1 = pts[rawValue(f,71)-1]
p2 = pts[rawValue(f,72)-1]
p3 = pts[rawValue(f,73)-1]
md.append([p1,p2,p3])
if rawValue(f,74) != None:
p4 = pts[rawValue(f,74)-1]
md.append([p1,p3,p4])
try:
return Mesh.Mesh(md)
except:
warn(mesh)
return None
def drawSolid(solid):
"returns a Part shape from a dxf solid"
p4 = None
p1x = rawValue(solid,10)
p1y = rawValue(solid,20)
p1z = rawValue(solid,30) or 0
p2x = rawValue(solid,11)
p2y = rawValue(solid,21)
p2z = rawValue(solid,31) or p1z
p3x = rawValue(solid,12)
p3y = rawValue(solid,22)
p3z = rawValue(solid,32) or p1z
p4x = rawValue(solid,13)
p4y = rawValue(solid,23)
p4z = rawValue(solid,33) or p1z
p1 = FreeCAD.Vector(p1x,p1y,p1z)
p2 = FreeCAD.Vector(p2x,p2y,p2z)
p3 = FreeCAD.Vector(p3x,p3y,p3z)
if p4x != None: p4 = FreeCAD.Vector(p4x,p4y,p4z)
if p4 and (p4 != p3) and (p4 != p2) and (p4 != p1):
try:
return Part.Face(Part.makePolygon([p1,p2,p4,p3,p1]))
except:
warn(solid)
else:
try:
return Part.Face(Part.makePolygon([p1,p2,p3,p1]))
except:
warn(solid)
return None
def drawSpline(spline,shapemode=False):
"returns a Part Shape from a dxf spline"
flag = rawValue(spline,70)
if flag == 1:
closed = True
else:
closed = False
verts = []
knots = []
for dline in spline.data:
if dline[0] == 10:
cp = [dline[1]]
elif dline[0] == 20:
cp.append(dline[1])
elif dline[0] == 30:
cp.append(dline[1])
pt = Vector(cp[0],cp[1],cp[2])
if verts:
if pt != verts[-1]:
verts.append(pt)
else:
verts.append(pt)
elif dline[0] == 40:
knots.append(dline[1])
try:
if (fmt.paramstyle == 4) and (not shapemode):
ob = Draft.makeSpline(verts)
ob.Closed = closed
return ob
else:
sp = Part.BSplineCurve()
# print knots
sp.interpolate(verts)
sh = Part.Wire(sp.toShape())
if closed:
return Part.Face(sh)
else:
return sh
except:
warn(spline)
return None
def drawBlock(blockref,num=None):
"returns a shape from a dxf block reference"
if not fmt.paramstarblocks:
if blockref.name[0] == '*':
return None
shapes = []
for line in blockref.entities.get_type('line'):
s = drawLine(line,shapemode=True)
if s: shapes.append(s)
for polyline in blockref.entities.get_type('polyline'):
s = drawPolyline(polyline,shapemode=True)
if s: shapes.append(s)
for polyline in blockref.entities.get_type('lwpolyline'):
s = drawPolyline(polyline,shapemode=True)
if s: shapes.append(s)
for arc in blockref.entities.get_type('arc'):
s = drawArc(arc,shapemode=True)
if s: shapes.append(s)
for circle in blockref.entities.get_type('circle'):
s = drawCircle(circle,shapemode=True)
if s: shapes.append(s)
for insert in blockref.entities.get_type('insert'):
print "insert ",insert," in block ",insert.block[0]
if fmt.paramstarblocks or insert.block[0] != '*':
s = drawInsert(insert)
if s: shapes.append(s)
for solid in blockref.entities.get_type('solid'):
s = drawSolid(solid)
if s: shapes.append(s)
for spline in blockref.entities.get_type('spline'):
s = drawSpline(spline,shapemode=True)
if s: shapes.append(s)
for text in blockref.entities.get_type('text'):
if fmt.paramtext:
if fmt.dxflayout or (not rawValue(text,67)):
addText(text)
for text in blockref.entities.get_type('mtext'):
if fmt.paramtext:
if fmt.dxflayout or (not rawValue(text,67)):
print "adding block text",text.value, " from ",blockref
addText(text)
try: shape = Part.makeCompound(shapes)
except: warn(blockref)
if shape:
blockshapes[blockref.name]=shape
return shape
return None
def drawInsert(insert,num=None):
if blockshapes.has_key(insert):
shape = blockshapes[insert.block].copy()
else:
shape = None
for b in drawing.blocks.data:
if b.name == insert.block:
shape = drawBlock(b,num)
if fmt.paramtext:
attrs = attribs(insert)
for a in attrs:
addText(a,attrib=True)
if shape:
pos = vec(insert.loc)
rot = math.radians(insert.rotation)
scale = insert.scale
tsf = FreeCAD.Matrix()
tsf.scale(scale[0],scale[1],0) # for some reason z must be 0 to work
tsf.rotateZ(rot)
shape = shape.transformGeometry(tsf)
shape.translate(pos)
return shape
return None
def drawLayerBlock(objlist):
"draws a Draft block with the given shapes or objects"
obj = None
if fmt.paramstyle >= 4:
try:
obj = Draft.makeBlock(objlist)
except:
pass
else:
try:
obj = Part.makeCompound(objlist)
except:
pass
return obj
def attribs(insert):
"checks if an insert has attributes, and returns the values if yes"
atts = []
if rawValue(insert,66) != 1: return []
index = None
for i in range(len(drawing.entities.data)):
if drawing.entities.data[i] == insert:
index = i
break
if index == None: return []
j = index+1
while True:
ent = drawing.entities.data[j]
if str(ent) == 'seqend':
return atts
elif str(ent) == 'attrib':
atts.append(ent)
j += 1
def addObject(shape,name="Shape",layer=None):
"adds a new object to the document with passed arguments"
if isinstance(shape,Part.Shape):
newob=doc.addObject("Part::Feature",name)
newob.Shape = shape
else:
newob = shape
if layer:
lay=locateLayer(layer)
lay.addObject(newob)
fmt.formatObject(newob)
return newob
def addText(text,attrib=False):
"adds a new text to the document"
if attrib:
lay = locateLayer(rawValue(text,8))
val = rawValue(text,1)
pos = FreeCAD.Vector(rawValue(text,10),rawValue(text,20),rawValue(text,30))
hgt = rawValue(text,40)
else:
lay = locateLayer(text.layer)
val = text.value
pos = FreeCAD.Vector(text.loc[0],text.loc[1],text.loc[2])
hgt = text.height
if val:
if attrib:
newob = doc.addObject("App::Annotation","Attribute")
else:
newob = doc.addObject("App::Annotation","Text")
lay.addObject(newob)
val = deformat(val)
#val = val.decode("Latin1").encode("Latin1")
rx = rawValue(text,11)
ry = rawValue(text,21)
rz = rawValue(text,31)
if rx or ry or rz:
xv = Vector(rx,ry,rz)
if not DraftVecUtils.isNull(xv):
ax = DraftVecUtils.neg(xv.cross(Vector(1,0,0)))
if DraftVecUtils.isNull(ax):
ax = Vector(0,0,1)
ang = -math.degrees(DraftVecUtils.angle(xv,Vector(1,0,0),ax))
Draft.rotate(newob,ang,axis=ax)
elif hasattr(text,"rotation"):
if text.rotation:
Draft.rotate(newob,text.rotation)
newob.LabelText = val.split("\n")
newob.Position = pos
if gui:
if fmt.stdSize:
newob.ViewObject.FontSize = FreeCADGui.draftToolBar.fontsize
else:
newob.ViewObject.FontSize = float(hgt)
if hasattr(text,"alignment"):
if text.alignment in [2,5,8]:
newob.ViewObject.Justification = "Center"
elif text.alignment in [3,6,9]:
newob.ViewObject.Justification = "Right"
newob.ViewObject.DisplayMode = "World"
fmt.formatObject(newob,text)
def addToBlock(obj,layer):
"adds given shape to the layer dict"
if layer in layerBlocks:
layerBlocks[layer].append(obj)
else:
layerBlocks[layer] = [obj]
def processdxf(document,filename):
"this does the translation of the dxf contents into FreeCAD Part objects"
global drawing # for debugging - so drawing is still accessible to python after the script
FreeCAD.Console.PrintMessage("opening "+filename+"...\n")
drawing = readDXF(filename)
global layers
layers = []
global doc
doc = document
global blockshapes
blockshapes = {}
global badobjects
badobjects = []
global layerBlocks
layerBlocks = {}
sketch = None
# getting config parameters
global fmt
fmt = fcformat(drawing)
shapes = []
# drawing lines
lines = drawing.entities.get_type("line")
if lines: FreeCAD.Console.PrintMessage("drawing "+str(len(lines))+" lines...\n")
for line in lines:
if fmt.dxflayout or (not rawValue(line,67)):
shape = drawLine(line)
if shape:
if fmt.paramstyle == 5:
if fmt.makeBlocks or fmt.join:
if sketch:
shape = Draft.makeSketch(shape,autoconstraints=True,addTo=sketch)
else:
shape = Draft.makeSketch(shape,autoconstraints=True)
sketch = shape
else:
shape = Draft.makeSketch(shape,autoconstraints=True)
elif fmt.join:
if isinstance(shape,Part.Shape):
shapes.append(shape)
else:
shapes.append(shape.Shape)
elif fmt.makeBlocks:
addToBlock(shape,line.layer)
else:
newob = addObject(shape,"Line",line.layer)
if gui: fmt.formatObject(newob,line)
# drawing polylines
pls = drawing.entities.get_type("lwpolyline")
pls.extend(drawing.entities.get_type("polyline"))
polylines = []
meshes = []
for p in pls:
if hasattr(p,"flags"):
if p.flags in [16,64]:
meshes.append(p)
else:
polylines.append(p)
else:
polylines.append(p)
if polylines:
FreeCAD.Console.PrintMessage("drawing "+str(len(polylines))+" polylines...\n")
num = 0
for polyline in polylines:
if fmt.dxflayout or (not rawValue(polyline,67)):
shape = drawPolyline(polyline,num)
if shape:
if fmt.paramstyle == 5:
if isinstance(shape,Part.Shape):
t = FreeCAD.ActiveDocument.addObject("Part::Feature","Shape")
t.Shape = shape
shape = t
if fmt.makeBlocks or fmt.join:
if sketch:
shape = Draft.makeSketch(shape,autoconstraints=True,addTo=sketch)
else:
shape = Draft.makeSketch(shape,autoconstraints=True)
sketch = shape
else:
shape = Draft.makeSketch(shape,autoconstraints=True)
elif fmt.join:
if isinstance(shape,Part.Shape):
shapes.append(shape)
else:
shapes.append(shape.Shape)
elif fmt.makeBlocks:
addToBlock(shape,polyline.layer)
else:
newob = addObject(shape,"Polyline",polyline.layer)
if gui: fmt.formatObject(newob,polyline)
num += 1
# drawing arcs
arcs = drawing.entities.get_type("arc")
if arcs: FreeCAD.Console.PrintMessage("drawing "+str(len(arcs))+" arcs...\n")
for arc in arcs:
if fmt.dxflayout or (not rawValue(arc,67)):
shape = drawArc(arc)
if shape:
if fmt.paramstyle == 5:
if fmt.makeBlocks or fmt.join:
if sketch:
shape = Draft.makeSketch(shape,autoconstraints=True,addTo=sketch)
else:
shape = Draft.makeSketch(shape,autoconstraints=True)
sketch = shape
else:
shape = Draft.makeSketch(shape,autoconstraints=True)
elif fmt.join:
if isinstance(shape,Part.Shape):
shapes.append(shape)
else:
shapes.append(shape.Shape)
elif fmt.makeBlocks:
addToBlock(shape,arc.layer)
else:
newob = addObject(shape,"Arc",arc.layer)
if gui: fmt.formatObject(newob,arc)
# joining lines, polylines and arcs if needed
if fmt.join and shapes:
FreeCAD.Console.PrintMessage("Joining geometry...\n")
edges = []
for s in shapes:
edges.extend(s.Edges)
shapes = DraftGeomUtils.findWires(edges)
for s in shapes:
newob = addObject(s)
# drawing circles
circles = drawing.entities.get_type("circle")
if circles: FreeCAD.Console.PrintMessage("drawing "+str(len(circles))+" circles...\n")
for circle in circles:
if fmt.dxflayout or (not rawValue(circle,67)):
shape = drawCircle(circle)
if shape:
if fmt.paramstyle == 5:
if fmt.makeBlocks or fmt.join:
if sketch:
shape = Draft.makeSketch(shape,autoconstraints=True,addTo=sketch)
else:
shape = Draft.makeSketch(shape,autoconstraints=True)
sketch = shape
else:
shape = Draft.makeSketch(shape,autoconstraints=True)
elif fmt.makeBlocks:
addToBlock(shape,circle.layer)
else:
newob = addObject(shape,"Circle",circle.layer)
if gui: fmt.formatObject(newob,circle)
# drawing solids
solids = drawing.entities.get_type("solid")
if solids: FreeCAD.Console.PrintMessage("drawing "+str(len(circles))+" solids...\n")
for solid in solids:
lay = rawValue(solid,8)
if fmt.dxflayout or (not rawValue(solid,67)):
shape = drawSolid(solid)
if shape:
if fmt.makeBlocks:
addToBlock(shape,lay)
else:
newob = addObject(shape,"Solid",lay)
if gui: fmt.formatObject(newob,solid)
# drawing splines
splines = drawing.entities.get_type("spline")
if splines: FreeCAD.Console.PrintMessage("drawing "+str(len(splines))+" splines...\n")
for spline in splines:
lay = rawValue(spline,8)
if fmt.dxflayout or (not rawValue(spline,67)):
shape = drawSpline(spline)
if shape:
if fmt.makeBlocks:
addToBlock(shape,lay)
else:
newob = addObject(shape,"Spline",lay)
if gui: fmt.formatObject(newob,spline)
# drawing texts
if fmt.paramtext:
texts = drawing.entities.get_type("mtext")
texts.extend(drawing.entities.get_type("text"))
if texts:
FreeCAD.Console.PrintMessage("drawing "+str(len(texts))+" texts...\n")
for text in texts:
if fmt.dxflayout or (not rawValue(text,67)):
addText(text)
else: FreeCAD.Console.PrintMessage("skipping texts...\n")
# drawing 3D objects
faces3d = drawing.entities.get_type("3dface")
if faces3d: FreeCAD.Console.PrintMessage("drawing "+str(len(faces3d))+" 3dfaces...\n")
for face3d in faces3d:
shape = drawFace(face3d)
if shape:
newob = addObject(shape,"Face",face3d.layer)
if gui: fmt.formatObject(newob,face3d)
if meshes: FreeCAD.Console.PrintMessage("drawing "+str(len(meshes))+" 3dmeshes...\n")
for mesh in meshes:
me = drawMesh(mesh)
if me:
newob = doc.addObject("Mesh::Feature","Mesh")
lay = locateLayer(rawValue(mesh,8))
lay.addObject(newob)
newob.Mesh = me
if gui: fmt.formatObject(newob,mesh)
# drawing dims
if fmt.paramtext:
dims = drawing.entities.get_type("dimension")
FreeCAD.Console.PrintMessage("drawing "+str(len(dims))+" dimensions...\n")
for dim in dims:
if fmt.dxflayout or (not rawValue(dim,67)):
try:
layer = rawValue(dim,8)
x1 = float(rawValue(dim,10))
y1 = float(rawValue(dim,20))
z1 = float(rawValue(dim,30))
x2 = float(rawValue(dim,13))
y2 = float(rawValue(dim,23))
z2 = float(rawValue(dim,33))
x3 = float(rawValue(dim,14))
y3 = float(rawValue(dim,24))
z3 = float(rawValue(dim,34))
d = rawValue(dim,70)
if d: align = int(d)
else: align = 0
d = rawValue(dim,50)
if d: angle = float(d)
else: angle = 0
except:
warn(dim)
else:
lay=locateLayer(layer)
pt = FreeCAD.Vector(x1,y1,z1)
p1 = FreeCAD.Vector(x2,y2,z2)
p2 = FreeCAD.Vector(x3,y3,z3)
if align == 0:
if angle in [0,180]:
p2 = FreeCAD.Vector(x3,y2,z2)
elif angle in [90,270]:
p2 = FreeCAD.Vector(x2,y3,z2)
newob = doc.addObject("App::FeaturePython","Dimension")
lay.addObject(newob)
_Dimension(newob)
_ViewProviderDimension(newob.ViewObject)
newob.Start = p1
newob.End = p2
newob.Dimline = pt
if gui:
dim.layer = layer
dim.color_index = 256
fmt.formatObject (newob,dim)
if fmt.stdSize:
newob.ViewObject.FontSize = FreeCADGui.draftToolBar.fontsize
else:
st = rawValue(dim,3)
newob.ViewObject.FontSize = float(getdimheight(st))
else: FreeCAD.Console.PrintMessage("skipping dimensions...\n")
# drawing points
points = drawing.entities.get_type("point")
if points: FreeCAD.Console.PrintMessage("drawing "+str(len(points))+" points...\n")
for point in points:
x = rawValue(point,10)
y = rawValue(point,20)
z = rawValue(point,30)
lay = rawValue(point,8)
if fmt.dxflayout or (not rawValue(point,67)):
if fmt.makeBlocks:
shape = Part.Vertex(x,y,z)
addToBlock(shape,lay)
else:
newob = Draft.makePoint(x,y,z)
lay = locateLayer(lay)
lay.addObject(newob)
if gui:
fmt.formatObject(newob,point)
# drawing leaders
if fmt.paramtext:
leaders = drawing.entities.get_type("leader")
if leaders:
FreeCAD.Console.PrintMessage("drawing "+str(len(leaders))+" leaders...\n")
for leader in leaders:
if fmt.dxflayout or (not rawValue(leader,67)):
points = getMultiplePoints(leader)
newob = Draft.makeWire(points)
lay = locateLayer(rawValue(leader,8))
lay.addObject(newob)
if gui:
newob.ViewObject.EndArrow = True
fmt.formatObject(newob,leader)
else:
FreeCAD.Console.PrintMessage("skipping leaders...\n")
# drawing hatches
if fmt.importDxfHatches:
hatches = drawing.entities.get_type("hatch")
if hatches:
FreeCAD.Console.PrintMessage("drawing "+str(len(hatches))+" hatches...\n")
for hatch in hatches:
if fmt.dxflayout or (not rawValue(hatch,67)):
points = getMultiplePoints(hatch)
if len(points) > 1:
lay = rawValue(hatch,8)
points = points[:-1]
newob = None
if (fmt.paramstyle == 0) or fmt.makeBlocks:
points.append(points[0])
s = Part.makePolygon(points)
if fmt.makeBlocks:
addToBlock(s,lay)
else:
newob = addObject(s,"Hatch",lay)
if gui:
fmt.formatObject(newob,hatch)
else:
newob = Draft.makeWire(points)
locateLayer(lay).addObject(newob)
if gui:
fmt.formatObject(newob,hatch)
else:
FreeCAD.Console.PrintMessage("skipping hatches...\n")
# drawing blocks
inserts = drawing.entities.get_type("insert")
if not fmt.paramstarblocks:
FreeCAD.Console.PrintMessage("skipping *blocks...\n")
newinserts = []
for i in inserts:
if fmt.dxflayout or (not rawValue(i,67)):
if i.block[0] != '*':
newinserts.append(i)
inserts = newinserts
if inserts:
FreeCAD.Console.PrintMessage("drawing "+str(len(inserts))+" blocks...\n")
blockrefs = drawing.blocks.data
for ref in blockrefs:
drawBlock(ref)
num = 0
for insert in inserts:
shape = drawInsert(insert,num)
if shape:
if fmt.makeBlocks:
addToBlock(shape,insert.layer)
else:
newob = addObject(shape,"Block."+insert.block,insert.layer)
if gui: fmt.formatObject(newob,insert)
num += 1
# make blocks, if any
if fmt.makeBlocks:
print "creating layerblocks..."
for k,l in layerBlocks.iteritems():
shape = drawLayerBlock(l)
if shape:
newob = addObject(shape,k)
del layerBlocks
# finishing
print "done processing"
doc.recompute()
FreeCAD.Console.PrintMessage("successfully imported "+filename+"\n")
if badobjects: print "dxf: ",len(badobjects)," objects were not imported"
del fmt
del doc
del blockshapes
def warn(dxfobject,num=None):
"outputs a warning if a dxf object couldn't be imported"
print "dxf: couldn't import ", dxfobject, " (",num,")"
badobjects.append(dxfobject)
def open(filename):
"called when freecad opens a file."
docname = os.path.splitext(os.path.basename(filename))[0]
doc = FreeCAD.newDocument(docname)
doc.Label = decodeName(docname)
processdxf(doc,filename)
return doc
def insert(filename,docname):
"called when freecad imports a file"
groupname = os.path.splitext(os.path.basename(filename))[0]
try:
doc=FreeCAD.getDocument(docname)
except:
doc=FreeCAD.newDocument(docname)
FreeCAD.setActiveDocument(docname)
importgroup = doc.addObject("App::DocumentObjectGroup",groupname)
importgroup.Label = decodeName(groupname)
processdxf(doc,filename)
for l in layers:
importgroup.addObject(l)
# EXPORT ########################################################################
def projectShape(shape,direction):
import Drawing
edges = []
try:
groups = Drawing.projectEx(shape,direction)
except:
print "unable to project shape"
return shape
else:
for g in groups[0:5]:
if g:
edges.append(g)
return DraftGeomUtils.cleanProjection(Part.makeCompound(edges))
def getArcData(edge):
"returns center, radius, start and end angles of a circle-based edge"
ce = edge.Curve.Center
radius = edge.Curve.Radius
if len(edge.Vertexes) == 1:
# closed circle
return DraftVecUtils.tup(ce), radius, 0, 0
else:
# method 1 - find direction of arc from tangents - not reliable
#tang1 = edge.Curve.tangent(edge.ParameterRange[0])
#tang2 = edge.Curve.tangent(edge.ParameterRange[1])
# following code doesn't seem to give right result?
# cross1 = Vector.cross(Vector(tang1[0][0],tang1[0][1],tang1[0][2]),Vector(tang2[0][0],tang2[0][1],tang2[0][2]))
# if cross1[2] > 0: # >0 ccw <0 cw
# ve1 = edge.Vertexes[0].Point
# ve2 = edge.Vertexes[-1].Point
# else:
# ve1 = edge.Vertexes[-1].Point
# ve2 = edge.Vertexes[0].Point
# method 3 - recreate an arc and check if the length is the same
ve1 = edge.Vertexes[0].Point
ve2 = edge.Vertexes[-1].Point
ang1 = -math.degrees(DraftVecUtils.angle(ve1.sub(ce)))
ang2 = -math.degrees(DraftVecUtils.angle(ve2.sub(ce)))
a1 = -DraftVecUtils.angle(ve1.sub(ce))
a2 = -DraftVecUtils.angle(ve2.sub(ce))
pseudoarc = Part.ArcOfCircle(edge.Curve,a1,a2).toShape()
if round(pseudoarc.Length,Draft.precision()) != round(edge.Length,Draft.precision()):
ang1, ang2 = ang2, ang1
# method 2 - check the midpoint - not reliable either
#ve3 = DraftGeomUtils.findMidpoint(edge)
#ang3 = -math.degrees(DraftVecUtils.angle(ve3.sub(ce)))
#print "edge ",edge.hashCode()," data ",ang1, " , ",ang2," , ", ang3
#if (ang3 < ang1) and (ang2 < ang3):
# print "inverting, case1"
# ang1, ang2 = ang2, ang1
#elif (ang3 > ang1) and (ang3 > ang2):
# print "inverting, case2"
# ang1, ang2 = ang2, ang1
#elif (ang3 < ang1) and (ang3 < ang2):
# print "inverting, case3"
# ang1, ang2 = ang2, ang1
return DraftVecUtils.tup(ce), radius, ang1, ang2
def getSplineSegs(edge):
"returns an array of vectors from a bSpline edge"
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
seglength = params.GetInt("maxsplinesegment")
points = []
if seglength == 0:
points.append(edge.Vertexes[0].Point)
points.append(edge.Vertexes[-1].Point)
else:
l = edge.Length
points.append(edge.valueAt(0))
if l > seglength:
nbsegs = int(math.ceil(l/seglength))
step = l/nbsegs
for nv in range(1,nbsegs):
v = edge.valueAt(nv*step)
points.append(v)
points.append(edge.valueAt(edge.Length))
return points
def getWire(wire,nospline=False):
"returns an array of dxf-ready points and bulges from a wire"
edges = DraftGeomUtils.sortEdges(wire.Edges)
points = []
# print "processing wire ",wire.Edges
for edge in edges:
v1 = edge.Vertexes[0].Point
if len(edge.Vertexes) < 2:
points.append((v1.x,v1.y,v1.z,None,None,0.0))
elif DraftGeomUtils.geomType(edge) == "Circle":
mp = DraftGeomUtils.findMidpoint(edge)
v2 = edge.Vertexes[-1].Point
c = edge.Curve.Center
angle = abs(DraftVecUtils.angle(v1.sub(c),v2.sub(c)))
if DraftGeomUtils.isWideAngle(edge):
if angle < math.pi:
angle = math.pi*2 - angle
# if (DraftVecUtils.angle(v2.sub(c)) < DraftVecUtils.angle(v1.sub(c))):
# angle = -angle
# polyline bulge -> negative makes the arc go clockwise
bul = math.tan(angle/4)
# OBSOLETE because arcs can have wrong normal
# the next bit of code is for finding the direction of the arc
# a negative cross product means the arc is clockwise
#tang1 = edge.Curve.tangent(edge.ParameterRange[0])
#tang2 = edge.Curve.tangent(edge.ParameterRange[1])
#cross1 = Vector.cross(Vector(tang1[0][0],tang1[0][1],tang1[0][2]),Vector(tang2[0][0],tang2[0][1],tang2[0][2]))
#if DraftVecUtils.isNull(cross1):
# special case, both tangents are opposite, unable to take their cross vector
# we try again with an arbitrary point at a third of the arc length
#tang2 = edge.Curve.tangent(edge.ParameterRange[0]+(edge.ParameterRange[1]-edge.ParameterRange[0]/3))
#cross1 = Vector.cross(Vector(tang1[0][0],tang1[0][1],tang1[0][2]),Vector(tang2[0][0],tang2[0][1],tang2[0][2]))
#if cross1[2] < 0:
# polyline bulge -> negative makes the arc go clockwise
#bul = -bul
if not DraftGeomUtils.isClockwise(edge):
bul = -bul
points.append((v1.x,v1.y,v1.z,None,None,bul))
elif (DraftGeomUtils.geomType(edge) == "BSplineCurve") and (not nospline):
spline = getSplineSegs(edge)
spline.pop()
for p in spline:
points.append((p.x,p.y,p.z,None,None,0.0))
else:
points.append((v1.x,v1.y,v1.z,None,None,0.0))
if not DraftGeomUtils.isReallyClosed(wire):
v = edges[-1].Vertexes[-1].Point
points.append(DraftVecUtils.tup(v))
# print "wire verts: ",points
return points
def getBlock(sh,obj):
"returns a dxf block with the contents of the object"
block = dxfLibrary.Block(name=obj.Name,layer=getGroup(obj,exportList))
writeShape(sh,obj,block)
return block
def writeShape(sh,ob,dxfobject,nospline=False):
"writes the object's shape contents in the given dxf object"
processededges = []
for wire in sh.Wires: # polylines
for e in wire.Edges:
processededges.append(e.hashCode())
if (len(wire.Edges) == 1) and (DraftGeomUtils.geomType(wire.Edges[0]) == "Circle"):
center, radius, ang1, ang2 = getArcData(wire.Edges[0])
if len(wire.Edges[0].Vertexes) == 1: # circle
dxfobject.append(dxfLibrary.Circle(center, radius,
color=getACI(ob),
layer=getGroup(ob,exportList)))
else: # arc
dxfobject.append(dxfLibrary.Arc(center, radius,
ang1, ang2, color=getACI(ob),
layer=getGroup(ob,exportList)))
else:
dxfobject.append(dxfLibrary.PolyLine(getWire(wire,nospline), [0.0,0.0,0.0],
int(DraftGeomUtils.isReallyClosed(wire)), color=getACI(ob),
layer=getGroup(ob,exportList)))
if len(processededges) < len(sh.Edges): # lone edges
loneedges = []
for e in sh.Edges:
if not(e.hashCode() in processededges): loneedges.append(e)
# print "lone edges ",loneedges
for edge in loneedges:
if (DraftGeomUtils.geomType(edge) == "BSplineCurve") and ((not nospline) or (len(edge.Vertexes) == 1)): # splines
if (len(edge.Vertexes) == 1) and (edge.Curve.isClosed()):
# special case: 1-vert closed spline, approximate as a circle
c = DraftGeomUtils.getCircleFromSpline(edge)
if c:
dxfobject.append(dxfLibrary.Circle(DraftVecUtils.tup(c.Curve.Center), c.Curve.Radius,
color=getACI(ob),
layer=getGroup(ob,exportList)))
else:
points = []
spline = getSplineSegs(edge)
for p in spline:
points.append((p.x,p.y,p.z,None,None,0.0))
dxfobject.append(dxfLibrary.PolyLine(points, [0.0,0.0,0.0],
0, color=getACI(ob),
layer=getGroup(ob,exportList)))
elif DraftGeomUtils.geomType(edge) == "Circle": # curves
center, radius, ang1, ang2 = getArcData(edge)
if not isinstance(center,tuple):
center = DraftVecUtils.tup(center)
if len(edge.Vertexes) == 1: # circles
dxfobject.append(dxfLibrary.Circle(center, radius,
color=getACI(ob),
layer=getGroup(ob,exportList)))
else : # arcs
dxfobject.append(dxfLibrary.Arc(center, radius,
ang1, ang2, color=getACI(ob),
layer=getGroup(ob,exportList)))
else: # anything else is treated as lines
if len(edge.Vertexes) > 1:
ve1=edge.Vertexes[0].Point
ve2=edge.Vertexes[1].Point
dxfobject.append(dxfLibrary.Line([DraftVecUtils.tup(ve1), DraftVecUtils.tup(ve2)],
color=getACI(ob),
layer=getGroup(ob,exportList)))
def writeMesh(ob,dxfobject):
"export a shape as a polyface mesh"
meshdata = ob.Shape.tessellate(0.5)
# print meshdata
points = []
faces = []
for p in meshdata[0]:
points.append([p.x,p.y,p.z])
for f in meshdata[1]:
faces.append([f[0]+1,f[1]+1,f[2]+1])
# print len(points),len(faces)
dxfobject.append(dxfLibrary.PolyLine([points,faces], [0.0,0.0,0.0],
64, color=getACI(ob),
layer=getGroup(ob,exportList)))
def export(objectslist,filename,nospline=False):
"called when freecad exports a file. If nospline=True, bsplines are exported as straight segs"
global exportList
exportList = objectslist
if (len(exportList) == 1) and (Draft.getType(exportList[0]) == "ArchSectionView"):
# arch view: export it "as is"
dxf = exportList[0].Proxy.getDXF()
if dxf:
f = open(filename,"w")
f.write(dxf)
f.close()
elif (len(exportList) == 1) and (exportList[0].isDerivedFrom("Drawing::FeaturePage")):
# page: special hack-export! (see below)
exportPage(exportList[0],filename)
else:
# other cases, treat edges
dxf = dxfLibrary.Drawing()
for ob in exportList:
print "processing ",ob.Name
if ob.isDerivedFrom("Part::Feature"):
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfmesh"):
sh = None
if not ob.Shape.isNull():
writeMesh(ob,dxf)
elif FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetBool("dxfproject"):
direction = FreeCADGui.ActiveDocument.ActiveView.getViewDirection()
sh = projectShape(ob.Shape,direction)
else:
if ob.Shape.Volume > 0:
sh = projectShape(ob.Shape,Vector(0,0,1))
else:
sh = ob.Shape
if sh:
if not sh.isNull():
if sh.ShapeType == 'Compound':
if (len(sh.Wires) == 1):
# only one wire in this compound, no lone edge -> polyline
if (len(sh.Wires[0].Edges) == len(sh.Edges)):
writeShape(sh,ob,dxf,nospline)
else:
# 1 wire + lone edges -> block
block = getBlock(sh,ob)
dxf.blocks.append(block)
dxf.append(dxfLibrary.Insert(name=ob.Name.upper()))
else:
# all other cases: block
block = getBlock(sh,ob)
dxf.blocks.append(block)
dxf.append(dxfLibrary.Insert(name=ob.Name.upper()))
else:
writeShape(sh,ob,dxf,nospline)
elif Draft.getType(ob) == "Annotation":
# texts
# temporary - as dxfLibrary doesn't support mtexts well, we use several single-line texts
# well, anyway, at the moment, Draft only writes single-line texts, so...
for text in ob.LabelText:
point = DraftVecUtils.tup(FreeCAD.Vector(ob.Position.x,
ob.Position.y-ob.LabelText.index(text),
ob.Position.z))
if gui: height = float(ob.ViewObject.FontSize)
else: height = 1
dxf.append(dxfLibrary.Text(text,point,height=height,
color=getACI(ob,text=True),
style='STANDARD',
layer=getGroup(ob,exportList)))
elif Draft.getType(ob) == "Dimension":
p1 = DraftVecUtils.tup(ob.Start)
p2 = DraftVecUtils.tup(ob.End)
base = Part.Line(ob.Start,ob.End).toShape()
proj = DraftGeomUtils.findDistance(ob.Dimline,base)
if not proj:
pbase = DraftVecUtils.tup(ob.End)
else:
pbase = DraftVecUtils.tup(ob.End.add(DraftVecUtils.neg(proj)))
dxf.append(dxfLibrary.Dimension(pbase,p1,p2,color=getACI(ob),
layer=getGroup(ob,exportList)))
dxf.saveas(filename)
FreeCAD.Console.PrintMessage("successfully exported "+filename+"\r\n")
def exportPage(page,filename):
"special export for pages"
import importSVG
tempdoc = importSVG.open(page.PageResult)
tempobj = tempdoc.Objects
export(tempobj,filename,nospline=True)
FreeCAD.closeDocument(tempdoc.Name)