/// <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> /// <param name="containsBRepGeometry">True if the geometry contains BRep geoemtry. If so, we will export an IfcMaterialList</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, bool containsBRepGeometry) { 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 scaledOffset = 0.0, scaledWallWidth = 0.0, wallHeight = 0.0; Wall wall = hostObject as Wall; if (wall != null) { scaledWallWidth = UnitUtil.ScaleLength(wall.Width); scaledOffset = -scaledWallWidth / 2.0; BoundingBoxXYZ boundingBox = wall.get_BoundingBox(null); if (boundingBox != null) { wallHeight = boundingBox.Max.Z - boundingBox.Min.Z; } } List <ElementId> matIds; IFCAnyHandle primaryMaterialHnd; IFCAnyHandle materialLayerSet = ExporterUtil.CollectMaterialLayerSet(exporterIFC, hostObject, productWrapper, out matIds, out primaryMaterialHnd); if (containsBRepGeometry && matIds.Count > 0) { foreach (IFCAnyHandle elemHnd in elemHnds) { CategoryUtil.CreateMaterialAssociation(exporterIFC, elemHnd, matIds); } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(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; } SpaceBoundingElementUtil.RegisterSpaceBoundingElementHandle(exporterIFC, elemHnd, hostObject.Id, levelId); if (containsBRepGeometry) { continue; } HashSet <IFCAnyHandle> relDecomposesSet = IFCAnyHandleUtil.GetRelDecomposes(elemHnd); IList <IFCAnyHandle> subElemHnds = null; if (relDecomposesSet != null && relDecomposesSet.Count == 1) { IFCAnyHandle relAggregates = relDecomposesSet.First(); if (IFCAnyHandleUtil.IsTypeOf(relAggregates, IFCEntityType.IfcRelAggregates)) { subElemHnds = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(relAggregates, "RelatedObjects"); } } bool hasSubElems = (subElemHnds != null && subElemHnds.Count != 0); bool isRoof = IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcRoof); bool isDisallowedWallType = (IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcWall) && !ExporterCacheManager.ExportOptionsCache.ExportAs4); // Create IfcMaterialLayerSetUsage unless we have sub-elements, are exporting a Roof, or are exporting a pre-IFC4 IfcWall. if (!hasSubElems && !isRoof && !isDisallowedWallType) { 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; Transform lcs = Transform.Identity; bool curveFlipped = GeometryUtil.MustFlipCurve(lcs, curve); flipDirSense = !(wall.Flipped ^ curveFlipped); } } else if (hostObject is CeilingAndFloor) { 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); } } } } tr.Commit(); return(true); } }
/// <summary> /// Exports a beam to IFC beam if it has an axis representation and only one Solid as its geometry, ideally as an extrusion, potentially with clippings and openings. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element to be exported.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <param name="dontExport">An output value that says that the element shouldn't be exported at all.</param> /// <returns>The created handle.</returns> /// <remarks>In the original implementation, the ExportBeam function would export each beam as its own individual geometry (that is, not use representation maps). /// For non-standard beams, this could result in massive IFC files. Now, we use the ExportBeamAsStandardElement function and limit its scope, and instead /// resort to the standard FamilyInstanceExporter.ExportFamilyInstanceAsMappedItem for more complicated objects categorized as beams. This has the following pros and cons: /// Pro: possiblity for massively reduced file sizes for files containing repeated complex beam families /// Con: some beams that may have had an "Axis" representation before will no longer have them, although this possibility is minimized. /// Con: some beams that have 1 Solid and an axis, but that Solid will be heavily faceted, won't be helped by this improvement. /// It is intended that we phase out this routine entirely and instead teach ExportFamilyInstanceAsMappedItem how to sometimes export the Axis representation for beams.</remarks> public static IFCAnyHandle ExportBeamAsStandardElement(ExporterIFC exporterIFC, Element element, IFCExportInfoPair exportType, GeometryElement geometryElement, ProductWrapper productWrapper, out bool dontExport) { dontExport = true; IList <GeometryObject> geomObjects = BeamGeometryToExport(exporterIFC, element, geometryElement, out dontExport); if (dontExport) { return(null); } IFCAnyHandle beam = null; IFCFile file = exporterIFC.GetFile(); MaterialAndProfile materialAndProfile = null; IFCAnyHandle materialProfileSet = null; using (IFCTransaction transaction = new IFCTransaction(file)) { BeamAxisInfo axisInfo = GetBeamAxisTransform(element); bool canExportAxis = (axisInfo != null); Curve curve = canExportAxis ? axisInfo.Axis : null; XYZ beamDirection = canExportAxis ? axisInfo.AxisDirection : null; Transform orientTrf = canExportAxis ? axisInfo.LCSAsTransform : null; // Check for containment override IFCAnyHandle overrideContainerHnd = null; ElementId overrideContainerId = ParameterUtil.OverrideContainmentParameter(exporterIFC, element, out overrideContainerHnd); using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, orientTrf, overrideContainerId, overrideContainerHnd)) { IFCAnyHandle localPlacement = setter.LocalPlacement; using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { extrusionCreationData.SetLocalPlacement(localPlacement); if (canExportAxis && (orientTrf.BasisX != null)) { extrusionCreationData.CustomAxis = beamDirection; extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom; } else { extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryXY; } ElementId catId = CategoryUtil.GetSafeCategoryId(element); // There may be an offset to make the local coordinate system // be near the origin. This offset will be used to move the axis to the new LCS. Transform offsetTransform = null; // The list of materials in the solids or meshes. ICollection <ElementId> materialIds = null; // If the beam is a FamilyInstance, and it uses transformed FamilySymbol geometry only, then // let's only try to CreateBeamGeometryAsExtrusion unsuccesfully once. Otherwise, we can spend a lot of time trying // unsuccessfully to do so. bool tryToCreateBeamGeometryAsExtrusion = true; //bool useFamilySymbolGeometry = (element is FamilyInstance) ? !ExporterIFCUtils.UsesInstanceGeometry(element as FamilyInstance) : false; bool useFamilySymbolGeometry = (element is FamilyInstance) && !GeometryUtil.UsesInstanceGeometry(element as FamilyInstance); ElementId beamTypeId = element.GetTypeId(); if (useFamilySymbolGeometry) { tryToCreateBeamGeometryAsExtrusion = !ExporterCacheManager.CanExportBeamGeometryAsExtrusionCache.ContainsKey(beamTypeId) || ExporterCacheManager.CanExportBeamGeometryAsExtrusionCache[beamTypeId]; } // The representation handle generated from one of the methods below. BeamBodyAsExtrusionInfo extrusionInfo = null; if (tryToCreateBeamGeometryAsExtrusion) { extrusionInfo = CreateBeamGeometryAsExtrusion(exporterIFC, element, catId, geomObjects, axisInfo); if (useFamilySymbolGeometry) { ExporterCacheManager.CanExportBeamGeometryAsExtrusionCache[beamTypeId] = (extrusionInfo != null); } } if (extrusionInfo != null && extrusionInfo.DontExport) { dontExport = true; return(null); } IFCAnyHandle repHnd = extrusionInfo?.RepresentationHandle; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { materialIds = extrusionInfo.Materials; extrusionCreationData.Slope = extrusionInfo.Slope; } else { // Here is where we limit the scope of how complex a case we will still try to export as a standard element. // This is explicitly added so that many curved beams that can be represented by a reasonable facetation because of the // SweptSolidExporter can still have an Axis representation. BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { bodyExporterOptions.CollectMaterialAndProfile = false; } else { bodyExporterOptions.CollectMaterialAndProfile = true; } if (geomObjects != null && geomObjects.Count == 1 && geomObjects[0] is Solid) { bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, geomObjects[0], bodyExporterOptions, extrusionCreationData); repHnd = bodyData.RepresentationHnd; materialIds = bodyData.MaterialIds; if (!bodyData.OffsetTransform.IsIdentity) { offsetTransform = bodyData.OffsetTransform; } materialAndProfile = bodyData.MaterialAndProfile; } } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { extrusionCreationData.ClearOpenings(); return(null); } IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); IFCAnyHandle axisRep = CreateBeamAxis(exporterIFC, element, catId, axisInfo, offsetTransform); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(axisRep)) { representations.Add(axisRep); } representations.Add(repHnd); Transform boundingBoxTrf = offsetTransform?.Inverse ?? Transform.Identity; IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, boundingBoxTrf); if (boundingBoxRep != null) { representations.Add(boundingBoxRep); } IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); string instanceGUID = GUIDUtil.CreateGUID(element); beam = IFCInstanceExporter.CreateBeam(exporterIFC, element, instanceGUID, ExporterCacheManager.OwnerHistoryHandle, extrusionCreationData.GetLocalPlacement(), prodRep, exportType.ValidatedPredefinedType); IFCAnyHandle mpSetUsage; if (materialProfileSet != null) { mpSetUsage = IFCInstanceExporter.CreateMaterialProfileSetUsage(file, materialProfileSet, null, null); } productWrapper.AddElement(element, beam, setter, extrusionCreationData, true, exportType); ExportBeamType(exporterIFC, productWrapper, beam, element, exportType.ValidatedPredefinedType); OpeningUtil.CreateOpeningsIfNecessary(beam, element, extrusionCreationData, offsetTransform, exporterIFC, extrusionCreationData.GetLocalPlacement(), setter, productWrapper); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); typeInfo.extraParams = extrusionCreationData; PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, beam, element, typeInfo, null); if (materialIds.Count != 0) { CategoryUtil.CreateMaterialAssociation(exporterIFC, beam, materialIds); } // Register the beam's IFC handle for later use by truss and beam system export. ExporterCacheManager.ElementToHandleCache.Register(element.Id, beam, exportType); } } transaction.Commit(); return(beam); } }
/// <summary> /// Exports an element as a covering of type insulation. /// </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 ProductWrapper.</param> /// <returns>True if exported successfully, false otherwise.</returns> protected static bool ExportInsulation(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { if (element == null || geometryElement == null) { return(false); } // Check the intended IFC entity or type name is in the exclude list specified in the UI Common.Enums.IFCEntityType elementClassTypeEnum = Common.Enums.IFCEntityType.IfcCovering; if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum)) { return(false); } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { // Check for containment override IFCAnyHandle overrideContainer = null; ElementId overrideContainerId = ParameterUtil.OverrideContainmentParameter(exporterIFC, element, out overrideContainer); using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, element, null, null, overrideContainerId, overrideContainer)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(placementSetter.LocalPlacement); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); IFCAnyHandle representation = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, categoryId, geometryElement, bodyExporterOptions, null, ecData, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(representation)) { ecData.ClearOpenings(); return(false); } string guid = GUIDUtil.CreateGUID(element); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; IFCAnyHandle localPlacement = ecData.GetLocalPlacement(); IFCAnyHandle insulation = IFCInstanceExporter.CreateCovering(exporterIFC, element, guid, ownerHistory, localPlacement, representation, "Insulation"); IFCExportInfoPair exportInfo = new IFCExportInfoPair(IFCEntityType.IfcCovering, "Insulation"); ExporterCacheManager.ElementToHandleCache.Register(element.Id, insulation); productWrapper.AddElement(element, insulation, placementSetter.LevelInfo, ecData, true, exportInfo); ElementId matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, element); CategoryUtil.CreateMaterialAssociation(exporterIFC, insulation, matId); } } tr.Commit(); return(true); } }
private static bool ExportGenericElementAsMappedItem(ExporterIFC exporterIFC, Element element, GeometryElement geomElem, IFCExportInfoPair exportType, ProductWrapper wrapper) { GeometryInstance geometryInstance = GetTheGeometryInstance(geomElem); if (geometryInstance == null) { return(false); } GeometryElement exportGeometry = geometryInstance.GetSymbolGeometry(); if (exportGeometry == null) { return(false); } ElementId symbolId = geometryInstance.GetSymbolGeometryId()?.SymbolId ?? ElementId.InvalidElementId; ElementType elementType = element.Document.GetElement(symbolId) as ElementType; if (elementType == null) { return(false); } Transform originalTrf = geometryInstance.Transform; // Can't handle mirrored transforms yet. if (originalTrf.HasReflection) { return(false); } ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); IFCFile file = exporterIFC.GetFile(); IList <Transform> repMapTrfList = new List <Transform>(); BodyData bodyData = null; FamilyTypeInfo typeInfo = new FamilyTypeInfo(); IFCExtrusionCreationData extraParams = typeInfo.extraParams; Transform offsetTransform = Transform.Identity; // We will create a new mapped type if we haven't already created the type. FamilyTypeInfo currentTypeInfo = ExporterCacheManager.FamilySymbolToTypeInfoCache.Find(symbolId, false, exportType); bool found = currentTypeInfo.IsValid(); if (!found) { IList <IFCAnyHandle> representations3D = new List <IFCAnyHandle>(); IFCAnyHandle dummyPlacement = ExporterUtil.CreateLocalPlacement(file, null, null); extraParams.SetLocalPlacement(dummyPlacement); using (TransformSetter trfSetter = TransformSetter.Create()) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(false, ExportOptionsCache.ExportTessellationLevel.ExtraLow); bodyData = BodyExporter.ExportBody(exporterIFC, element, categoryId, ExporterUtil.GetSingleMaterial(element), exportGeometry, bodyExporterOptions, extraParams); typeInfo.MaterialIdList = bodyData.MaterialIds; offsetTransform = bodyData.OffsetTransform; // This code does not handle openings yet. // The intention for this is FabricationParts and DirectShapes which do not // currently have opening. // If they can have openings in the future, we can add this. IFCAnyHandle bodyRepHnd = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepHnd) || extraParams.GetOpenings().Count > 0) { return(false); } representations3D.Add(bodyRepHnd); repMapTrfList.Add(null); } typeInfo.StyleTransform = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, extraParams.GetLocalPlacement()); IFCAnyHandle typeStyle = FamilyInstanceExporter.CreateTypeEntityHandle(exporterIFC, ref typeInfo, null, representations3D, repMapTrfList, null, element, elementType, elementType, false, false, exportType, out HashSet <IFCAnyHandle> propertySets); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle)) { wrapper.RegisterHandleWithElementType(elementType, exportType, typeStyle, propertySets); typeInfo.Style = typeStyle; CategoryUtil.TryToCreateMaterialAssocation(exporterIFC, bodyData, elementType, element, exportGeometry, typeStyle, typeInfo); // Create other generic classification from ClassificationCode(s) ClassificationUtil.CreateClassification(exporterIFC, file, elementType, typeStyle); ClassificationUtil.CreateUniformatClassification(exporterIFC, file, elementType, typeStyle); } } if (found && !typeInfo.IsValid()) { typeInfo = currentTypeInfo; } // we'll pretend we succeeded, but we'll do nothing. if (!typeInfo.IsValid()) { return(false); } extraParams = typeInfo.extraParams; // We expect no openings, so always add to map. ExporterCacheManager.FamilySymbolToTypeInfoCache.Register(symbolId, false, exportType, typeInfo); XYZ scaledMapOrigin = XYZ.Zero; Transform scaledTrf = originalTrf.Multiply(typeInfo.StyleTransform); // create instance. IList <IFCAnyHandle> shapeReps = FamilyInstanceExporter.CreateShapeRepresentations(exporterIFC, file, element, categoryId, typeInfo, scaledMapOrigin); if (shapeReps == null) { return(false); } Transform boundingBoxTrf = (offsetTransform != null) ? offsetTransform.Inverse : Transform.Identity; boundingBoxTrf = boundingBoxTrf.Multiply(scaledTrf.Inverse); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomElem, boundingBoxTrf); if (boundingBoxRep != null) { shapeReps.Add(boundingBoxRep); } IFCAnyHandle repHnd = (shapeReps.Count > 0) ? IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps) : null; using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, scaledTrf, null)) { IFCAnyHandle instanceHandle = null; IFCAnyHandle localPlacement = setter.LocalPlacement; bool materialAlreadyAssociated = false; // We won't create the instance if: // (1) we are exporting to CV2.0/RV, (2) we have no 2D, 3D, or bounding box geometry, and (3) we aren't exporting parts. if (!(repHnd == null && (ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2 || ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView))) { string instanceGUID = GUIDUtil.CreateGUID(element); bool isChildInContainer = element.AssemblyInstanceId != ElementId.InvalidElementId; if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { bool isBuildingElementProxy = ((exportType.ExportInstance == IFCEntityType.IfcBuildingElementProxy) || (exportType.ExportType == IFCEntityType.IfcBuildingElementProxyType)); ElementId roomId = setter.UpdateRoomRelativeCoordinates(element, out IFCAnyHandle localPlacementToUse); bool containedInSpace = (roomId != ElementId.InvalidElementId) && (exportType.ExportInstance != IFCEntityType.IfcSystemFurnitureElement); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; if (!isBuildingElementProxy) { instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(exportType, exporterIFC, element, instanceGUID, ownerHistory, localPlacementToUse, repHnd); } else { instanceHandle = IFCInstanceExporter.CreateBuildingElementProxy(exporterIFC, element, instanceGUID, ownerHistory, localPlacementToUse, repHnd, exportType.ValidatedPredefinedType); } bool associateToLevel = !containedInSpace && !isChildInContainer; wrapper.AddElement(element, instanceHandle, setter, extraParams, associateToLevel, exportType); if (containedInSpace) { ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle); } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { if (ElementFilteringUtil.IsMEPType(exportType) || ElementFilteringUtil.ProxyForMEPType(element, exportType)) { ExporterCacheManager.MEPCache.Register(element, instanceHandle); } ExporterCacheManager.HandleToElementCache.Register(instanceHandle, element.Id); if (!materialAlreadyAssociated) { // Create material association for the instance only if the the istance geometry is different from the type // or the type does not have any material association IFCAnyHandle constituentSetHnd = ExporterCacheManager.MaterialSetCache.FindConstituentSetHnd(symbolId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(constituentSetHnd) && bodyData != null && bodyData.RepresentationItemInfo != null && bodyData.RepresentationItemInfo.Count > 0) { CategoryUtil.CreateMaterialAssociationWithShapeAspect(exporterIFC, element, instanceHandle, bodyData.RepresentationItemInfo); } else { // Create material association in case if bodyData is null CategoryUtil.CreateMaterialAssociation(exporterIFC, instanceHandle, typeInfo.MaterialIdList); } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeInfo.Style)) { ExporterCacheManager.TypeRelationsCache.Add(typeInfo.Style, instanceHandle); } } } } return(true); }
/// <summary> /// Exports an element to IfcPile. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="ifcEnumType">The string value represents the IFC type.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportPile(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, string ifcEnumType, ProductWrapper productWrapper) { // NOTE: We expect to incorporate this code into the generic FamilyInstanceExporter at some point. // Export parts or not bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, element.LevelId, false)) { return; } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { // Check for containment override IFCAnyHandle overrideContainerHnd = null; ElementId overrideContainerId = ParameterUtil.OverrideContainmentParameter(exporterIFC, element, out overrideContainerHnd); using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, null, overrideContainerId, overrideContainerHnd)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(setter.LocalPlacement); IFCAnyHandle prodRep = null; ElementId matId = ElementId.InvalidElementId; if (!exportParts) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); StructuralMemberAxisInfo axisInfo = StructuralMemberExporter.GetStructuralMemberAxisTransform(element); if (axisInfo != null) { ecData.CustomAxis = axisInfo.AxisDirection; ecData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom; } else { ecData.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; } prodRep = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, catId, geometryElement, bodyExporterOptions, null, ecData, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodRep)) { ecData.ClearOpenings(); return; } } string instanceGUID = GUIDUtil.CreateGUID(element); IFCExportInfoPair exportInfo = new IFCExportInfoPair(Common.Enums.IFCEntityType.IfcPile, ifcEnumType); IFCAnyHandle pile = IFCInstanceExporter.CreatePile(exporterIFC, element, instanceGUID, ExporterCacheManager.OwnerHistoryHandle, ecData.GetLocalPlacement(), prodRep, ifcEnumType, null); // TODO: to allow shared geometry for Piles. For now, Pile export will not use shared geometry if (exportInfo.ExportType != Common.Enums.IFCEntityType.UnKnown) { IFCAnyHandle type = ExporterUtil.CreateGenericTypeFromElement(element, exportInfo, file, ExporterCacheManager.OwnerHistoryHandle, exportInfo.ValidatedPredefinedType, productWrapper); ExporterCacheManager.TypeRelationsCache.Add(type, pile); } if (exportParts) { PartExporter.ExportHostPart(exporterIFC, element, pile, productWrapper, setter, setter.LocalPlacement, null); } else { if (matId != ElementId.InvalidElementId) { CategoryUtil.CreateMaterialAssociation(exporterIFC, pile, matId); } } productWrapper.AddElement(element, pile, setter, ecData, true, exportInfo); OpeningUtil.CreateOpeningsIfNecessary(pile, element, ecData, null, exporterIFC, ecData.GetLocalPlacement(), setter, productWrapper); } } tr.Commit(); } }
/// <summary> /// Exports a ramp to IfcRamp, without decomposing into separate runs and landings. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="ifcEnumType">The ramp type.</param> /// <param name="ramp">The ramp element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="numFlights">The number of flights for a multistory ramp.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportRamp(ExporterIFC exporterIFC, string ifcEnumType, Element ramp, GeometryElement geometryElement, int numFlights, ProductWrapper productWrapper) { if (ramp == null || geometryElement == null) { return; } // Check the intended IFC entity or type name is in the exclude list specified in the UI Common.Enums.IFCEntityType elementClassTypeEnum; if (Enum.TryParse <Common.Enums.IFCEntityType>("IfcRamp", out elementClassTypeEnum)) { if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum)) { return; } } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, ramp)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(placementSetter.LocalPlacement); ecData.ReuseLocalPlacement = false; GeometryElement rampGeom = GeometryUtil.GetOneLevelGeometryElement(geometryElement, numFlights); BodyData bodyData; ElementId categoryId = CategoryUtil.GetSafeCategoryId(ramp); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); IFCAnyHandle representation = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, ramp, categoryId, rampGeom, bodyExporterOptions, null, ecData, out bodyData); if (IFCAnyHandleUtil.IsNullOrHasNoValue(representation)) { ecData.ClearOpenings(); return; } string containedRampGuid = GUIDUtil.CreateSubElementGUID(ramp, (int)IFCRampSubElements.ContainedRamp); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; IFCAnyHandle containedRampLocalPlacement = ExporterUtil.CreateLocalPlacement(file, ecData.GetLocalPlacement(), null); string rampType = GetIFCRampType(ifcEnumType); List <IFCAnyHandle> components = new List <IFCAnyHandle>(); IList <IFCExtrusionCreationData> componentExtrusionData = new List <IFCExtrusionCreationData>(); IFCAnyHandle containedRampHnd = IFCInstanceExporter.CreateRamp(exporterIFC, ramp, containedRampGuid, ownerHistory, containedRampLocalPlacement, representation, rampType); components.Add(containedRampHnd); componentExtrusionData.Add(ecData); //productWrapper.AddElement(containedRampHnd, placementSetter.LevelInfo, ecData, false); CategoryUtil.CreateMaterialAssociation(exporterIFC, containedRampHnd, bodyData.MaterialIds); string guid = GUIDUtil.CreateGUID(ramp); IFCAnyHandle localPlacement = ecData.GetLocalPlacement(); IFCAnyHandle rampHnd = IFCInstanceExporter.CreateRamp(exporterIFC, ramp, guid, ownerHistory, localPlacement, null, rampType); productWrapper.AddElement(ramp, rampHnd, placementSetter.LevelInfo, ecData, true); StairRampContainerInfo stairRampInfo = new StairRampContainerInfo(rampHnd, components, localPlacement); ExporterCacheManager.StairRampContainerInfoCache.AddStairRampContainerInfo(ramp.Id, stairRampInfo); ExportMultistoryRamp(exporterIFC, ramp, numFlights, rampHnd, components, componentExtrusionData, placementSetter, productWrapper); } tr.Commit(); } } }
/// <summary> /// Exports a roof to IfcRoof. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="ifcEnumType">The roof type.</param> /// <param name="roof">The roof element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportRoof(ExporterIFC exporterIFC, string ifcEnumType, Element roof, GeometryElement geometryElement, ProductWrapper productWrapper) { if (roof == null || geometryElement == null) { return; } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, roof)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { // If the roof is an in-place family, we will allow any arbitrary orientation. While this may result in some // in-place "cubes" exporting with the wrong direction, it is unlikely that an in-place family would be // used for this reason in the first place. ecData.PossibleExtrusionAxes = (roof is FamilyInstance) ? IFCExtrusionAxes.TryXYZ : IFCExtrusionAxes.TryZ; ecData.AreInnerRegionsOpenings = true; ecData.SetLocalPlacement(placementSetter.LocalPlacement); ElementId categoryId = CategoryUtil.GetSafeCategoryId(roof); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); BodyData bodyData; IFCAnyHandle representation = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, roof, categoryId, geometryElement, bodyExporterOptions, null, ecData, out bodyData); if (IFCAnyHandleUtil.IsNullOrHasNoValue(representation)) { ecData.ClearOpenings(); return; } bool exportSlab = ecData.ScaledLength > MathUtil.Eps(); string guid = GUIDUtil.CreateGUID(roof); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; IFCAnyHandle localPlacement = ecData.GetLocalPlacement(); string predefinedType = GetIFCRoofType(ifcEnumType); //roofType = IFCValidateEntry.GetValidIFCPredefinedType(roof, ifcEnumType); IFCAnyHandle roofHnd = IFCInstanceExporter.CreateRoof(exporterIFC, roof, guid, ownerHistory, localPlacement, exportSlab ? null : representation, predefinedType); // Export IfcRoofType IFCExportInfoPair exportInfo = new IFCExportInfoPair(IFCEntityType.IfcRoof, IFCEntityType.IfcRoofType, null); if (exportInfo.ExportType != IFCEntityType.UnKnown) { if ((ParameterUtil.GetStringValueFromElementOrSymbol(roof, "IfcExportType", out predefinedType) == null) && // change IFCType to consistent parameter of IfcExportType (ParameterUtil.GetStringValueFromElementOrSymbol(roof, "IfcType", out predefinedType) == null)) // support IFCType for legacy support { predefinedType = "NotDefined"; } exportInfo.ValidatedPredefinedType = predefinedType; IFCAnyHandle typeHnd = ExporterUtil.CreateGenericTypeFromElement(roof, exportInfo, file, ownerHistory, predefinedType, productWrapper); ExporterCacheManager.TypeRelationsCache.Add(typeHnd, roofHnd); } productWrapper.AddElement(roof, roofHnd, placementSetter.LevelInfo, ecData, true); // will export its host object materials later if it is a roof if (!(roof is RoofBase)) { CategoryUtil.CreateMaterialAssociation(exporterIFC, roofHnd, bodyData.MaterialIds); } if (exportSlab) { string slabGUID = GUIDUtil.CreateSubElementGUID(roof, (int)IFCRoofSubElements.RoofSlabStart); string slabName = IFCAnyHandleUtil.GetStringAttribute(roofHnd, "Name") + ":1"; IFCAnyHandle slabLocalPlacementHnd = ExporterUtil.CopyLocalPlacement(file, localPlacement); IFCAnyHandle slabHnd = IFCInstanceExporter.CreateSlab(exporterIFC, roof, slabGUID, ownerHistory, slabLocalPlacementHnd, representation, "ROOF"); IFCAnyHandleUtil.OverrideNameAttribute(slabHnd, slabName); Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(slabHnd, roof, ecData, offsetTransform, exporterIFC, slabLocalPlacementHnd, placementSetter, productWrapper); ExporterUtil.RelateObject(exporterIFC, roofHnd, slabHnd); productWrapper.AddElement(null, slabHnd, placementSetter.LevelInfo, ecData, false); CategoryUtil.CreateMaterialAssociation(exporterIFC, slabHnd, bodyData.MaterialIds); } } tr.Commit(); } } }
/// <summary> /// Exports a roof or floor as a container of multiple roof slabs. Returns the handle, if successful. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="element">The roof or floor element.</param> /// <param name="geometry">The geometry of the element.</param> /// <param name="productWrapper">The product wrapper.</param> /// <returns>The roof handle.</returns> /// <remarks>For floors, if there is only one component, return null, as we do not want to create a container.</remarks> public static IFCAnyHandle ExportRoofOrFloorAsContainer(ExporterIFC exporterIFC, Element element, GeometryElement geometry, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); // We support ExtrusionRoofs, FootPrintRoofs, and Floors only. bool elementIsRoof = (element is ExtrusionRoof) || (element is FootPrintRoof); bool elementIsFloor = (element is Floor); if (!elementIsRoof && !elementIsFloor) { return(null); } string ifcEnumType; IFCExportInfoPair roofExportType = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType); if (roofExportType.IsUnKnown) { IFCEntityType elementClassTypeEnum = elementIsFloor ? IFCEntityType.IfcSlab: IFCEntityType.IfcRoof; roofExportType = new IFCExportInfoPair(elementClassTypeEnum, ""); } // Check the intended IFC entity or type name is in the exclude list specified in the UI if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(roofExportType.ExportType)) { return(null); } Document doc = element.Document; using (SubTransaction tempPartTransaction = new SubTransaction(doc)) { MaterialLayerSetInfo layersetInfo = new MaterialLayerSetInfo(exporterIFC, element, productWrapper); bool hasLayers = false; if (layersetInfo.MaterialIds.Count > 1) { hasLayers = true; } bool exportByComponents = ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView && hasLayers; using (IFCTransaction transaction = new IFCTransaction(file)) { // Check for containment override IFCAnyHandle overrideContainerHnd = null; ElementId overrideContainerId = ParameterUtil.OverrideContainmentParameter(exporterIFC, element, out overrideContainerHnd); // We want to delay creating entity handles until as late as possible, so that if we abort the IFC transaction, // we don't have to delete elements. This is both for performance reasons and to potentially extend the number // of projects that can be exported by reducing (a small amount) of waste. IList <HostObjectSubcomponentInfo> hostObjectSubcomponents = null; try { hostObjectSubcomponents = ExporterIFCUtils.ComputeSubcomponents(element as HostObject); } catch { return(null); } if (hostObjectSubcomponents == null) { return(null); } int numSubcomponents = hostObjectSubcomponents.Count; if (numSubcomponents == 0 || (elementIsFloor && numSubcomponents == 1)) { return(null); } using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, null, overrideContainerId, overrideContainerHnd)) { IFCAnyHandle localPlacement = setter.LocalPlacement; IFCAnyHandle hostObjectHandle = null; try { using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; extrusionCreationData.SetLocalPlacement(localPlacement); extrusionCreationData.ReuseLocalPlacement = true; using (TransformSetter trfSetter = TransformSetter.Create()) { IList <GeometryObject> geometryList = new List <GeometryObject>(); geometryList.Add(geometry); trfSetter.InitializeFromBoundingBox(exporterIFC, geometryList, extrusionCreationData); IFCAnyHandle prodRepHnd = null; string elementGUID = GUIDUtil.CreateGUID(element); hostObjectHandle = IFCInstanceExporter.CreateGenericIFCEntity( roofExportType, exporterIFC, element, elementGUID, ownerHistory, localPlacement, prodRepHnd); if (IFCAnyHandleUtil.IsNullOrHasNoValue(hostObjectHandle)) { return(null); } IList <IFCAnyHandle> elementHandles = new List <IFCAnyHandle>(); elementHandles.Add(hostObjectHandle); // If element is floor, then the profile curve loop of hostObjectSubComponent is computed from the top face of the floor // else if element is roof, then the profile curve loop is taken from the bottom face of the roof instead XYZ extrusionDir = elementIsFloor ? new XYZ(0, 0, -1) : new XYZ(0, 0, 1); ElementId catId = CategoryUtil.GetSafeCategoryId(element); IList <IFCAnyHandle> slabHandles = new List <IFCAnyHandle>(); IList <CurveLoop> hostObjectOpeningLoops = new List <CurveLoop>(); double maximumScaledDepth = 0.0; using (IFCExtrusionCreationData slabExtrusionCreationData = new IFCExtrusionCreationData()) { slabExtrusionCreationData.SetLocalPlacement(extrusionCreationData.GetLocalPlacement()); slabExtrusionCreationData.ReuseLocalPlacement = false; slabExtrusionCreationData.ForceOffset = true; int loopNum = 0; int subElementStart = elementIsRoof ? (int)IFCRoofSubElements.RoofSlabStart : (int)IFCSlabSubElements.SubSlabStart; string subSlabType = roofExportType.ValidatedPredefinedType; foreach (HostObjectSubcomponentInfo hostObjectSubcomponent in hostObjectSubcomponents) { trfSetter.InitializeFromBoundingBox(exporterIFC, geometryList, slabExtrusionCreationData); Plane plane = hostObjectSubcomponent.GetPlane(); Transform lcs = GeometryUtil.CreateTransformFromPlane(plane); IList <CurveLoop> curveLoops = new List <CurveLoop>(); CurveLoop slabCurveLoop = hostObjectSubcomponent.GetCurveLoop(); curveLoops.Add(slabCurveLoop); double slope = Math.Abs(plane.Normal.Z); double scaledDepth = UnitUtil.ScaleLength(hostObjectSubcomponent.Depth); double scaledExtrusionDepth = scaledDepth * slope; IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); IFCAnyHandle repHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); string shapeIdent = "Body"; IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle(shapeIdent); string representationType = ShapeRepresentationType.SweptSolid.ToString(); // Create representation items based on the layers // Because in this case, the Roof components are not derived from Parts, but by "splitting" geometry part that can be extruded, // the creation of the Items for IFC4RV will be different by using "manual" split based on the layer thickness HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); if (!exportByComponents) { IFCAnyHandle itemShapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, lcs, extrusionDir, scaledExtrusionDepth, false); if (IFCAnyHandleUtil.IsNullOrHasNoValue(itemShapeRep)) { productWrapper.ClearInternalHandleWrapperData(element); return(null); } ElementId matId = HostObjectExporter.GetFirstLayerMaterialId(element as HostObject); BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, element.Document, itemShapeRep, matId); bodyItems.Add(itemShapeRep); } else { double scaleProj = extrusionDir.DotProduct(plane.Normal); foreach (Tuple <ElementId, string, double> matLayerInfo in layersetInfo.MaterialIds) { double itemExtrDepth = matLayerInfo.Item3; IFCAnyHandle itemShapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, lcs, extrusionDir, itemExtrDepth, false); if (IFCAnyHandleUtil.IsNullOrHasNoValue(itemShapeRep)) { productWrapper.ClearInternalHandleWrapperData(element); return(null); } //ElementId matId = HostObjectExporter.GetFirstLayerMaterialId(element as HostObject); BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, element.Document, itemShapeRep, matLayerInfo.Item1); bodyItems.Add(itemShapeRep); IFCAnyHandle representationOfItem = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItems, shapeIdent, representationType, new HashSet <IFCAnyHandle>() { itemShapeRep }); IFCAnyHandle shapeAspect = IFCInstanceExporter.CreateShapeAspect(file, new List <IFCAnyHandle>() { representationOfItem }, matLayerInfo.Item2, null, null, repHnd); XYZ offset = new XYZ(0, 0, itemExtrDepth / scaleProj); // offset is calculated as extent in the direction of extrusion lcs.Origin += offset; } } IFCAnyHandle shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); shapeReps.Add(shapeRep); IFCAnyHandleUtil.SetAttribute(repHnd, "Representations", shapeReps); // Allow support for up to 256 named IfcSlab components, as defined in IFCSubElementEnums.cs. string slabGUID = (loopNum < 256) ? GUIDUtil.CreateSubElementGUID(element, subElementStart + loopNum) : GUIDUtil.CreateGUID(); IFCAnyHandle slabPlacement = ExporterUtil.CreateLocalPlacement(file, slabExtrusionCreationData.GetLocalPlacement(), null); IFCAnyHandle slabHnd = IFCInstanceExporter.CreateSlab(exporterIFC, element, slabGUID, ownerHistory, slabPlacement, repHnd, subSlabType); IFCExportInfoPair exportType = new IFCExportInfoPair(IFCEntityType.IfcSlab, subSlabType); //slab quantities slabExtrusionCreationData.ScaledLength = scaledExtrusionDepth; slabExtrusionCreationData.ScaledArea = UnitUtil.ScaleArea(UnitUtil.ScaleArea(hostObjectSubcomponent.AreaOfCurveLoop)); slabExtrusionCreationData.ScaledOuterPerimeter = UnitUtil.ScaleLength(curveLoops[0].GetExactLength()); slabExtrusionCreationData.Slope = UnitUtil.ScaleAngle(MathUtil.SafeAcos(Math.Abs(slope))); IFCExportInfoPair slabRoofExportType = new IFCExportInfoPair(IFCEntityType.IfcSlab, slabRoofPredefinedType); productWrapper.AddElement(null, slabHnd, setter, slabExtrusionCreationData, false, slabRoofExportType); // Create type IFCAnyHandle slabRoofTypeHnd = ExporterUtil.CreateGenericTypeFromElement(element, slabRoofExportType, exporterIFC.GetFile(), ownerHistory, slabRoofPredefinedType, productWrapper); ExporterCacheManager.TypeRelationsCache.Add(slabRoofTypeHnd, slabHnd); elementHandles.Add(slabHnd); slabHandles.Add(slabHnd); hostObjectOpeningLoops.Add(slabCurveLoop); maximumScaledDepth = Math.Max(maximumScaledDepth, scaledDepth); loopNum++; ExporterUtil.AddIntoComplexPropertyCache(slabHnd, layersetInfo); // Create material association here if (layersetInfo != null && !IFCAnyHandleUtil.IsNullOrHasNoValue(layersetInfo.MaterialLayerSetHandle)) { CategoryUtil.CreateMaterialAssociation(exporterIFC, slabHnd, layersetInfo.MaterialLayerSetHandle); } } } productWrapper.AddElement(element, hostObjectHandle, setter, extrusionCreationData, true, roofExportType); ExporterUtil.RelateObjects(exporterIFC, null, hostObjectHandle, slabHandles); OpeningUtil.AddOpeningsToElement(exporterIFC, elementHandles, hostObjectOpeningLoops, element, null, maximumScaledDepth, null, setter, localPlacement, productWrapper); transaction.Commit(); return(hostObjectHandle); } } } catch { // SOmething wrong with the above process, unable to create the extrusion data. Reset any internal handles that may have been partially created since they are not committed productWrapper.ClearInternalHandleWrapperData(element); return(null); } finally { exporterIFC.ClearFaceWithElementHandleMap(); } } } } }
/// <summary> /// Exports an element as an IfcReinforcingMesh. /// </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 ProductWrapper.</param> /// <returns>True if exported successfully, false otherwise.</returns> public static bool ExportFabricSheet(ExporterIFC exporterIFC, FabricSheet sheet, GeometryElement geometryElement, ProductWrapper productWrapper) { if (sheet == null || geometryElement == null) { return(false); } Document doc = sheet.Document; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, sheet)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(placementSetter.LocalPlacement); ElementId categoryId = CategoryUtil.GetSafeCategoryId(sheet); ElementId materialId = ElementId.InvalidElementId; ParameterUtil.GetElementIdValueFromElementOrSymbol(sheet, BuiltInParameter.MATERIAL_ID_PARAM, out materialId); string guid = GUIDUtil.CreateGUID(sheet); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; string revitObjectType = exporterIFC.GetFamilyName(); string name = NamingUtil.GetNameOverride(sheet, revitObjectType); string description = NamingUtil.GetDescriptionOverride(sheet, null); string objectType = NamingUtil.GetObjectTypeOverride(sheet, revitObjectType); IFCAnyHandle localPlacement = ecData.GetLocalPlacement(); string elementTag = NamingUtil.CreateIFCElementId(sheet); string steelGrade = NamingUtil.GetOverrideStringValue(sheet, "SteelGrade", null); double?meshLength = sheet.CutOverallLength; double?meshWidth = sheet.CutOverallWidth; Element fabricSheetTypeElem = doc.GetElement(sheet.GetTypeId()); FabricSheetType fabricSheetType = (fabricSheetTypeElem == null) ? null : (fabricSheetTypeElem as FabricSheetType); double longitudinalBarNominalDiameter = 0.0; double transverseBarNominalDiameter = 0.0; double longitudinalBarCrossSectionArea = 0.0; double transverseBarCrossSectionArea = 0.0; double longitudinalBarSpacing = 0.0; double transverseBarSpacing = 0.0; if (fabricSheetType != null) { Element majorFabricWireTypeElem = doc.GetElement(fabricSheetType.MajorDirectionWireType); FabricWireType majorFabricWireType = (majorFabricWireTypeElem == null) ? null : (majorFabricWireTypeElem as FabricWireType); if (majorFabricWireType != null) { longitudinalBarNominalDiameter = UnitUtil.ScaleLength(majorFabricWireType.WireDiameter); double localRadius = longitudinalBarNominalDiameter / 2.0; longitudinalBarCrossSectionArea = localRadius * localRadius * Math.PI; } Element minorFabricWireTypeElem = doc.GetElement(fabricSheetType.MinorDirectionWireType); FabricWireType minorFabricWireType = (minorFabricWireTypeElem == null) ? null : (minorFabricWireTypeElem as FabricWireType); if (minorFabricWireType != null) { transverseBarNominalDiameter = UnitUtil.ScaleLength(minorFabricWireType.WireDiameter); double localRadius = transverseBarNominalDiameter / 2.0; transverseBarCrossSectionArea = localRadius * localRadius * Math.PI; } longitudinalBarSpacing = UnitUtil.ScaleLength(fabricSheetType.MajorSpacing); transverseBarSpacing = UnitUtil.ScaleLength(fabricSheetType.MinorSpacing); } ISet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); IList <Curve> wireCenterlines = sheet.GetWireCenterlines(WireDistributionDirection.Major); foreach (Curve wireCenterline in wireCenterlines) { IFCAnyHandle bodyItem = GeometryUtil.CreateSweptDiskSolid(exporterIFC, file, wireCenterline, longitudinalBarNominalDiameter, null); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyItem)) { bodyItems.Add(bodyItem); } } wireCenterlines = sheet.GetWireCenterlines(WireDistributionDirection.Minor); foreach (Curve wireCenterline in wireCenterlines) { IFCAnyHandle bodyItem = GeometryUtil.CreateSweptDiskSolid(exporterIFC, file, wireCenterline, transverseBarNominalDiameter, null); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyItem)) { bodyItems.Add(bodyItem); } } IFCAnyHandle shapeRep = (bodyItems.Count > 0) ? RepresentationUtil.CreateAdvancedSweptSolidRep(exporterIFC, sheet, categoryId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null) : null; IList <IFCAnyHandle> shapeReps = null; if (shapeRep != null) { shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(shapeRep); } IFCAnyHandle prodRep = (shapeReps != null) ? IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps) : null; IFCAnyHandle fabricSheet = IFCInstanceExporter.CreateReinforcingMesh(file, guid, ownerHistory, name, description, objectType, localPlacement, prodRep, elementTag, steelGrade, meshLength, meshWidth, longitudinalBarNominalDiameter, transverseBarNominalDiameter, longitudinalBarCrossSectionArea, transverseBarCrossSectionArea, longitudinalBarSpacing, transverseBarSpacing); ElementId fabricAreaId = sheet.FabricAreaOwnerId; if (fabricAreaId != ElementId.InvalidElementId) { HashSet <IFCAnyHandle> fabricSheets = null; if (!ExporterCacheManager.FabricAreaHandleCache.TryGetValue(fabricAreaId, out fabricSheets)) { fabricSheets = new HashSet <IFCAnyHandle>(); ExporterCacheManager.FabricAreaHandleCache[fabricAreaId] = fabricSheets; } fabricSheets.Add(fabricSheet); } productWrapper.AddElement(sheet, fabricSheet, placementSetter.LevelInfo, ecData, true); CategoryUtil.CreateMaterialAssociation(exporterIFC, fabricSheet, materialId); } } tr.Commit(); return(true); } }
/// <summary> /// Exports mullion. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="mullion"> /// The mullion object. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="localPlacement"> /// The local placement handle. /// </param> /// <param name="setter"> /// The PlacementSetter. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void Export(ExporterIFC exporterIFC, Mullion mullion, GeometryElement geometryElement, IFCAnyHandle localPlacement, PlacementSetter setter, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); using (PlacementSetter mullionSetter = PlacementSetter.Create(exporterIFC, mullion)) { using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { IFCAnyHandle mullionPlacement = mullionSetter.LocalPlacement; Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(localPlacement, mullionPlacement); Transform inverseTrf = relTrf.Inverse; IFCAnyHandle mullionLocalPlacement = ExporterUtil.CreateLocalPlacement(file, localPlacement, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX); extraParams.SetLocalPlacement(mullionLocalPlacement); Transform extrusionLCS = null; // Add a custom direction for trying to create an extrusion based on the base curve of the mullion, if it is a line and not an arc. Curve baseCurve = mullion.LocationCurve; if ((baseCurve != null) && (baseCurve is Line)) { // We won't use curveBounds and origin yet; just need the axis for now. IFCRange curveBounds; XYZ origin, mullionDirection; GeometryUtil.GetAxisAndRangeFromCurve(baseCurve, out curveBounds, out mullionDirection, out origin); // approx 1.0/sqrt(2.0) XYZ planeY = (Math.Abs(mullionDirection.Z) < 0.707) ? XYZ.BasisZ.CrossProduct(mullionDirection) : XYZ.BasisX.CrossProduct(mullionDirection); planeY.Normalize(); XYZ projDir = mullionDirection.CrossProduct(planeY); extrusionLCS = Transform.Identity; extrusionLCS.BasisX = mullionDirection; extrusionLCS.BasisY = planeY; extrusionLCS.BasisZ = projDir; extrusionLCS.Origin = origin; } ElementId catId = CategoryUtil.GetSafeCategoryId(mullion); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); bodyExporterOptions.ExtrusionLocalCoordinateSystem = extrusionLCS; IFCAnyHandle repHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, mullion, catId, geometryElement, bodyExporterOptions, null, extraParams, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { extraParams.ClearOpenings(); return; } string elemGUID = GUIDUtil.CreateGUID(mullion); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string elemObjectType = NamingUtil.CreateIFCObjectName(exporterIFC, mullion); string name = NamingUtil.GetNameOverride(mullion, elemObjectType); string description = NamingUtil.GetDescriptionOverride(mullion, null); string objectType = NamingUtil.GetObjectTypeOverride(mullion, elemObjectType); string elemTag = NamingUtil.GetTagOverride(mullion, NamingUtil.CreateIFCElementId(mullion)); IFCAnyHandle mullionHnd = IFCInstanceExporter.CreateMember(file, elemGUID, ownerHistory, name, description, objectType, mullionLocalPlacement, repHnd, elemTag, "MULLION"); ExporterCacheManager.HandleToElementCache.Register(mullionHnd, mullion.Id); productWrapper.AddElement(mullion, mullionHnd, mullionSetter, extraParams, false); ElementId matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, mullion); CategoryUtil.CreateMaterialAssociation(exporterIFC, mullionHnd, matId); } } }
private static void ExportAsMappedItem(ExporterIFC exporterIFC, Element element, IFCFile file, IFCExportInfoPair exportType, string ifcEnumType, IFCExtrusionCreationData extraParams, PlacementSetter setter, IFCAnyHandle localPlacementToUse, IFCAnyHandle productRepresentation, ProductWrapper productWrapper) { IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; ElementId typeId = element.GetTypeId(); ElementType type = element.Document.GetElement(typeId) as ElementType; IFCAnyHandle styleHandle = null; ElementId matId = ElementId.InvalidElementId; Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); bool hasMaterialAssociatedToType = false; if (type != null) { FamilyTypeInfo currentTypeInfo = ExporterCacheManager.FamilySymbolToTypeInfoCache.Find(typeId, false, exportType); if (!currentTypeInfo.IsValid()) { string typeObjectType = NamingUtil.CreateIFCObjectName(exporterIFC, type); HashSet <IFCAnyHandle> propertySetsOpt = new HashSet <IFCAnyHandle>(); IList <IFCAnyHandle> repMapListOpt = new List <IFCAnyHandle>(); styleHandle = FamilyExporterUtil.ExportGenericType(exporterIFC, exportType, ifcEnumType, propertySetsOpt, repMapListOpt, element, type); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle)) { propertySetsOpt = ExporterUtil.ExtractElementTypeProperties(exporterIFC, type, styleHandle); productWrapper.RegisterHandleWithElementType(type, exportType, styleHandle, propertySetsOpt); currentTypeInfo.Style = styleHandle; ExporterCacheManager.FamilySymbolToTypeInfoCache.Register(typeId, false, exportType, currentTypeInfo); Element elementType = element.Document.GetElement(element.GetTypeId()); matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(element.get_Geometry(geomOptions), exporterIFC, elementType); if (matId == ElementId.InvalidElementId) { matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(element.get_Geometry(geomOptions), exporterIFC, element); } if (matId != ElementId.InvalidElementId) { currentTypeInfo.MaterialIds = new HashSet <ElementId>() { matId }; hasMaterialAssociatedToType = true; CategoryUtil.CreateMaterialAssociation(exporterIFC, styleHandle, matId); } } } else { styleHandle = currentTypeInfo.Style; if (currentTypeInfo.MaterialIds != null && currentTypeInfo.MaterialIds.Count > 0) { hasMaterialAssociatedToType = true; } } } string instanceGUID = GUIDUtil.CreateGUID(element); bool roomRelated = !FamilyExporterUtil.IsDistributionFlowElementSubType(exportType); ElementId roomId = ElementId.InvalidElementId; if (roomRelated) { roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); } IFCAnyHandle instanceHandle = null; // For MEP objects //string exportEntityStr = exportType.ToString(); //Common.Enums.IFCEntityType exportEntity; //if (String.Compare(exportEntityStr.Substring(exportEntityStr.Length - 4), "Type", true) == 0) // exportEntityStr = exportEntityStr.Substring(0, (exportEntityStr.Length - 4)); //if (Enum.TryParse(exportEntityStr, out exportEntity)) //{ // For MEP object creation instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(exportType, exporterIFC, element, instanceGUID, ownerHistory, localPlacementToUse, productRepresentation); //} if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { return; } if (matId == ElementId.InvalidElementId && !hasMaterialAssociatedToType) { matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(element.get_Geometry(geomOptions), exporterIFC, element); if (matId != ElementId.InvalidElementId) { CategoryUtil.CreateMaterialAssociation(exporterIFC, instanceHandle, matId); } } if (roomId != ElementId.InvalidElementId) { //exporterIFC.RelateSpatialElement(roomId, instanceHandle); ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, instanceHandle); productWrapper.AddElement(element, instanceHandle, setter, extraParams, false, exportType); } else { productWrapper.AddElement(element, instanceHandle, setter, extraParams, true, exportType); } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, element, extraParams, null, exporterIFC, localPlacementToUse, setter, productWrapper); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle)) { ExporterCacheManager.TypeRelationsCache.Add(styleHandle, instanceHandle); } PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, productWrapper.GetAllObjects()); ExporterCacheManager.MEPCache.Register(element, instanceHandle); // add to system export cache // SystemExporter.ExportSystem(exporterIFC, element, instanceHandle); }
/// <summary> /// Exports an element to IfcPile. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="ifcEnumType">The string value represents the IFC type.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportPile(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, string ifcEnumType, ProductWrapper productWrapper) { // export parts or not bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, element.LevelId, false)) { return; } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(setter.LocalPlacement); IFCAnyHandle prodRep = null; ElementId matId = ElementId.InvalidElementId; if (!exportParts) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); prodRep = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, catId, geometryElement, bodyExporterOptions, null, ecData, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodRep)) { ecData.ClearOpenings(); return; } } string instanceGUID = GUIDUtil.CreateGUID(element); string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName()); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); string pileType = IFCValidateEntry.GetValidIFCType(element, ifcEnumType); IFCAnyHandle pile = IFCInstanceExporter.CreatePile(file, instanceGUID, ExporterCacheManager.OwnerHistoryHandle, instanceName, instanceDescription, instanceObjectType, ecData.GetLocalPlacement(), prodRep, instanceTag, pileType, null); if (exportParts) { PartExporter.ExportHostPart(exporterIFC, element, pile, productWrapper, setter, setter.LocalPlacement, null); } else { if (matId != ElementId.InvalidElementId) { CategoryUtil.CreateMaterialAssociation(exporterIFC, pile, matId); } } productWrapper.AddElement(element, pile, setter, ecData, true); OpeningUtil.CreateOpeningsIfNecessary(pile, element, ecData, null, exporterIFC, ecData.GetLocalPlacement(), setter, productWrapper); } } tr.Commit(); } }
/// <summary> /// Exports an element as IFC railing. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element to be exported. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportRailing(ExporterIFC exporterIFC, Element element, GeometryElement geomElem, string ifcEnumType, ProductWrapper productWrapper) { ElementType elemType = element.Document.GetElement(element.GetTypeId()) as ElementType; IFCFile file = exporterIFC.GetFile(); Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); using (IFCTransaction transaction = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { IFCAnyHandle localPlacement = setter.LocalPlacement; StairRampContainerInfo stairRampInfo = null; ElementId hostId = GetStairOrRampHostId(exporterIFC, element as Railing); Transform inverseTrf = Transform.Identity; if (hostId != ElementId.InvalidElementId) { stairRampInfo = ExporterCacheManager.StairRampContainerInfoCache.GetStairRampContainerInfo(hostId); IFCAnyHandle stairRampLocalPlacement = stairRampInfo.LocalPlacements[0]; Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(stairRampLocalPlacement, localPlacement); inverseTrf = relTrf.Inverse; IFCAnyHandle railingLocalPlacement = ExporterUtil.CreateLocalPlacement(file, stairRampLocalPlacement, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX); localPlacement = railingLocalPlacement; } ecData.SetLocalPlacement(localPlacement); SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geomElem); IList <Solid> solids = solidMeshInfo.GetSolids(); IList <Mesh> meshes = solidMeshInfo.GetMeshes(); Railing railingElem = element as Railing; IList <ElementId> subElementIds = CollectSubElements(railingElem); foreach (ElementId subElementId in subElementIds) { Element subElement = railingElem.Document.GetElement(subElementId); if (subElement != null) { GeometryElement subElementGeom = GeometryUtil.GetOneLevelGeometryElement(subElement.get_Geometry(geomOptions), 0); SolidMeshGeometryInfo subElementSolidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(subElementGeom); IList <Solid> subElementSolids = subElementSolidMeshInfo.GetSolids(); IList <Mesh> subElementMeshes = subElementSolidMeshInfo.GetMeshes(); foreach (Solid subElementSolid in subElementSolids) { solids.Add(subElementSolid); } foreach (Mesh subElementMesh in subElementMeshes) { meshes.Add(subElementMesh); } } } ElementId catId = CategoryUtil.GetSafeCategoryId(element); BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.Medium); //bodyExporterOptions.UseGroupsIfPossible = true; //bodyExporterOptions.UseMappedGeometriesIfPossible = true; if (solids.Count > 0 || meshes.Count > 0) { bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, solids, meshes, bodyExporterOptions, ecData); } else { IList <GeometryObject> geomlist = new List <GeometryObject>(); geomlist.Add(geomElem); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, geomlist, bodyExporterOptions, ecData); } IFCAnyHandle bodyRep = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { if (ecData != null) { ecData.ClearOpenings(); } return; } IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); representations.Add(bodyRep); IList <GeometryObject> geomObjects = new List <GeometryObject>(); foreach (Solid solid in solids) { geomObjects.Add(solid); } foreach (Mesh mesh in meshes) { geomObjects.Add(mesh); } Transform boundingBoxTrf = (bodyData.OffsetTransform != null) ? bodyData.OffsetTransform.Inverse : Transform.Identity; boundingBoxTrf = inverseTrf.Multiply(boundingBoxTrf); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomObjects, boundingBoxTrf); if (boundingBoxRep != null) { representations.Add(boundingBoxRep); } IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; string instanceGUID = GUIDUtil.CreateGUID(element); string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName()); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); string railingType = IFCValidateEntry.GetValidIFCType(element, ifcEnumType); IFCAnyHandle railing = IFCInstanceExporter.CreateRailing(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, ecData.GetLocalPlacement(), prodRep, instanceTag, railingType); bool associateToLevel = (hostId == ElementId.InvalidElementId); productWrapper.AddElement(element, railing, setter, ecData, associateToLevel); OpeningUtil.CreateOpeningsIfNecessary(railing, element, ecData, bodyData.OffsetTransform, exporterIFC, ecData.GetLocalPlacement(), setter, productWrapper); CategoryUtil.CreateMaterialAssociation(exporterIFC, railing, bodyData.MaterialIds); // Create multi-story duplicates of this railing. if (stairRampInfo != null) { stairRampInfo.AddComponent(0, railing); List <IFCAnyHandle> stairHandles = stairRampInfo.StairOrRampHandles; for (int ii = 1; ii < stairHandles.Count; ii++) { IFCAnyHandle railingLocalPlacement = stairRampInfo.LocalPlacements[ii]; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(railingLocalPlacement)) { IFCAnyHandle railingHndCopy = CopyRailingHandle(exporterIFC, element, catId, railingLocalPlacement, railing); stairRampInfo.AddComponent(ii, railingHndCopy); productWrapper.AddElement(element, railingHndCopy, (IFCLevelInfo)null, ecData, false); CategoryUtil.CreateMaterialAssociation(exporterIFC, railingHndCopy, bodyData.MaterialIds); } } ExporterCacheManager.StairRampContainerInfoCache.AddStairRampContainerInfo(hostId, stairRampInfo); } } transaction.Commit(); } } }
/// <summary> /// Exports a generic element as an IfcSlab.</summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="floor">The floor element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="ifcEnumType">The string value represents the IFC type.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>True if the floor is exported successfully, false otherwise.</returns> public static void ExportGenericSlab(ExporterIFC exporterIFC, Element slabElement, GeometryElement geometryElement, string ifcEnumType, ProductWrapper productWrapper) { if (geometryElement == null) { return; } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (IFCTransformSetter transformSetter = IFCTransformSetter.Create()) { using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, slabElement)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { bool exportParts = PartExporter.CanExportParts(slabElement); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; IFCAnyHandle localPlacement = placementSetter.LocalPlacement; IFCAnyHandle prodDefHnd = null; bool isBRepSlabHnd = false; if (!exportParts) { ecData.SetLocalPlacement(localPlacement); ElementId catId = CategoryUtil.GetSafeCategoryId(slabElement); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.Medium); BodyData bodyData; prodDefHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, slabElement, catId, geometryElement, bodyExporterOptions, null, ecData, out bodyData); if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodDefHnd)) { ecData.ClearOpenings(); return; } isBRepSlabHnd = (bodyData.ShapeRepresentationType == ShapeRepresentationType.Brep || bodyData.ShapeRepresentationType == ShapeRepresentationType.Tessellation); } // Create the slab from either the extrusion or the BRep information. string ifcGUID = GUIDUtil.CreateGUID(slabElement); string entityType = IFCValidateEntry.GetValidIFCType <IFCSlabType>(slabElement, ifcEnumType, "FLOOR"); IFCAnyHandle slabHnd = IFCInstanceExporter.CreateSlab(exporterIFC, slabElement, ifcGUID, ownerHistory, localPlacement, exportParts ? null : prodDefHnd, entityType); if (IFCAnyHandleUtil.IsNullOrHasNoValue(slabHnd)) { return; } if (exportParts) { PartExporter.ExportHostPart(exporterIFC, slabElement, slabHnd, productWrapper, placementSetter, localPlacement, null); } productWrapper.AddElement(slabElement, slabHnd, placementSetter, ecData, true); if (!exportParts) { IFCExportInfoPair exportInfo = new IFCExportInfoPair(IFCEntityType.IfcSlab, IFCEntityType.IfcSlabType, entityType); IFCAnyHandle typeHnd = ExporterUtil.CreateGenericTypeFromElement(slabElement, exportInfo, file, ownerHistory, entityType, productWrapper); ExporterCacheManager.TypeRelationsCache.Add(typeHnd, slabHnd); if (slabElement is HostObject) { HostObject hostObject = slabElement as HostObject; HostObjectExporter.ExportHostObjectMaterials(exporterIFC, hostObject, slabHnd, geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, isBRepSlabHnd, typeHnd); } else if (slabElement is FamilyInstance) { ElementId matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, slabElement); //Document doc = slabElement.Document; if (typeHnd != null) { CategoryUtil.CreateMaterialAssociation(exporterIFC, typeHnd, matId); } else { CategoryUtil.CreateMaterialAssociation(exporterIFC, slabHnd, matId); } } OpeningUtil.CreateOpeningsIfNecessary(slabHnd, slabElement, ecData, null, exporterIFC, ecData.GetLocalPlacement(), placementSetter, productWrapper); } } } tr.Commit(); return; } } }
/// <summary> /// Exports a Rebar to IFC ReinforcingBar. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="rebarItem">The rebar to be exported. This might be an element or a sub-element.</param> /// <param name="rebarElement">The element that contains the rebar to be exported. This may be the same as rebarItem.</param> /// <param name="itemIndex">If greater than 0, the index of the first rebar in the rebarItem in the rebarElement, used for naming and GUID creation.</param> /// <param name="productWrapper">The ProductWrapper object.</param> /// <returns>The set of handles created, to add to the ProductWrapper in the calling function.</returns> private static ISet <DelayedProductWrapper> ExportRebar(ExporterIFC exporterIFC, object rebarItem, Element rebarElement, int itemIndex, ProductWrapper productWrapper) { // Check the intended IFC entity or type name is in the exclude list specified in the UI Common.Enums.IFCEntityType elementClassTypeEnum = Common.Enums.IFCEntityType.IfcReinforcingBar; if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum)) { return(null); } IFCFile file = exporterIFC.GetFile(); HashSet <DelayedProductWrapper> createdRebars = new HashSet <DelayedProductWrapper>(); int rebarQuantity = GetRebarQuantity(rebarItem); if (rebarQuantity == 0) { return(null); } using (IFCTransaction transaction = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, rebarElement)) { bool cannotExportRebar = false; IFCAnyHandle rebarHandle = ExportRebarAsProxyElementInView(exporterIFC, rebarElement, productWrapper, out cannotExportRebar); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(rebarHandle) || cannotExportRebar) { if (!cannotExportRebar) { transaction.Commit(); } return(null); // Rebar doesn't create a group. } IFCAnyHandle prodRep = null; double totalBarLengthUnscale = GetRebarTotalLength(rebarItem); double volumeUnscale = GetRebarVolume(rebarItem); double totalBarLength = UnitUtil.ScaleLength(totalBarLengthUnscale); if (MathUtil.IsAlmostZero(totalBarLength)) { return(null); } ElementId materialId = ElementId.InvalidElementId; ParameterUtil.GetElementIdValueFromElementOrSymbol(rebarElement, BuiltInParameter.MATERIAL_ID_PARAM, out materialId); double diameter = GetBarDiameter(rebarItem); double radius = diameter / 2.0; double longitudinalBarNominalDiameter = diameter; double longitudinalBarCrossSectionArea = UnitUtil.ScaleArea(volumeUnscale / totalBarLengthUnscale); int numberOfBarPositions = GetNumberOfBarPositions(rebarItem); string steelGrade = NamingUtil.GetOverrideStringValue(rebarElement, "SteelGrade", null); // Allow use of IFC2x3 or IFC4 naming. string predefinedType = NamingUtil.GetOverrideStringValue(rebarElement, "BarRole", null); if (string.IsNullOrWhiteSpace(predefinedType)) { predefinedType = NamingUtil.GetOverrideStringValue(rebarElement, "PredefinedType", null); } IFCReinforcingBarRole role = GetReinforcingBarRole(predefinedType); string origRebarName = NamingUtil.GetNameOverride(rebarElement, NamingUtil.GetIFCName(rebarElement)); const int maxBarGUIDS = IFCReinforcingBarSubElements.BarEnd - IFCReinforcingBarSubElements.BarStart + 1; ElementId categoryId = CategoryUtil.GetSafeCategoryId(rebarElement); IFCAnyHandle originalPlacement = setter.LocalPlacement; // Potential issue : totalBarLength has a rounded value but individual lengths (from centerlines) do not have rounded values. // Also dividing a rounded totalBarLength does not result in barLength rounded by the same round value. double barLength = totalBarLength / rebarQuantity; IList <Curve> baseCurves = GetRebarCenterlineCurves(rebarItem, true, false, false); ElementId barLengthParamId = new ElementId(BuiltInParameter.REBAR_ELEM_LENGTH); ParameterSet rebarElementParams = rebarElement.Parameters; for (int ii = 0; ii < numberOfBarPositions; ii++) { if (!DoesBarExistAtPosition(rebarItem, ii)) { continue; } Rebar rebar = rebarElement as Rebar; if ((rebar != null) && (rebar.DistributionType == DistributionType.VaryingLength || rebar.IsRebarFreeForm())) { baseCurves = GetRebarCenterlineCurves(rebar, true, false, false, MultiplanarOption.IncludeOnlyPlanarCurves, ii); DoubleParameterValue barLengthParamVal = rebar.GetParameterValueAtIndex(barLengthParamId, ii) as DoubleParameterValue; if (barLengthParamVal != null) { barLength = barLengthParamVal.Value; } } string rebarNameFormated = origRebarName; if (rebar != null && rebar.CanBeMatchedWithMultipleShapes()) { string shapeName = getShapeNameAtIndex(rebar, ii); string elementName = rebar.Name; string strVaries = ""; if (!elementName.Contains(shapeName)) { // it means that element name contains "Shape Varies" // get "Varies" string from elem name for (int iChar = elementName.Length - 1; iChar > 0; iChar--) { if (elementName[iChar] == ' ') { break; } strVaries = strVaries.Insert(0, elementName[iChar].ToString()); } // Replace "Varies" with shape name. rebarNameFormated = origRebarName.Replace(strVaries, shapeName); } } int indexForNamingAndGUID = (itemIndex > 0) ? ii + itemIndex : ii + 1; string rebarName = NamingUtil.GetNameOverride(rebarElement, rebarNameFormated + ": " + indexForNamingAndGUID); Transform barTrf = GetBarPositionTransform(rebarItem, ii); IList <Curve> curves = new List <Curve>(); double endParam = 0.0; foreach (Curve baseCurve in baseCurves) { if (baseCurve is Arc || baseCurve is Ellipse) { if (baseCurve.IsBound) { endParam += UnitUtil.ScaleAngle(baseCurve.GetEndParameter(1) - baseCurve.GetEndParameter(0)); } else { endParam += UnitUtil.ScaleAngle(2 * Math.PI); } } else { endParam += 1.0; } curves.Add(baseCurve.CreateTransformed(barTrf)); } IFCAnyHandle compositeCurve = GeometryUtil.CreateCompositeCurve(exporterIFC, curves); IFCAnyHandle sweptDiskSolid = IFCInstanceExporter.CreateSweptDiskSolid(file, compositeCurve, radius, null, 0, endParam); HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); bodyItems.Add(sweptDiskSolid); IFCAnyHandle shapeRep = RepresentationUtil.CreateAdvancedSweptSolidRep(exporterIFC, rebarElement, categoryId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(shapeRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle copyLevelPlacement = (ii == 0) ? originalPlacement : ExporterUtil.CopyLocalPlacement(file, originalPlacement); string rebarGUID = (indexForNamingAndGUID < maxBarGUIDS) ? GUIDUtil.CreateSubElementGUID(rebarElement, indexForNamingAndGUID + (int)IFCReinforcingBarSubElements.BarStart - 1) : GUIDUtil.CreateGUID(); IFCAnyHandle elemHnd = IFCInstanceExporter.CreateReinforcingBar(exporterIFC, rebarElement, rebarGUID, ExporterCacheManager.OwnerHistoryHandle, copyLevelPlacement, prodRep, steelGrade, longitudinalBarNominalDiameter, longitudinalBarCrossSectionArea, barLength, role, null); IFCAnyHandleUtil.OverrideNameAttribute(elemHnd, rebarName); // We will not add the element ot the productWrapper here, but instead in the function that calls // ExportRebar. The reason for this is that we don't currently know if the handles such be associated // to the level or not, depending on whether they will or won't be grouped. createdRebars.Add(new DelayedProductWrapper(rebarElement, elemHnd, setter.LevelInfo)); CacheSubelementParameterValues(rebarElement, rebarElementParams, ii, elemHnd); ExporterCacheManager.HandleToElementCache.Register(elemHnd, rebarElement.Id); CategoryUtil.CreateMaterialAssociation(exporterIFC, elemHnd, materialId); } } transaction.Commit(); } return(createdRebars); }
/// <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> /// <param name="containsBRepGeometry">True if the geometry contains BRep geoemtry. If so, we will export an IfcMaterialList</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, bool containsBRepGeometry, IFCAnyHandle typeHnd = null) { 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)) { double scaledOffset = 0.0, scaledWallWidth = 0.0, wallHeight = 0.0; Wall wall = hostObject as Wall; if (wall != null) { scaledWallWidth = UnitUtil.ScaleLength(wall.Width); scaledOffset = -scaledWallWidth / 2.0; BoundingBoxXYZ boundingBox = wall.get_BoundingBox(null); if (boundingBox != null) { wallHeight = boundingBox.Max.Z - boundingBox.Min.Z; } } MaterialLayerSetInfo mlsInfo = new MaterialLayerSetInfo(exporterIFC, hostObject, productWrapper); IFCAnyHandle materialLayerSet = mlsInfo.MaterialLayerSetHandle; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet)) { // If there is an override for creating IfcMaterial instead of IfcMaterialLayer for a single material/layer, assign the material directly to type or element(s) if (IFCAnyHandleUtil.IsTypeOf(materialLayerSet, IFCEntityType.IfcMaterial)) { if (typeHnd != null) { CategoryUtil.CreateMaterialAssociation(exporterIFC, typeHnd, materialLayerSet); } foreach (IFCAnyHandle elemHnd in elemHnds) { CategoryUtil.CreateMaterialAssociation(exporterIFC, elemHnd, materialLayerSet); } } else { // 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; } SpaceBoundingElementUtil.RegisterSpaceBoundingElementHandle(exporterIFC, elemHnd, hostObject.Id, levelId); // Even if it is Tessellated geometry in IFC4RV, the material layer will still be assigned if (containsBRepGeometry && !ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { continue; } HashSet <IFCAnyHandle> relDecomposesSet = IFCAnyHandleUtil.GetRelDecomposes(elemHnd); IList <IFCAnyHandle> subElemHnds = null; if (relDecomposesSet != null && relDecomposesSet.Count == 1) { IFCAnyHandle relAggregates = relDecomposesSet.First(); if (IFCAnyHandleUtil.IsTypeOf(relAggregates, IFCEntityType.IfcRelAggregates)) { subElemHnds = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(relAggregates, "RelatedObjects"); } } bool hasSubElems = (subElemHnds != null && subElemHnds.Count != 0); bool isRoof = IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcRoof); bool isDisallowedWallType = (IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcWall) && !ExporterCacheManager.ExportOptionsCache.ExportAs4); // Create IfcMaterialLayerSetUsage unless we have sub-elements, are exporting a Roof, or are exporting a pre-IFC4 IfcWall. if (!hasSubElems && !isRoof && !isDisallowedWallType) { bool materialAlreadyAssoc = false; if (typeHnd != null) { CategoryUtil.CreateMaterialAssociation(exporterIFC, typeHnd, materialLayerSet); } if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { if (!materialAlreadyAssoc) { CategoryUtil.CreateMaterialAssociation(exporterIFC, elemHnd, materialLayerSet); } } else { 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; Transform lcs = Transform.Identity; bool curveFlipped = GeometryUtil.MustFlipCurve(lcs, curve); flipDirSense = !(wall.Flipped ^ curveFlipped); } } else if (hostObject is CeilingAndFloor) { 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) { // TODO: still need to figure out the best way to create type for the sub elements because at this time a lot of information is not available, e.g. // the Revit Element to get the type, other information for name, GUID, etc. if (!IFCAnyHandleUtil.IsNullOrHasNoValue(subElemHnd)) { CategoryUtil.CreateMaterialAssociation(exporterIFC, subElemHnd, materialLayerSet); } } } else if (!isRoof) { if (typeHnd != null) { CategoryUtil.CreateMaterialAssociation(exporterIFC, typeHnd, materialLayerSet); } else { CategoryUtil.CreateMaterialAssociation(exporterIFC, elemHnd, materialLayerSet); } } else if (mlsInfo.PrimaryMaterialHandle != null) { if (typeHnd != null) { CategoryUtil.CreateMaterialAssociation(exporterIFC, typeHnd, materialLayerSet); } else { CategoryUtil.CreateMaterialAssociation(exporterIFC, elemHnd, materialLayerSet); } } } } } } tr.Commit(); return(true); } }
/// <summary> /// Exports an element to IFC footing. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="ifcEnumType"> /// The string value represents the IFC type. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportFooting(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, string ifcEnumType, ProductWrapper productWrapper) { // export parts or not bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, element.LevelId, false)) { return; } // Check the intended IFC entity or type name is in the exclude list specified in the UI Common.Enums.IFCEntityType elementClassTypeEnum; if (Enum.TryParse <Common.Enums.IFCEntityType>("IfcFooting", out elementClassTypeEnum)) { if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum)) { return; } } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(setter.LocalPlacement); IFCAnyHandle prodRep = null; ElementId matId = ElementId.InvalidElementId; if (!exportParts) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); prodRep = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, catId, geometryElement, bodyExporterOptions, null, ecData, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodRep)) { ecData.ClearOpenings(); return; } } string instanceGUID = GUIDUtil.CreateGUID(element); string footingType = GetIFCFootingType(ifcEnumType); // need to keep it for legacy support when original data follows slightly diff naming //footingType = IFCValidateEntry.GetValidIFCPredefinedType(element, footingType, "IfcFootingType"); IFCAnyHandle footing = IFCInstanceExporter.CreateFooting(exporterIFC, element, instanceGUID, ExporterCacheManager.OwnerHistoryHandle, ecData.GetLocalPlacement(), prodRep, footingType); if (exportParts) { PartExporter.ExportHostPart(exporterIFC, element, footing, productWrapper, setter, setter.LocalPlacement, null); } else { if (matId != ElementId.InvalidElementId) { CategoryUtil.CreateMaterialAssociation(exporterIFC, footing, matId); } } productWrapper.AddElement(element, footing, setter, ecData, true); OpeningUtil.CreateOpeningsIfNecessary(footing, element, ecData, null, exporterIFC, ecData.GetLocalPlacement(), setter, productWrapper); } } tr.Commit(); } }
/// <summary> /// Exports a roof to IfcRoof. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="roof">The roof element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportRoof(ExporterIFC exporterIFC, Element roof, GeometryElement geometryElement, ProductWrapper productWrapper) { if (roof == null || geometryElement == null) { return; } string ifcEnumType; IFCExportInfoPair roofExportType = ExporterUtil.GetExportType(exporterIFC, roof, out ifcEnumType); if (roofExportType.IsUnKnown) { roofExportType = new IFCExportInfoPair(IFCEntityType.IfcRoof, ""); } MaterialLayerSetInfo layersetInfo = null; IFCFile file = exporterIFC.GetFile(); Document doc = roof.Document; using (SubTransaction tempPartTransaction = new SubTransaction(doc)) { // For IFC4RV export, Roof will be split into its parts(temporarily) in order to export the roof by its parts bool exportByComponents = ExporterUtil.ShouldExportByComponents(roof); using (IFCTransaction tr = new IFCTransaction(file)) { // Check for containment override IFCAnyHandle overrideContainerHnd = null; ElementId overrideContainerId = ParameterUtil.OverrideContainmentParameter(exporterIFC, roof, out overrideContainerHnd); using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, roof, null, null, overrideContainerId, overrideContainerHnd)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { // If the roof is an in-place family, we will allow any arbitrary orientation. While this may result in some // in-place "cubes" exporting with the wrong direction, it is unlikely that an in-place family would be // used for this reason in the first place. ecData.PossibleExtrusionAxes = (roof is FamilyInstance) ? IFCExtrusionAxes.TryXYZ : IFCExtrusionAxes.TryZ; ecData.AreInnerRegionsOpenings = true; ecData.SetLocalPlacement(placementSetter.LocalPlacement); ElementId categoryId = CategoryUtil.GetSafeCategoryId(roof); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); BodyData bodyData = null; IFCAnyHandle prodRep = null; IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); IList <ElementId> materialIds = new List <ElementId>(); if (!exportByComponents) { prodRep = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, roof, categoryId, geometryElement, bodyExporterOptions, null, ecData, out bodyData); if (bodyData != null && bodyData.MaterialIds != null) { materialIds = bodyData.MaterialIds; } } else { prodRep = RepresentationUtil.CreateProductDefinitionShapeWithoutBodyRep(exporterIFC, roof, categoryId, geometryElement, representations); } if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodRep)) { ecData.ClearOpenings(); return; } bool exportSlab = ((ecData.ScaledLength > MathUtil.Eps() || exportByComponents) && roofExportType.ExportInstance == IFCEntityType.IfcRoof); string guid = GUIDUtil.CreateGUID(roof); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; IFCAnyHandle localPlacement = ecData.GetLocalPlacement(); IFCAnyHandle roofHnd = IFCInstanceExporter.CreateGenericIFCEntity( roofExportType, exporterIFC, roof, guid, ownerHistory, localPlacement, exportSlab ? null : prodRep); IFCAnyHandle typeHnd = ExporterUtil.CreateGenericTypeFromElement(roof, roofExportType, file, ownerHistory, roofExportType.ValidatedPredefinedType, productWrapper); ExporterCacheManager.TypeRelationsCache.Add(typeHnd, roofHnd); productWrapper.AddElement(roof, roofHnd, placementSetter.LevelInfo, ecData, true, roofExportType); if (exportSlab) { string slabGUID = GUIDUtil.CreateSubElementGUID(roof, (int)IFCRoofSubElements.RoofSlabStart); string slabName = IFCAnyHandleUtil.GetStringAttribute(roofHnd, "Name") + ":1"; IFCAnyHandle slabLocalPlacementHnd = ExporterUtil.CopyLocalPlacement(file, localPlacement); if (exportByComponents) { IFCAnyHandle hostShapeRepFromParts = PartExporter.ExportHostPartAsShapeAspects(exporterIFC, roof, prodRep, productWrapper, placementSetter, localPlacement, ElementId.InvalidElementId, out layersetInfo, ecData); if (layersetInfo != null && layersetInfo.MaterialIds != null) { materialIds = layersetInfo.MaterialIds.Select(x => x.Item1).ToList(); } } IFCAnyHandle slabHnd = IFCInstanceExporter.CreateSlab(exporterIFC, roof, slabGUID, ownerHistory, slabLocalPlacementHnd, prodRep, slabRoofPredefinedType); IFCAnyHandleUtil.OverrideNameAttribute(slabHnd, slabName); Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(slabHnd, roof, ecData, offsetTransform, exporterIFC, slabLocalPlacementHnd, placementSetter, productWrapper); ExporterUtil.RelateObject(exporterIFC, roofHnd, slabHnd); IFCExportInfoPair slabRoofExportType = new IFCExportInfoPair(IFCEntityType.IfcSlab, slabRoofPredefinedType); productWrapper.AddElement(null, slabHnd, placementSetter.LevelInfo, ecData, false, slabRoofExportType); // Create type IFCAnyHandle slabRoofTypeHnd = ExporterUtil.CreateGenericTypeFromElement(roof, slabRoofExportType, exporterIFC.GetFile(), ownerHistory, slabRoofPredefinedType, productWrapper); ExporterCacheManager.TypeRelationsCache.Add(slabRoofTypeHnd, slabHnd); if (!ExporterUtil.AddIntoComplexPropertyCache(slabHnd, layersetInfo) && bodyData != null) { CategoryUtil.CreateMaterialAssociation(exporterIFC, slabHnd, bodyData.MaterialIds); } // Create material association here if (layersetInfo != null && !IFCAnyHandleUtil.IsNullOrHasNoValue(layersetInfo.MaterialLayerSetHandle)) { CategoryUtil.CreateMaterialAssociation(exporterIFC, slabHnd, layersetInfo.MaterialLayerSetHandle); } else if (!(roof is RoofBase)) { CategoryUtil.CreateMaterialAssociation(exporterIFC, roofHnd, materialIds); } } } tr.Commit(); } } } }
/// <summary> /// Exports an element as IFC covering. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element to be exported.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportCovering(ExporterIFC exporterIFC, Element element, GeometryElement geomElem, string ifcEnumType, ProductWrapper productWrapper) { bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, element.LevelId, false)) { return; } ElementType elemType = element.Document.GetElement(element.GetTypeId()) as ElementType; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); IFCAnyHandle prodRep = null; if (!exportParts) { ecData.SetLocalPlacement(setter.LocalPlacement); ecData.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); prodRep = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, categoryId, geomElem, bodyExporterOptions, null, ecData, true); if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodRep)) { ecData.ClearOpenings(); return; } } // We will use the category of the element to set a default value for the covering. string defaultCoveringEnumType = null; if (categoryId == new ElementId(BuiltInCategory.OST_Ceilings)) { defaultCoveringEnumType = "CEILING"; } else if (categoryId == new ElementId(BuiltInCategory.OST_Floors)) { defaultCoveringEnumType = "FLOORING"; } else if (categoryId == new ElementId(BuiltInCategory.OST_Roofs)) { defaultCoveringEnumType = "ROOFING"; } string instanceGUID = GUIDUtil.CreateGUID(element); string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName()); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); string coveringType = IFCValidateEntry.GetValidIFCType(element, ifcEnumType, defaultCoveringEnumType); IFCAnyHandle covering = IFCInstanceExporter.CreateCovering(file, instanceGUID, exporterIFC.GetOwnerHistoryHandle(), instanceName, instanceDescription, instanceObjectType, setter.LocalPlacement, prodRep, instanceTag, coveringType); if (exportParts) { PartExporter.ExportHostPart(exporterIFC, element, covering, productWrapper, setter, setter.LocalPlacement, null); } bool containInSpace = false; IFCAnyHandle localPlacementToUse = setter.LocalPlacement; // Ceiling containment in Space is generally required and not specific to any view if (ExporterCacheManager.CeilingSpaceRelCache.ContainsKey(element.Id)) { IList <ElementId> roomlist = ExporterCacheManager.CeilingSpaceRelCache[element.Id]; // Process Ceiling to be contained in a Space only when it is exactly bounding one Space if (roomlist.Count == 1) { productWrapper.AddElement(element, covering, setter, null, false); // Modify the Ceiling placement to be relative to the Space that it bounds IFCAnyHandle roomPlacement = IFCAnyHandleUtil.GetObjectPlacement(ExporterCacheManager.SpaceInfoCache.FindSpaceHandle(roomlist[0])); Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(roomPlacement, localPlacementToUse); Transform inverseTrf = relTrf.Inverse; IFCAnyHandle relLocalPlacement = ExporterUtil.CreateAxis2Placement3D(file, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX); IFCAnyHandleUtil.SetAttribute(localPlacementToUse, "PlacementRelTo", roomPlacement); GeometryUtil.SetRelativePlacement(localPlacementToUse, relLocalPlacement); ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomlist[0], covering); containInSpace = true; } } // if not contained in Space, assign it to default containment in Level if (!containInSpace) { productWrapper.AddElement(element, covering, setter, null, true); } if (!exportParts) { Ceiling ceiling = element as Ceiling; if (ceiling != null) { HostObjectExporter.ExportHostObjectMaterials(exporterIFC, ceiling, covering, geomElem, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, null); } else { ElementId matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geomElem, exporterIFC, element); CategoryUtil.CreateMaterialAssociation(exporterIFC, covering, matId); } } OpeningUtil.CreateOpeningsIfNecessary(covering, element, ecData, null, exporterIFC, ecData.GetLocalPlacement(), setter, productWrapper); } } transaction.Commit(); } }