diff --git a/src/Gui/Action.cpp b/src/Gui/Action.cpp index ae4758f95b..3e0adde729 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() diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 0e15fc6acd..cd3f2bddcb 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 2f88dbfc17..ab7f177d0b 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 3383ae78a9..ddaea9b589 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 = [] diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index b9dd867c38..c6175a250a 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 c8b063a4d9..916e495fa9 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 118500a04d..843ba60dde 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 a3b69b123d..2cbdde8c34 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;