From 82a2c1b753e86fa5bf81d21c59a205d5de04123d Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Fri, 18 Sep 2020 09:50:12 +0200 Subject: [PATCH] Arch: ifc export, workaround for draft array export and some small improvements --- src/Mod/Arch/exportIFC.py | 95 +++++++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/src/Mod/Arch/exportIFC.py b/src/Mod/Arch/exportIFC.py index b8853e442d..6990e25330 100644 --- a/src/Mod/Arch/exportIFC.py +++ b/src/Mod/Arch/exportIFC.py @@ -332,6 +332,7 @@ def export(exportList, filename, colors=None, preferences=None): description = getText("Description",obj) uid = getUID(obj,preferences) ifctype = getIfcTypeFromObj(obj) + # print(ifctype) if ifctype == "IfcGroup": groups[obj.Name] = [o.Name for o in obj.Group] @@ -341,9 +342,13 @@ def export(exportList, filename, colors=None, preferences=None): assemblyElements = [] - if ifctype == "IfcArray": + # if ifctype == "IfcArray": + # FIXME: the first array element is not placed correct if the array is not on coordinate origin + # https://forum.freecadweb.org/viewtopic.php?f=39&t=50085&p=431476#p431476 + # workaround: do not use the assembly in ifc but a normal compound instead + if False: + clonedeltas = [] if obj.ArrayType == "ortho": - clonedeltas = [] for i in range(obj.NumberX): clonedeltas.append(obj.Placement.Base+(i*obj.IntervalX)) for j in range(obj.NumberY): @@ -352,31 +357,39 @@ def export(exportList, filename, colors=None, preferences=None): for k in range(obj.NumberZ): if k > 0: clonedeltas.append(obj.Placement.Base+(i*obj.IntervalX)+(j*obj.IntervalY)+(k*obj.IntervalZ)) - #print("clonedeltas:",clonedeltas) - for delta in clonedeltas: - representation,placement,shapetype = getRepresentation( - ifcfile, - context, - obj.Base, - forcebrep=(getBrepFlag(obj.Base,preferences)), - colors=colors, - preferences=preferences, - forceclone=delta - ) - subproduct = createProduct( - ifcfile, - obj.Base, - getIfcTypeFromObj(obj.Base), - getUID(obj.Base,preferences), - history, - getText("Name",obj.Base), - getText("Description",obj.Base), - placement, - representation, - preferences) - assemblyElements.append(subproduct) + #print("clonedeltas:",clonedeltas) + if clonedeltas: ifctype = "IfcElementAssembly" + for delta in clonedeltas: + # print("delta: {}".format(delta)) + representation,placement,shapetype = getRepresentation( + ifcfile, + context, + obj.Base, + forcebrep=(getBrepFlag(obj.Base,preferences)), + colors=colors, + preferences=preferences, + forceclone=delta + ) + subproduct = createProduct( + ifcfile, + obj.Base, + getIfcTypeFromObj(obj.Base), + getUID(obj.Base,preferences), + history, + getText("Name",obj.Base), + getText("Description",obj.Base), + placement, + representation, + preferences + ) + assemblyElements.append(subproduct) + # if an array was handled assemblyElements is not empty + # if assemblyElements is not empty later on + # the own Shape is ignored if representation is retrieved + # this because we will build an assembly for the assemblyElements + # from here and the assembly itself should not have a representation elif ifctype == "IfcApp::Part": for subobj in [FreeCAD.ActiveDocument.getObject(n[:-1]) for n in obj.getSubObjects()]: @@ -466,6 +479,12 @@ def export(exportList, filename, colors=None, preferences=None): ifctype = "IfcBuildingElementProxy" # getting the representation + + # ignore the own shape for assembly objects + skipshape = False + if assemblyElements: + # print("Assembly object: {}, thus own Shape will have no representation.".format(obj.Name)) + skipshape = True representation,placement,shapetype = getRepresentation( ifcfile, @@ -473,7 +492,8 @@ def export(exportList, filename, colors=None, preferences=None): obj, forcebrep=(getBrepFlag(obj,preferences)), colors=colors, - preferences=preferences + preferences=preferences, + skipshape=skipshape ) if preferences['GET_STANDARD']: if isStandardCase(obj,ifctype): @@ -1615,7 +1635,15 @@ def getIfcTypeFromObj(obj): if ifctype in translationtable.keys(): ifctype = translationtable[ifctype] - return "Ifc" + ifctype + if not "::" in ifctype: + ifctype = "Ifc" + ifctype + else: + # it makes no sense to return IfcPart::Cylinder for a Part::Cylinder + # this is not a ifctype at all + ifctype = None + + # print("Return value of getIfcTypeFromObj: {}".format(ifctype)) + return ifctype def exportIFC2X3Attributes(obj, kwargs, scale=0.001): @@ -1862,7 +1890,7 @@ def getProfile(ifcfile,p): return profile -def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tessellation=1,colors=None,preferences=None,forceclone=False): +def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tessellation=1,colors=None,preferences=None,forceclone=False,skipshape=False): """returns an IfcShapeRepresentation object or None. forceclone can be False (does nothing), "store" or True (stores the object as clone base) or a Vector (creates a clone)""" @@ -1876,7 +1904,6 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess shapetype = "no shape" tostore = False subplacement = None - skipshape = False # check for clones @@ -1910,10 +1937,6 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess if obj.isDerivedFrom("Part::Feature") and (len(obj.Shape.Solids) > 1) and hasattr(obj,"Axis") and obj.Axis: forcebrep = True - # specific cases that must ignore their own shape - if Draft.getType(obj) in ["Array"]: - skipshape = True - if (not shapes) and (not forcebrep) and (not skipshape): profile = None ev = FreeCAD.Vector() @@ -2300,6 +2323,12 @@ def createProduct(ifcfile,obj,ifctype,uid,history,name,description,placement,rep kwargs = exportIFC2X3Attributes(obj, kwargs, preferences['SCALE_FACTOR']) else: kwargs = exportIfcAttributes(obj, kwargs, preferences['SCALE_FACTOR']) + # in some cases object have wrong ifctypes, thus set it + # https://forum.freecadweb.org/viewtopic.php?f=39&t=50085 + if ifctype not in ArchIFCSchema.IfcProducts.keys(): + # print("Wrong IfcType: IfcBuildingElementProxy is used. {}".format(ifctype)) + ifctype = "IfcBuildingElementProxy" + # print("createProduct: {}".format(ifctype)) product = getattr(ifcfile,"create"+ifctype)(**kwargs) return product