private static void ExportAsMappedItem(ExporterIFC exporterIFC, Element element, IFCFile file, IFCExportType exportType, string ifcEnumType, IFCExtrusionCreationData extraParams, PlacementSetter setter, IFCAnyHandle localPlacementToUse, IFCAnyHandle productRepresentation, ProductWrapper productWrapper) { IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; ElementId typeId = element.GetTypeId(); ElementType type = element.Document.GetElement(typeId) as ElementType; IFCAnyHandle styleHandle = null; if (type != null) { FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(typeId, false, exportType); bool found = currentTypeInfo.IsValid(); if (!found) { string typeObjectType = NamingUtil.CreateIFCObjectName(exporterIFC, type); HashSet <IFCAnyHandle> propertySetsOpt = new HashSet <IFCAnyHandle>(); IList <IFCAnyHandle> repMapListOpt = new List <IFCAnyHandle>(); styleHandle = FamilyExporterUtil.ExportGenericType(exporterIFC, exportType, ifcEnumType, propertySetsOpt, repMapListOpt, element, type); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle)) { propertySetsOpt = ExporterUtil.ExtractElementTypeProperties(exporterIFC, type, styleHandle); productWrapper.RegisterHandleWithElementType(type, styleHandle, propertySetsOpt); string applicableOccurrence = NamingUtil.GetObjectTypeOverride(type, typeObjectType); if (!string.IsNullOrEmpty(applicableOccurrence)) { IFCAnyHandleUtil.SetAttribute(styleHandle, "ApplicableOccurrence", applicableOccurrence); } currentTypeInfo.Style = styleHandle; ExporterCacheManager.TypeObjectsCache.Register(typeId, false, exportType, currentTypeInfo); } } else { styleHandle = currentTypeInfo.Style; } } string instanceGUID = GUIDUtil.CreateGUID(element); bool roomRelated = !FamilyExporterUtil.IsDistributionFlowElementSubType(exportType); ElementId roomId = ElementId.InvalidElementId; if (roomRelated) { roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); } IFCAnyHandle instanceHandle = null; // For MEP objects string exportEntityStr = exportType.ToString(); Common.Enums.IFCEntityType exportEntity; if (String.Compare(exportEntityStr.Substring(exportEntityStr.Length - 4), "Type", true) == 0) { exportEntityStr = exportEntityStr.Substring(0, (exportEntityStr.Length - 4)); } if (Enum.TryParse(exportEntityStr, out exportEntity)) { // For MEP object creation instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(exportEntity, exporterIFC, element, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation); } if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { return; } if (roomId != ElementId.InvalidElementId) { //exporterIFC.RelateSpatialElement(roomId, instanceHandle); ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle); productWrapper.AddElement(element, instanceHandle, setter, extraParams, false); } else { productWrapper.AddElement(element, instanceHandle, setter, extraParams, true); } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, element, extraParams, null, exporterIFC, localPlacementToUse, setter, productWrapper); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle)) { ExporterCacheManager.TypeRelationsCache.Add(styleHandle, instanceHandle); } PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, productWrapper.GetAllObjects()); ExporterCacheManager.MEPCache.Register(element, instanceHandle); // add to system export cache // SystemExporter.ExportSystem(exporterIFC, element, instanceHandle); }
/// <summary> /// Exports a family instance as a mapped item. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="familyInstance">The family instance to be exported.</param> /// <param name="exportType">The export type.</param> /// <param name="ifcEnumType">The string value represents the IFC type.</param> /// <param name="wrapper">The ProductWrapper.</param> /// <param name="overrideLevelId">The level id.</param> /// <param name="range">The range of this family instance to be exported.</param> public static void ExportFamilyInstanceAsMappedItem(ExporterIFC exporterIFC, FamilyInstance familyInstance, IFCExportType exportType, string ifcEnumType, ProductWrapper wrapper, ElementId overrideLevelId, IFCRange range, IFCAnyHandle parentLocalPlacement) { bool exportParts = PartExporter.CanExportParts(familyInstance); bool isSplit = range != null; if (exportParts && !PartExporter.CanExportElementInPartExport(familyInstance, isSplit ? overrideLevelId : familyInstance.LevelId, isSplit)) return; Document doc = familyInstance.Document; IFCFile file = exporterIFC.GetFile(); // The "originalFamilySymbol" has the right geometry, but should be used as little as possible. FamilySymbol originalFamilySymbol = ExporterIFCUtils.GetOriginalSymbol(familyInstance); FamilySymbol familySymbol = familyInstance.Symbol; if (originalFamilySymbol == null || familySymbol == null) return; ProductWrapper familyProductWrapper = ProductWrapper.Create(wrapper); Options options = GeometryUtil.GetIFCExportGeometryOptions(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); HostObject hostElement = familyInstance.Host as HostObject; //hostElement could be null ElementId categoryId = CategoryUtil.GetSafeCategoryId(familySymbol); //string emptyString = ""; string familyName = familySymbol.Name; string revitObjectType = familyName; // A Family Instance can have its own copy of geometry, or use the symbol's copy with a transform. // The routine below tells us whether to use the Instance's copy or the Symbol's copy. bool useInstanceGeometry = ExporterIFCUtils.UsesInstanceGeometry(familyInstance); Transform trf = familyInstance.GetTransform(); using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { // Extra information if we are exporting a door or a window. DoorWindowInfo doorWindowInfo = null; if (exportType == IFCExportType.IfcDoorType) doorWindowInfo = DoorWindowExporter.CreateDoor(exporterIFC, familyInstance, hostElement, overrideLevelId, trf); else if (exportType == IFCExportType.IfcWindowType) doorWindowInfo = DoorWindowExporter.CreateWindow(exporterIFC, familyInstance, hostElement, overrideLevelId, trf); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); bool flipped = doorWindowInfo != null ? doorWindowInfo.FlippedSymbol : false; FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(originalFamilySymbol.Id, flipped); bool found = currentTypeInfo.IsValid(); Family family = familySymbol.Family; IList<GeometryObject> geomObjects = new List<GeometryObject>(); Transform offsetTransform = null; Transform doorWindowTrf = Transform.Identity; // We will create a new mapped type if: // 1. We are exporting part of a column or in-place wall (range != null), OR // 2. We are using the instance's copy of the geometry (that it, it has unique geometry), OR // 3. We haven't already created the type. bool creatingType = ((range != null) || useInstanceGeometry || !found); if (creatingType) { IFCAnyHandle bodyRepresentation = null; IFCAnyHandle planRepresentation = null; IFCAnyHandle dummyPlacement = null; if (doorWindowInfo != null) { doorWindowTrf = ExporterIFCUtils.GetTransformForDoorOrWindow(familyInstance, originalFamilySymbol, doorWindowInfo.FlippedX, doorWindowInfo.FlippedY); } else { dummyPlacement = ExporterUtil.CreateLocalPlacement(file, null, null); extraParams.SetLocalPlacement(dummyPlacement); } bool needToCreate2d = ExporterCacheManager.ExportOptionsCache.ExportAnnotations; GeometryElement exportGeometry = useInstanceGeometry ? familyInstance.get_Geometry(options) : originalFamilySymbol.get_Geometry(options); if (!exportParts) { using (TransformSetter trfSetter = TransformSetter.Create()) { if (doorWindowInfo != null) { trfSetter.Initialize(exporterIFC, doorWindowTrf); } if (exportGeometry == null) return; SolidMeshGeometryInfo solidMeshCapsule = null; if (range == null) { solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(exportGeometry); } else { solidMeshCapsule = GeometryUtil.GetSplitClippedSolidMeshGeometry(exportGeometry, range); } IList<Solid> solids = solidMeshCapsule.GetSolids(); IList<Mesh> polyMeshes = solidMeshCapsule.GetMeshes(); // If we are exporting parts, it is OK to have no geometry here - it will be added by the host Part. bool hasSolidsOrMeshesInSymbol = (solids.Count > 0 || polyMeshes.Count > 0); if (range != null && !hasSolidsOrMeshesInSymbol) return; // no proper split geometry to export. if (hasSolidsOrMeshesInSymbol) { geomObjects = FamilyExporterUtil.RemoveSolidsAndMeshesSetToDontExport(doc, exporterIFC, solids, polyMeshes); if ((geomObjects.Count == 0)) return; // no proper visible split geometry to export. } else geomObjects.Add(exportGeometry); bool tryToExportAsExtrusion = (!ExporterCacheManager.ExportOptionsCache.ExportAs2x2 || (exportType == IFCExportType.IfcColumnType)); if (exportType == IFCExportType.IfcColumnType) { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; if (ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2 && solids.Count > 0) { LocationPoint point = familyInstance.Location as LocationPoint; XYZ orig = XYZ.Zero; if (point != null) orig = point.Point; Plane plane = new Plane(XYZ.BasisX, XYZ.BasisY, orig); bool completelyClipped = false; HashSet<ElementId> materialIds = null; bodyRepresentation = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, familyInstance, categoryId, solids, plane, XYZ.BasisZ, null, out completelyClipped, out materialIds); typeInfo.MaterialIds = materialIds; } } else { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryXYZ; } BodyData bodyData = null; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation)) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(tryToExportAsExtrusion); bodyData = BodyExporter.ExportBody(exporterIFC, familyInstance, categoryId, ElementId.InvalidElementId, geomObjects, bodyExporterOptions, extraParams); typeInfo.MaterialIds = bodyData.MaterialIds; bodyRepresentation = bodyData.RepresentationHnd; offsetTransform = bodyData.OffsetTransform; } // We will allow a door or window to be exported without any geometry, or an element with parts. // Anything else doesn't really make sense. if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation) && (doorWindowInfo == null)) { extraParams.ClearOpenings(); return; } } // By default: if exporting IFC2x3 or later, export 2D plan rep of family, if it exists, unless we are exporting Coordination View V2. // This default can be overridden in the export options. if (needToCreate2d) { XYZ curveOffset = new XYZ(0, 0, 0); if (offsetTransform != null) curveOffset = -UnitUtil.UnscaleLength(offsetTransform.Origin); HashSet<IFCAnyHandle> curveSet = new HashSet<IFCAnyHandle>(); { Transform planeTrf = doorWindowTrf.Inverse; Plane plane = new Plane(planeTrf.get_Basis(0), planeTrf.get_Basis(1), planeTrf.Origin); XYZ projDir = new XYZ(0, 0, 1); IFCGeometryInfo IFCGeometryInfo = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, true); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, IFCGeometryInfo, exportGeometry, curveOffset, false); IList<IFCAnyHandle> curves = IFCGeometryInfo.GetCurves(); foreach (IFCAnyHandle curve in curves) curveSet.Add(curve); if (curveSet.Count > 0) { IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle(); IFCAnyHandle curveRepresentationItem = IFCInstanceExporter.CreateGeometricSet(file, curveSet); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(curveRepresentationItem); planRepresentation = RepresentationUtil.CreateGeometricSetRep(exporterIFC, familyInstance, categoryId, "FootPrint", contextOfItems2d, bodyItems); } } } } if (doorWindowInfo != null) typeInfo.StyleTransform = doorWindowTrf.Inverse; else typeInfo.StyleTransform = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, extraParams.GetLocalPlacement()); // for many HashSet<IFCAnyHandle> propertySets = null; IFCAnyHandle typeStyle = CreateFamilyTypeHandle(exporterIFC, typeInfo, doorWindowInfo, bodyRepresentation, planRepresentation, familyInstance, familySymbol, originalFamilySymbol, useInstanceGeometry, exportParts, exportType, revitObjectType, ifcEnumType, out propertySets); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle)) { wrapper.RegisterHandleWithElementType(familySymbol, typeStyle, propertySets); CategoryUtil.CreateMaterialAssociations(exporterIFC, typeStyle, typeInfo.MaterialIds); typeInfo.Style = typeStyle; if ((exportType == IFCExportType.IfcColumnType) || (exportType == IFCExportType.IfcMemberType)) { typeInfo.ScaledArea = extraParams.ScaledArea; typeInfo.ScaledDepth = extraParams.ScaledLength; typeInfo.ScaledInnerPerimeter = extraParams.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extraParams.ScaledOuterPerimeter; } ClassificationUtil.CreateClassification(exporterIFC, file, familySymbol, typeStyle); // Create other generic classification from ClassificationCode(s) ClassificationUtil.CreateUniformatClassification(exporterIFC, file, originalFamilySymbol, typeStyle); } } if (found && !typeInfo.IsValid()) typeInfo = currentTypeInfo; // we'll pretend we succeeded, but we'll do nothing. if (!typeInfo.IsValid()) return; // add to the map, as long as we are not using range, not using instance geometry, and don't have extra openings. if ((range == null) && !useInstanceGeometry && (extraParams.GetOpenings().Count == 0)) ExporterCacheManager.TypeObjectsCache.Register(originalFamilySymbol.Id, flipped, typeInfo); // If we are using the instance geometry, ignore the transformation. if (useInstanceGeometry) trf = Transform.Identity; if ((range != null) && exportParts) { XYZ rangeOffset = trf.Origin; rangeOffset += new XYZ(0, 0, range.Start); trf.Origin = rangeOffset; } Transform originalTrf = new Transform(trf); XYZ scaledMapOrigin = XYZ.Zero; trf = trf.Multiply(typeInfo.StyleTransform); // create instance. IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); { IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle(); IFCAnyHandle contextOfItems3d = exporterIFC.Get3DContextHandle("Body"); // for proxies, we store the IfcRepresentationMap directly since there is no style. IFCAnyHandle style = typeInfo.Style; IList<IFCAnyHandle> repMapList = !IFCAnyHandleUtil.IsNullOrHasNoValue(style) ? GeometryUtil.GetRepresentationMaps(style) : null; int numReps = repMapList != null ? repMapList.Count : 0; IFCAnyHandle repMap2dHnd = typeInfo.Map2DHandle; IFCAnyHandle repMap3dHnd = typeInfo.Map3DHandle; if (IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd) && (numReps > 0)) repMap3dHnd = repMapList[0]; if (IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd) && (numReps > 1)) repMap2dHnd = repMapList[1]; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd)) { ISet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>(); representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap3dHnd, scaledMapOrigin)); IFCAnyHandle shapeRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, familyInstance, categoryId, contextOfItems3d, representations); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return; shapeReps.Add(shapeRep); } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd)) { HashSet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>(); representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap2dHnd, scaledMapOrigin)); IFCAnyHandle shapeRep = RepresentationUtil.CreatePlanMappedItemRep(exporterIFC, familyInstance, categoryId, contextOfItems2d, representations); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return; shapeReps.Add(shapeRep); } } IFCAnyHandle boundingBoxRep = null; Transform boundingBoxTrf = (offsetTransform != null) ? offsetTransform.Inverse : Transform.Identity; if (geomObjects.Count > 0) boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomObjects, boundingBoxTrf); else { boundingBoxTrf = boundingBoxTrf.Multiply(trf.Inverse); boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, familyInstance.get_Geometry(options), 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, familyInstance, trf, null, overrideLevelId)) { IFCAnyHandle instanceHandle = null; IFCAnyHandle localPlacement = setter.LocalPlacement; // We won't create the instance if: // (1) we are exporting to CV2.0, (2) we have no 2D, 3D, or bounding box geometry, and (3) we aren't exporting parts. if (!(repHnd == null && ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2 && !exportParts)) { string instanceGUID = null; int subElementIndex = ExporterStateManager.GetCurrentRangeIndex(); if (subElementIndex == 0) instanceGUID = GUIDUtil.CreateGUID(familyInstance); else if (subElementIndex <= ExporterStateManager.RangeIndexSetter.GetMaxStableGUIDs()) instanceGUID = GUIDUtil.CreateSubElementGUID(familyInstance, subElementIndex + (int)IFCGenericSubElements.SplitInstanceStart - 1); else instanceGUID = GUIDUtil.CreateGUID(); string instanceName = NamingUtil.GetNameOverride(familyInstance, NamingUtil.GetIFCName(familyInstance)); string instanceDescription = NamingUtil.GetDescriptionOverride(familyInstance, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(familyInstance, revitObjectType); string instanceTag = NamingUtil.GetTagOverride(familyInstance, NamingUtil.CreateIFCElementId(familyInstance)); IFCAnyHandle overrideLocalPlacement = null; bool isChildInContainer = familyInstance.AssemblyInstanceId != ElementId.InvalidElementId; if (parentLocalPlacement != null) { Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(parentLocalPlacement, localPlacement); Transform inverseTrf = relTrf.Inverse; IFCAnyHandle plateLocalPlacement = ExporterUtil.CreateLocalPlacement(file, parentLocalPlacement, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX); overrideLocalPlacement = plateLocalPlacement; } instanceHandle = FamilyExporterUtil.ExportGenericInstance(exportType, exporterIFC, familyInstance, wrapper, setter, extraParams, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, exportParts ? null : repHnd, instanceTag, overrideLocalPlacement); if (exportParts) PartExporter.ExportHostPart(exporterIFC, familyInstance, instanceHandle, familyProductWrapper, setter, setter.LocalPlacement, overrideLevelId); if (ElementFilteringUtil.IsMEPType(exportType) || ElementFilteringUtil.ProxyForMEPType(familyInstance, exportType)) { ExporterCacheManager.MEPCache.Register(familyInstance, instanceHandle); // For ducts and pipes, check later if there is an associated duct or pipe. if (exportType == IFCExportType.IfcDuctFittingType || exportType == IFCExportType.IfcPipeFittingType || exportType == IFCExportType.IfcDuctSegmentType || exportType == IFCExportType.IfcPipeSegmentType) ExporterCacheManager.MEPCache.CoveredElementsCache.Add(familyInstance.Id); } switch (exportType) { case IFCExportType.IfcColumnType: { IFCAnyHandle placementToUse = localPlacement; if (!useInstanceGeometry) { bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams); if (needToCreateOpenings) { Transform openingTrf = new Transform(originalTrf); Transform extraRot = new Transform(originalTrf); extraRot.Origin = XYZ.Zero; openingTrf = openingTrf.Multiply(extraRot); openingTrf = openingTrf.Multiply(typeInfo.StyleTransform); XYZ scaledOrigin = UnitUtil.ScaleLength(openingTrf.Origin); IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, scaledOrigin, openingTrf.get_Basis(2), openingTrf.get_Basis(0)); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement); GeometryUtil.SetRelativePlacement(openingPlacement, openingRelativePlacement); placementToUse = openingPlacement; } } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform, exporterIFC, placementToUse, setter, wrapper); //export Base Quantities. PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo, geomObjects); break; } case IFCExportType.IfcDoorType: case IFCExportType.IfcWindowType: { double doorHeight = GetMinSymbolHeight(originalFamilySymbol); double doorWidth = GetMinSymbolWidth(originalFamilySymbol); double height = UnitUtil.ScaleLength(doorHeight); double width = UnitUtil.ScaleLength(doorWidth); IFCAnyHandle doorWindowLocalPlacement = !IFCAnyHandleUtil.IsNullOrHasNoValue(overrideLocalPlacement) ? overrideLocalPlacement : localPlacement; if (exportType == IFCExportType.IfcDoorType) instanceHandle = IFCInstanceExporter.CreateDoor(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, repHnd, instanceTag, height, width, doorWindowInfo.PreDefinedType,doorWindowInfo.DoorOperationTypeString, doorWindowInfo.UserDefinedOperationType); else if (exportType == IFCExportType.IfcWindowType) instanceHandle = IFCInstanceExporter.CreateWindow(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, repHnd, instanceTag, height, width, doorWindowInfo.PreDefinedType, DoorWindowUtil.GetIFCWindowPartitioningType(originalFamilySymbol), doorWindowInfo.UserDefinedPartitioningType); wrapper.AddElement(familyInstance, instanceHandle, setter, extraParams, true); SpaceBoundingElementUtil.RegisterSpaceBoundingElementHandle(exporterIFC, instanceHandle, familyInstance.Id, setter.LevelId); IFCAnyHandle placementToUse = doorWindowLocalPlacement; if (!useInstanceGeometry) { // correct the placement to the symbol space bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams); if (needToCreateOpenings) { Transform openingTrf = Transform.Identity; openingTrf.Origin = new XYZ(0, 0, setter.Offset); openingTrf = openingTrf.Multiply(doorWindowTrf); XYZ scaledOrigin = UnitUtil.ScaleLength(openingTrf.Origin); IFCAnyHandle openingLocalPlacement = ExporterUtil.CreateLocalPlacement(file, doorWindowLocalPlacement, scaledOrigin, openingTrf.BasisZ, openingTrf.BasisX); placementToUse = openingLocalPlacement; } } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform, exporterIFC, placementToUse, setter, wrapper); break; } case IFCExportType.IfcMemberType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform, exporterIFC, localPlacement, setter, wrapper); //export Base Quantities. PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo, null); break; } case IFCExportType.IfcPlateType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform, exporterIFC, localPlacement, setter, wrapper); break; } case IFCExportType.IfcTransportElementType: { IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); string operationTypeStr; if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { // It is PreDefinedType attribute in IFC4 Toolkit.IFC4.IFCTransportElementType operationType = FamilyExporterUtil.GetPreDefinedType<Toolkit.IFC4.IFCTransportElementType>(familyInstance, ifcEnumType); operationTypeStr = operationType.ToString(); } else { Toolkit.IFCTransportElementType operationType = FamilyExporterUtil.GetPreDefinedType<Toolkit.IFCTransportElementType>(familyInstance, ifcEnumType); operationTypeStr = operationType.ToString(); } double capacityByWeight = 0.0; ParameterUtil.GetDoubleValueFromElementOrSymbol(familyInstance, "IfcCapacityByWeight", out capacityByWeight); double capacityByNumber = 0.0; ParameterUtil.GetDoubleValueFromElementOrSymbol(familyInstance, "IfcCapacityByNumber", out capacityByNumber); instanceHandle = IFCInstanceExporter.CreateTransportElement(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, repHnd, instanceTag, operationTypeStr, capacityByWeight, capacityByNumber); bool containedInSpace = (roomId != ElementId.InvalidElementId); wrapper.AddElement(familyInstance, instanceHandle, setter, extraParams, !containedInSpace); if (containedInSpace) ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle); break; } //case IFCExportType.IfcBuildingElementProxy: //case IFCExportType.IfcBuildingElementProxyType: default: { if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { bool isBuildingElementProxy = ((exportType == IFCExportType.IfcBuildingElementProxy) || (exportType == IFCExportType.IfcBuildingElementProxyType)); IFCAnyHandle localPlacementToUse = null; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); if (!isBuildingElementProxy && FamilyExporterUtil.IsDistributionControlElementSubType(exportType)) { string ifcelementType = null; ParameterUtil.GetStringValueFromElement(familyInstance.Id, "IfcElementType", out ifcelementType); instanceHandle = IFCInstanceExporter.CreateDistributionControlElement(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, repHnd, instanceTag, ifcelementType); } else { instanceHandle = IFCInstanceExporter.CreateBuildingElementProxy(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, repHnd, instanceTag, null); } bool containedInSpace = (roomId != ElementId.InvalidElementId); bool associateToLevel = containedInSpace ? false : !isChildInContainer; wrapper.AddElement(familyInstance, instanceHandle, setter, extraParams, associateToLevel); if (containedInSpace) ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle); } IFCAnyHandle placementToUse = localPlacement; if (!useInstanceGeometry) { bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams); if (needToCreateOpenings) { Transform openingTrf = new Transform(originalTrf); Transform extraRot = new Transform(originalTrf); extraRot.Origin = XYZ.Zero; openingTrf = openingTrf.Multiply(extraRot); openingTrf = openingTrf.Multiply(typeInfo.StyleTransform); XYZ scaledOrigin = UnitUtil.ScaleLength(openingTrf.Origin); IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, scaledOrigin, openingTrf.get_Basis(2), openingTrf.get_Basis(0)); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement); GeometryUtil.SetRelativePlacement(openingPlacement, openingRelativePlacement); placementToUse = openingPlacement; } } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform, exporterIFC, placementToUse, setter, wrapper); break; } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { ExporterCacheManager.HandleToElementCache.Register(instanceHandle, familyInstance.Id); if (!exportParts) CategoryUtil.CreateMaterialAssociations(exporterIFC, instanceHandle, typeInfo.MaterialIds); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeInfo.Style)) ExporterCacheManager.TypeRelationsCache.Add(typeInfo.Style, instanceHandle); } } if (doorWindowInfo != null) { DoorWindowDelayedOpeningCreator delayedCreator = DoorWindowDelayedOpeningCreator.Create(exporterIFC, doorWindowInfo, instanceHandle, setter.LevelId); if (delayedCreator != null) ExporterCacheManager.DoorWindowDelayedOpeningCreatorCache.Add(delayedCreator); } } } }
/// <summary> /// Exports a MEP family instance. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="exportType">The export type of the element. /// <param name="ifcEnumType">The sub-type of the element.</param></param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>True if an entity was created, false otherwise.</returns> public static bool Export(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCExportType exportType, string ifcEnumType, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { IFCAnyHandle localPlacementToUse = setter.LocalPlacement; using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { extraParams.SetLocalPlacement(localPlacementToUse); ElementId catId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); BodyData bodyData = null; IFCAnyHandle productRepresentation = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, catId, geometryElement, bodyExporterOptions, null, extraParams, out bodyData); if (IFCAnyHandleUtil.IsNullOrHasNoValue(productRepresentation)) { extraParams.ClearOpenings(); return(false); } IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); ElementId typeId = element.GetTypeId(); ElementType type = element.Document.GetElement(typeId) as ElementType; FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(typeId, false); bool found = currentTypeInfo.IsValid(); if (!found) { string typeGUID = GUIDUtil.CreateGUID(type); string typeName = NamingUtil.GetNameOverride(type, NamingUtil.GetIFCName(type)); string typeObjectType = NamingUtil.GetObjectTypeOverride(type, NamingUtil.CreateIFCObjectName(exporterIFC, type)); string applicableOccurence = NamingUtil.GetOverrideStringValue(type, "IfcApplicableOccurrence", typeObjectType); string typeDescription = NamingUtil.GetDescriptionOverride(type, null); string typeTag = NamingUtil.GetTagOverride(type, NamingUtil.CreateIFCElementId(type)); string typeElementType = NamingUtil.GetOverrideStringValue(type, "IfcElementType", typeName); IList <IFCAnyHandle> repMapListOpt = new List <IFCAnyHandle>(); IFCAnyHandle styleHandle = FamilyExporterUtil.ExportGenericType(exporterIFC, exportType, ifcEnumType, typeGUID, typeName, typeDescription, applicableOccurence, null, repMapListOpt, typeTag, typeElementType, element, type); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle)) { productWrapper.RegisterHandleWithElementType(type, styleHandle, null); currentTypeInfo.Style = styleHandle; ExporterCacheManager.TypeObjectsCache.Register(typeId, false, currentTypeInfo); } } string instanceGUID = GUIDUtil.CreateGUID(element); string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); bool roomRelated = !FamilyExporterUtil.IsDistributionFlowElementSubType(exportType); ElementId roomId = ElementId.InvalidElementId; if (roomRelated) { roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); } IFCAnyHandle instanceHandle = null; // For MEP objects string exportEntityStr = exportType.ToString(); Common.Enums.IFCEntityType exportEntity; if (String.Compare(exportEntityStr.Substring(exportEntityStr.Length - 4), "Type", true) == 0) { exportEntityStr = exportEntityStr.Substring(0, (exportEntityStr.Length - 4)); } if (Enum.TryParse(exportEntityStr, out exportEntity)) { // For MEP object creation instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(exportEntity, file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { return(false); } bool relatedToSpace = (roomId != ElementId.InvalidElementId); productWrapper.AddElement(element, instanceHandle, setter, extraParams, !relatedToSpace); if (relatedToSpace) { ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle); } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, element, extraParams, null, exporterIFC, localPlacementToUse, setter, productWrapper); if (currentTypeInfo.IsValid()) { ExporterCacheManager.TypeRelationsCache.Add(currentTypeInfo.Style, instanceHandle); } if (bodyData != null && bodyData.MaterialIds.Count != 0) { CategoryUtil.CreateMaterialAssociations(exporterIFC, instanceHandle, bodyData.MaterialIds); } ExporterCacheManager.MEPCache.Register(element, instanceHandle); tr.Commit(); } } } return(true); }
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); }