From cfba4a3d5cb4e62128286265e61d53171ab120fb Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 Dec 2015 10:39:27 -0200 Subject: [PATCH 1/3] Changed default shortcuts for 10 first workbenches from CTRL+number to ALT+CTRL+number --- src/Gui/Action.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/Action.cpp b/src/Gui/Action.cpp index ae4758f95..3e0adde72 100644 --- a/src/Gui/Action.cpp +++ b/src/Gui/Action.cpp @@ -536,7 +536,7 @@ void WorkbenchGroup::setWorkbenchData(int i, const QString& wb) workbenches[i]->setStatusTip(tr("Select the '%1' workbench").arg(name)); workbenches[i]->setVisible(true); if (i < 10) - workbenches[i]->setShortcut(QKeySequence(QString::fromUtf8("Ctrl+%1").arg(i))); + workbenches[i]->setShortcut(QKeySequence(QString::fromUtf8("Ctrl+Alt+%1").arg(i))); } void WorkbenchGroup::refreshWorkbenchList() From 45292eb9ee5705c7bf433bb2c59878a51ec365b7 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 Dec 2015 10:39:40 -0200 Subject: [PATCH 2/3] Arch: IFC bugfix + added pref option to use DAE triangulation options --- src/Mod/Arch/ArchCommands.py | 12 ++++++--- src/Mod/Arch/Resources/ui/preferences-ifc.ui | 26 +++++++++++++++++--- src/Mod/Arch/importIFC.py | 21 +++++++++++----- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 0e15fc6ac..cd3f2bddc 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -498,11 +498,15 @@ def meshToShape(obj,mark=True,fast=True,tol=0.001,flat=False,cut=True): return newobj return None -def removeCurves(shape,tolerance=5): - '''removeCurves(shape,tolerance=5): replaces curved faces in a shape - with faceted segments''' +def removeCurves(shape,dae=False,tolerance=5): + '''removeCurves(shape,dae,tolerance=5): replaces curved faces in a shape + with faceted segments. If dae is True, DAE triangulation options are used''' import Mesh - t = shape.cleaned().tessellate(tolerance) + if dae: + import importDAE + t = importDAE.triangulate(shape.cleaned()) + else: + t = shape.cleaned().tessellate(tolerance) m = Mesh.Mesh(t) return getShapeFromMesh(m) diff --git a/src/Mod/Arch/Resources/ui/preferences-ifc.ui b/src/Mod/Arch/Resources/ui/preferences-ifc.ui index 2f88dbfc1..ab7f177d0 100644 --- a/src/Mod/Arch/Resources/ui/preferences-ifc.ui +++ b/src/Mod/Arch/Resources/ui/preferences-ifc.ui @@ -319,13 +319,33 @@ - Curved shapes that cannot be represented as curves in IFC are decomposed into flat facets. If this is checked, simple triangulation will be used, otherwise some additional calculation is done to join coplanar facets. + Use triangulation options set in the DAE options page - Use classic triangulation + Use DAE triangulation options - ifcClassicTriangulation + ifcUseDaeOptions + + + Mod/Arch + + + + + + + + + + + Curved shapes that cannot be represented as curves in IFC are decomposed into flat facets. If this is checked, some additional calculation is done to join coplanar facets. + + + Join coplanar facets when triangulating + + + ifcJoinCoplanarFacets Mod/Arch diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index 3383ae78a..ddaea9b58 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -832,8 +832,8 @@ def export(exportList,filename): if b: clones.setdefault(b.Name,[]).append(o.Name) - print "clones table: ",clones - print objectslist + #print "clones table: ",clones + #print objectslist # products for obj in objectslist: @@ -1170,7 +1170,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess dataset = fcshape.Solids else: dataset = fcshape.Shells - print "Warning! object contains no solids" + if DEBUG: print "Warning! object contains no solids" for fcsolid in dataset: fcsolid.scale(0.001) # to meters faces = [] @@ -1183,9 +1183,15 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess curves = True break if curves: - if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("ifcClassicTriangulation",False): + joinfacets = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("ifcJoinCoplanarFacets",False) + usedae = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("ifcUseDaeOptions",False) + if not joinfacets: shapetype = "triangulated" - tris = fcsolid.tessellate(tessellation) + if usedae: + import importDAE + tris = importDAE.triangulate(fcsolid) + else: + tris = fcsolid.tessellate(tessellation) for tri in tris[1]: pts = [ifcfile.createIfcCartesianPoint(tuple(tris[0][i])) for i in tri] loop = ifcfile.createIfcPolyLoop(pts) @@ -1194,7 +1200,10 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess faces.append(face) fcsolid = Part.Shape() # empty shape so below code is not executed else: - fcsolid = Arch.removeCurves(fcsolid) + fcsolid = Arch.removeCurves(fcsolid,dae=usedae) + if not fcsolid: + if DEBUG: print "Error: Unable to triangulate shape" + fcsolid = Part.Shape() for fcface in fcsolid.Faces: loops = [] From dab7ef4262f50f232ca340d30616cccc3c3e31fa Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 18 Dec 2015 10:47:14 -0200 Subject: [PATCH 3/3] Draft: workaround for exporting DXF with R14+ templates - fixes 2177 - Adapted Drawing algos to export R14+ compatible DXF code - Added option in DXF prefs to disable groups (not supported in R14+ templates) --- src/Mod/Draft/Draft.py | 7 +- src/Mod/Draft/Resources/ui/preferences-dxf.ui | 23 ++++++ src/Mod/Draft/importDXF.py | 82 +++++++++++-------- src/Mod/Drawing/App/DrawingExport.cpp | 37 ++++++--- 4 files changed, 103 insertions(+), 46 deletions(-) diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index b9dd867c3..c6175a250 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1672,7 +1672,10 @@ def getDXF(obj,direction=None): 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) + if not direction: + direction = FreeCAD.Vector(0,0,-1) + if DraftVecUtils.isNull(direction): + direction = FreeCAD.Vector(0,0,-1) result += Drawing.projectToDXF(obj.Shape,direction) else: @@ -4522,7 +4525,7 @@ class _DrawingView(_DraftObject): if o.ViewObject.isVisible(): result += getDXF(o,obj.Direction) else: - result += getDXF(o,obj.Direction) + result += getDXF(obj.Source,obj.Direction) return result class _BSpline(_DraftObject): diff --git a/src/Mod/Draft/Resources/ui/preferences-dxf.ui b/src/Mod/Draft/Resources/ui/preferences-dxf.ui index c8b063a4d..916e495fa 100644 --- a/src/Mod/Draft/Resources/ui/preferences-dxf.ui +++ b/src/Mod/Draft/Resources/ui/preferences-dxf.ui @@ -478,6 +478,29 @@ + + + + + + if this is checked, Drawing Views will be exported as blocks. This might fail for post-R12 templates. + + + Export Drawing Views as blocks + + + true + + + dxfExportBlocks + + + Mod/Draft + + + + + diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 118500a04..843ba60dd 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -1861,18 +1861,23 @@ def export(objectslist,filename,nospline=False,lwPoly=False): FreeCAD.Console.PrintMessage("successfully exported "+filename+"\r\n") else: errorDXFLib(gui) + +class dxfcounter: + def __init__(self): + self.count = 10000 # this leaves 10000 entities for the template... + def incr(self,matchobj): + self.count += 1 + #print format(self.count,'02x') + return format(self.count,'02x') 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,"U") template = f.read() f.close() # find & replace editable texts - import re f = pythonopen(page.Template,"rb") svgtemplate = f.read() f.close() @@ -1886,8 +1891,8 @@ def exportPage(page,filename): 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\nSECTION\n2\nBLOCKS\n999\n$blocks\n0\nENDSEC\n" + template += "0\nSECTION\n2\nENTITIES\n999\n$entities\n0\nENDSEC\n" template += "0\nEOF" blocks = "" entities = "" @@ -1895,18 +1900,23 @@ def exportPage(page,filename): b,e = getViewDXF(view) blocks += b entities += e - result = template.replace("999\n$blocks",blocks[:-1]) - result = result.replace("999\n$entities",entities[:-1]) + if blocks: + template = template.replace("999\n$blocks",blocks[:-1]) + if entities: + template = template.replace("999\n$entities",entities[:-1]) + c = dxfcounter() + pat = re.compile("(_handle_)") + template = pat.sub(c.incr,template) f = pythonopen(filename,"wb") - f.write(result) + f.write(template) f.close() -def getViewDXF(view): +def getViewDXF(view,blocks=True): "returns a DXF fragment from a Drawing View" - global dxfhandle block = "" insert = "" + blockcount = 1 if view.isDerivedFrom("App::DocumentObjectGroup"): for child in view.Group: @@ -1918,47 +1928,52 @@ def getViewDXF(view): 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 + 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 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 + if dxfExportBlocks: + proj = proj.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 += proj + 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: + proj = proj.replace("sheet_layer\n","0\n5\n_handle_\n") + insert += proj 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 ="0\nTEXT\n5\n_handle_\n8\n0\n100\nAcDbEntity\n100\nAcDbText\n5\n_handle_" 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) @@ -1979,7 +1994,7 @@ def readPreferences(): global dxfCreatePart, dxfCreateDraft, dxfCreateSketch, dxfDiscretizeCurves, dxfStarBlocks global dxfMakeBlocks, dxfJoin, dxfRenderPolylineWidth, dxfImportTexts, dxfImportLayouts global dxfImportPoints, dxfImportHatches, dxfUseStandardSize, dxfGetColors, dxfUseDraftVisGroups - global dxfFillMode, dxfBrightBackground, dxfDefaultColor, dxfUseLegacyImporter + global dxfFillMode, dxfBrightBackground, dxfDefaultColor, dxfUseLegacyImporter, dxfExportBlocks dxfCreatePart = p.GetBool("dxfCreatePart",True) dxfCreateDraft = p.GetBool("dxfCreateDraft",False) dxfCreateSketch = p.GetBool("dxfCreateSketch",False) @@ -1999,3 +2014,4 @@ def readPreferences(): dxfUseLegacyImporter = p.GetBool("dxfUseLegacyImporter",True) dxfBrightBackground = isBrightBackground() dxfDefaultColor = getColor() + dxfExportBlocks = p.GetBool("dxfExportBlocks",True) diff --git a/src/Mod/Drawing/App/DrawingExport.cpp b/src/Mod/Drawing/App/DrawingExport.cpp index a3b69b123..2cbdde8c3 100644 --- a/src/Mod/Drawing/App/DrawingExport.cpp +++ b/src/Mod/Drawing/App/DrawingExport.cpp @@ -495,6 +495,10 @@ void DXFOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out) out << "CIRCLE" << endl; out << 8 << endl; // Group code for layer name out << "sheet_layer" << endl; // Layer number + out << "100" << endl; + out << "AcDbEntity" << endl; + out << "100" << endl; + out << "AcDbCircle" << endl; out << 10 << endl; // Centre X out << p.X() << endl; // X in WCS coordinates out << 20 << endl; @@ -534,6 +538,10 @@ void DXFOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out) out << "ARC" << endl; out << 8 << endl; // Group code for layer name out << "sheet_layer" << endl; // Layer number + out << "100" << endl; + out << "AcDbEntity" << endl; + out << "100" << endl; + out << "AcDbCircle" << endl; out << 10 << endl; // Centre X out << p.X() << endl; // X in WCS coordinates out << 20 << endl; @@ -542,6 +550,8 @@ void DXFOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out) out << 0 << endl; // Z in WCS coordinates out << 40 << endl; // out << r << endl; // Radius + out << "100" << endl; + out << "AcDbArc" << endl; out << 50 << endl; out << start_angle << endl; // Start angle out << 51 << endl; @@ -601,6 +611,10 @@ void DXFOutput::printEllipse(const BRepAdaptor_Curve& c, int id, std::ostream& o out << "ELLIPSE" << endl; out << 8 << endl; // Group code for layer name out << "sheet_layer" << endl; // Layer number + out << "100" << endl; + out << "AcDbEntity" << endl; + out << "100" << endl; + out << "AcDbEllipse" << endl; out << 10 << endl; // Centre X out << p.X() << endl; // X in WCS coordinates out << 20 << endl; @@ -657,17 +671,14 @@ void DXFOutput::printBSpline(const BRepAdaptor_Curve& c, int id, std::ostream& o str << 0 << endl - << "SECTION" << endl - << 2 << endl - << "ENTITIES" << endl - << 0 << endl - << "SPLINE" << endl; - //<< 8 << endl - //<< 0 << endl - //<< 66 << endl - //<< 1 << endl - //<< 0 << endl; - str << 70 << endl + << "SPLINE" << endl + << 8 << endl // Group code for layer name + << "sheet_layer" << endl // Layer name + << "100" << endl + << "AcDbEntity" << endl + << "100" << endl + << "AcDbSpline" << endl + << 70 << endl << spline->IsRational()*4 << endl //flags << 71 << endl << spline->Degree() << endl << 72 << endl << knotsequence.Length() << endl @@ -711,6 +722,10 @@ void DXFOutput::printGeneric(const BRepAdaptor_Curve& c, int id, std::ostream& o out << "LINE" << endl; out << "8" << endl; // Group code for layer name out << "sheet_layer" << endl; // Layer name + out << "100" << endl; + out << "AcDbEntity" << endl; + out << "100" << endl; + out << "AcDbLine" << endl; out << "10" << endl; // Start point of line out << PS.X() << endl; // X in WCS coordinates out << "20" << endl;