static public void RegisterSpaceBoundingElementHandle(ExporterIFC exporterIFC, IFCAnyHandle elemHnd, ElementId elementId, ElementId levelId) { int idx; if (!ExporterCacheManager.HostObjectsLevelIndex.TryGetValue(levelId, out idx)) { int nextIndex = ExporterCacheManager.HostObjectsLevelIndex.Count; ExporterCacheManager.HostObjectsLevelIndex.Add(levelId, nextIndex); } exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, elementId, levelId); }
/// <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.Level.Id, isSplit)) return; Document doc = familyInstance.Document; IFCFile file = exporterIFC.GetFile(); FamilySymbol familySymbol = ExporterIFCUtils.GetOriginalSymbol(familyInstance); if (familySymbol == null) return; ProductWrapper familyProductWrapper = ProductWrapper.Create(wrapper); double scale = exporterIFC.LinearScale; 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 objectType = 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); IList<IFCExtrusionData> cutPairOpeningsForColumns = new List<IFCExtrusionData>(); using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { Transform trf = familyInstance.GetTransform(); // Extra information if we are exporting a door or a window. IFCDoorWindowInfo doorWindowInfo = null; if (exportType == IFCExportType.ExportDoorType) doorWindowInfo = IFCDoorWindowInfo.CreateDoorInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf); else if (exportType == IFCExportType.ExportWindowType) doorWindowInfo = IFCDoorWindowInfo.CreateWindowInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); XYZ extraOffset = XYZ.Zero; bool flipped = doorWindowInfo != null ? doorWindowInfo.IsSymbolFlipped : false; FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(familySymbol.Id, flipped); bool found = currentTypeInfo.IsValid(); Family family = familySymbol.Family; // TODO: this code to be removed by ExtrusionAnalyzer code. bool trySpecialColumnCreation = ((exportType == IFCExportType.ExportColumnType) && (!family.IsInPlace)); IList<GeometryObject> geomObjects = new List<GeometryObject>(); Transform brepOffsetTransform = 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; // If we are using the instance geometry, ignore the transformation. if (useInstanceGeometry) trf = Transform.Identity; // TODO: this code to be removed by ExtrusionAnalyzer code. if (trySpecialColumnCreation) { XYZ rangeOffset = trf.Origin; IFCFamilyInstanceExtrusionExportResults results; results = ExporterIFCUtils.ExportFamilyInstanceAsExtrusion(exporterIFC, familyInstance, useInstanceGeometry, range, overrideLevelId, extraParams); bodyRepresentation = results.GetExtrusionHandle(); extraOffset = results.ExtraOffset; cutPairOpeningsForColumns = results.GetCutPairOpenings(); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation)) { typeInfo.MaterialIds.Add(results.MaterialId); // add in level for real columns, not in-place ones. Element actualLevel = (overrideLevelId == ElementId.InvalidElementId) ? familyInstance.Level : doc.GetElement(overrideLevelId); if (actualLevel != null) { IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(actualLevel.Id); double nonStoryLevelOffset = LevelUtil.GetNonStoryLevelOffsetIfAny(exporterIFC, actualLevel as Level); if (range != null) { rangeOffset = new XYZ(rangeOffset.X, rangeOffset.Y, levelInfo.Elevation + nonStoryLevelOffset); } } } rangeOffset += extraOffset; trf.Origin = rangeOffset; } IFCAnyHandle dummyPlacement = null; if (doorWindowInfo != null) { doorWindowTrf = ExporterIFCUtils.GetTransformForDoorOrWindow(familyInstance, familySymbol, doorWindowInfo); } else { dummyPlacement = IFCInstanceExporter.CreateLocalPlacement(file, null, ExporterUtil.CreateAxis2Placement3D(file)); extraParams.SetLocalPlacement(dummyPlacement); } bool needToCreate2d = ExporterCacheManager.ExportOptionsCache.ExportAnnotations; bool needToCreate3d = IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation); if (needToCreate2d || needToCreate3d) { using (IFCTransformSetter trfSetter = IFCTransformSetter.Create()) { if (doorWindowInfo != null) { trfSetter.Initialize(exporterIFC, doorWindowTrf); } GeometryElement exportGeometry = useInstanceGeometry ? familyInstance.get_Geometry(options) : familySymbol.get_Geometry(options); if (exportGeometry == null) return; if (needToCreate3d) { SolidMeshGeometryInfo solidMeshCapsule = null; if (range == null) { solidMeshCapsule = GeometryUtil.GetSolidMeshGeometry(exportGeometry, Transform.Identity); } else { solidMeshCapsule = GeometryUtil.GetClippedSolidMeshGeometry(exportGeometry, range); } IList<Solid> solids = solidMeshCapsule.GetSolids(); IList<Mesh> polyMeshes = solidMeshCapsule.GetMeshes(); if (range != null && (solids.Count == 0 && polyMeshes.Count == 0)) return; // no proper split geometry geomObjects = FamilyExporterUtil.RemoveSolidsAndMeshesSetToDontExport(doc, exporterIFC, solids, polyMeshes); if (geomObjects.Count == 0 && (solids.Count > 0 || polyMeshes.Count > 0)) return; bool tryToExportAsExtrusion = (!exporterIFC.ExportAs2x2 || (exportType == IFCExportType.ExportColumnType)); if (exportType == IFCExportType.ExportColumnType) { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; if (ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 && 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); if (geomObjects.Count > 0) { bodyData = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, familyInstance, categoryId, ElementId.InvalidElementId, geomObjects, bodyExporterOptions, extraParams); typeInfo.MaterialIds = bodyData.MaterialIds; } else { IList<GeometryObject> exportedGeometries = new List<GeometryObject>(); exportedGeometries.Add(exportGeometry); bodyData = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, familyInstance, categoryId, ElementId.InvalidElementId, exportedGeometries, bodyExporterOptions, extraParams); } bodyRepresentation = bodyData.RepresentationHnd; brepOffsetTransform = bodyData.BrepOffsetTransform; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation)) { 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 (brepOffsetTransform != null) curveOffset = -brepOffsetTransform.Origin / scale; 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, "Annotation", contextOfItems2d, bodyItems); } } } } } if (doorWindowInfo != null) { typeInfo.StyleTransform = doorWindowTrf.Inverse; } else { if (!MathUtil.IsAlmostZero(extraOffset.DotProduct(extraOffset))) { Transform newTransform = typeInfo.StyleTransform; XYZ newOrig = newTransform.Origin + extraOffset; newTransform.Origin = newOrig; typeInfo.StyleTransform = newTransform; } typeInfo.StyleTransform = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, extraParams.GetLocalPlacement()); } IFCAnyHandle origin = ExporterUtil.CreateAxis2Placement3D(file); IFCAnyHandle repMap2dHnd = null; IFCAnyHandle repMap3dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyRepresentation); IList<IFCAnyHandle> repMapList = new List<IFCAnyHandle>(); repMapList.Add(repMap3dHnd); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(planRepresentation)) { repMap2dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, planRepresentation); repMapList.Add(repMap2dHnd); } // for Door, Window bool paramTakesPrecedence = false; // For Revit, this is currently always false. bool sizeable = false; // for many HashSet<IFCAnyHandle> propertySets = new HashSet<IFCAnyHandle>(); string guid = GUIDUtil.CreateGUID(familySymbol); string symId = NamingUtil.CreateIFCElementId(familySymbol); // This covers many generic types. If we can't find it in the list here, do custom exports. IFCAnyHandle typeStyle = FamilyExporterUtil.ExportGenericType(file, exportType, ifcEnumType, guid, ownerHistory, objectType, null, null, propertySets, repMapList, symId, objectType, familyInstance, familySymbol); // Cover special cases not covered above. if (IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle)) { switch (exportType) { case IFCExportType.ExportColumnType: { // If we are using the instance GRep, then we have to create a generic GUID for the // column type, as they share the same ElementId. string colGUID = null; string colElemId = null; if (useInstanceGeometry) colGUID = GUIDUtil.CreateGUID(); else colGUID = guid; colElemId = NamingUtil.CreateIFCElementId(familySymbol); string columnType = "Column"; typeStyle = IFCInstanceExporter.CreateColumnType(file, colGUID, ownerHistory, objectType, null, null, propertySets, repMapList, colElemId, objectType, GetColumnType(familyInstance, columnType)); break; } case IFCExportType.ExportDoorType: { string constructionType = string.Empty; ParameterUtil.GetStringValueFromElementOrSymbol(familyInstance, "Construction", out constructionType); IFCAnyHandle doorLining = DoorWindowUtil.CreateDoorLiningProperties(exporterIFC, familyInstance); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(doorLining)) propertySets.Add(doorLining); IList<IFCAnyHandle> doorPanels = DoorWindowUtil.CreateDoorPanelProperties(exporterIFC, doorWindowInfo, familyInstance); propertySets.UnionWith(doorPanels); string doorStyleGUID = GUIDUtil.CreateGUID(); string doorStyleElemId = NamingUtil.CreateIFCElementId(familySymbol); typeStyle = IFCInstanceExporter.CreateDoorStyle(file, doorStyleGUID, ownerHistory, objectType, null, null, propertySets, repMapList, doorStyleElemId, GetDoorStyleOperation(doorWindowInfo.DoorOperationType), GetDoorStyleConstruction(familyInstance, constructionType), paramTakesPrecedence, sizeable); break; } case IFCExportType.ExportSystemFurnitureElementType: { string furnitureId = NamingUtil.CreateIFCElementId(familySymbol); typeStyle = IFCInstanceExporter.CreateSystemFurnitureElementType(file, guid, ownerHistory, objectType, null, null, propertySets, repMapList, furnitureId, objectType); break; } case IFCExportType.ExportWindowType: { Toolkit.IFCWindowStyleOperation operationType = DoorWindowUtil.GetIFCWindowStyleOperation(familySymbol); IFCWindowStyleConstruction constructionType = DoorWindowUtil.GetIFCWindowStyleConstruction(familyInstance, ""); IFCAnyHandle windowLining = DoorWindowUtil.CreateWindowLiningProperties(exporterIFC, familyInstance, null); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(windowLining)) propertySets.Add(windowLining); IList<IFCAnyHandle> windowPanels = DoorWindowUtil.CreateWindowPanelProperties(exporterIFC, familyInstance, null); propertySets.UnionWith(windowPanels); string windowStyleGUID = GUIDUtil.CreateGUID(); string windowStyleElemId = NamingUtil.CreateIFCElementId(familySymbol); typeStyle = IFCInstanceExporter.CreateWindowStyle(file, windowStyleGUID, ownerHistory, objectType, null, null, propertySets, repMapList, windowStyleElemId, constructionType, operationType, paramTakesPrecedence, sizeable); break; } case IFCExportType.ExportBuildingElementProxy: default: { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd)) typeInfo.Map2DHandle = repMap2dHnd; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd)) typeInfo.Map3DHandle = repMap3dHnd; break; } } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle)) { CategoryUtil.CreateMaterialAssociations(doc, exporterIFC, typeStyle, typeInfo.MaterialIds); typeInfo.Style = typeStyle; if (((exportType == IFCExportType.ExportColumnType) && trySpecialColumnCreation) || (exportType == IFCExportType.ExportMemberType)) { typeInfo.ScaledArea = extraParams.ScaledArea; typeInfo.ScaledDepth = extraParams.ScaledLength; typeInfo.ScaledInnerPerimeter = extraParams.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extraParams.ScaledOuterPerimeter; } ClassificationUtil.CreateUniformatClassification(exporterIFC, file, familySymbol, typeStyle); } } else if (!creatingType && (trySpecialColumnCreation)) { // still need to modify instance trf for columns. trf.Origin += GetLevelOffsetForExtrudedColumns(exporterIFC, familyInstance, overrideLevelId, extraParams); } 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(familySymbol.Id, flipped, typeInfo); Transform oldTrf = 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)) { IList<IFCAnyHandle> representations = new List<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 = (brepOffsetTransform != null) ? brepOffsetTransform.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 rep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle instanceHandle = null; using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, familyInstance, trf, null, overrideLevelId)) { string instanceGUID = GUIDUtil.CreateGUID(familyInstance); string instanceName = NamingUtil.GetIFCName(familyInstance); string instanceDescription = NamingUtil.GetDescriptionOverride(familyInstance, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(familyInstance, objectType); string instanceElemId = NamingUtil.CreateIFCElementId(familyInstance); IFCAnyHandle localPlacement = setter.GetPlacement(); IFCAnyHandle overrideLocalPlacement = null; if (parentLocalPlacement != null) { Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(parentLocalPlacement, localPlacement); Transform inverseTrf = relTrf.Inverse; IFCAnyHandle relativePlacement = ExporterUtil.CreateAxis2Placement3D(file, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX); IFCAnyHandle plateLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, parentLocalPlacement, relativePlacement); overrideLocalPlacement = plateLocalPlacement; } instanceHandle = FamilyExporterUtil.ExportGenericInstance(exportType, exporterIFC, familyInstance, wrapper, setter, extraParams, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, exportParts ? null : rep, instanceElemId, overrideLocalPlacement); if (exportParts) { PartExporter.ExportHostPart(exporterIFC, familyInstance, instanceHandle, familyProductWrapper, setter, setter.GetPlacement(), overrideLevelId); } if (ElementFilteringUtil.IsMEPType(exportType)) ExporterCacheManager.MEPCache.Register(familyInstance, instanceHandle); switch (exportType) { case IFCExportType.ExportColumnType: { IFCAnyHandle placementToUse = localPlacement; if (!useInstanceGeometry) { bool needToCreateOpenings = (cutPairOpeningsForColumns.Count != 0) || OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams); if (needToCreateOpenings) { Transform openingTrf = new Transform(oldTrf); Transform extraRot = new Transform(oldTrf); extraRot.Origin = XYZ.Zero; openingTrf = openingTrf.Multiply(extraRot); openingTrf = openingTrf.Multiply(typeInfo.StyleTransform); IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, openingTrf.Origin * scale, openingTrf.get_Basis(2), openingTrf.get_Basis(0)); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement); GeometryUtil.SetRelativePlacement(openingPlacement, openingRelativePlacement); placementToUse = openingPlacement; } } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, cutPairOpeningsForColumns, exporterIFC, placementToUse, setter, wrapper); OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, placementToUse, setter, wrapper); //export Base Quantities. PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportDoorType: case IFCExportType.ExportWindowType: { double doorHeight = doorWindowInfo.OpeningHeight; if (doorHeight < MathUtil.Eps()) doorHeight = GetMinSymbolHeight(familySymbol); double doorWidth = doorWindowInfo.OpeningWidth; if (doorWidth < MathUtil.Eps()) doorWidth = GetMinSymbolWidth(familySymbol); double height = doorHeight * scale; double width = doorWidth * scale; if (IFCAnyHandleUtil.IsNullOrHasNoValue(doorWindowInfo.GetLocalPlacement())) doorWindowInfo.SetLocalPlacement(localPlacement); IFCAnyHandle doorWindowOrigLocalPlacement = doorWindowInfo.GetLocalPlacement(); Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(localPlacement, doorWindowOrigLocalPlacement); IFCAnyHandle doorWindowRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, relTrf.Origin, relTrf.BasisZ, relTrf.BasisX); IFCAnyHandle doorWindowLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, doorWindowOrigLocalPlacement, doorWindowRelativePlacement); if (exportType == IFCExportType.ExportDoorType) instanceHandle = IFCInstanceExporter.CreateDoor(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, rep, instanceElemId, height, width); else if (exportType == IFCExportType.ExportWindowType) instanceHandle = IFCInstanceExporter.CreateWindow(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, rep, instanceElemId, height, width); wrapper.AddElement(instanceHandle, setter, extraParams, true); exporterIFC.RegisterSpaceBoundingElementHandle(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 = openingTrf.Origin * exporterIFC.LinearScale; IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, scaledOrigin, openingTrf.BasisZ, openingTrf.BasisX); IFCAnyHandle openingLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, doorWindowLocalPlacement, openingRelativePlacement); placementToUse = openingLocalPlacement; } } // only necessary when exporting as possible breps. OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, placementToUse, setter, wrapper); if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) ExporterIFCUtils.CreateDoorWindowBaseQuantities(exporterIFC, instanceHandle, (doorHeight * scale), (doorWidth * scale)); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportMemberType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); //export Base Quantities. PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo); // TODO: create PropertySet! //createMemberPropertySet(exporter, pFamInst, pWrapper, extraParams); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportPlateType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); // TODO: create PropertySet! //createPlatePropertySet(exporter, pFamInst, pWrapper, extraParams); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportTransportElementType: { IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); instanceHandle = IFCInstanceExporter.CreateTransportElement(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, rep, instanceElemId, null, null, null); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportBuildingElementProxy: default: { bool isBuildingElementProxy = (exportType == IFCExportType.ExportBuildingElementProxy); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); if (!isBuildingElementProxy) { if (FamilyExporterUtil.IsDistributionControlElementSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateDistributionControlElement(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, rep, instanceElemId, null); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } } else if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { isBuildingElementProxy = true; } } if (isBuildingElementProxy) { Toolkit.IFCElementComposition proxyType = Toolkit.IFCElementComposition.Element; instanceHandle = IFCInstanceExporter.CreateBuildingElementProxy(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, rep, instanceElemId, proxyType); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } } IFCAnyHandle placementToUse = localPlacement; if (!useInstanceGeometry) { bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams); if (needToCreateOpenings) { Transform openingTrf = new Transform(oldTrf); Transform extraRot = new Transform(oldTrf); extraRot.Origin = XYZ.Zero; openingTrf = openingTrf.Multiply(extraRot); openingTrf = openingTrf.Multiply(typeInfo.StyleTransform); IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, openingTrf.Origin * scale, 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, exporterIFC, placementToUse, setter, wrapper); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { if (doorWindowInfo != null) { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(doorWindowInfo.GetOpening())) { string relGUID = GUIDUtil.CreateGUID(); IFCInstanceExporter.CreateRelFillsElement(file, relGUID, ownerHistory, null, null, doorWindowInfo.GetOpening(), instanceHandle); } else if (doorWindowInfo.NeedsOpening) { bool added = doorWindowInfo.SetDelayedFamilyInstance(instanceHandle, localPlacement, doorWindowInfo.AssignedLevelId); if (added) exporterIFC.RegisterDoorWindowForOpeningUpdate(doorWindowInfo); else { // we need to fill a later opening. exporterIFC.RegisterDoorWindowForUncreatedOpening(familyInstance.Id, instanceHandle); } } } if (!exportParts) CategoryUtil.CreateMaterialAssociations(doc, exporterIFC, instanceHandle, typeInfo.MaterialIds); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeInfo.Style)) ExporterCacheManager.TypeRelationsCache.Add(typeInfo.Style, instanceHandle); } } } }
/// <summary> /// Export the dummy wall to host an orphan part. It usually happens in the cases of associated parts are higher than split sub-wall. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The wall element.</param> /// <param name="geometryElement">The geometry of wall.</param> /// <param name="origWrapper">The IFCProductWrapper.</param> /// <param name="overrideLevelId">The ElementId that will crate the dummy wall.</param> /// <param name="range">The IFCRange corresponding to the dummy wall.</param> /// <returns>The handle of dummy wall.</returns> public static IFCAnyHandle ExportDummyWall(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range) { using (IFCProductWrapper localWrapper = IFCProductWrapper.Create(origWrapper)) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; if (wallElement == null) return null; if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return null; // get global values. Document doc = element.Document; double scale = exporterIFC.LinearScale; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); bool exportParts = PartExporter.CanExportParts(wallElement); if (exportParts && !PartExporter.CanExportElementInPartExport(wallElement, validRange ? overrideLevelId : wallElement.Level.Id, validRange)) return null; string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = null; string elemGUID = (validRange) ? ExporterIFCUtils.CreateGUID() : ExporterIFCUtils.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, exporterIFC.GetName()); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemId = NamingUtil.CreateIFCElementId(element); Transform orientationTrf = Transform.Identity; using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.GetPlacement(); wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, null, elemId); if (exportParts) PartExporter.ExportHostPart(exporterIFC, wallElement, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData(); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; localWrapper.AddElement(wallHnd, setter, extraParams, true); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, localWrapper); ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId); } return wallHnd; } }
/// <summary> /// Main implementation to export walls. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="origWrapper"> /// The IFCProductWrapper. /// </param> /// <param name="overrideLevelId"> /// The level id. /// </param> /// <param name="range"> /// The range to be exported for the element. /// </param> /// <returns> /// The exported wall handle. /// </returns> public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range) { using (IFCProductWrapper localWrapper = IFCProductWrapper.Create(origWrapper)) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; FamilyInstance famInstWallElem = element as FamilyInstance; if (wallElement == null && famInstWallElem == null) return null; if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return null; // get global values. Document doc = element.Document; double scale = exporterIFC.LinearScale; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis"); IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); IFCRange zSpan = new IFCRange(); double depth = 0.0; bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); bool exportParts = PartExporter.CanExportParts(wallElement); if (exportParts && !PartExporter.CanExportElementInPartExport(wallElement, validRange? overrideLevelId : wallElement.Level.Id, validRange)) return null; // get bounding box height so that we can subtract out pieces properly. // only for Wall, not FamilyInstance. if (wallElement != null && geometryElement != null) { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox == null) return null; zSpan = new IFCRange(boundingBox.Min.Z, boundingBox.Max.Z); // if we have a top clipping plane, modify depth accordingly. double bottomHeight = validRange ? Math.Max(zSpan.Start, range.Start) : zSpan.Start; double topHeight = validRange ? Math.Min(zSpan.End, range.End) : zSpan.End; depth = topHeight - bottomHeight; if (MathUtil.IsAlmostZero(depth)) return null; depth *= scale; } IFCAnyHandle axisRep = null; IFCAnyHandle bodyRep = null; bool exportingAxis = false; Curve curve = null; bool exportedAsWallWithAxis = false; bool exportedBodyDirectly = false; bool exportingInplaceOpenings = false; Curve centerCurve = GetWallAxis(wallElement); XYZ localXDir = new XYZ(1, 0, 0); XYZ localYDir = new XYZ(0, 1, 0); XYZ localZDir = new XYZ(0, 0, 1); XYZ localOrig = new XYZ(0, 0, 0); double eps = MathUtil.Eps(); if (centerCurve != null) { Curve baseCurve = GetWallAxisAtBaseHeight(wallElement); curve = GetWallTrimmedCurve(wallElement, baseCurve); IFCRange curveBounds; XYZ oldOrig; GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig); localOrig = oldOrig; if (baseCurve != null) { if (!validRange || (MathUtil.IsAlmostEqual(range.Start, zSpan.Start))) { XYZ newOrig = baseCurve.Evaluate(curveBounds.Start, false); if (!validRange && (zSpan.Start < newOrig[2] - eps)) localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan.Start); else localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]); } else { localOrig = new XYZ(localOrig.X, localOrig.Y, range.Start); } } double dist = localOrig[2] - oldOrig[2]; if (!MathUtil.IsAlmostZero(dist)) { XYZ moveVec = new XYZ(0, 0, dist); curve = GeometryUtil.MoveCurve(curve, moveVec); } localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } Transform orientationTrf = Transform.Identity; orientationTrf.BasisX = localXDir; orientationTrf.BasisY = localYDir; orientationTrf.BasisZ = localZDir; orientationTrf.Origin = localOrig; using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.GetPlacement(); Plane plane = new Plane(localXDir, localYDir, localOrig); // project curve to XY plane. XYZ projDir = XYZ.BasisZ; // two representations: axis, body. { if ((centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve))) { exportingAxis = true; string identifierOpt = "Axis"; // IFC2x2 convention string representationTypeOpt = "Curve2D"; // IFC2x2 convention IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true); IList<IFCAnyHandle> axisItems = info.GetCurves(); if (axisItems.Count == 0) { exportingAxis = false; } else { HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>(); foreach (IFCAnyHandle axisItem in axisItems) axisItemSet.Add(axisItem); axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItemsAxis, identifierOpt, representationTypeOpt, axisItemSet); } } } IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>(); Document document = element.Document; if (wallElement != null && exportingAxis && curve != null) { SolidMeshGeometryInfo solidMeshInfo = (range == null) ? GeometryUtil.GetSolidMeshGeometry(geometryElement, Transform.Identity) : GeometryUtil.GetClippedSolidMeshGeometry(geometryElement, range); IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> meshes = solidMeshInfo.GetMeshes(); if (solids.Count == 0 && meshes.Count == 0) return null; bool useNewCode = false; if (useNewCode && solids.Count == 1 && meshes.Count == 0) { bool completelyClipped; bodyRep = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, wallElement, catId, solids[0], plane, projDir, range, out completelyClipped); if (completelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { exportedAsWallWithAxis = true; exportedBodyDirectly = true; } else { exportedAsWallWithAxis = false; exportedBodyDirectly = false; } } if (!exportedAsWallWithAxis) { // Fallback - use native routines to try to export wall. bool isCompletelyClipped; bodyRep = FallbackTryToCreateAsExtrusion(exporterIFC, wallElement, solidMeshInfo, catId, curve, plane, depth, zSpan, range, setter, out cutPairOpenings, out isCompletelyClipped); if (isCompletelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) exportedAsWallWithAxis = true; } } using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { ElementId matId = ElementId.InvalidElementId; if (!exportedAsWallWithAxis) { SolidMeshGeometryInfo solidMeshCapsule = null; if (wallElement != null) { if (validRange) { solidMeshCapsule = GeometryUtil.GetClippedSolidMeshGeometry(geometryElement, range); } else { solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); } if (solidMeshCapsule.SolidsCount() == 0 && solidMeshCapsule.MeshesCount() == 0) { return null; } } else { GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem); if (geomElemToUse != null) { exportingInplaceOpenings = true; } else { exportingInplaceOpenings = false; geomElemToUse = geometryElement; } Transform trf = Transform.Identity; if (geomElemToUse != geometryElement) trf = famInstWallElem.GetTransform(); solidMeshCapsule = GeometryUtil.GetSolidMeshGeometry(geomElemToUse, trf); } IList<Solid> solids = solidMeshCapsule.GetSolids(); IList<Mesh> meshes = solidMeshCapsule.GetMeshes(); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); if ((solids.Count > 0) || (meshes.Count > 0)) { matId = BodyExporter.GetBestMaterialIdForGeometry(solids, meshes); bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, catId, solids, meshes, bodyExporterOptions, extraParams).RepresentationHnd; } else { IList<GeometryObject> geomElemList = new List<GeometryObject>(); geomElemList.Add(geometryElement); BodyData bodyData = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, catId, geomElemList, bodyExporterOptions, extraParams); bodyRep = bodyData.RepresentationHnd; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { extraParams.ClearOpenings(); return null; } // We will be able to export as a IfcWallStandardCase as long as we have an axis curve. XYZ extrDirUsed = XYZ.Zero; if (extraParams.HasExtrusionDirection) { extrDirUsed = extraParams.ExtrusionDirection; if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0)) { if ((solids.Count == 1) && (meshes.Count == 0)) exportedAsWallWithAxis = exportingAxis; exportedBodyDirectly = true; } } } IFCAnyHandle prodRep = null; IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (exportingAxis) representations.Add(axisRep); representations.Add(bodyRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = null; string elemGUID = (validRange) ? ExporterIFCUtils.CreateGUID() : ExporterIFCUtils.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, exporterIFC.GetName()); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemId = NamingUtil.CreateIFCElementId(element); if (exportedAsWallWithAxis) { wallHnd = IFCInstanceExporter.CreateWallStandardCase(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemId); if (exportParts) PartExporter.ExportHostPart(exporterIFC, wallElement, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(wallHnd, setter, extraParams, true); OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, exporterIFC, localPlacement, setter, localWrapper); if (exportedBodyDirectly) { OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper); } else { double scaledWidth = wallElement.Width * scale; ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper); } // export Base Quantities if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth); } } else { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemId); if (exportParts) PartExporter.ExportHostPart(exporterIFC, wallElement, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(wallHnd, setter, extraParams, true); // Only export one material for 2x2; for future versions, export the whole list. if (exporterIFC.ExportAs2x2 && (matId != ElementId.InvalidElementId) && !exportParts) { CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, wallHnd, matId); } if (exportingInplaceOpenings) { ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, famInstWallElem, 0.0, range, setter, localPlacement, localWrapper); } if (exportedBodyDirectly) OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper); } PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, localWrapper); ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; if (wallElement != null && !exportParts) { if (!exporterIFC.ExportAs2x2 || exportedAsWallWithAxis) //will move this check into ExportHostObject HostObjectExporter.ExportHostObjectMaterials(exporterIFC, wallElement, localWrapper.GetAnElement(), geometryElement, localWrapper, wallLevelId, Toolkit.IFCLayerSetDirection.Axis2); } exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId); return wallHnd; } } } }
/// <summary> /// Export Curtain Walls and Roofs. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="allSubElements">Collection of elements contained in the host curtain element.</param> /// <param name="element">The element to be exported.</param> /// <param name="productWrapper">The ProductWrapper.</param> private static void ExportBase(ExporterIFC exporterIFC, ICollection <ElementId> allSubElements, Element element, ProductWrapper wrapper) { IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCPlacementSetter setter = null; using (ProductWrapper curtainWallSubWrapper = ProductWrapper.Create(wrapper, false)) { try { Transform orientationTrf = Transform.Identity; IFCAnyHandle localPlacement = null; setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, ExporterUtil.GetBaseLevelIdForElement(element)); localPlacement = setter.GetPlacement(); string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle prodRepHnd = null; IFCAnyHandle elemHnd = null; string elemGUID = GUIDUtil.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); if (element is Wall || element is CurtainSystem || IsLegacyCurtainElement(element)) { elemHnd = IFCInstanceExporter.CreateCurtainWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemTag); } else if (element is RoofBase) { //need to convert the string to enum string ifcEnumType = ExporterUtil.GetIFCTypeFromExportTable(exporterIFC, element); elemHnd = IFCInstanceExporter.CreateRoof(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemTag, RoofExporter.GetIFCRoofType(ifcEnumType)); } else { return; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd)) { return; } wrapper.AddElement(element, elemHnd, setter, null, true); bool canExportCurtainWallAsContainer = CanExportCurtainWallAsContainer(allSubElements, element.Document); IFCAnyHandle rep = null; if (!canExportCurtainWallAsContainer) { rep = ExportCurtainObjectCommonAsOneBRep(allSubElements, element, exporterIFC, setter, localPlacement); if (IFCAnyHandleUtil.IsNullOrHasNoValue(rep)) { return; } } else { ExportCurtainObjectCommonAsContainer(allSubElements, element, exporterIFC, curtainWallSubWrapper, setter); } ICollection <IFCAnyHandle> relatedElementIds = curtainWallSubWrapper.GetAllObjects(); if (relatedElementIds.Count > 0) { string guid = GUIDUtil.CreateSubElementGUID(element, (int)IFCCurtainWallSubElements.RelAggregates); HashSet <IFCAnyHandle> relatedElementIdSet = new HashSet <IFCAnyHandle>(relatedElementIds); IFCInstanceExporter.CreateRelAggregates(file, guid, ownerHistory, null, null, elemHnd, relatedElementIdSet); } exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, element.Id, ElementId.InvalidElementId); ExportCurtainWallType(exporterIFC, wrapper, elemHnd, element); } finally { if (setter != null) { setter.Dispose(); } } } }
/// <summary> /// Exports materials for host object. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="hostObject"> /// The host object. /// </param> /// <param name="elemHnds"> /// The host IFC handles. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> /// <param name="levelId"> /// The level id. /// </param> /// <param name="direction"> /// The IFCLayerSetDirection. /// </param> /// <returns> /// True if exported successfully, false otherwise. /// </returns> public static bool ExportHostObjectMaterials(ExporterIFC exporterIFC, HostObject hostObject, IList <IFCAnyHandle> elemHnds, GeometryElement geometryElement, IFCProductWrapper productWrapper, ElementId levelId, Toolkit.IFCLayerSetDirection direction) { if (hostObject == null) { return(true); //nothing to do } if (elemHnds == null || (elemHnds.Count == 0)) { return(true); //nothing to do } IFCFile file = exporterIFC.GetFile(); // Roofs with no components are only allowed one material. We will arbitrarily choose the thickest material. IFCAnyHandle primaryMaterialHnd = null; using (IFCTransaction tr = new IFCTransaction(file)) { if (productWrapper != null) { productWrapper.ClearFinishMaterials(); } double scale = exporterIFC.LinearScale; double scaledOffset = 0.0, scaledWallWidth = 0.0, wallHeight = 0.0; Wall wall = hostObject as Wall; if (wall != null) { scaledWallWidth = wall.Width * scale; scaledOffset = -scaledWallWidth / 2.0; BoundingBoxXYZ boundingBox = wall.get_BoundingBox(null); if (boundingBox != null) { wallHeight = boundingBox.Max.Z - boundingBox.Min.Z; } } ElementId typeElemId = hostObject.GetTypeId(); IFCAnyHandle materialLayerSet = ExporterCacheManager.MaterialLayerSetCache.Find(typeElemId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet)) { HostObjAttributes hostObjAttr = hostObject.Document.GetElement(typeElemId) as HostObjAttributes; if (hostObjAttr == null) { return(true); //nothing to do } List <ElementId> matIds = new List <ElementId>(); List <double> widths = new List <double>(); List <MaterialFunctionAssignment> functions = new List <MaterialFunctionAssignment>(); ElementId baseMatId = CategoryUtil.GetBaseMaterialIdForElement(hostObject); CompoundStructure cs = hostObjAttr.GetCompoundStructure(); if (cs != null) { //TODO: Vertically compound structures are not yet supported by export. if (!cs.IsVerticallyHomogeneous() && !MathUtil.IsAlmostZero(wallHeight)) { cs = cs.GetSimpleCompoundStructure(wallHeight, wallHeight / 2.0); } for (int i = 0; i < cs.LayerCount; ++i) { ElementId matId = cs.GetMaterialId(i); if (matId != ElementId.InvalidElementId) { matIds.Add(matId); } else { matIds.Add(baseMatId); } widths.Add(cs.GetLayerWidth(i)); // save layer function into IFCProductWrapper, // it's used while exporting "Function" of Pset_CoveringCommon functions.Add(cs.GetLayerFunction(i)); } } if (matIds.Count == 0) { matIds.Add(baseMatId); widths.Add(cs != null ? cs.GetWidth() : 0); functions.Add(MaterialFunctionAssignment.None); } List <IFCAnyHandle> layers = new List <IFCAnyHandle>(); double thickestLayer = 0.0; for (int i = 0; i < matIds.Count; ++i) { if (widths[i] < MathUtil.Eps()) { continue; } IFCAnyHandle materialHnd = CategoryUtil.GetOrCreateMaterialHandle(hostObjAttr.Document, exporterIFC, matIds[i]); if (primaryMaterialHnd == null || (widths[i] > thickestLayer)) { primaryMaterialHnd = materialHnd; thickestLayer = widths[i]; } double scaledWidth = widths[i] * scale; IFCAnyHandle materialLayer = IFCInstanceExporter.CreateMaterialLayer(file, materialHnd, scaledWidth, null); layers.Add(materialLayer); if ((productWrapper != null) && (functions[i] == MaterialFunctionAssignment.Finish1 || functions[i] == MaterialFunctionAssignment.Finish2)) { productWrapper.AddFinishMaterial(materialHnd); } } if (layers.Count == 0) { return(false); } string layerSetName = NamingUtil.CreateIFCFamilyName(exporterIFC, -1); materialLayerSet = IFCInstanceExporter.CreateMaterialLayerSet(file, layers, layerSetName); ExporterCacheManager.MaterialLayerSetCache.Register(typeElemId, materialLayerSet); } // IfcMaterialLayerSetUsage is not supported for IfcWall, only IfcWallStandardCase. IFCAnyHandle layerSetUsage = null; for (int ii = 0; ii < elemHnds.Count; ii++) { IFCAnyHandle elemHnd = elemHnds[ii]; if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd)) { continue; } HashSet <IFCAnyHandle> relDecomposesSet = IFCAnyHandleUtil.GetRelDecomposes(elemHnd); IList <IFCAnyHandle> subElemHnds = new List <IFCAnyHandle>(); if (relDecomposesSet != null && relDecomposesSet.Count == 1) { IFCAnyHandle relAggregates = relDecomposesSet.First(); if (IFCAnyHandleUtil.IsTypeOf(relAggregates, IFCEntityType.IfcRelAggregates)) { IFCData ifcData = relAggregates.GetAttribute("RelatedObjects"); if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate) { IFCAggregate aggregate = ifcData.AsAggregate(); if (aggregate != null && aggregate.Count > 0) { foreach (IFCData val in aggregate) { if (val.PrimitiveType == IFCDataPrimitiveType.Instance) { subElemHnds.Add(val.AsInstance()); } } } } } } bool hasSubElems = !(subElemHnds.Count == 0); bool isRoof = IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcRoof); if (!hasSubElems && !isRoof && !IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcWall)) { if (layerSetUsage == null) { bool flipDirSense = true; if (wall != null) { // if we have flipped the center curve on export, we need to take that into account here. // We flip the center curve on export if it is an arc and it has a negative Z direction. LocationCurve locCurve = wall.Location as LocationCurve; if (locCurve != null) { Curve curve = locCurve.Curve; Plane defPlane = new Plane(XYZ.BasisX, XYZ.BasisY, XYZ.Zero); bool curveFlipped = GeometryUtil.MustFlipCurve(defPlane, curve); flipDirSense = !(wall.Flipped ^ curveFlipped); } } else if (hostObject is Floor) { flipDirSense = false; } double offsetFromReferenceLine = flipDirSense ? -scaledOffset : scaledOffset; IFCDirectionSense sense = flipDirSense ? IFCDirectionSense.Negative : IFCDirectionSense.Positive; layerSetUsage = IFCInstanceExporter.CreateMaterialLayerSetUsage(file, materialLayerSet, direction, sense, offsetFromReferenceLine); } ExporterCacheManager.MaterialLayerRelationsCache.Add(layerSetUsage, elemHnd); } else { if (hasSubElems) { foreach (IFCAnyHandle subElemHnd in subElemHnds) { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(subElemHnd)) { ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, subElemHnd); } } } else if (!isRoof) { ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, elemHnd); } else if (primaryMaterialHnd != null) { ExporterCacheManager.MaterialLayerRelationsCache.Add(primaryMaterialHnd, elemHnd); } } exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, hostObject.Id, levelId); } tr.Commit(); return(true); } }
/// <summary> /// Export Curtain Walls and Roofs. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="allSubElements">Collection of elements contained in the host curtain element.</param> /// <param name="element">The element to be exported.</param> /// <param name="productWrapper">The ProductWrapper.</param> private static void ExportBase(ExporterIFC exporterIFC, ICollection<ElementId> allSubElements, Element element, ProductWrapper wrapper) { IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCPlacementSetter setter = null; using (ProductWrapper curtainWallSubWrapper = ProductWrapper.Create(wrapper, false)) { try { ElementId curtainWallLevel = ElementId.InvalidElementId; if (element.Level != null) { curtainWallLevel = element.Level.Id; } Transform orientationTrf = Transform.Identity; IFCAnyHandle localPlacement = null; setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, curtainWallLevel); localPlacement = setter.GetPlacement(); string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle prodRepHnd = null; IFCAnyHandle elemHnd = null; string elemGUID = GUIDUtil.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); if (element is Wall || element is CurtainSystem || IsLegacyCurtainElement(element)) { elemHnd = IFCInstanceExporter.CreateCurtainWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemTag); } else if (element is RoofBase) { //need to convert the string to enum string ifcEnumType = CategoryUtil.GetIFCEnumTypeName(exporterIFC, element); elemHnd = IFCInstanceExporter.CreateRoof(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemTag, RoofExporter.GetIFCRoofType(ifcEnumType)); } else { return; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd)) return; wrapper.AddElement(elemHnd, setter, null, true); bool canExportCurtainWallAsContainer = CanExportCurtainWallAsContainer(allSubElements, element.Document); IFCAnyHandle rep = null; if (!canExportCurtainWallAsContainer) { rep = ExportCurtainObjectCommonAsOneBRep(allSubElements, element, exporterIFC, setter, localPlacement); if (IFCAnyHandleUtil.IsNullOrHasNoValue(rep)) return; } else { ExportCurtainObjectCommonAsContainer(allSubElements, element, exporterIFC, curtainWallSubWrapper, setter); } PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, wrapper); ICollection<IFCAnyHandle> relatedElementIds = curtainWallSubWrapper.GetAllObjects(); if (relatedElementIds.Count > 0) { string guid = ExporterIFCUtils.CreateSubElementGUID(element, (int)IFCCurtainWallSubElements.RelAggregates); HashSet<IFCAnyHandle> relatedElementIdSet = new HashSet<IFCAnyHandle>(relatedElementIds); IFCInstanceExporter.CreateRelAggregates(file, guid, ownerHistory, null, null, elemHnd, relatedElementIdSet); } exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, element.Id, ElementId.InvalidElementId); } finally { if (setter != null) setter.Dispose(); } } }
/// <summary> /// Exports materials for host object. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="hostObject"> /// The host object. /// </param> /// <param name="elemHnds"> /// The host IFC handles. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> /// <param name="levelId"> /// The level id. /// </param> /// <param name="direction"> /// The IFCLayerSetDirection. /// </param> /// <returns> /// True if exported successfully, false otherwise. /// </returns> public static bool ExportHostObjectMaterials(ExporterIFC exporterIFC, HostObject hostObject, IList<IFCAnyHandle> elemHnds, GeometryElement geometryElement, ProductWrapper productWrapper, ElementId levelId, Toolkit.IFCLayerSetDirection direction) { if (hostObject == null) return true; //nothing to do if (elemHnds == null || (elemHnds.Count == 0)) return true; //nothing to do IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { if (productWrapper != null) productWrapper.ClearFinishMaterials(); double scale = exporterIFC.LinearScale; double scaledOffset = 0.0, scaledWallWidth = 0.0, wallHeight = 0.0; Wall wall = hostObject as Wall; if (wall != null) { scaledWallWidth = wall.Width * scale; scaledOffset = -scaledWallWidth / 2.0; BoundingBoxXYZ boundingBox = wall.get_BoundingBox(null); if (boundingBox != null) wallHeight = boundingBox.Max.Z - boundingBox.Min.Z; } ElementId typeElemId = hostObject.GetTypeId(); IFCAnyHandle materialLayerSet = ExporterCacheManager.MaterialLayerSetCache.Find(typeElemId); // Roofs with no components are only allowed one material. We will arbitrarily choose the thickest material. IFCAnyHandle primaryMaterialHnd = ExporterCacheManager.MaterialLayerSetCache.FindPrimaryMaterialHnd(typeElemId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet)) { HostObjAttributes hostObjAttr = hostObject.Document.GetElement(typeElemId) as HostObjAttributes; if (hostObjAttr == null) return true; //nothing to do List<ElementId> matIds = new List<ElementId>(); List<double> widths = new List<double>(); List<MaterialFunctionAssignment> functions = new List<MaterialFunctionAssignment>(); ElementId baseMatId = CategoryUtil.GetBaseMaterialIdForElement(hostObject); CompoundStructure cs = hostObjAttr.GetCompoundStructure(); if (cs != null) { //TODO: Vertically compound structures are not yet supported by export. if (!cs.IsVerticallyHomogeneous() && !MathUtil.IsAlmostZero(wallHeight)) cs = cs.GetSimpleCompoundStructure(wallHeight, wallHeight / 2.0); for (int i = 0; i < cs.LayerCount; ++i) { ElementId matId = cs.GetMaterialId(i); if (matId != ElementId.InvalidElementId) { matIds.Add(matId); } else { matIds.Add(baseMatId); } widths.Add(cs.GetLayerWidth(i)); // save layer function into ProductWrapper, // it's used while exporting "Function" of Pset_CoveringCommon functions.Add(cs.GetLayerFunction(i)); } } if (matIds.Count == 0) { matIds.Add(baseMatId); widths.Add(cs != null ? cs.GetWidth() : 0); functions.Add(MaterialFunctionAssignment.None); } List<IFCAnyHandle> layers = new List<IFCAnyHandle>(); double thickestLayer = 0.0; for (int i = 0; i < matIds.Count; ++i) { if (widths[i] < MathUtil.Eps()) continue; IFCAnyHandle materialHnd = CategoryUtil.GetOrCreateMaterialHandle(hostObjAttr.Document, exporterIFC, matIds[i], true); if (primaryMaterialHnd == null || (widths[i] > thickestLayer)) { primaryMaterialHnd = materialHnd; thickestLayer = widths[i]; } double scaledWidth = widths[i] * scale; IFCAnyHandle materialLayer = IFCInstanceExporter.CreateMaterialLayer(file, materialHnd, scaledWidth, null); layers.Add(materialLayer); if ((productWrapper != null) && (functions[i] == MaterialFunctionAssignment.Finish1 || functions[i] == MaterialFunctionAssignment.Finish2)) { productWrapper.AddFinishMaterial(materialHnd); } } if (layers.Count == 0) return false; string layerSetName = exporterIFC.GetFamilyName(); materialLayerSet = IFCInstanceExporter.CreateMaterialLayerSet(file, layers, layerSetName); ExporterCacheManager.MaterialLayerSetCache.Register(typeElemId, materialLayerSet); ExporterCacheManager.MaterialLayerSetCache.RegisterPrimaryMaterialHnd(typeElemId, primaryMaterialHnd); } // IfcMaterialLayerSetUsage is not supported for IfcWall, only IfcWallStandardCase. IFCAnyHandle layerSetUsage = null; for (int ii = 0; ii < elemHnds.Count; ii++) { IFCAnyHandle elemHnd = elemHnds[ii]; if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd)) continue; HashSet<IFCAnyHandle> relDecomposesSet = IFCAnyHandleUtil.GetRelDecomposes(elemHnd); IList<IFCAnyHandle> subElemHnds = new List<IFCAnyHandle>(); if (relDecomposesSet != null && relDecomposesSet.Count == 1) { IFCAnyHandle relAggregates = relDecomposesSet.First(); if (IFCAnyHandleUtil.IsTypeOf(relAggregates, IFCEntityType.IfcRelAggregates)) { IFCData ifcData = relAggregates.GetAttribute("RelatedObjects"); if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate) { IFCAggregate aggregate = ifcData.AsAggregate(); if (aggregate != null && aggregate.Count > 0) { foreach (IFCData val in aggregate) { if (val.PrimitiveType == IFCDataPrimitiveType.Instance) { subElemHnds.Add(val.AsInstance()); } } } } } } bool hasSubElems = !(subElemHnds.Count == 0); bool isRoof = IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcRoof); if (!hasSubElems && !isRoof && !IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcWall)) { if (layerSetUsage == null) { bool flipDirSense = true; if (wall != null) { // if we have flipped the center curve on export, we need to take that into account here. // We flip the center curve on export if it is an arc and it has a negative Z direction. LocationCurve locCurve = wall.Location as LocationCurve; if (locCurve != null) { Curve curve = locCurve.Curve; Plane defPlane = new Plane(XYZ.BasisX, XYZ.BasisY, XYZ.Zero); bool curveFlipped = GeometryUtil.MustFlipCurve(defPlane, curve); flipDirSense = !(wall.Flipped ^ curveFlipped); } } else if (hostObject is Floor) { flipDirSense = false; } double offsetFromReferenceLine = flipDirSense ? -scaledOffset : scaledOffset; IFCDirectionSense sense = flipDirSense ? IFCDirectionSense.Negative : IFCDirectionSense.Positive; layerSetUsage = IFCInstanceExporter.CreateMaterialLayerSetUsage(file, materialLayerSet, direction, sense, offsetFromReferenceLine); } ExporterCacheManager.MaterialLayerRelationsCache.Add(layerSetUsage, elemHnd); } else { if (hasSubElems) { foreach (IFCAnyHandle subElemHnd in subElemHnds) { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(subElemHnd)) ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, subElemHnd); } } else if (!isRoof) { ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, elemHnd); } else if (primaryMaterialHnd != null) { ExporterCacheManager.MaterialLayerRelationsCache.Add(primaryMaterialHnd, elemHnd); } } exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, hostObject.Id, levelId); } tr.Commit(); return true; } }
/// <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 IFCProductWrapper. /// </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, IFCProductWrapper wrapper, ElementId overrideLevelId, UV range) { Document doc = familyInstance.Document; IFCFile file = exporterIFC.GetFile(); FamilySymbol familySymbol = ExporterIFCUtils.GetOriginalSymbol(familyInstance); if (familySymbol == null) return; IFCProductWrapper familyProductWrapper = IFCProductWrapper.Create(wrapper); double scale = exporterIFC.LinearScale; 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; IFCLabel objectType = IFCLabel.Create(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); IList<IFCExtrusionData> cutPairOpeningsForColumns = new List<IFCExtrusionData>(); IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData(); Transform trf = familyInstance.GetTransform(); // Extra information if we are exporting a door or a window. IFCDoorWindowInfo doorWindowInfo = null; if (exportType == IFCExportType.ExportDoorType) doorWindowInfo = IFCDoorWindowInfo.CreateDoorInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf); else if (exportType == IFCExportType.ExportWindowType) doorWindowInfo = IFCDoorWindowInfo.CreateWindowInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf); IFCTypeInfo typeInfo = new IFCTypeInfo(); XYZ extraOffset = XYZ.Zero; bool flipped = doorWindowInfo != null ? doorWindowInfo.IsSymbolFlipped : false; IFCTypeInfo currentTypeInfo = exporterIFC.FindType(familySymbol.Id, flipped); bool found = currentTypeInfo.IsValid(); Family family = familySymbol.Family; // TODO: this code to be removed by ExtrusionAnalyzer code. bool trySpecialColumnCreation = ((exportType == IFCExportType.ExportColumnType) && (!family.IsInPlace)); // 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 = IFCAnyHandle.Create(); IFCAnyHandle planRepresentation = IFCAnyHandle.Create(); // If we are using the instance geometry, ignore the transformation. if (useInstanceGeometry) trf = Transform.Identity; // TODO: this code to be removed by ExtrusionAnalyzer code. if (trySpecialColumnCreation) { XYZ rangeOffset = trf.Origin; IFCFamilyInstanceExtrusionExportResults results; if (range != null) { results = ExporterIFCUtils.ExportFamilyInstanceAsExtrusion(exporterIFC, familyInstance, useInstanceGeometry, range, overrideLevelId, extraParams); } else { results = ExporterIFCUtils.ExportFamilyInstanceAsExtrusion(exporterIFC, familyInstance, useInstanceGeometry, overrideLevelId, extraParams); } bodyRepresentation = results.GetExtrusionHandle(); extraOffset = results.ExtraOffset; cutPairOpeningsForColumns = results.GetCutPairOpenings(); if (bodyRepresentation.HasValue) { typeInfo.MaterialId = results.MaterialId; // add in level for real columns, not in-place ones. Element actualLevel = (overrideLevelId == ElementId.InvalidElementId) ? familyInstance.Level : doc.get_Element(overrideLevelId); if (actualLevel != null) { IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(actualLevel.Id); double nonStoryLevelOffset = LevelUtil.GetNonStoryLevelOffsetIfAny(exporterIFC, actualLevel as Level); if (range != null) { rangeOffset = new XYZ(rangeOffset.X, rangeOffset.Y, levelInfo.Elevation + nonStoryLevelOffset); } } } rangeOffset += extraOffset; trf.Origin = rangeOffset; } Transform doorWindowTrf = Transform.Identity; IFCAnyHandle dummyPlacement = IFCAnyHandle.Create(); if (doorWindowInfo != null) { doorWindowTrf = ExporterIFCUtils.GetTransformForDoorOrWindow(familyInstance, familySymbol, doorWindowInfo); } else { dummyPlacement = file.CreateLocalPlacement(IFCAnyHandle.Create(), file.CreateAxis2Placement3D()); extraParams.SetLocalPlacement(dummyPlacement); } bool needToCreate2d = (!exporterIFC.ExportAs2x2); bool needToCreate3d = (!bodyRepresentation.HasValue); if (needToCreate2d || needToCreate3d) { using (IFCTransformSetter trfSetter = IFCTransformSetter.Create()) { if (doorWindowInfo != null) { trfSetter.Initialize(exporterIFC, doorWindowTrf); } Options options = new Options(); GeometryElement exportGeometry = useInstanceGeometry ? familyInstance.get_Geometry(options) : familySymbol.get_Geometry(options); if (exportGeometry == null) return; if (needToCreate3d) { IFCSolidMeshGeometryInfo solidMeshInfo; if (range == null) solidMeshInfo = ExporterIFCUtils.GetSolidMeshGeometry(exporterIFC, exportGeometry, Transform.Identity); else solidMeshInfo = ExporterIFCUtils.GetClippedSolidMeshGeometry(exporterIFC, range, exportGeometry); IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> polyMeshes = solidMeshInfo.GetMeshes(); bool tryToExportAsExtrusion = (!exporterIFC.ExportAs2x2 || (exportType == IFCExportType.ExportColumnType)); if (exportType == IFCExportType.ExportColumnType) { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; } else { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryXYZ; } if (solids.Count > 0 || polyMeshes.Count > 0) { bodyRepresentation = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, categoryId, solids, polyMeshes, tryToExportAsExtrusion, extraParams); typeInfo.MaterialId = BodyExporter.GetBestMaterialIdForGeometry(solids, polyMeshes); } else { IList<GeometryObject> exportedGeometries = new List<GeometryObject>(); exportedGeometries.Add(exportGeometry); bodyRepresentation = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, categoryId, exportedGeometries, tryToExportAsExtrusion, extraParams); } if (!bodyRepresentation.HasValue) { extraParams.ClearOpenings(); return; } } // if exporting IFC2x3 (or later), export 2D plan rep of family (if it exists). if (needToCreate2d) { 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, planeTrf.Origin, false); IList<IFCAnyHandle> curves = IFCGeometryInfo.GetCurves(); foreach (IFCAnyHandle curve in curves) curveSet.Add(curve); if (curveSet.Count > 0) { IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle(); IFCAnyHandle curveRepresentationItem = file.CreateGeometricSet(curveSet); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(curveRepresentationItem); planRepresentation = RepresentationUtil.CreateGeometricSetRep(exporterIFC, categoryId, "Annotation", contextOfItems2d, bodyItems); } } } } } if (doorWindowInfo != null) { typeInfo.SetStyleTransform(doorWindowTrf.Inverse); } else { if (!MathUtil.IsAlmostZero(extraOffset.DotProduct(extraOffset))) { Transform newTransform = typeInfo.GetStyleTransform(); XYZ newOrig = newTransform.Origin + extraOffset; newTransform.Origin = newOrig; typeInfo.SetStyleTransform(newTransform); } typeInfo.SetStyleTransform(ExporterIFCUtils.GetUnscaledTransform(exporterIFC, extraParams.GetLocalPlacement())); } IFCLabel descriptionOpt = IFCLabel.Create(); IFCLabel applicableOccurrenceOpt = IFCLabel.Create(); IFCAnyHandle origin = file.CreateAxis2Placement3D(); IFCAnyHandle repMap2dHnd = IFCAnyHandle.Create(); IFCAnyHandle repMap3dHnd = file.CreateRepresentationMap(origin, bodyRepresentation); IList<IFCAnyHandle> repMapList = new List<IFCAnyHandle>(); repMapList.Add(repMap3dHnd); if (planRepresentation.HasValue) { repMap2dHnd = file.CreateRepresentationMap(origin, planRepresentation); repMapList.Add(repMap2dHnd); } // for Door, Window bool paramTakesPrecedence = false; // For Revit, this is currently always false. bool sizeable = false; // for many HashSet<IFCAnyHandle> propertySets = new HashSet<IFCAnyHandle>(); IFCLabel guid = IFCLabel.CreateGUID(familySymbol); IFCLabel symIdAsLabel = NamingUtil.CreateIFCElementId(familySymbol); // This covers many generic types. If we can't find it in the list here, do custom exports. IFCAnyHandle typeStyle = FamilyExporterUtil.ExportGenericType(file, exportType, ifcEnumType, guid, ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, symIdAsLabel, objectType, familyInstance, familySymbol); // Cover special cases not covered above. if (!typeStyle.HasValue) { switch (exportType) { case IFCExportType.ExportColumnType: { // If we are using the instance GRep, then we have to create a generic GUID for the // column type, as they share the same ElementId. IFCLabel colGUID = IFCLabel.Create(); IFCLabel colElemId = IFCLabel.Create(); if (useInstanceGeometry) { colGUID = IFCLabel.CreateGUID(); colElemId = NamingUtil.CreateIFCElementId(familyInstance); } else { colGUID = guid; colElemId = NamingUtil.CreateIFCElementId(familySymbol); } string columnType = "Column"; typeStyle = file.CreateColumnType(columnType, colGUID, ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, colElemId, objectType, familyInstance, familySymbol); break; } case IFCExportType.ExportDoorType: { string constructionType = string.Empty; ParameterUtil.GetStringValueFromElementOrSymbol(familyInstance, "Construction", out constructionType); IFCAnyHandle doorLining = DoorWindowUtil.CreateDoorLiningProperties(exporterIFC, familyInstance); if (doorLining.HasValue) propertySets.Add(doorLining); IList<IFCAnyHandle> doorPanels = DoorWindowUtil.CreateDoorPanelProperties(exporterIFC, doorWindowInfo, familyInstance); propertySets.UnionWith(doorPanels); IFCLabel doorStyleGUID = IFCLabel.CreateGUID(); IFCLabel doorStyleElemId = NamingUtil.CreateIFCElementId(familyInstance); typeStyle = file.CreateDoorStyle(doorStyleGUID, ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, doorStyleElemId, doorWindowInfo.DoorOperationType, constructionType, paramTakesPrecedence, sizeable); break; } case IFCExportType.ExportSystemFurnitureElementType: { IFCLabel furnitureId = NamingUtil.CreateIFCElementId(familyInstance); typeStyle = file.CreateSystemFurnitureElementType(guid, ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, furnitureId, objectType); break; } case IFCExportType.ExportWindowType: { IFCWindowStyleOperation operationType = DoorWindowUtil.GetIFCWindowStyleOperation(familySymbol); string constructionType = DoorWindowUtil.GetIFCWindowStyleConstruction(familyInstance, ""); IFCAnyHandle windowLining = DoorWindowUtil.CreateWindowLiningProperties(exporterIFC, familyInstance, descriptionOpt); if (windowLining.HasValue) propertySets.Add(windowLining); IList<IFCAnyHandle> windowPanels = DoorWindowUtil.CreateWindowPanelProperties(exporterIFC, familyInstance, descriptionOpt); propertySets.UnionWith(windowPanels); IFCLabel windowStyleGUID = IFCLabel.CreateGUID(); IFCLabel windowStyleElemId = NamingUtil.CreateIFCElementId(familyInstance); typeStyle = file.CreateWindowStyle(windowStyleGUID, ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, windowStyleElemId, operationType, constructionType, paramTakesPrecedence, sizeable); break; } case IFCExportType.ExportBuildingElementProxy: default: { typeInfo.Set2DMapHandle(repMap2dHnd); typeInfo.Set3DMapHandle(repMap3dHnd); break; } } } typeInfo.SetStyle(typeStyle); // Transfer extraParams information for certain types. if (typeStyle.HasValue) { if (((exportType == IFCExportType.ExportColumnType) && trySpecialColumnCreation) || (exportType == IFCExportType.ExportMemberType)) { typeInfo.ScaledArea = extraParams.ScaledArea; typeInfo.ScaledDepth = extraParams.ScaledLength; typeInfo.ScaledInnerPerimeter = extraParams.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extraParams.ScaledOuterPerimeter; } } } else if (!creatingType && (trySpecialColumnCreation)) { // still need to modify instance trf for columns. trf.Origin += GetLevelOffsetForExtrudedColumns(exporterIFC, familyInstance, overrideLevelId, extraParams); } if (found && !typeInfo.GetStyle().HasValue) { typeInfo = currentTypeInfo; } // we'll pretend we succeeded, but we'll do nothing. if (!typeInfo.GetStyle().HasValue && !typeInfo.Get2DMapHandle().HasValue && !typeInfo.Get3DMapHandle().HasValue) 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)) exporterIFC.AddType(familySymbol.Id, flipped, typeInfo); Transform oldTrf = new Transform(trf); XYZ scaledMapOrigin = XYZ.Zero; trf = trf.Multiply(typeInfo.GetStyleTransform()); // create instance. IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); { IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle(); IFCAnyHandle contextOfItems3d = exporterIFC.Get3DContextHandle(); // for proxies, we store the IfcRepresentationMap directly since there is no style. IList<IFCAnyHandle> repMapList = IFCGeometryUtils.GetRepresentationMaps(typeInfo.GetStyle()); int numReps = repMapList.Count; IFCAnyHandle repMap2dHnd = typeInfo.Get2DMapHandle(); IFCAnyHandle repMap3dHnd = typeInfo.Get3DMapHandle(); if (!repMap3dHnd.HasValue && (numReps > 0)) repMap3dHnd = repMapList[0]; if (!repMap2dHnd.HasValue && (numReps > 1)) repMap2dHnd = repMapList[1]; if (repMap3dHnd.HasValue) { HashSet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>(); representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap3dHnd, scaledMapOrigin)); IFCAnyHandle shapeRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, categoryId, contextOfItems3d, representations); if (!shapeRep.HasValue) return; shapeReps.Add(shapeRep); } if (repMap2dHnd.HasValue) { HashSet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>(); representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap2dHnd, scaledMapOrigin)); IFCAnyHandle shapeRep = RepresentationUtil.CreatePlanMappedItemRep(exporterIFC, categoryId, contextOfItems2d, representations); if (!shapeRep.HasValue) return; shapeReps.Add(shapeRep); } } IFCLabel noDescriptionOpt = IFCLabel.Create(); IFCLabel noNameOpt = IFCLabel.Create(); IFCAnyHandle rep = file.CreateProductDefinitionShape(noNameOpt, noDescriptionOpt, shapeReps); IFCAnyHandle instanceHandle = IFCAnyHandle.Create(); using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, familyInstance, trf, null, overrideLevelId)) { IFCLabel instanceGUID = IFCLabel.CreateGUID(familyInstance); IFCLabel origInstanceName = NamingUtil.CreateIFCName(exporterIFC, -1); IFCLabel instanceName = NamingUtil.GetNameOverride(familyInstance, origInstanceName); IFCLabel instanceDescription = NamingUtil.GetDescriptionOverride(familyInstance, noDescriptionOpt); IFCLabel instanceObjectType = NamingUtil.GetObjectTypeOverride(familyInstance, objectType); IFCLabel instanceElemId = NamingUtil.CreateIFCElementId(familyInstance); IFCAnyHandle localPlacement = setter.GetPlacement(); instanceHandle = FamilyExporterUtil.ExportGenericInstance(exportType, exporterIFC, familyInstance, wrapper, setter, extraParams, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, rep, instanceElemId); switch (exportType) { case IFCExportType.ExportColumnType: { IFCAnyHandle placementToUse = localPlacement; if (!useInstanceGeometry) { Transform openingTrf = new Transform(oldTrf); Transform extraRot = new Transform(oldTrf); extraRot.Origin = XYZ.Zero; openingTrf = openingTrf.Multiply(extraRot); openingTrf = openingTrf.Multiply(typeInfo.GetStyleTransform()); IFCAnyHandle openingRelativePlacement = file.CreateAxis2Placement3D(openingTrf.Origin * scale, openingTrf.get_Basis(2), openingTrf.get_Basis(0)); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement); IFCGeometryUtils.SetRelativePlacement(openingPlacement, openingRelativePlacement); placementToUse = openingPlacement; } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, cutPairOpeningsForColumns, exporterIFC, placementToUse, setter, wrapper); OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, placementToUse, setter, wrapper); //export Base Quantities. ExporterIFCUtils.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo); CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, instanceHandle, typeInfo.MaterialId); ExporterIFCUtils.CreateColumnPropertySet(exporterIFC, familyInstance, extraParams, wrapper); break; } case IFCExportType.ExportDoorType: case IFCExportType.ExportWindowType: { double doorHeight = doorWindowInfo.OpeningHeight; if (doorHeight < MathUtil.Eps()) doorHeight = GetMinSymbolHeight(familySymbol); double doorWidth = doorWindowInfo.OpeningWidth; if (doorWidth < MathUtil.Eps()) doorWidth = GetMinSymbolWidth(familySymbol); IFCMeasureValue height = IFCMeasureValue.Create(doorHeight * scale); IFCMeasureValue width = IFCMeasureValue.Create(doorWidth * scale); if (!doorWindowInfo.GetLocalPlacement().HasValue) doorWindowInfo.SetLocalPlacement(localPlacement); IFCAnyHandle doorWindowOrigLocalPlacement = doorWindowInfo.GetLocalPlacement(); Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(localPlacement, doorWindowOrigLocalPlacement); IFCAnyHandle doorWindowRelativePlacement = file.CreateAxis2Placement3D(relTrf); IFCAnyHandle doorWindowLocalPlacement = file.CreateLocalPlacement(doorWindowOrigLocalPlacement, doorWindowRelativePlacement); if (exportType == IFCExportType.ExportDoorType) instanceHandle = file.CreateDoor(instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, rep, instanceElemId, height, width); else if (exportType == IFCExportType.ExportWindowType) instanceHandle = file.CreateWindow(instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, rep, instanceElemId, height, width); wrapper.AddElement(instanceHandle, setter, extraParams, true); exporterIFC.RegisterSpaceBoundingElementHandle(instanceHandle, familyInstance.Id, setter.LevelId); // only necessary when exporting as possible breps. OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, doorWindowLocalPlacement, setter, wrapper); if (exporterIFC.ExportBaseQuantities) ExporterIFCUtils.CreateDoorWindowBaseQuantities(exporterIFC, instanceHandle, (doorHeight * scale), (doorWidth * scale)); if (exportType == IFCExportType.ExportDoorType) ExporterIFCUtils.CreateDoorPropertySet(exporterIFC, familyInstance, wrapper); else ExporterIFCUtils.CreateWindowPropertySet(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportMemberType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, instanceHandle, typeInfo.MaterialId); //export Base Quantities. ExporterIFCUtils.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo); // TODO: create PropertySet! //createMemberPropertySet(exporter, pFamInst, pWrapper, extraParams); ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportPlateType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, instanceHandle, typeInfo.MaterialId); // TODO: create PropertySet! //createPlatePropertySet(exporter, pFamInst, pWrapper, extraParams); ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportTransportElementType: { string operationTypeOpt = ""; IFCMeasureValue capByWeightOpt = IFCMeasureValue.Create(); IFCMeasureValue capByNumOpt = IFCMeasureValue.Create(); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); instanceHandle = file.CreateTransportElement(instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, rep, instanceElemId, operationTypeOpt, capByWeightOpt, capByNumOpt, familyInstance, familySymbol); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportBuildingElementProxy: default: { bool isBuildingElementProxy = (exportType == IFCExportType.ExportBuildingElementProxy); if (!isBuildingElementProxy) { if (FamilyExporterUtil.IsDistributionControlElementSubType(exportType)) { IFCLabel controlElementId = IFCLabel.Create(); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); instanceHandle = file.CreateDistributionControlElement(instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacement, rep, instanceElemId, controlElementId); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); } else if (!instanceHandle.HasValue) { isBuildingElementProxy = true; } } if (isBuildingElementProxy) { IFCElementComposition proxyType = IFCElementComposition.Element; IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); instanceHandle = file.CreateBuildingElementProxy(instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, rep, instanceElemId, proxyType); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); } ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper); break; } } if (instanceHandle.HasValue) { if (doorWindowInfo != null) { if (doorWindowInfo.GetOpening().HasValue) { IFCLabel relGUID = IFCLabel.CreateGUID(); file.CreateRelFillsElement(relGUID, ownerHistory, IFCLabel.Create(), IFCLabel.Create(), doorWindowInfo.GetOpening(), instanceHandle); } else if (doorWindowInfo.NeedsOpening) { bool added = doorWindowInfo.SetDelayedFamilyInstance(instanceHandle, localPlacement, doorWindowInfo.AssignedLevelId); if (added) exporterIFC.RegisterDoorWindowForOpeningUpdate(doorWindowInfo); else { // we need to fill a later opening. exporterIFC.RegisterDoorWindowForUncreatedOpening(familyInstance.Id, instanceHandle); } } } if (typeInfo.GetStyle().HasValue) exporterIFC.AddTypeRelation(typeInfo.GetStyle(), instanceHandle); } } }
/// <summary> /// Export Curtain Walls and Roofs. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="allSubElements"> /// Collection of elements contained in the host curtain element. /// </param> /// <param name="hostElement"> /// The host element to be exported. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> public static void ExportBase(ExporterIFC exporterIFC, ElementSet allSubElements, HostObject hostElement, IFCProductWrapper wrapper) { IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCPlacementSetter setter = null; IFCProductWrapper curtainWallSubWrapper = null; try { IFCAnyHandle localPlacement = IFCAnyHandle.Create(); bool canExportCurtainWallAsContainer = CanExportCurtainWallAsContainer(allSubElements); IFCAnyHandle rep = IFCAnyHandle.Create(); if (canExportCurtainWallAsContainer) { curtainWallSubWrapper = IFCProductWrapper.Create(exporterIFC, true); setter = IFCPlacementSetter.Create(exporterIFC, hostElement); localPlacement = setter.GetPlacement(); rep = ExportCurtainObjectCommonAsOneBRep(allSubElements, hostElement, exporterIFC, setter, localPlacement); } else { ExportCurtainObjectCommonAsContainer(allSubElements, hostElement, exporterIFC, out curtainWallSubWrapper); // This has to go LAST. Why? Because otherwise we apply the level transform twice -- once in the familyTrf, once here. // This will be used just to put the CurtainWall on the right level. setter = IFCPlacementSetter.Create(exporterIFC, hostElement); localPlacement = setter.GetPlacement(); } if (!rep.HasValue) return; IFCLabel objectType = NamingUtil.CreateIFCObjectName(exporterIFC, hostElement); IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData(); extraParams.SetLocalPlacement(localPlacement); IFCAnyHandle prodRepHnd = IFCAnyHandle.Create(); IFCAnyHandle elemHnd = IFCAnyHandle.Create(); IFCLabel elemGUID = IFCLabel.CreateGUID(hostElement); IFCLabel elemName = NamingUtil.GetNameOverride(hostElement, exporterIFC.GetNameFromExportState()); IFCLabel elemDesc = NamingUtil.GetDescriptionOverride(hostElement, IFCLabel.Create()); IFCLabel elemType = NamingUtil.GetObjectTypeOverride(hostElement, objectType); IFCLabel elemId = NamingUtil.CreateIFCElementId(hostElement); if (hostElement is Wall || hostElement is CurtainSystem) { elemHnd = file.CreateCurtainWall(elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, elemId, prodRepHnd); } else if (hostElement is RoofBase) { string ifcEnumType = CategoryUtil.GetIFCEnumTypeName(exporterIFC, hostElement); elemHnd = file.CreateRoof(elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, elemId, ifcEnumType, prodRepHnd); } else { return; } if (!elemHnd.HasValue) return; wrapper.AddElement(elemHnd, setter, extraParams, true); OpeningUtil.CreateOpeningsIfNecessary(elemHnd, hostElement, extraParams, exporterIFC, localPlacement, setter, wrapper); ExporterIFCUtils.CreateCurtainWallPropertySet(exporterIFC, hostElement, wrapper); ICollection<IFCAnyHandle> relatedElementIds = curtainWallSubWrapper.GetAllObjects(); if (relatedElementIds.Count > 0) { IFCLabel guid = IFCLabel.CreateGUID(); IFCLabel nameOpt = IFCLabel.Create(); IFCLabel descOpt = IFCLabel.Create(); file.CreateRelAggregates(guid, ownerHistory, nameOpt, descOpt, elemHnd, relatedElementIds); } exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, hostElement.Id, ElementId.InvalidElementId); } finally { if (setter != null) setter.Dispose(); if (curtainWallSubWrapper != null) curtainWallSubWrapper.Dispose(); } }
/// <summary> /// Main implementation to export walls. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="origWrapper"> /// The ProductWrapper. /// </param> /// <param name="overrideLevelId"> /// The level id. /// </param> /// <param name="range"> /// The range to be exported for the element. /// </param> /// <returns> /// The exported wall handle. /// </returns> public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (ProductWrapper localWrapper = ProductWrapper.Create(origWrapper)) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; FamilyInstance famInstWallElem = element as FamilyInstance; FaceWall faceWall = element as FaceWall; if (wallElement == null && famInstWallElem == null && faceWall == null) return null; if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return null; Document doc = element.Document; double scale = exporterIFC.LinearScale; double baseWallElevation = 0.0; ElementId baseLevelId = ExporterUtil.GetBaseLevelIdForElement(element); if (baseLevelId != ElementId.InvalidElementId) { Element baseLevel = doc.GetElement(baseLevelId); if (baseLevel is Level) baseWallElevation = (baseLevel as Level).Elevation; } IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis"); IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); IFCRange zSpan = new IFCRange(); double depth = 0.0; bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, validRange ? overrideLevelId : element.Level.Id, validRange)) return null; // get bounding box height so that we can subtract out pieces properly. // only for Wall, not FamilyInstance. if (wallElement != null && geometryElement != null) { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox == null) return null; zSpan = new IFCRange(boundingBox.Min.Z, boundingBox.Max.Z); // if we have a top clipping plane, modify depth accordingly. double bottomHeight = validRange ? Math.Max(zSpan.Start, range.Start) : zSpan.Start; double topHeight = validRange ? Math.Min(zSpan.End, range.End) : zSpan.End; depth = topHeight - bottomHeight; if (MathUtil.IsAlmostZero(depth)) return null; depth *= scale; } IFCAnyHandle axisRep = null; IFCAnyHandle bodyRep = null; bool exportingAxis = false; Curve curve = null; bool exportedAsWallWithAxis = false; bool exportedBodyDirectly = false; bool exportingInplaceOpenings = false; Curve centerCurve = GetWallAxis(wallElement); XYZ localXDir = new XYZ(1, 0, 0); XYZ localYDir = new XYZ(0, 1, 0); XYZ localZDir = new XYZ(0, 0, 1); XYZ localOrig = new XYZ(0, 0, 0); double eps = MathUtil.Eps(); if (centerCurve != null) { Curve baseCurve = GetWallAxisAtBaseHeight(wallElement); curve = GetWallTrimmedCurve(wallElement, baseCurve); IFCRange curveBounds; XYZ oldOrig; GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig); localOrig = oldOrig; if (baseCurve != null) { if (!validRange || (MathUtil.IsAlmostEqual(range.Start, zSpan.Start))) { XYZ newOrig = baseCurve.Evaluate(curveBounds.Start, false); if (!validRange && (zSpan.Start < newOrig[2] - eps)) localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan.Start); else localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]); } else { localOrig = new XYZ(localOrig.X, localOrig.Y, range.Start); } } double dist = localOrig[2] - oldOrig[2]; if (!MathUtil.IsAlmostZero(dist)) { XYZ moveVec = new XYZ(0, 0, dist); curve = GeometryUtil.MoveCurve(curve, moveVec); } localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } else { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox != null) { XYZ bBoxMin = boundingBox.Min; XYZ bBoxMax = boundingBox.Max; if (validRange) localOrig = new XYZ(bBoxMin.X, bBoxMin.Y, range.Start); else localOrig = boundingBox.Min; XYZ localXDirMax = null; Transform bTrf = boundingBox.Transform; XYZ localXDirMax1 = new XYZ(bBoxMax.X, localOrig.Y, localOrig.Z); localXDirMax1 = bTrf.OfPoint(localXDirMax1); XYZ localXDirMax2 = new XYZ(localOrig.X, bBoxMax.Y, localOrig.Z); localXDirMax2 = bTrf.OfPoint(localXDirMax2); if (localXDirMax1.DistanceTo(localOrig) >= localXDirMax2.DistanceTo(localOrig)) localXDirMax = localXDirMax1; else localXDirMax = localXDirMax2; localXDir = localXDirMax.Subtract(localOrig); localXDir = localXDir.Normalize(); localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } } Transform orientationTrf = Transform.Identity; orientationTrf.BasisX = localXDir; orientationTrf.BasisY = localYDir; orientationTrf.BasisZ = localZDir; orientationTrf.Origin = localOrig; if (overrideLevelId == ElementId.InvalidElementId) overrideLevelId = ExporterUtil.GetBaseLevelIdForElement(element); using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.GetPlacement(); Plane plane = new Plane(localXDir, localYDir, localOrig); // project curve to XY plane. XYZ projDir = XYZ.BasisZ; // two representations: axis, body. { if (!exportParts && (centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve))) { exportingAxis = true; string identifierOpt = "Axis"; // IFC2x2 convention string representationTypeOpt = "Curve2D"; // IFC2x2 convention IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true); IList<IFCAnyHandle> axisItems = info.GetCurves(); if (axisItems.Count == 0) { exportingAxis = false; } else { HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>(); foreach (IFCAnyHandle axisItem in axisItems) axisItemSet.Add(axisItem); axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItemsAxis, identifierOpt, representationTypeOpt, axisItemSet); } } } IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>(); Document document = element.Document; IList<Solid> solids = new List<Solid>(); IList<Mesh> meshes = new List<Mesh>(); if (!exportParts && wallElement != null && exportingAxis && curve != null) { SolidMeshGeometryInfo solidMeshInfo = (range == null) ? GeometryUtil.GetSplitSolidMeshGeometry(geometryElement) : GeometryUtil.GetSplitClippedSolidMeshGeometry(geometryElement, range); solids = solidMeshInfo.GetSolids(); meshes = solidMeshInfo.GetMeshes(); if (solids.Count == 0 && meshes.Count == 0) return null; bool useNewCode = false; if (useNewCode && solids.Count == 1 && meshes.Count == 0) { bool completelyClipped; bodyRep = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, wallElement, catId, solids[0], plane, projDir, range, out completelyClipped); if (completelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { exportedAsWallWithAxis = true; exportedBodyDirectly = true; } else { exportedAsWallWithAxis = false; exportedBodyDirectly = false; } } if (!exportedAsWallWithAxis) { // Fallback - use native routines to try to export wall. bool isCompletelyClipped; bodyRep = FallbackTryToCreateAsExtrusion(exporterIFC, wallElement, solidMeshInfo, baseWallElevation, catId, curve, plane, depth, zSpan, range, setter, out cutPairOpenings, out isCompletelyClipped); if (isCompletelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) exportedAsWallWithAxis = true; } } using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { BodyData bodyData = null; if (!exportedAsWallWithAxis) { SolidMeshGeometryInfo solidMeshCapsule = null; if (wallElement != null || faceWall != null) { if (validRange) { solidMeshCapsule = GeometryUtil.GetSplitClippedSolidMeshGeometry(geometryElement, range); } else { solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); } if (solidMeshCapsule.SolidsCount() == 0 && solidMeshCapsule.MeshesCount() == 0) { return null; } } else { GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem); if (geomElemToUse != null) { exportingInplaceOpenings = true; } else { exportingInplaceOpenings = false; geomElemToUse = geometryElement; } Transform trf = Transform.Identity; if (geomElemToUse != geometryElement) trf = famInstWallElem.GetTransform(); solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geomElemToUse, trf); } solids = solidMeshCapsule.GetSolids(); meshes = solidMeshCapsule.GetMeshes(); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); // Swept solids are not natively exported as part of CV2.0. // We have removed the UI toggle for this, so that it is by default false, but keep for possible future use. if (ExporterCacheManager.ExportOptionsCache.ExportAdvancedSweptSolids) bodyExporterOptions.TryToExportAsSweptSolid = true; ElementId overrideMaterialId = ElementId.InvalidElementId; if (wallElement != null) overrideMaterialId = HostObjectExporter.GetFirstLayerMaterialId(wallElement); if (!exportParts) { if ((solids.Count > 0) || (meshes.Count > 0)) { bodyRep = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId, solids, meshes, bodyExporterOptions, extraParams).RepresentationHnd; } else { IList<GeometryObject> geomElemList = new List<GeometryObject>(); geomElemList.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId, geomElemList, bodyExporterOptions, extraParams); bodyRep = bodyData.RepresentationHnd; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { extraParams.ClearOpenings(); return null; } } // We will be able to export as a IfcWallStandardCase as long as we have an axis curve. XYZ extrDirUsed = XYZ.Zero; if (extraParams.HasExtrusionDirection) { extrDirUsed = extraParams.ExtrusionDirection; if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0)) { if ((solids.Count == 1) && (meshes.Count == 0)) exportedAsWallWithAxis = exportingAxis; exportedBodyDirectly = true; } } } IFCAnyHandle prodRep = null; if (!exportParts) { IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (exportingAxis) representations.Add(axisRep); representations.Add(bodyRep); IFCAnyHandle boundingBoxRep = null; if ((solids.Count > 0) || (meshes.Count > 0)) boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, solids, meshes, Transform.Identity); else boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) representations.Add(boundingBoxRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); } ElementId matId = ElementId.InvalidElementId; string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = null; string elemGUID = (validRange) ? GUIDUtil.CreateGUID() : GUIDUtil.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); // For Foundation and Retaining walls, allow exporting as IfcFooting instead. bool exportAsFooting = false; string enumTypeValue = null; if (wallElement != null) { WallType wallType = wallElement.WallType; if (wallType != null) { int wallFunction; if (ParameterUtil.GetIntValueFromElement(wallType, BuiltInParameter.FUNCTION_PARAM, out wallFunction) != null) { if (wallFunction == (int)WallFunction.Retaining || wallFunction == (int)WallFunction.Foundation) { // In this case, allow potential to export foundation and retaining walls as footing. IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, wallElement, out enumTypeValue); if (exportType == IFCExportType.ExportFooting) exportAsFooting = true; } } } } if (exportedAsWallWithAxis) { if (exportAsFooting) { Toolkit.IFCFootingType footingType = FootingExporter.GetIFCFootingType(element, enumTypeValue); wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, footingType); } else if (exportParts) { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, null, elemTag); } else { wallHnd = IFCInstanceExporter.CreateWallStandardCase(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, prodRep, elemTag); } if (exportParts) PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(element, wallHnd, setter, extraParams, true); if (!exportParts) { OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, null, exporterIFC, localPlacement, setter, localWrapper); if (exportedBodyDirectly) { Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform, exporterIFC, localPlacement, setter, localWrapper); } else { ICollection<IFCAnyHandle> beforeOpenings = localWrapper.GetAllObjects(); double scaledWidth = wallElement.Width * scale; ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper.ToNative()); ICollection<IFCAnyHandle> afterOpenings = localWrapper.GetAllObjects(); if (beforeOpenings.Count != afterOpenings.Count) { foreach (IFCAnyHandle before in beforeOpenings) afterOpenings.Remove(before); foreach (IFCAnyHandle potentiallyBadOpening in afterOpenings) { PotentiallyCorrectOpeningOrientationAndOpeningType(potentiallyBadOpening, localPlacement, scaledWidth); } } } } // export Base Quantities if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth); } } else { if (exportAsFooting) { Toolkit.IFCFootingType footingType = FootingExporter.GetIFCFootingType(element, enumTypeValue); wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, footingType); } else { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag); } if (exportParts) PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(element, wallHnd, setter, extraParams, true); if (!exportParts) { // Only export one material for 2x2; for future versions, export the whole list. if (exporterIFC.ExportAs2x2 || famInstWallElem != null) { matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids, meshes, element); if (matId != ElementId.InvalidElementId) CategoryUtil.CreateMaterialAssociation(exporterIFC, wallHnd, matId); } if (exportingInplaceOpenings) { ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, famInstWallElem, 0.0, range, setter, localPlacement, localWrapper.ToNative()); } if (exportedBodyDirectly) { Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform, exporterIFC, localPlacement, setter, localWrapper); } } } ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; if ((wallElement != null || faceWall != null) && !exportParts) { HostObject hostObject = null; if (wallElement != null) hostObject = wallElement; else hostObject = faceWall; if (!exporterIFC.ExportAs2x2 || exportedAsWallWithAxis) HostObjectExporter.ExportHostObjectMaterials(exporterIFC, hostObject, localWrapper.GetAnElement(), geometryElement, localWrapper, wallLevelId, Toolkit.IFCLayerSetDirection.Axis2, !exportedAsWallWithAxis); } ExportWallType(exporterIFC, localWrapper, wallHnd, element, matId, exportedAsWallWithAxis, exportAsFooting); exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId); tr.Commit(); return wallHnd; } } } } }
/// <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.Level.Id, 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); double scale = exporterIFC.LinearScale; 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()) { bool exportingDoor = (exportType == IFCExportType.ExportDoorType); bool exportingWindow = (exportType == IFCExportType.ExportWindowType); bool exportingHostParts = PartExporter.CanExportParts(hostElement); HostObject hostElementForDoorWindow = exportingHostParts ? null : hostElement; // Extra information if we are exporting a door or a window. IFCDoorWindowInfo doorWindowInfo = null; if (exportingDoor) doorWindowInfo = IFCDoorWindowInfo.CreateDoorInfo(exporterIFC, familyInstance, originalFamilySymbol, hostElementForDoorWindow, overrideLevelId, trf); else if (exportingWindow) doorWindowInfo = IFCDoorWindowInfo.CreateWindowInfo(exporterIFC, familyInstance, originalFamilySymbol, hostElementForDoorWindow, overrideLevelId, trf); bool ignoreDoorWindowOpening = ((exportingDoor || exportingWindow) && exportingHostParts); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); bool flipped = doorWindowInfo != null ? doorWindowInfo.IsSymbolFlipped : 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); } else { dummyPlacement = IFCInstanceExporter.CreateLocalPlacement(file, null, ExporterUtil.CreateAxis2Placement3D(file)); extraParams.SetLocalPlacement(dummyPlacement); } bool needToCreate2d = ExporterCacheManager.ExportOptionsCache.ExportAnnotations; GeometryElement exportGeometry = useInstanceGeometry ? familyInstance.get_Geometry(options) : originalFamilySymbol.get_Geometry(options); if (!exportParts) { using (IFCTransformSetter trfSetter = IFCTransformSetter.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.ExportColumnType)); if (exportType == IFCExportType.ExportColumnType) { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; if (ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 && 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 = -offsetTransform.Origin / scale; 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.ExportColumnType) || (exportType == IFCExportType.ExportMemberType)) { 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)) { IList<IFCAnyHandle> representations = new List<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; // 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.ExportAs2x3CoordinationView2 && !exportParts)) { IFCAnyHandle instanceHandle = null; if (overrideLevelId == ElementId.InvalidElementId) overrideLevelId = ExporterUtil.GetBaseLevelIdForElement(familyInstance); using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, familyInstance, trf, null, overrideLevelId)) { string instanceGUID = GUIDUtil.CreateGUID(familyInstance); 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)); bool isChildInContainer = familyInstance.AssemblyInstanceId != ElementId.InvalidElementId; IFCAnyHandle localPlacement = setter.GetPlacement(); IFCAnyHandle overrideLocalPlacement = null; if (parentLocalPlacement != null) { Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(parentLocalPlacement, localPlacement); Transform inverseTrf = relTrf.Inverse; IFCAnyHandle relativePlacement = ExporterUtil.CreateAxis2Placement3D(file, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX); IFCAnyHandle plateLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, parentLocalPlacement, relativePlacement); 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.GetPlacement(), 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.ExportDuctFittingType || exportType == IFCExportType.ExportPipeFittingType || exportType == IFCExportType.ExportDuctSegmentType || exportType == IFCExportType.ExportPipeSegmentType) ExporterCacheManager.MEPCache.CoveredElementsCache.Add(familyInstance.Id); } switch (exportType) { case IFCExportType.ExportColumnType: { 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); IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, openingTrf.Origin * scale, 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); break; } case IFCExportType.ExportDoorType: case IFCExportType.ExportWindowType: { double doorHeight = doorWindowInfo.OpeningHeight; if (doorHeight < MathUtil.Eps()) doorHeight = GetMinSymbolHeight(originalFamilySymbol) * scale; else { // The native OpeningHeight code is not reliable if the opening has an arc in the boundary. Potentially fix this case. doorHeight = PotentiallyCorrectDoorHeight(doorWindowInfo.GetOpening(), doorHeight * scale); } double doorWidth = doorWindowInfo.OpeningWidth; if (doorWidth < MathUtil.Eps()) doorWidth = GetMinSymbolWidth(originalFamilySymbol); double height = doorHeight; // Already scaled. double width = doorWidth * scale; IFCAnyHandle doorWindowLocalPlacement = null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(overrideLocalPlacement)) doorWindowLocalPlacement = overrideLocalPlacement; else { if (IFCAnyHandleUtil.IsNullOrHasNoValue(doorWindowInfo.GetLocalPlacement())) doorWindowInfo.SetLocalPlacement(localPlacement); IFCAnyHandle doorWindowOrigLocalPlacement = doorWindowInfo.GetLocalPlacement(); Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(localPlacement, doorWindowOrigLocalPlacement); IFCAnyHandle doorWindowRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, relTrf.Origin, relTrf.BasisZ, relTrf.BasisX); doorWindowLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, doorWindowOrigLocalPlacement, doorWindowRelativePlacement); } if (exportType == IFCExportType.ExportDoorType) instanceHandle = IFCInstanceExporter.CreateDoor(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, repHnd, instanceTag, height, width); else if (exportType == IFCExportType.ExportWindowType) instanceHandle = IFCInstanceExporter.CreateWindow(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, repHnd, instanceTag, height, width); wrapper.AddElement(familyInstance, instanceHandle, setter, extraParams, true); exporterIFC.RegisterSpaceBoundingElementHandle(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 = openingTrf.Origin * exporterIFC.LinearScale; IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, scaledOrigin, openingTrf.BasisZ, openingTrf.BasisX); IFCAnyHandle openingLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, doorWindowLocalPlacement, openingRelativePlacement); placementToUse = openingLocalPlacement; } } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform, exporterIFC, placementToUse, setter, wrapper); break; } case IFCExportType.ExportMemberType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform, exporterIFC, localPlacement, setter, wrapper); //export Base Quantities. PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo); break; } case IFCExportType.ExportPlateType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, offsetTransform, exporterIFC, localPlacement, setter, wrapper); break; } case IFCExportType.ExportTransportElementType: { IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); IFCTransportElementType operationType = FamilyExporterUtil.GetTransportElementType(familyInstance); 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, operationType, capacityByWeight, capacityByNumber); bool containedInSpace = (roomId != ElementId.InvalidElementId); wrapper.AddElement(familyInstance, instanceHandle, setter, extraParams, !containedInSpace); if (containedInSpace) exporterIFC.RelateSpatialElement(roomId, instanceHandle); break; } //case IFCExportType.ExportBuildingElementProxy: //case IFCExportType.ExportBuildingElementProxyType: default: { if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { bool isBuildingElementProxy = ((exportType == IFCExportType.ExportBuildingElementProxy) || (exportType == IFCExportType.ExportBuildingElementProxyType)); 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) exporterIFC.RelateSpatialElement(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 = openingTrf.Origin * scale; 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 (doorWindowInfo != null) { if (!ignoreDoorWindowOpening) { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(doorWindowInfo.GetOpening())) { string relGUID = GUIDUtil.CreateGUID(); IFCInstanceExporter.CreateRelFillsElement(file, relGUID, ownerHistory, null, null, doorWindowInfo.GetOpening(), instanceHandle); } else if (doorWindowInfo.NeedsOpening) { bool added = doorWindowInfo.SetDelayedFamilyInstance(instanceHandle, localPlacement, doorWindowInfo.AssignedLevelId); if (added) exporterIFC.RegisterDoorWindowForOpeningUpdate(doorWindowInfo); else { // we need to fill a later opening. exporterIFC.RegisterDoorWindowForUncreatedOpening(familyInstance.Id, instanceHandle); } } } } if (!exportParts) CategoryUtil.CreateMaterialAssociations(exporterIFC, instanceHandle, typeInfo.MaterialIds); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeInfo.Style)) ExporterCacheManager.TypeRelationsCache.Add(typeInfo.Style, instanceHandle); } } } } }
/// <summary> /// Export Curtain Walls and Roofs. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="allSubElements"> /// Collection of elements contained in the host curtain element. /// </param> /// <param name="element"> /// The element to be exported. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> public static void ExportBase(ExporterIFC exporterIFC, ICollection <ElementId> allSubElements, Element element, IFCProductWrapper wrapper) { IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCPlacementSetter setter = null; using (IFCProductWrapper curtainWallSubWrapper = IFCProductWrapper.Create(wrapper, false)) { try { IFCAnyHandle localPlacement = null; bool canExportCurtainWallAsContainer = CanExportCurtainWallAsContainer(allSubElements, element.Document); IFCAnyHandle rep = null; if (!canExportCurtainWallAsContainer) { setter = IFCPlacementSetter.Create(exporterIFC, element); localPlacement = setter.GetPlacement(); rep = ExportCurtainObjectCommonAsOneBRep(allSubElements, element, exporterIFC, setter, localPlacement); if (IFCAnyHandleUtil.IsNullOrHasNoValue(rep)) { return; } } else { ExportCurtainObjectCommonAsContainer(allSubElements, element, exporterIFC, curtainWallSubWrapper); // This has to go LAST. Why? Because otherwise we apply the level transform twice -- once in the familyTrf, once here. // This will be used just to put the CurtainWall on the right level. setter = IFCPlacementSetter.Create(exporterIFC, element); localPlacement = setter.GetPlacement(); } string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); { IFCAnyHandle prodRepHnd = null; IFCAnyHandle elemHnd = null; string elemGUID = ExporterIFCUtils.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, exporterIFC.GetName()); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemId = NamingUtil.CreateIFCElementId(element); if (element is Wall || element is CurtainSystem || IsLegacyCurtainElement(element)) { elemHnd = IFCInstanceExporter.CreateCurtainWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemId); } else if (element is RoofBase) { //need to convert the string to enum string ifcEnumType = CategoryUtil.GetIFCEnumTypeName(exporterIFC, element); elemHnd = IFCInstanceExporter.CreateRoof(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemId, RoofExporter.GetIFCRoofType(ifcEnumType)); } else { return; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd)) { return; } wrapper.AddElement(elemHnd, setter, null, true); ExporterIFCUtils.CreateCurtainWallPropertySet(exporterIFC, element, wrapper); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, wrapper); ICollection <IFCAnyHandle> relatedElementIds = curtainWallSubWrapper.GetAllObjects(); if (relatedElementIds.Count > 0) { string guid = ExporterIFCUtils.CreateSubElementGUID(element, (int)IFCCurtainWallSubElements.RelAggregates); HashSet <IFCAnyHandle> relatedElementIdSet = new HashSet <IFCAnyHandle>(relatedElementIds); IFCInstanceExporter.CreateRelAggregates(file, guid, ownerHistory, null, null, elemHnd, relatedElementIdSet); } exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, element.Id, ElementId.InvalidElementId); } } finally { if (setter != null) { setter.Dispose(); } } } }
/// <summary> /// Export Curtain Walls and Roofs. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="allSubElements"> /// Collection of elements contained in the host curtain element. /// </param> /// <param name="element"> /// The element to be exported. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> public static void ExportBase(ExporterIFC exporterIFC, ICollection<ElementId> allSubElements, Element element, IFCProductWrapper wrapper) { IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCPlacementSetter setter = null; using (IFCProductWrapper curtainWallSubWrapper = IFCProductWrapper.Create(wrapper, false)) { try { IFCAnyHandle localPlacement = null; bool canExportCurtainWallAsContainer = CanExportCurtainWallAsContainer(allSubElements, element.Document); IFCAnyHandle rep = null; if (!canExportCurtainWallAsContainer) { setter = IFCPlacementSetter.Create(exporterIFC, element); localPlacement = setter.GetPlacement(); rep = ExportCurtainObjectCommonAsOneBRep(allSubElements, element, exporterIFC, setter, localPlacement); if (IFCAnyHandleUtil.IsNullOrHasNoValue(rep)) return; } else { ExportCurtainObjectCommonAsContainer(allSubElements, element, exporterIFC, curtainWallSubWrapper); // This has to go LAST. Why? Because otherwise we apply the level transform twice -- once in the familyTrf, once here. // This will be used just to put the CurtainWall on the right level. setter = IFCPlacementSetter.Create(exporterIFC, element); localPlacement = setter.GetPlacement(); } string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); { IFCAnyHandle prodRepHnd = null; IFCAnyHandle elemHnd = null; string elemGUID = ExporterIFCUtils.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, exporterIFC.GetName()); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemId = NamingUtil.CreateIFCElementId(element); if (element is Wall || element is CurtainSystem || IsLegacyCurtainElement(element)) { elemHnd = IFCInstanceExporter.CreateCurtainWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemId); } else if (element is RoofBase) { //need to convert the string to enum string ifcEnumType = CategoryUtil.GetIFCEnumTypeName(exporterIFC, element); elemHnd = IFCInstanceExporter.CreateRoof(file, elemGUID, ownerHistory, elemName, elemDesc, elemType, localPlacement, prodRepHnd, elemId, RoofExporter.GetIFCRoofType(ifcEnumType)); } else { return; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd)) return; wrapper.AddElement(elemHnd, setter, null, true); ExporterIFCUtils.CreateCurtainWallPropertySet(exporterIFC, element, wrapper); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, wrapper); ICollection<IFCAnyHandle> relatedElementIds = curtainWallSubWrapper.GetAllObjects(); if (relatedElementIds.Count > 0) { string guid = ExporterIFCUtils.CreateSubElementGUID(element, (int)IFCCurtainWallSubElements.RelAggregates); HashSet<IFCAnyHandle> relatedElementIdSet = new HashSet<IFCAnyHandle>(relatedElementIds); IFCInstanceExporter.CreateRelAggregates(file, guid, ownerHistory, null, null, elemHnd, relatedElementIdSet); } exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, element.Id, ElementId.InvalidElementId); } } finally { if (setter != null) setter.Dispose(); } } }
/// <summary> /// Main implementation to export walls. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> /// <param name="overrideLevelId"> /// The level id. /// </param> /// <param name="range"> /// The range to be exported for the element. /// </param> /// <returns> /// The exported wall handle. /// </returns> public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCProductWrapper productWrapper, ElementId overrideLevelId, UV range) { using (IFCProductWrapper localWrapper = IFCProductWrapper.Create(productWrapper)) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; FamilyInstance famInstWallElem = element as FamilyInstance; if (wallElement == null && famInstWallElem == null) return IFCAnyHandle.Create(); if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return IFCAnyHandle.Create(); // get global values. Document doc = element.Document; double scale = exporterIFC.LinearScale; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle(); UV zSpan = UV.Zero; double depth = 0.0; bool validRange = (!MathUtil.IsAlmostZero(range.V - range.U)); // get bounding box height so that we can subtract out pieces properly. // only for Wall, not FamilyInstance. if (wallElement != null && geometryElement != null) { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); zSpan = new UV(boundingBox.Min.Z, boundingBox.Max.Z); // if we have a top clipping plane, modify depth accordingly. double bottomHeight = validRange ? Math.Max(zSpan[0], range[0]) : zSpan[0]; double topHeight = validRange ? Math.Min(zSpan[1], range[1]) : zSpan[1]; depth = topHeight - bottomHeight; if (MathUtil.IsAlmostZero(depth)) return IFCAnyHandle.Create(); depth *= scale; } IFCAnyHandle axisRep = IFCAnyHandle.Create(); IFCAnyHandle bodyRep = IFCAnyHandle.Create(); bool exportingAxis = false; Curve curve = null; bool exportedAsWallWithAxis = false; bool exportedBodyDirectly = false; bool exportingInplaceOpenings = false; Curve centerCurve = GetWallAxis(wallElement); XYZ localXDir = new XYZ(1, 0, 0); XYZ localYDir = new XYZ(0, 1, 0); XYZ localZDir = new XYZ(0, 0, 1); XYZ localOrig = new XYZ(0, 0, 0); double eps = MathUtil.Eps(); if (centerCurve != null) { Curve baseCurve = GetWallAxisAtBaseHeight(wallElement); curve = GetWallTrimmedCurve(wallElement, baseCurve); UV curveBounds; XYZ oldOrig; GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig); localOrig = oldOrig; if (baseCurve != null) { if (!validRange || (MathUtil.IsAlmostEqual(range[0], zSpan[0]))) { XYZ newOrig = baseCurve.Evaluate(curveBounds.U, false); if (validRange && (zSpan[0] < newOrig[2] - eps)) localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan[0]); else localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]); } else { localOrig = new XYZ(localOrig.X, localOrig.Y, range[0]); } } double dist = localOrig[2] - oldOrig[2]; if (!MathUtil.IsAlmostZero(dist)) { XYZ moveVec = new XYZ(0, 0, dist); curve = GeometryUtil.MoveCurve(curve, moveVec); } localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } Transform orientationTrf = Transform.Identity; orientationTrf.BasisX = localXDir; orientationTrf.BasisY = localYDir; orientationTrf.BasisZ = localZDir; orientationTrf.Origin = localOrig; using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.GetPlacement(); Plane plane = new Plane(localXDir, localYDir, localOrig); // project curve to XY plane. XYZ projDir = new XYZ(0, 0, 1); // two representations: axis, body. { if ((centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve))) { exportingAxis = true; IFCLabel identifierOpt = IFCLabel.Create("Axis"); // IFC2x2 convention IFCLabel representationTypeOpt = IFCLabel.Create("Curve2D"); // IFC2x2 convention IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true); IList<IFCAnyHandle> axisItems = info.GetCurves(); if (axisItems.Count == 0) { exportingAxis = false; } else { HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>(); foreach (IFCAnyHandle axisItem in axisItems) axisItemSet.Add(axisItem); axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, catId, contextOfItems, identifierOpt, representationTypeOpt, axisItemSet); } } } IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>(); do { if (wallElement == null || !exportingAxis || curve == null) break; bool hasExtrusion = HasElevationProfile(wallElement); if (hasExtrusion) { IList<CurveLoop> loops = GetElevationProfile(wallElement); if (loops.Count == 0) hasExtrusion = false; else { IList<IList<CurveLoop>> sortedLoops = ExporterIFCUtils.SortCurveLoops(loops); if (sortedLoops.Count == 0) break; // Current limitation: can't handle wall split into multiple disjointed pieces. int numSortedLoops = sortedLoops.Count; if (numSortedLoops > 1) break; bool ignoreExtrusion = true; bool cantHandle = false; bool hasGeometry = false; for (int ii = 0; (ii < numSortedLoops) && !cantHandle; ii++) { int sortedLoopSize = sortedLoops[ii].Count; if (sortedLoopSize == 0) continue; if (!ExporterIFCUtils.IsCurveLoopConvexWithOpenings(sortedLoops[ii][0], range, wallElement, out ignoreExtrusion)) { if (ignoreExtrusion) { // we need more information. Is there something to export? If so, we'll // ignore the extrusion. Otherwise, we will fail. IFCSolidMeshGeometryInfo solidMeshInfo = ExporterIFCUtils.GetClippedSolidMeshGeometry(exporterIFC, range, geometryElement); if (solidMeshInfo.GetSolids().Count == 0 && solidMeshInfo.GetMeshes().Count == 0) continue; hasExtrusion = false; } else { cantHandle = true; } hasGeometry = true; } else { hasGeometry = true; } } if (!hasGeometry) return IFCAnyHandle.Create(); if (cantHandle) break; } } if (!CanExportWallGeometryAsExtrusion(element, range)) break; // extrusion direction. XYZ extrusionDir = GetWallHeightDirection(wallElement); // create extrusion boundary. IList<CurveLoop> boundaryLoops = new List<CurveLoop>(); bool alwaysThickenCurve = IsWallBaseRectangular(wallElement, curve); if (!alwaysThickenCurve) { boundaryLoops = GetLoopsFromTopBottomFace(wallElement, exporterIFC); if (boundaryLoops.Count == 0) continue; } else { CurveLoop newLoop = CurveLoop.CreateViaThicken(curve, wallElement.Width, new XYZ(0, 0, 1)); if (newLoop == null) break; if (!GeometryUtil.IsIFCLoopCCW(newLoop, new XYZ(0, 0, 1))) newLoop = GeometryUtil.ReverseOrientation(newLoop); boundaryLoops.Add(newLoop); } // origin gets scaled later. XYZ setterOffset = new XYZ(0, 0, setter.Offset + (localOrig[2] - setter.BaseOffset)); IFCAnyHandle baseBodyItemHnd = file.CreateExtrudedSolidFromCurveLoop(exporterIFC, catId, boundaryLoops, plane, extrusionDir, depth); if (!baseBodyItemHnd.HasValue) break; IFCAnyHandle bodyItemHnd = AddClippingsToBaseExtrusion(exporterIFC, wallElement, setterOffset, range, zSpan, baseBodyItemHnd, out cutPairOpenings); if (!bodyItemHnd.HasValue) break; HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(bodyItemHnd); if (baseBodyItemHnd.Id == bodyItemHnd.Id) { bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, catId, contextOfItems, bodyItems, IFCAnyHandle.Create()); } else { bodyRep = RepresentationUtil.CreateClippingRep(exporterIFC, catId, contextOfItems, bodyItems); } if (bodyRep.HasValue) exportedAsWallWithAxis = true; } while (false); IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData(); ElementId matId = ElementId.InvalidElementId; if (!exportedAsWallWithAxis) { IFCSolidMeshGeometryInfo solidMeshInfo; if (wallElement != null) { if (validRange) { solidMeshInfo = ExporterIFCUtils.GetClippedSolidMeshGeometry(exporterIFC, range, geometryElement); if (solidMeshInfo.GetSolids().Count == 0 && solidMeshInfo.GetMeshes().Count == 0) return IFCAnyHandle.Create(); } else { solidMeshInfo = ExporterIFCUtils.GetSplitSolidMeshGeometry(exporterIFC, geometryElement); } } else { GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem); if (geomElemToUse != null) { exportingInplaceOpenings = true; } else { exportingInplaceOpenings = false; geomElemToUse = geometryElement; } Transform trf = Transform.Identity; if (geomElemToUse != geometryElement) trf = famInstWallElem.GetTransform(); solidMeshInfo = ExporterIFCUtils.GetSolidMeshGeometry(exporterIFC, geomElemToUse, trf); } IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> meshes = solidMeshInfo.GetMeshes(); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; if ((solids.Count > 0) || (meshes.Count > 0)) { matId = BodyExporter.GetBestMaterialIdForGeometry(solids, meshes); bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, catId, solids, meshes, true, extraParams); } else { IList<GeometryObject> geomElemList = new List<GeometryObject>(); geomElemList.Add(geometryElement); bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, catId, geomElemList, true, extraParams); } if (!bodyRep.HasValue) return IFCAnyHandle.Create(); // We will be able to export as a IfcWallStandardCase as long as we have an axis curve. XYZ extrDirUsed = XYZ.Zero; if (extraParams.HasCustomAxis) { extrDirUsed = extraParams.CustomAxis; if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0)) { if ((solids.Count == 1) && (meshes.Count == 0)) exportedAsWallWithAxis = exportingAxis; exportedBodyDirectly = true; } } } IFCAnyHandle prodRep = IFCAnyHandle.Create(); IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (exportingAxis) representations.Add(axisRep); representations.Add(bodyRep); prodRep = file.CreateProductDefinitionShape(IFCLabel.Create(), IFCLabel.Create(), representations); IFCLabel objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = IFCAnyHandle.Create(); IFCLabel elemGUID = (validRange) ? IFCLabel.CreateGUID() : IFCLabel.CreateGUID(element); IFCLabel elemName = NamingUtil.GetNameOverride(element, NamingUtil.CreateIFCName(exporterIFC, -1)); IFCLabel elemDesc = NamingUtil.GetDescriptionOverride(element, IFCLabel.Create()); IFCLabel elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); IFCLabel elemId = NamingUtil.CreateIFCElementId(element); if (exportedAsWallWithAxis) { wallHnd = file.CreateWallStandardCase(elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, elemId, prodRep); localWrapper.AddElement(wallHnd, setter, extraParams, true); OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, exporterIFC, localPlacement, setter, localWrapper); if (exportedBodyDirectly) { OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper); } else { double scaledWidth = wallElement.Width * scale; ExporterIFCUtils.AddOpeningsToWall(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper); } // export Base Quantities if (exporterIFC.ExportBaseQuantities) { CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth); } } else { wallHnd = file.CreateWall(elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, elemId, prodRep); localWrapper.AddElement(wallHnd, setter, extraParams, true); // Only export one material for 2x2; for future versions, export the whole list. if (exporterIFC.ExportAs2x2 && (matId != ElementId.InvalidElementId)) { CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, wallHnd, matId); } if (exportingInplaceOpenings) { double scaledWidth = wallElement.Width * scale; ExporterIFCUtils.AddOpeningsToWall(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper); } if (exportedBodyDirectly) OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper); } ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, element, localWrapper); ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; if (wallElement != null) ExporterIFCUtils.ExportHostObject(exporterIFC, wallElement, geometryElement, localWrapper); exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId); return wallHnd; } } }