From 0ad956c45be67b0e4168ab0016fa8b6a104cf795 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Wed, 14 Sep 2016 18:55:55 -0300 Subject: [PATCH] Arch: IFC exporter now exports 2D geometry as IfcAnnotations --- src/Mod/Arch/Resources/ui/preferences-ifc.ui | 22 ++- src/Mod/Arch/importIFC.py | 147 +++++++++++++------ src/Mod/Draft/Draft.py | 5 +- 3 files changed, 123 insertions(+), 51 deletions(-) diff --git a/src/Mod/Arch/Resources/ui/preferences-ifc.ui b/src/Mod/Arch/Resources/ui/preferences-ifc.ui index cba316bc8..abfae8f37 100644 --- a/src/Mod/Arch/Resources/ui/preferences-ifc.ui +++ b/src/Mod/Arch/Resources/ui/preferences-ifc.ui @@ -7,7 +7,7 @@ 0 0 456 - 637 + 666 @@ -470,6 +470,26 @@ + + + + + + Export 2D objects as IfcAnnotations + + + true + + + ifcExport2D + + + Mod/Arch + + + + + diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index 3af495357..08ccf05de 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -126,7 +126,7 @@ def getPreferences(): global ROOT_ELEMENT, GET_EXTRUSIONS, MERGE_MATERIALS global MERGE_MODE_ARCH, MERGE_MODE_STRUCT, CREATE_CLONES global FORCE_BREP, IMPORT_PROPERTIES, STORE_UID, SERIALIZE - global SPLIT_LAYERS + global SPLIT_LAYERS, EXPORT_2D p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") if FreeCAD.GuiUp and p.GetBool("ifcShowDialog",False): import FreeCADGui @@ -151,6 +151,7 @@ def getPreferences(): STORE_UID = p.GetBool("ifcStoreUid",True) SERIALIZE = p.GetBool("ifcSerialize",False) SPLIT_LAYERS = p.GetBool("ifcSplitLayers",False) + EXPORT_2D = p.GetBool("ifcExport2D",True) def explore(filename=None): @@ -963,6 +964,16 @@ def export(exportList,filename): context = ifcfile.by_type("IfcGeometricRepresentationContext")[0] project = ifcfile.by_type("IfcProject")[0] objectslist = Draft.getGroupContents(exportList,walls=True,addgroups=True) + annotations = [] + for obj in objectslist: + if obj.isDerivedFrom("Part::Part2DObject"): + annotations.append(obj) + elif obj.isDerivedFrom("App::Annotation"): + annotations.append(obj) + elif obj.isDerivedFrom("Part::Feature"): + if obj.Shape: + if not obj.Shape.Faces: + annotations.append(obj) objectslist = Arch.pruneIncluded(objectslist) products = {} # { Name: IfcEntity, ... } surfstyles = {} # { (r,g,b): IfcEntity, ... } @@ -1300,7 +1311,37 @@ def export(exportList,filename): products[g[0]] = grp ass = ifcfile.createIfcRelAssignsToGroup(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'GroupLink','',children,None,grp) - + # 2D objects + + if EXPORT_2D: + if annotations and DEBUG: print "exporting 2D objects..." + for anno in annotations: + xvc = ifcfile.createIfcDirection((1.0,0.0,0.0)) + zvc = ifcfile.createIfcDirection((0.0,0.0,1.0)) + ovc = ifcfile.createIfcCartesianPoint((0.0,0.0,0.0)) + gpl = ifcfile.createIfcAxis2Placement3D(ovc,zvc,xvc) + if anno.isDerivedFrom("Part::Feature"): + reps = [] + sh = anno.Shape.copy() + sh.scale(0.001) # to meters + ehc = [] + for w in sh.Wires: + reps.append(createCurve(ifcfile,w)) + for e in w.Edges: + ehc.append(e.hashCode()) + for e in sh.Edges: + if not e.hashCode in ehc: + reps.append(createCurve(ifcfile,e)) + elif anno.isDerivedFrom("App::Annotation"): + l = anno.Position + pos = ifcfile.createIfcCartesianPoint((l.x,l.y,l.z)) + tpl = ifcfile.createIfcAxis2Placement3D(pos,None,None) + txt = ifcfile.createIfcTextLiteral(";".join(anno.LabelText).encode("utf8"),tpl,"LEFT") + reps = [txt] + shp = ifcfile.createIfcShapeRepresentation(context,'Annotation','Annotation2D',reps) + rep = ifcfile.createIfcProductDefinitionShape(None,None,[shp]) + ann = ifcfile.createIfcAnnotation(ifcopenshell.guid.compress(uuid.uuid1().hex),history,anno.Label.encode('utf8'),'',None,gpl,rep) + if DEBUG: print "writing ",filename,"..." filename = decode(filename) @@ -1314,6 +1355,60 @@ def export(exportList,filename): os.remove(templatefile) +def createCurve(ifcfile,wire): + "creates an IfcCompositeCurve from a shape" + + segments = [] + pol = None + last = None + if wire.ShapeType == "edge": + edges = [edge] + else: + edges = Part.__sortEdges__(wire.Edges) + for e in edges: + if isinstance(e.Curve,Part.Circle): + follow = True + if last: + if not DraftVecUtils.equals(last,e.Vertexes[0].Point): + follow = False + last = e.Vertexes[0].Point + else: + last = e.Vertexes[-1].Point + else: + last = e.Vertexes[-1].Point + p1 = math.degrees(-DraftVecUtils.angle(e.Vertexes[0].Point.sub(e.Curve.Center))) + p2 = math.degrees(-DraftVecUtils.angle(e.Vertexes[-1].Point.sub(e.Curve.Center))) + da = DraftVecUtils.angle(e.valueAt(e.FirstParameter+0.1).sub(e.Curve.Center),e.Vertexes[0].Point.sub(e.Curve.Center)) + if p1 < 0: + p1 = 360 + p1 + if p2 < 0: + p2 = 360 + p2 + if da > 0: + follow = not(follow) + xvc = ifcfile.createIfcDirection((1.0,0.0)) + ovc = ifcfile.createIfcCartesianPoint(tuple(e.Curve.Center)[:2]) + plc = ifcfile.createIfcAxis2Placement2D(ovc,xvc) + cir = ifcfile.createIfcCircle(plc,e.Curve.Radius) + curve = ifcfile.createIfcTrimmedCurve(cir,[ifcfile.createIfcParameterValue(p1)],[ifcfile.createIfcParameterValue(p2)],follow,"PARAMETER") + else: + verts = [vertex.Point for vertex in e.Vertexes] + if last: + if not DraftVecUtils.equals(last,verts[0]): + verts.reverse() + last = e.Vertexes[0].Point + else: + last = e.Vertexes[-1].Point + else: + last = e.Vertexes[-1].Point + pts = [ifcfile.createIfcCartesianPoint(tuple(v)[:2]) for v in verts] + curve = ifcfile.createIfcPolyline(pts) + segment = ifcfile.createIfcCompositeCurveSegment("CONTINUOUS",True,curve) + segments.append(segment) + if segments: + pol = ifcfile.createIfcCompositeCurve(segments,False) + return pol + + def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tessellation=1): """returns an IfcShapeRepresentation object or None""" @@ -1325,7 +1420,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess tostore = False # check for clones - if not subtraction: + if (not subtraction) and (not forcebrep): for k,v in clones.items(): if (obj.Name == k ) or (obj.Name in v): if k in sharedobjects: @@ -1399,51 +1494,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess # extruded composite curve else: - segments = [] - last = None - edges = Part.__sortEdges__(p.Edges) - for e in edges: - if isinstance(e.Curve,Part.Circle): - follow = True - if last: - if not DraftVecUtils.equals(last,e.Vertexes[0].Point): - follow = False - last = e.Vertexes[0].Point - else: - last = e.Vertexes[-1].Point - else: - last = e.Vertexes[-1].Point - p1 = math.degrees(-DraftVecUtils.angle(e.Vertexes[0].Point.sub(e.Curve.Center))) - p2 = math.degrees(-DraftVecUtils.angle(e.Vertexes[-1].Point.sub(e.Curve.Center))) - da = DraftVecUtils.angle(e.valueAt(e.FirstParameter+0.1).sub(e.Curve.Center),e.Vertexes[0].Point.sub(e.Curve.Center)) - if p1 < 0: - p1 = 360 + p1 - if p2 < 0: - p2 = 360 + p2 - if da > 0: - follow = not(follow) - xvc = ifcfile.createIfcDirection((1.0,0.0)) - ovc = ifcfile.createIfcCartesianPoint(tuple(e.Curve.Center)[:2]) - plc = ifcfile.createIfcAxis2Placement2D(ovc,xvc) - cir = ifcfile.createIfcCircle(plc,e.Curve.Radius) - curve = ifcfile.createIfcTrimmedCurve(cir,[ifcfile.createIfcParameterValue(p1)],[ifcfile.createIfcParameterValue(p2)],follow,"PARAMETER") - - else: - verts = [vertex.Point for vertex in e.Vertexes] - if last: - if not DraftVecUtils.equals(last,verts[0]): - verts.reverse() - last = e.Vertexes[0].Point - else: - last = e.Vertexes[-1].Point - else: - last = e.Vertexes[-1].Point - pts = [ifcfile.createIfcCartesianPoint(tuple(v)[:2]) for v in verts] - curve = ifcfile.createIfcPolyline(pts) - segment = ifcfile.createIfcCompositeCurveSegment("CONTINUOUS",True,curve) - segments.append(segment) - - pol = ifcfile.createIfcCompositeCurve(segments,False) + po = createCurve(ifcfile,p) profile = ifcfile.createIfcArbitraryClosedProfileDef("AREA",None,pol) if profile and not(DraftVecUtils.isNull(extrusionv)): diff --git a/src/Mod/Draft/Draft.py b/src/Mod/Draft/Draft.py index deb84b4fa..acf2832d6 100644 --- a/src/Mod/Draft/Draft.py +++ b/src/Mod/Draft/Draft.py @@ -1765,8 +1765,9 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct l = p.GetString("svgDashdotLine","0.09,0.05,0.02,0.05") elif linestyle == "Dotted": l = p.GetString("svgDottedLine","0.02,0.02") - elif "," in linestyle: - l = linestyle + elif linestyle: + if "," in linestyle: + l = linestyle if l: l = l.split(",") try: