Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Draft - Allow to export Drawing pages to DXF - fixes #1686
* Uses DXF algos of the Drawing module instead of the Draft dxf library
* Uses a DXF template with the same name as the SVG template, if existing
* Only Draft, Arch, Part and Annotation views are currently supported
* Drawing module's projectToDXF() now returns only a fragment instead of a full DXF file
  • Loading branch information
yorikvanhavre committed Aug 15, 2014
1 parent 4dc1274 commit b33d8f6
Show file tree
Hide file tree
Showing 10 changed files with 35,073 additions and 263 deletions.
4 changes: 2 additions & 2 deletions src/Mod/Arch/ArchCommands.py
Expand Up @@ -348,14 +348,14 @@ def getCutVolume(cutplane,shapes):
else:
p = cutplane.copy().Faces[0]
except:
FreeCAD.Console.PrintMessage(translate("Arch","Invalid cutplane"))
FreeCAD.Console.PrintMessage(translate("Arch","Invalid cutplane\n"))
return None,None,None
ce = p.CenterOfMass
ax = p.normalAt(0,0)
u = p.Vertexes[1].Point.sub(p.Vertexes[0].Point).normalize()
v = u.cross(ax)
if not bb.isCutPlane(ce,ax):
FreeCAD.Console.PrintMessage(translate("Arch","No objects are cut by the plane"))
FreeCAD.Console.PrintMessage(translate("Arch","No objects are cut by the plane\n"))
return None,None,None
else:
corners = [FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin),
Expand Down
38 changes: 20 additions & 18 deletions src/Mod/Arch/ArchSectionPlane.py
Expand Up @@ -377,6 +377,7 @@ def onChanged(self, obj, prop):
self.svg += svgf
if hshapes:
hshapes = Part.makeCompound(hshapes)
self.hiddenshape = hshapes
svgh = Drawing.projectToSVG(hshapes,self.direction)
if svgh:
svgh = svgh.replace('stroke-width="0.35"','stroke-width="LWPlaceholder"')
Expand All @@ -386,6 +387,7 @@ def onChanged(self, obj, prop):
self.svg += svgh
if sshapes:
sshapes = Part.makeCompound(sshapes)
self.sectionshape = sshapes
svgs = Drawing.projectToSVG(sshapes,self.direction)
if svgs:
svgs = svgs.replace('stroke-width="0.35"','stroke-width="SWPlaceholder"')
Expand All @@ -407,26 +409,26 @@ def getDisplayModes(self,vobj):
def setDisplayMode(self,mode):
return mode

def getFlatShape(self):
"returns a flat shape representation of the view"
def getDXF(self,obj):
"returns a DXF representation of the view"
if obj.RenderingMode == "Solid":
print "Unable to get DXF from Solid mode: ",obj.Label
return ""
result = []
import Drawing
if not hasattr(self,"baseshape"):
self.onChanged(obj,"Source")
if hasattr(self,"baseshape"):
import Drawing
[V0,V1,H0,H1] = Drawing.project(self.baseshape,self.direction)
return V0.Edges+V1.Edges
else:
FreeCAD.Console.PrintMessage(translate("Arch","No shape has been computed yet, select wireframe rendering and render again"))
return None
if self.baseshape:
result.append(Drawing.projectToDXF(self.baseshape,self.direction))
if hasattr(self,"sectionshape"):
if self.sectionshape:
result.append(Drawing.projectToDXF(self.sectionshape,self.direction))
if hasattr(self,"hiddenshape"):
if self.hiddenshape:
result.append(Drawing.projectToDXF(self.hiddenshape,self.direction))
return result

def getDXF(self):
"returns a flat shape representation of the view"
if hasattr(self,"baseshape"):
import Drawing
[V0,V1,H0,H1] = Drawing.project(self.baseshape,self.direction)
DxfOutput = Drawing.projectToDXF(self.baseshape,self.direction)
return DxfOutput
else:
FreeCAD.Console.PrintMessage(translate("Arch","No shape has been computed yet, select wireframe rendering and render again"))
return None

