Skip to content

Commit

Permalink
Draft: implemented dxf export of techdraw pages
Browse files Browse the repository at this point in the history
  • Loading branch information
yorikvanhavre committed Nov 5, 2016
1 parent 6f4f920 commit 945d99f
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 114 deletions.
134 changes: 90 additions & 44 deletions src/Mod/Arch/ArchSectionPlane.py
Expand Up @@ -75,6 +75,50 @@ def makeSectionView(section,name="View"):
return view


def getCutShapes(objs,section,showHidden):
import Part,DraftGeomUtils
shapes = []
hshapes = []
sshapes = []
for o in objs:
if o.isDerivedFrom("Part::Feature"):
if o.Shape.isNull():
pass
elif section.OnlySolids:
if o.Shape.isValid():
shapes.extend(o.Shape.Solids)
else:
print section.Label,": Skipping invalid object:",o.Label
else:
shapes.append(o.Shape)
cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(section.Shape.copy(),shapes)
if cutvolume:
nsh = []
for sh in shapes:
for sol in sh.Solids:
if sol.Volume < 0:
sol.reverse()
c = sol.cut(cutvolume)
s = sol.section(cutface)
try:
wires = DraftGeomUtils.findWires(s.Edges)
for w in wires:
f = Part.Face(w)
sshapes.append(f)
#s = Part.Wire(s.Edges)
#s = Part.Face(s)
except Part.OCCError:
#print "ArchDrawingView: unable to get a face"
sshapes.append(s)
nsh.extend(c.Solids)
#sshapes.append(s)
if showHidden:
c = sol.cut(invcutvolume)
hshapes.append(c)
shapes = nsh
return shapes,hshapes,sshapes,cutface,cutvolume,invcutvolume


