private static bool ExportGenericElementAsMappedItem(ExporterIFC exporterIFC, Element element, GeometryElement geomElem, IFCExportInfoPair exportType, ProductWrapper wrapper) { GeometryInstance geometryInstance = GetTheGeometryInstance(geomElem); if (geometryInstance == null) { return(false); } GeometryElement exportGeometry = geometryInstance.GetSymbolGeometry(); if (exportGeometry == null) { return(false); } ElementId symbolId = geometryInstance.GetSymbolGeometryId()?.SymbolId ?? ElementId.InvalidElementId; ElementType elementType = element.Document.GetElement(symbolId) as ElementType; if (elementType == null) { return(false); } Transform originalTrf = geometryInstance.Transform; // Can't handle mirrored transforms yet. if (originalTrf.HasReflection) { return(false); } ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); IFCFile file = exporterIFC.GetFile(); IList <Transform> repMapTrfList = new List <Transform>(); BodyData bodyData = null; FamilyTypeInfo typeInfo = new FamilyTypeInfo(); IFCExtrusionCreationData extraParams = typeInfo.extraParams; Transform offsetTransform = Transform.Identity; // We will create a new mapped type if we haven't already created the type. FamilyTypeInfo currentTypeInfo = ExporterCacheManager.FamilySymbolToTypeInfoCache.Find(symbolId, false, exportType); bool found = currentTypeInfo.IsValid(); if (!found) { IList <IFCAnyHandle> representations3D = new List <IFCAnyHandle>(); IFCAnyHandle dummyPlacement = ExporterUtil.CreateLocalPlacement(file, null, null); extraParams.SetLocalPlacement(dummyPlacement); using (TransformSetter trfSetter = TransformSetter.Create()) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(false, ExportOptionsCache.ExportTessellationLevel.ExtraLow); bodyData = BodyExporter.ExportBody(exporterIFC, element, categoryId, ExporterUtil.GetSingleMaterial(element), exportGeometry, bodyExporterOptions, extraParams); typeInfo.MaterialIdList = bodyData.MaterialIds; offsetTransform = bodyData.OffsetTransform; // This code does not handle openings yet. // The intention for this is FabricationParts and DirectShapes which do not // currently have opening. // If they can have openings in the future, we can add this. IFCAnyHandle bodyRepHnd = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepHnd) || extraParams.GetOpenings().Count > 0) { return(false); } representations3D.Add(bodyRepHnd); repMapTrfList.Add(null); } typeInfo.StyleTransform = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, extraParams.GetLocalPlacement()); IFCAnyHandle typeStyle = FamilyInstanceExporter.CreateTypeEntityHandle(exporterIFC, ref typeInfo, null, representations3D, repMapTrfList, null, element, elementType, elementType, false, false, exportType, out HashSet <IFCAnyHandle> propertySets); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle)) { wrapper.RegisterHandleWithElementType(elementType, exportType, typeStyle, propertySets); typeInfo.Style = typeStyle; CategoryUtil.TryToCreateMaterialAssocation(exporterIFC, bodyData, elementType, element, exportGeometry, typeStyle, typeInfo); // Create other generic classification from ClassificationCode(s) ClassificationUtil.CreateClassification(exporterIFC, file, elementType, typeStyle); ClassificationUtil.CreateUniformatClassification(exporterIFC, file, elementType, typeStyle); } } if (found && !typeInfo.IsValid()) { typeInfo = currentTypeInfo; } // we'll pretend we succeeded, but we'll do nothing. if (!typeInfo.IsValid()) { return(false); } extraParams = typeInfo.extraParams; // We expect no openings, so always add to map. ExporterCacheManager.FamilySymbolToTypeInfoCache.Register(symbolId, false, exportType, typeInfo); XYZ scaledMapOrigin = XYZ.Zero; Transform scaledTrf = originalTrf.Multiply(typeInfo.StyleTransform); // create instance. IList <IFCAnyHandle> shapeReps = FamilyInstanceExporter.CreateShapeRepresentations(exporterIFC, file, element, categoryId, typeInfo, scaledMapOrigin); if (shapeReps == null) { return(false); } Transform boundingBoxTrf = (offsetTransform != null) ? offsetTransform.Inverse : Transform.Identity; boundingBoxTrf = boundingBoxTrf.Multiply(scaledTrf.Inverse); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomElem, boundingBoxTrf); if (boundingBoxRep != null) { shapeReps.Add(boundingBoxRep); } IFCAnyHandle repHnd = (shapeReps.Count > 0) ? IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps) : null; using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, scaledTrf, null)) { IFCAnyHandle instanceHandle = null; IFCAnyHandle localPlacement = setter.LocalPlacement; bool materialAlreadyAssociated = false; // We won't create the instance if: // (1) we are exporting to CV2.0/RV, (2) we have no 2D, 3D, or bounding box geometry, and (3) we aren't exporting parts. if (!(repHnd == null && (ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2 || ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView))) { string instanceGUID = GUIDUtil.CreateGUID(element); bool isChildInContainer = element.AssemblyInstanceId != ElementId.InvalidElementId; if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { bool isBuildingElementProxy = ((exportType.ExportInstance == IFCEntityType.IfcBuildingElementProxy) || (exportType.ExportType == IFCEntityType.IfcBuildingElementProxyType)); ElementId roomId = setter.UpdateRoomRelativeCoordinates(element, out IFCAnyHandle localPlacementToUse); bool containedInSpace = (roomId != ElementId.InvalidElementId) && (exportType.ExportInstance != IFCEntityType.IfcSystemFurnitureElement); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; if (!isBuildingElementProxy) { instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(exportType, exporterIFC, element, instanceGUID, ownerHistory, localPlacementToUse, repHnd); } else { instanceHandle = IFCInstanceExporter.CreateBuildingElementProxy(exporterIFC, element, instanceGUID, ownerHistory, localPlacementToUse, repHnd, exportType.ValidatedPredefinedType); } bool associateToLevel = !containedInSpace && !isChildInContainer; wrapper.AddElement(element, instanceHandle, setter, extraParams, associateToLevel, exportType); if (containedInSpace) { ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle); } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { if (ElementFilteringUtil.IsMEPType(exportType) || ElementFilteringUtil.ProxyForMEPType(element, exportType)) { ExporterCacheManager.MEPCache.Register(element, instanceHandle); } ExporterCacheManager.HandleToElementCache.Register(instanceHandle, element.Id); if (!materialAlreadyAssociated) { // Create material association for the instance only if the the istance geometry is different from the type // or the type does not have any material association IFCAnyHandle constituentSetHnd = ExporterCacheManager.MaterialSetCache.FindConstituentSetHnd(symbolId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(constituentSetHnd) && bodyData != null && bodyData.RepresentationItemInfo != null && bodyData.RepresentationItemInfo.Count > 0) { CategoryUtil.CreateMaterialAssociationWithShapeAspect(exporterIFC, element, instanceHandle, bodyData.RepresentationItemInfo); } else { // Create material association in case if bodyData is null CategoryUtil.CreateMaterialAssociation(exporterIFC, instanceHandle, typeInfo.MaterialIdList); } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeInfo.Style)) { ExporterCacheManager.TypeRelationsCache.Add(typeInfo.Style, instanceHandle); } } } } return(true); }