if FreeCAD.GuiUp:
FreeCADGui.addCommand('Arch_SectionPlane',_CommandSectionPlane())
60 changes: 60 additions & 0 deletions src/Mod/Draft/Draft.py
Expand Up @@ -1594,6 +1594,55 @@ def draftify(objectslist,makeblock=False,delete=True):
if len(newobjlist) == 1:
return newobjlist[0]
return newobjlist

def getDXF(obj,direction=None):
'''getDXF(object,[direction]): returns a DXF entity from the given
object. If direction is given, the object is projected in 2D.'''
plane = None
result = ""
if direction:
if isinstance(direction,FreeCAD.Vector):
if direction != Vector(0,0,0):
plane = WorkingPlane.plane()
plane.alignToPointAndAxis(Vector(0,0,0),direction)

def getProj(vec):
if not plane: return vec
nx = DraftVecUtils.project(vec,plane.u)
ny = DraftVecUtils.project(vec,plane.v)
return Vector(nx.Length,ny.Length,0)

if getType(obj) == "Dimension":
p1 = getProj(obj.Start)
p2 = getProj(obj.End)
p3 = getProj(obj.Dimline)
result += "0\nDIMENSION\n8\n0\n62\n0\n3\nStandard\n70\n1\n"
result += "10\n"+str(p3.x)+"\n20\n"+str(p3.y)+"\n30\n"+str(p3.z)+"\n"
result += "13\n"+str(p1.x)+"\n23\n"+str(p1.y)+"\n33\n"+str(p1.z)+"\n"
result += "14\n"+str(p2.x)+"\n24\n"+str(p2.y)+"\n34\n"+str(p2.z)+"\n"

elif getType(obj) == "Annotation":
p = getProj(obj.Position)
count = 0
for t in obj.LabeLtext:
result += "0\nTEXT\n8\n0\n62\n0\n"
result += "10\n"+str(p.x)+"\n20\n"+str(p.y+count)+"\n30\n"+str(p.z)+"\n"
result += "40\n1\n"
result += "1\n"+str(t)+"\n"
result += "7\nSTANDARD\n"
count += 1

elif obj.isDerivedFrom("Part::Feature"):
# TODO do this the Draft way, for ex. using polylines and rectangles
import Drawing
if not direction: direction = FreeCAD.Vector(0,0,-1)
result += Drawing.projectToDXF(obj.Shape,direction)

else:
print "Draft.getDXF: Unsupported object: ",obj.Label

return result