def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=False,scale=1,linewidth=1,fontsize=1,techdraw=False,rotation=0):
"""getSVG(section,[allOn,renderMode,showHidden,showFill,scale,linewidth,fontsize]) :
returns an SVG fragment from an Arch section plane. If
Expand Down Expand Up @@ -140,45 +184,7 @@ def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=
else:
# render using the Drawing module
import Drawing, Part
shapes = []
hshapes = []
sshapes = []
for o in objs:
if o.isDerivedFrom("Part::Feature"):
if o.Shape.isNull():
pass
elif o.Shape.isValid():
if section.OnlySolids:
shapes.extend(o.Shape.Solids)
else:
shapes.append(o.Shape)
else:
print section.Label,": Skipping invalid object:",o.Label
cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(section.Shape.copy(),shapes)
if cutvolume:
nsh = []
for sh in shapes:
for sol in sh.Solids:
if sol.Volume < 0:
sol.reverse()
c = sol.cut(cutvolume)
s = sol.section(cutface)
try:
wires = DraftGeomUtils.findWires(s.Edges)
for w in wires:
f = Part.Face(w)
sshapes.append(f)
#s = Part.Wire(s.Edges)
#s = Part.Face(s)
except Part.OCCError:
#print "ArchDrawingView: unable to get a face"
sshapes.append(s)
nsh.extend(c.Solids)
#sshapes.append(s)
if showHidden:
c = sol.cut(invcutvolume)
hshapes.append(c)
shapes = nsh
shapes,hshapes,sshapes,cutface,cutvolume,invcutvolume = getCutShapes(objs,section,showHidden)
if shapes:
baseshape = Part.makeCompound(shapes)
svgf = Drawing.projectToSVG(baseshape,direction)
Expand Down Expand Up @@ -255,11 +261,12 @@ def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=
c = Part.makeCompound(w.Proxy.sshapes)
c.Placement = w.Placement
sh.append(c)
if hasattr(w.Proxy,"vshapes"):
if w.Proxy.vshapes:
c = Part.makeCompound(w.Proxy.vshapes)
c.Placement = w.Placement
sh.append(c)
# buggy for now...
#if hasattr(w.Proxy,"vshapes"):
# if w.Proxy.vshapes:
# c = Part.makeCompound(w.Proxy.vshapes)
# c.Placement = w.Placement
# sh.append(c)
if sh:
if not techdraw:
svg += '<g transform="scale(1,-1)">'
Expand All @@ -272,6 +279,45 @@ def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=
return svg


def getDXF(obj):
"returns a DXF representation from a TechDraw/Drawing view"
allOn = True
if hasattr(obj,"AllOn"):
allOn = obj.AllOn
elif hasattr(obj,"AlwaysOn"):
allOn = obj.AlwaysOn
showHidden = False
if hasattr(obj,"showCut"):
showHidden = obj.showCut
elif hasattr(obj,"showHidden"):
showHidden = obj.showHidden
result = []
import Drawing,Part
if not obj.Source:
return result
section = obj.Source
if not section.Objects:
return result
p = FreeCAD.Placement(section.Placement)
direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
objs = Draft.getGroupContents(section.Objects,walls=True,addgroups=True)
if not allOn:
objs = Draft.removeHidden(objs)
# separate spaces and Draft objects
spaces = []
nonspaces = []
drafts = []
objs = [o for o in objs if ((not(Draft.getType(o) in ["Space","Dimension","Annotation"])) and (not (o.isDerivedFrom("Part::Part2DObject"))))]
shapes,hshapes,sshapes,cutface,cutvolume,invcutvolume = getCutShapes(objs,section,showHidden)
if shapes:
result.append(Drawing.projectToDXF(Part.makeCompound(shapes),direction))
if sshapes:
result.append(Drawing.projectToDXF(Part.makeCompound(sshapes),direction))
if hshapes:
result.append(Drawing.projectToDXF(Part.makeCompound(hshapes),direction))
return result


class _CommandSectionPlane:
"the Arch SectionPlane command definition"
def GetResources(self):
Expand Down
103 changes: 54 additions & 49 deletions src/Mod/Draft/Draft.py
Expand Up @@ -1671,6 +1671,13 @@ def getDXF(obj,direction=None):
object. If direction is given, the object is projected in 2D.'''
plane = None
result = ""
if obj.isDerivedFrom("Drawing::View") or obj.isDerivedFrom("TechDraw::DrawView"):
if obj.Source.isDerivedFrom("App::DocumentObjectGroup"):
for o in obj.Source.Group:
result += getDXF(o,obj.Direction)
else:
result += getDXF(obj.Source,obj.Direction)
return result
if direction:
if isinstance(direction,FreeCAD.Vector):
if direction != Vector(0,0,0):
Expand Down Expand Up @@ -1846,52 +1853,57 @@ def getPath(edges=[],wires=[],pathname=None):
isellipse = DraftGeomUtils.geomType(e) == "Ellipse"
if iscircle or isellipse:
import math
c = e.Curve
if len(e.Vertexes) == 1 and iscircle: #complete curve
svg = getCircle(e)
return svg
elif len(e.Vertexes) == 1 and isellipse:
#svg = getEllipse(e)
#return svg
endpoints = (getProj(c.value((c.LastParameter-\
c.FirstParameter)/2.0)), \
getProj(vs[-1].Point))
else:
endpoints = (getProj(vs[-1].Point),)

# arc
if iscircle:
rx = ry = c.Radius
rot = 0
else: #ellipse
rx = c.MajorRadius
ry = c.MinorRadius
rot = math.degrees(c.AngleXU * (c.Axis * \
FreeCAD.Vector(0,0,1)))
if rot > 90:
rot -=180
if rot < -90:
rot += 180
#be carefull with the sweep flag
if hasattr(FreeCAD,"DraftWorkingPlane"):
drawing_plane_normal = FreeCAD.DraftWorkingPlane.axis
else:
drawing_plane_normal = FreeCAD.Vector(0,0,1)
if plane: drawing_plane_normal = plane.axis
flag_large_arc = (((e.ParameterRange[1] - \
e.ParameterRange[0]) / math.pi) % 2) > 1
#flag_sweep = (c.Axis * drawing_plane_normal >= 0) \
# == (e.LastParameter > e.FirstParameter)
# == (e.Orientation == "Forward")
# other method: check the direction of the angle between tangents
t1 = e.tangentAt(e.FirstParameter)
t2 = e.tangentAt(e.FirstParameter + (e.LastParameter-e.FirstParameter)/10)
flag_sweep = (DraftVecUtils.angle(t1,t2,drawing_plane_normal) < 0)
for v in endpoints:
edata += 'A %s %s %s %s %s %s %s ' % \
(str(rx),str(ry),str(rot),\
str(int(flag_large_arc)),\
str(int(flag_sweep)),str(v.x),str(v.y))
c = e.Curve
if round(c.Axis.getAngle(drawing_plane_normal),2) == 1.57:
# arc is perpendicular to view direction: represent as a line
v = getProj(vs[-1].Point)
edata += 'L '+ str(v.x) +' '+ str(v.y) + ' '
else:
if len(e.Vertexes) == 1 and iscircle: #complete curve
svg = getCircle(e)
return svg
elif len(e.Vertexes) == 1 and isellipse:
#svg = getEllipse(e)
#return svg
endpoints = (getProj(c.value((c.LastParameter-\
c.FirstParameter)/2.0)), \
getProj(vs[-1].Point))
else:
endpoints = (getProj(vs[-1].Point),)

# arc
if iscircle:
rx = ry = c.Radius
rot = 0
else: #ellipse
rx = c.MajorRadius
ry = c.MinorRadius
rot = math.degrees(c.AngleXU * (c.Axis * \
FreeCAD.Vector(0,0,1)))
if rot > 90:
rot -=180
if rot < -90:
rot += 180
#be carefull with the sweep flag
flag_large_arc = (((e.ParameterRange[1] - \
e.ParameterRange[0]) / math.pi) % 2) > 1
#flag_sweep = (c.Axis * drawing_plane_normal >= 0) \
# == (e.LastParameter > e.FirstParameter)
# == (e.Orientation == "Forward")
# other method: check the direction of the angle between tangents
t1 = e.tangentAt(e.FirstParameter)
t2 = e.tangentAt(e.FirstParameter + (e.LastParameter-e.FirstParameter)/10)
flag_sweep = (DraftVecUtils.angle(t1,t2,drawing_plane_normal) < 0)
for v in endpoints:
edata += 'A %s %s %s %s %s %s %s ' % \
(str(rx),str(ry),str(rot),\
str(int(flag_large_arc)),\
str(int(flag_sweep)),str(v.x),str(v.y))
elif DraftGeomUtils.geomType(e) == "Line":
v = getProj(vs[-1].Point)
edata += 'L '+ str(v.x) +' '+ str(v.y) + ' '
Expand Down Expand Up @@ -4773,14 +4785,7 @@ def execute(self, obj):

def getDXF(self,obj):
"returns a DXF fragment"
result = ""
if obj.Source.isDerivedFrom("App::DocumentObjectGroup"):
for o in obj.Source.Group:
if o.ViewObject.isVisible():
result += getDXF(o,obj.Direction)
else:
result += getDXF(obj.Source,obj.Direction)
return result
return getDXF(obj)

class _BSpline(_DraftObject):
"The BSpline object"
Expand Down
65 changes: 44 additions & 21 deletions src/Mod/Draft/importDXF.py
Expand Up @@ -1813,6 +1813,10 @@ def export(objectslist,filename,nospline=False,lwPoly=False):
# page: special hack-export! (see below)
exportPage(exportList[0],filename)

elif (len(exportList) == 1) and (exportList[0].isDerivedFrom("TechDraw::DrawPage")):
# page: special hack-export! (see below)
exportPage(exportList[0],filename)

else:
# other cases, treat edges
dxf = dxfLibrary.Drawing()
Expand Down Expand Up @@ -1900,7 +1904,12 @@ def incr(self,matchobj):

def exportPage(page,filename):
"special export for pages"
template = os.path.splitext(page.Template)[0]+".dxf"
if hasattr(page.Template,"Template"): #techdraw
template="" # not supported for now...
views = page.Views
else: #drawing
template = os.path.splitext(page.Template)[0]+".dxf"
views = page.Group
if os.path.exists(template):
f = pythonopen(template,"U")
template = f.read()
Expand Down Expand Up @@ -1930,7 +1939,7 @@ def exportPage(page,filename):
# at the moment this is not used. TODO: if r12, do not print ellipses or splines
if ver[0].upper() in ["AC1009","AC1010","AC1011","AC1012","AC1013"]:
r12 = True
for view in page.Group:
for view in views:
b,e = getViewDXF(view)
blocks += b
entities += e
Expand All @@ -1945,6 +1954,28 @@ def exportPage(page,filename):
f.write(template)
f.close()

def getBlock(geom,view,blockcount):
insert = ""
block = ""
r = view.Rotation
if r != 0: r = -r # fix rotation direction
if not isinstance(geom,list): geom = [geom]
for g in geom: # getDXF returns a list of entities
if dxfExportBlocks:
g = g.replace("sheet_layer\n","0\n6\nBYBLOCK\n62\n0\n5\n_handle_\n") # change layer and set color and ltype to BYBLOCK (0)
block += "0\nBLOCK\n5\n_handle_\n100\nAcDbEntity\n8\n0\n100\nAcDbBlockBegin\n2\n"+view.Name+str(blockcount)+"\n70\n0\n10\n0\n20\n0\n3\n"+view.Name+str(blockcount)+"\n1\n\n"
block += g
block += "0\nENDBLK\n5\n_handle_\n100\nAcDbEntity\n8\n0\n100\nAcDbBlockEnd\n"
insert += "0\nINSERT\n5\n_handle_\n8\n0\n6\nBYLAYER\n62\n256\n2\n"+view.Name+str(blockcount)
insert += "\n10\n"+str(view.X)+"\n20\n"+str(-view.Y)
insert += "\n30\n0\n41\n"+str(view.Scale)+"\n42\n"+str(view.Scale)+"\n43\n"+str(view.Scale)
insert += "\n50\n"+str(r)+"\n"
blockcount += 1
else:
g = g.replace("sheet_layer\n","0\n5\n_handle_\n") # change layer, add handle
insert += g
return block,insert,blockcount


def getViewDXF(view,blocks=True):
"returns a DXF fragment from a Drawing View"
Expand All @@ -1960,26 +1991,17 @@ def getViewDXF(view,blocks=True):

elif view.isDerivedFrom("Drawing::FeatureViewPython"):
if hasattr(view.Proxy,"getDXF"):
r = view.Rotation
if r != 0: r = -r # fix rotation direction
block = ""
insert = ""
geom = view.Proxy.getDXF(view)
if not isinstance(geom,list): geom = [geom]
for g in geom: # getDXF returns a list of entities
if dxfExportBlocks:
g = g.replace("sheet_layer\n","0\n6\nBYBLOCK\n62\n0\n5\n_handle_\n") # change layer and set color and ltype to BYBLOCK (0)
block += "0\nBLOCK\n5\n_handle_\n100\nAcDbEntity\n8\n0\n100\nAcDbBlockBegin\n2\n"+view.Name+str(blockcount)+"\n70\n0\n10\n0\n20\n0\n3\n"+view.Name+str(blockcount)+"\n1\n\n"
block += g
block += "0\nENDBLK\n5\n_handle_\n100\nAcDbEntity\n8\n0\n100\nAcDbBlockEnd\n"
insert += "0\nINSERT\n5\n_handle_\n8\n0\n6\nBYLAYER\n62\n256\n2\n"+view.Name+str(blockcount)
insert += "\n10\n"+str(view.X)+"\n20\n"+str(-view.Y)
insert += "\n30\n0\n41\n"+str(view.Scale)+"\n42\n"+str(view.Scale)+"\n43\n"+str(view.Scale)
insert += "\n50\n"+str(r)+"\n"
blockcount += 1
else:
g = g.replace("sheet_layer\n","0\n5\n_handle_\n") # change layer, add handle
insert += g
block,insert,blockcount = getBlock(geom,view,blockcount)

elif view.isDerivedFrom("TechDraw::DrawViewDraft"):
geom = Draft.getDXF(view)
block,insert,blockcount = getBlock(geom,view,blockcount)

elif view.isDerivedFrom("TechDraw::DrawViewArch"):
import ArchSectionPlane
geom = ArchSectionPlane.getDXF(view)
block,insert,blockcount = getBlock(geom,view,blockcount)

elif view.isDerivedFrom("Drawing::FeatureViewPart"):
r = view.Rotation
Expand Down Expand Up @@ -2022,6 +2044,7 @@ def exportPageLegacy(page,filename):
export(tempobj,filename,nospline=True,lwPoly=False)
FreeCAD.closeDocument(tempdoc.Name)


def readPreferences():
# reading parameters
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
Expand Down

0 comments on commit 945d99f

Please sign in to comment.