def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direction=None,linestyle=None,color=None):
'''getSVG(object,[scale], [linewidth],[fontsize],[fillstyle],[direction],[linestyle],[color]):
Expand Down Expand Up @@ -4133,6 +4182,17 @@ def execute(self, obj):
result += svg
result += '</g>'
obj.ViewResult = result

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(o,obj.Direction)
return result

class _BSpline(_DraftObject):
"The BSpline object"
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Draft/WorkingPlane.py
Expand Up @@ -112,7 +112,7 @@ def projectPointOld(self, p, direction=None):
t.multiply(self.offsetToPoint(p, direction))
return p.add(t)

def alignToPointAndAxis(self, point, axis, offset, upvec=None):
def alignToPointAndAxis(self, point, axis, offset=0, upvec=None):
self.doc = FreeCAD.ActiveDocument
self.axis = axis;
self.axis.normalize()
Expand Down
104 changes: 104 additions & 0 deletions src/Mod/Draft/importDXF.py
Expand Up @@ -1666,8 +1666,112 @@ def export(objectslist,filename,nospline=False,lwPoly=False):
dxf.saveas(filename)
FreeCAD.Console.PrintMessage("successfully exported "+filename+"\r\n")


def exportPage(page,filename):
"special export for pages"
template = os.path.splitext(page.Template)[0]+".dxf"
global dxfhandle
dxfhandle = 1
if os.path.exists(template):
f = pythonopen(template,"rb")
template = f.read()
f.close()
# find & replace editable texts
import re
f = pythonopen(page.Template,"rb")
svgtemplate = f.read()
f.close()
editables = re.findall("freecad:editable=\"(.*?)\"",svgtemplate)
values = page.EditableTexts
for i in range(len(editables)):
if len(values) > i:
template = template.replace(editables[i],values[i])
else:
# dummy default template
print "DXF version of the template not found. Creating a default empty template."
template = "999\nFreeCAD DXF exporter v"+FreeCAD.Version()[0]+"."+FreeCAD.Version()[1]+"-"+FreeCAD.Version()[2]+"\n"
template += "0\nSECTION\n2\nHEADER\n9\n$ACADVER\n1\nAC1009\n0\nENDSEC\n"
template += "0\nSECTION\n2\nBLOCKS\n$blocks\n0\nENDSEC\n"
template += "0\nSECTION\n2\nENTITIES\n$entities\n0\nENDSEC\n"
template += "0\nEOF"
blocks = ""
entities = ""
for view in page.Group:
b,e = getViewDXF(view)
blocks += b
entities += e
result = template.replace("$blocks",blocks[:-1])
result = result.replace("$entities",entities[:-1])
f = pythonopen(filename,"wb")
f.write(result)
f.close()


def getViewDXF(view):
"returns a DXF fragment from a Drawing View"
global dxfhandle
block = ""
insert = ""

if view.isDerivedFrom("App::DocumentObjectGroup"):
for child in view.Group:
b,e = getViewDXF(child)
block += b
insert += e

elif view.isDerivedFrom("Drawing::FeatureViewPython"):
if hasattr(view.Proxy,"getDXF"):
r = view.Rotation
if r != 0: r = -r # fix rotation direction
count = 0
block = ""
insert = ""
geom = view.Proxy.getDXF(view)
if not isinstance(geom,list): geom = [geom]
for g in geom: # getDXF returns a list of entities
g = g.replace("sheet_layer\n","0\n6\nBYBLOCK\n62\n0\n") # change layer and set color and ltype to BYBLOCK (0)
block += "0\nBLOCK\n8\n0\n2\n"+view.Name+str(count)+"\n70\n0\n10\n0\n20\n0\n3\n"+view.Name+str(count)+"\n1\n\n"
block += g
block += "0\nENDBLK\n8\n0\n"
insert += "0\nINSERT\n5\naaaa"+hex(dxfhandle)[2:]+"\n8\n0\n6\nBYLAYER\n62\n256\n2\n"+view.Name+str(count)
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"
dxfhandle += 1
count += 1

elif view.isDerivedFrom("Drawing::FeatureViewPart"):
r = view.Rotation
if r != 0: r = -r # fix rotation direction
import Drawing
proj = Drawing.projectToDXF(view.Source.Shape,view.Direction)
proj = proj.replace("sheet_layer\n","0\n6\nBYBLOCK\n62\n0\n") # change layer and set color and ltype to BYBLOCK (0)
block = "0\nBLOCK\n8\n0\n2\n"+view.Name+"\n70\n0\n10\n0\n20\n0\n3\n"+view.Name+"\n1\n\n"
block += proj
block += "0\nENDBLK\n8\n0\n"
insert = "0\nINSERT\n5\naaaa"+hex(dxfhandle)[2:]+"\n8\n0\n6\nBYLAYER\n62\n256\n2\n"+view.Name
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"
dxfhandle += 1

elif view.isDerivedFrom("Drawing::FeatureViewAnnotation"):
r = view.Rotation
if r != 0: r = -r # fix rotation direction
insert ="0\nTEXT\n5\n"+hex(dxfhandle)[2:]+"\n8\n0"
insert += "\n10\n"+str(view.X)+"\n20\n"+str(-view.Y)
insert += "\n30\n0\n40\n"+str(view.Scale/2)
insert += "\n50\n"+str(r)
insert += "\n1\n"+view.Text[0]+"\n"
dxfhandle += 1

else:
print "Unable to get DXF representation from view: ",view.Label
return block,insert


def exportPageLegacy(page,filename):
"exports the given page the old way, by converting its SVG code to DXF with the Draft module"
import importSVG
tempdoc = importSVG.open(page.PageResult)
tempobj = tempdoc.Objects
Expand Down
89 changes: 6 additions & 83 deletions src/Mod/Drawing/App/ProjectionAlgos.cpp
Expand Up @@ -273,113 +273,36 @@ std::string ProjectionAlgos::getDXF(ExtractionType type, double scale, double to
std::stringstream result;
DXFOutput output;

result << "0" << endl
<< "SECTION" << endl

<< "2" << endl
<< "ENTITIES" << endl;

if (!H.IsNull() && (type & WithHidden)) {
//float width = 0.15f/scale;
BRepMesh_IncrementalMesh(H,tolerance);
result //<< "<g"
//<< " id=\"" << ViewName << "\"" << endl
/*<< " stroke=\"rgb(0, 0, 0)\"" << endl
<< " stroke-width=\"" << width << "\"" << endl
<< " stroke-linecap=\"butt\"" << endl
<< " stroke-linejoin=\"miter\"" << endl
<< " stroke-dasharray=\"5 3\"" << endl
<< " fill=\"none\"" << endl
<< " >" << endl*/
<< output.exportEdges(H);
//<< "</g>" << endl;
result << output.exportEdges(H);
}
if (!HO.IsNull() && (type & WithHidden)) {
//float width = 0.15f/scale;
BRepMesh_IncrementalMesh(HO,tolerance);
result //<< "<g"
//<< " id=\"" << ViewName << "\"" << endl
/*<< " stroke=\"rgb(0, 0, 0)\"" << endl
<< " stroke-width=\"" << width << "\"" << endl
<< " stroke-linecap=\"butt\"" << endl
<< " stroke-linejoin=\"miter\"" << endl
<< " stroke-dasharray=\"5 3\"" << endl
<< " fill=\"none\"" << endl
<< " >" << endl*/
<< output.exportEdges(HO);
//<< "</g>" << endl;
result << output.exportEdges(HO);
}
if (!VO.IsNull()) {
//float width = 0.35f/scale;
BRepMesh_IncrementalMesh(VO,tolerance);
result //<< "<g"
//<< " id=\"" << ViewName << "\"" << endl

/*<< " stroke=\"rgb(0, 0, 0)\"" << endl
<< " stroke-width=\"" << width << "\"" << endl
<< " stroke-linecap=\"butt\"" << endl
<< " stroke-linejoin=\"miter\"" << endl
<< " fill=\"none\"" << endl
<< " >" << endl*/

<< output.exportEdges(VO);
//<< "</g>" << endl;
result << output.exportEdges(VO);
}
if (!V.IsNull()) {
//float width = 0.35f/scale;
BRepMesh_IncrementalMesh(V,tolerance);
result //<< "<g"
//<< " id=\"" << ViewName << "\"" << endl
/*<< " stroke=\"rgb(0, 0, 0)\"" << endl
<< " stroke-width=\"" << width << "\"" << endl
<< " stroke-linecap=\"butt\"" << endl
<< " stroke-linejoin=\"miter\"" << endl
<< " fill=\"none\"" << endl
<< " >" << endl*/
<< output.exportEdges(V);
//<< "</g>" << endl;

result << output.exportEdges(V);
}
if (!V1.IsNull() && (type & WithSmooth)) {
//float width = 0.35f/scale;
BRepMesh_IncrementalMesh(V1,tolerance);
result //<< "<g"

//<< " id=\"" << ViewName << "\"" << endl
/* << " stroke=\"rgb(0, 0, 0)\"" << endl
<< " stroke-width=\"" << width << "\"" << endl
<< " stroke-linecap=\"butt\"" << endl
<< " stroke-linejoin=\"miter\"" << endl
<< " fill=\"none\"" << endl
<< " >" << endl*/
<< output.exportEdges(V1);
//<< "</g>" << endl;
result << output.exportEdges(V1);
}
if (!H1.IsNull() && (type & WithSmooth) && (type & WithHidden)) {
//float width = 0.15f/scale;
BRepMesh_IncrementalMesh(H1,tolerance);
result //<< "<g"
//<< " id=\"" << ViewName << "\"" << endl
/*<< " stroke=\"rgb(0, 0, 0)\"" << endl
<< " stroke-width=\"" << width << "\"" << endl
<< " stroke-linecap=\"butt\"" << endl
<< " stroke-linejoin=\"miter\"" << endl
<< " stroke-dasharray=\"5 3\"" << endl
<< " fill=\"none\"" << endl
<< " >" << endl*/

<< output.exportEdges(H1);
//<< "</g>" << endl;
result << output.exportEdges(H1);
}


result << 0 << endl
<< "ENDSEC" << endl
<< 0 << endl
<< "EOF";

return result.str();
}

0 comments on commit b33d8f6

Please sign in to comment.