/// <summary> /// Creates openings if there is necessary. /// </summary> /// <param name="elementHandle">The element handle to create openings.</param> /// <param name="element">The element to create openings.</param> /// <param name="info">The extrusion data.</param> /// <param name="extraParams">The extrusion creation data.</param> /// <param name="offsetTransform">The offset transform from ExportBody, or the identity transform.</param> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="originalPlacement">The original placement handle.</param> /// <param name="setter">The PlacementSetter.</param> /// <param name="wrapper">The ProductWrapper.</param> private static void CreateOpeningsIfNecessaryBase(IFCAnyHandle elementHandle, Element element, IList<IFCExtrusionData> info, IFCExtrusionCreationData extraParams, Transform offsetTransform, ExporterIFC exporterIFC, IFCAnyHandle originalPlacement, PlacementSetter setter, ProductWrapper wrapper) { if (IFCAnyHandleUtil.IsNullOrHasNoValue(elementHandle)) return; int sz = info.Count; if (sz == 0) return; using (TransformSetter transformSetter = TransformSetter.Create()) { if (offsetTransform != null) transformSetter.Initialize(exporterIFC, offsetTransform.Inverse); IFCFile file = exporterIFC.GetFile(); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); Document document = element.Document; string openingObjectType = "Opening"; int openingNumber = 1; for (int curr = info.Count - 1; curr >= 0; curr--) { IFCAnyHandle extrusionHandle = ExtrusionExporter.CreateExtrudedSolidFromExtrusionData(exporterIFC, element, info[curr]); if (IFCAnyHandleUtil.IsNullOrHasNoValue(extrusionHandle)) continue; IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, extrusionHandle, ElementId.InvalidElementId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(extrusionHandle); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); IFCAnyHandle bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, categoryId, contextOfItems, bodyItems, null); IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); representations.Add(bodyRep); IFCAnyHandle openingRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, originalPlacement); string guid = GUIDUtil.CreateGUID(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string openingName = NamingUtil.GetIFCNamePlusIndex(element, openingNumber++); string elementId = NamingUtil.CreateIFCElementId(element); IFCAnyHandle openingElement = IFCInstanceExporter.CreateOpeningElement(file, guid, ownerHistory, openingName, null, openingObjectType, openingPlacement, openingRep, elementId); wrapper.AddElement(null, openingElement, setter, extraParams, true); if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities && (extraParams != null)) PropertyUtil.CreateOpeningQuantities(exporterIFC, openingElement, extraParams); string voidGuid = GUIDUtil.CreateGUID(); IFCInstanceExporter.CreateRelVoidsElement(file, voidGuid, ownerHistory, null, null, elementHandle, openingElement); } } }
/// <summary> /// Exports a geometry element to boundary representation. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="exportBoundaryRep">True if to export boundary representation.</param> /// <param name="exportAsFacetation">True if to export the geometry as facetation.</param> /// <param name="bodyRep">Body representation.</param> /// <param name="boundaryRep">Boundary representation.</param> /// <returns>True if success, false if fail.</returns> public static bool ExportSurface(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, bool exportBoundaryRep, bool exportAsFacetation, ref IFCAnyHandle bodyRep, ref IFCAnyHandle boundaryRep) { if (geometryElement == null) return false; IFCGeometryInfo ifcGeomInfo = null; Document doc = element.Document; Plane plane = GeometryUtil.CreateDefaultPlane(); XYZ projDir = new XYZ(0, 0, 1); double eps = doc.Application.VertexTolerance * exporterIFC.LinearScale; ifcGeomInfo = IFCGeometryInfo.CreateFaceGeometryInfo(exporterIFC, plane, projDir, eps, exportBoundaryRep); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, ifcGeomInfo, geometryElement, XYZ.Zero, true); IFCFile file = exporterIFC.GetFile(); HashSet<IFCAnyHandle> faceSets = new HashSet<IFCAnyHandle>(); IList<ICollection<IFCAnyHandle>> faceList = ifcGeomInfo.GetFaces(); foreach (ICollection<IFCAnyHandle> faces in faceList) { // no faces, don't complain. if (faces.Count == 0) continue; HashSet<IFCAnyHandle> faceSet = new HashSet<IFCAnyHandle>(faces); faceSets.Add(IFCInstanceExporter.CreateConnectedFaceSet(file, faceSet)); } if (faceSets.Count == 0) return false; IFCAnyHandle surface = IFCInstanceExporter.CreateFaceBasedSurfaceModel(file, faceSets); BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, doc, surface, BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, element)); IList<IFCAnyHandle> surfaceItems = new List<IFCAnyHandle>(); surfaceItems.Add(surface); ElementId catId = CategoryUtil.GetSafeCategoryId(element); bodyRep = RepresentationUtil.CreateSurfaceRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("Body"), surfaceItems, exportAsFacetation, bodyRep); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) return false; ICollection<IFCAnyHandle> boundaryRepresentations = ifcGeomInfo.GetRepresentations(); if (exportBoundaryRep && boundaryRepresentations.Count > 0) { boundaryRep = RepresentationUtil.CreateBoundaryRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("FootPrint"), boundaryRepresentations, boundaryRep); } return true; }
private static IFCAnyHandle ExportBoundingBoxBase(ExporterIFC exporterIFC, XYZ cornerXYZ, double xDim, double yDim, double zDim) { double eps = MathUtil.Eps(); if (xDim < eps || yDim < eps || zDim < eps) return null; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle cornerHnd = ExporterUtil.CreateCartesianPoint(file, cornerXYZ); IFCAnyHandle boundingBoxItem = IFCInstanceExporter.CreateBoundingBox(file, cornerHnd, xDim, yDim, zDim); if (IFCAnyHandleUtil.IsNullOrHasNoValue(boundingBoxItem)) return null; IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Box"); return RepresentationUtil.CreateBoundingBoxRep(exporterIFC, contextOfItems, boundingBoxItem); }
/// <summary> /// Gets material handle from material id or creates one if there is none. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="materialId">The material id.</param> /// <returns>The handle.</returns> public static IFCAnyHandle GetOrCreateMaterialHandle(ExporterIFC exporterIFC, ElementId materialId) { Document document = ExporterCacheManager.Document; IFCAnyHandle materialNameHandle = ExporterCacheManager.MaterialHandleCache.Find(materialId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialNameHandle)) { string materialName = " <Unnamed>"; if (materialId != ElementId.InvalidElementId) { Material material = document.GetElement(materialId) as Material; if (material != null) { materialName = material.Name; } } materialNameHandle = IFCInstanceExporter.CreateMaterial(exporterIFC.GetFile(), materialName); ExporterCacheManager.MaterialHandleCache.Register(materialId, materialNameHandle); // associate Material with SurfaceStyle if necessary. IFCFile file = exporterIFC.GetFile(); if (materialId != ElementId.InvalidElementId && !ExporterCacheManager.ExportOptionsCache.ExportAs2x2 && materialNameHandle.HasValue) { HashSet <IFCAnyHandle> matRepHandles = IFCAnyHandleUtil.GetHasRepresentation(materialNameHandle); if (matRepHandles.Count == 0) { Material matElem = document.GetElement(materialId) as Material; ElementId fillPatternId = (matElem != null) ? matElem.CutPatternId : ElementId.InvalidElementId; Autodesk.Revit.DB.Color color = (matElem != null) ? matElem.CutPatternColor : new Color(0, 0, 0); double planScale = 100.0; HashSet <IFCAnyHandle> styles = new HashSet <IFCAnyHandle>(); bool hasFill = false; IFCAnyHandle styledRepItem = null; IFCAnyHandle matStyleHnd = CategoryUtil.GetOrCreateMaterialStyle(document, exporterIFC, materialId); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(matStyleHnd)) { styles.Add(matStyleHnd); bool supportCutStyles = !ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2; if (fillPatternId != ElementId.InvalidElementId && supportCutStyles) { IFCAnyHandle cutStyleHnd = exporterIFC.GetOrCreateFillPattern(fillPatternId, color, planScale); if (cutStyleHnd.HasValue) { styles.Add(cutStyleHnd); hasFill = true; } } IFCAnyHandle presStyleHnd = IFCInstanceExporter.CreatePresentationStyleAssignment(file, styles); HashSet <IFCAnyHandle> presStyleSet = new HashSet <IFCAnyHandle>(); presStyleSet.Add(presStyleHnd); IFCAnyHandle styledItemHnd = IFCInstanceExporter.CreateStyledItem(file, styledRepItem, presStyleSet, null); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle(""); string repId = "Style"; string repType = (hasFill) ? "Material and Cut Pattern" : "Material"; HashSet <IFCAnyHandle> repItems = new HashSet <IFCAnyHandle>(); repItems.Add(styledItemHnd); IFCAnyHandle styleRepHnd = IFCInstanceExporter.CreateStyledRepresentation(file, contextOfItems, repId, repType, repItems); List <IFCAnyHandle> repList = new List <IFCAnyHandle>(); repList.Add(styleRepHnd); IFCAnyHandle matDefRepHnd = IFCInstanceExporter.CreateMaterialDefinitionRepresentation(file, null, null, repList, materialNameHandle); } } } } return(materialNameHandle); }
/// <summary> /// Create the handle corresponding to the "Axis" IfcRepresentation for a beam, if possible. /// </summary> /// <param name="exporterIFC">The ExporterIFC class.</param> /// <param name="element">The beam element.</param> /// <param name="catId">The beam category id.</param> /// <param name="axisInfo">The optional beam axis information.</param> /// <param name="offsetTransform">The optional offset transform applied to the "Body" representation.</param> /// <returns>The handle, or null if not created.</returns> private static IFCAnyHandle CreateBeamAxis(ExporterIFC exporterIFC, Element element, ElementId catId, BeamAxisInfo axisInfo, Transform offsetTransform) { if (axisInfo == null) { return(null); } Curve curve = axisInfo.Axis; XYZ projDir = axisInfo.AxisNormal; Transform lcs = axisInfo.LCSAsTransform; string representationTypeOpt = "Curve2D"; // This is by IFC2x2+ convention. XYZ curveOffset = XYZ.Zero; if (offsetTransform != null) { curveOffset = -UnitUtil.UnscaleLength(offsetTransform.Origin); } else { // Note that we do not have to have any scaling adjustment here, since the curve origin is in the // same internal coordinate system as the curve. curveOffset = -lcs.Origin; } Transform offsetLCS = new Transform(lcs); offsetLCS.Origin = XYZ.Zero; IList <IFCAnyHandle> axis_items = null; if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { IFCFile file = exporterIFC.GetFile(); IList <int> segmentIndex = null; IList <IList <double> > pointList = GeometryUtil.PointListFromCurve(exporterIFC, curve, null, null, out segmentIndex); // For now because of no support in creating IfcLineIndex and IfcArcIndex yet, it is set to null //IList<IList<int>> segmentIndexList = new List<IList<int>>(); //segmentIndexList.Add(segmentIndex); IList <IList <int> > segmentIndexList = null; IFCAnyHandle pointListHnd = IFCInstanceExporter.CreateCartesianPointList3D(file, pointList); IFCAnyHandle axisHnd = IFCInstanceExporter.CreateIndexedPolyCurve(file, pointListHnd, segmentIndexList, false); axis_items = new List <IFCAnyHandle>(); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(axisHnd)) { axis_items.Add(axisHnd); representationTypeOpt = "Curve3D"; // We use Curve3D for IFC4RV Axis } } else { IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, offsetLCS, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, curveOffset, true); axis_items = info.GetCurves(); } if (axis_items.Count > 0) { string identifierOpt = "Axis"; // This is by IFC2x2+ convention. IFCAnyHandle axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); return(axisRep); } return(null); }
/// <summary> /// Exports a gutter element. /// </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> public static void ExportGutter(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { 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); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(); IFCAnyHandle bodyRep = BodyExporter.ExportBody(exporterIFC, element, categoryId, ElementId.InvalidElementId, geometryElement, bodyExporterOptions, ecData).RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { if (ecData != null) ecData.ClearOpenings(); return; } IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string originalTag = NamingUtil.CreateIFCElementId(element); // In Revit, we don't have a corresponding type, so we create one for every gutter. IFCAnyHandle origin = ExporterUtil.CreateAxis2Placement3D(file); IFCAnyHandle repMap3dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyRep); List<IFCAnyHandle> repMapList = new List<IFCAnyHandle>(); repMapList.Add(repMap3dHnd); string elementTypeName = NamingUtil.CreateIFCObjectName(exporterIFC, element); string typeGuid = GUIDUtil.CreateSubElementGUID(element, (int) IFCHostedSweepSubElements.PipeSegmentType); IFCAnyHandle style = IFCInstanceExporter.CreatePipeSegmentType(file, typeGuid, ownerHistory, elementTypeName, null, null, null, repMapList, originalTag, elementTypeName, IFCPipeSegmentType.Gutter); List<IFCAnyHandle> representationMaps = GeometryUtil.GetRepresentationMaps(style); IFCAnyHandle mappedItem = ExporterUtil.CreateDefaultMappedItem(file, representationMaps[0]); ISet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>(); representations.Add(mappedItem); IFCAnyHandle bodyMappedItemRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, element, categoryId, exporterIFC.Get3DContextHandle("Body"), representations); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyMappedItemRep)) return; List<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(bodyMappedItemRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); if (roomId == ElementId.InvalidElementId) localPlacementToUse = ecData.GetLocalPlacement(); string guid = GUIDUtil.CreateGUID(element); string name = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, elementTypeName); string tag = NamingUtil.GetTagOverride(element, originalTag); IFCAnyHandle elemHnd = IFCInstanceExporter.CreateFlowSegment(file, guid, ownerHistory, name, description, objectType, localPlacementToUse, prodRep, tag); bool containedInSpace = (roomId != ElementId.InvalidElementId); productWrapper.AddElement(element, elemHnd, setter.LevelInfo, ecData, !containedInSpace); if (containedInSpace) ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, elemHnd); // Associate segment with type. ExporterCacheManager.TypeRelationsCache.Add(style, elemHnd); OpeningUtil.CreateOpeningsIfNecessary(elemHnd, element, ecData, null, exporterIFC, localPlacementToUse, setter, productWrapper); } tr.Commit(); } } }
/// <summary> /// Gets material handle from material id or creates one if there is none. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="materialId">The material id.</param> /// <returns>The handle.</returns> public static IFCAnyHandle GetOrCreateMaterialHandle(ExporterIFC exporterIFC, ElementId materialId) { Document document = ExporterCacheManager.Document; IFCAnyHandle materialNameHandle = ExporterCacheManager.MaterialHandleCache.Find(materialId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialNameHandle)) { string materialName = " <Unnamed>"; if (materialId != ElementId.InvalidElementId) { Material material = document.GetElement(materialId) as Material; if (material != null) { materialName = material.Name; } } materialNameHandle = IFCInstanceExporter.CreateMaterial(exporterIFC.GetFile(), materialName); ExporterCacheManager.MaterialHandleCache.Register(materialId, materialNameHandle); // associate Material with SurfaceStyle if necessary. IFCFile file = exporterIFC.GetFile(); if (materialId != ElementId.InvalidElementId && !ExporterCacheManager.ExportOptionsCache.ExportAs2x2 && materialNameHandle.HasValue) { HashSet<IFCAnyHandle> matRepHandles = IFCAnyHandleUtil.GetHasRepresentation(materialNameHandle); if (matRepHandles.Count == 0) { Material matElem = document.GetElement(materialId) as Material; ElementId fillPatternId = (matElem != null) ? matElem.CutPatternId : ElementId.InvalidElementId; Autodesk.Revit.DB.Color color = (matElem != null) ? GetSafeColor(matElem.CutPatternColor) : new Color(0, 0, 0); double planScale = 100.0; HashSet<IFCAnyHandle> styles = new HashSet<IFCAnyHandle>(); bool hasFill = false; IFCAnyHandle styledRepItem = null; IFCAnyHandle matStyleHnd = CategoryUtil.GetOrCreateMaterialStyle(document, exporterIFC, materialId); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(matStyleHnd)) { styles.Add(matStyleHnd); bool supportCutStyles = !ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2; if (fillPatternId != ElementId.InvalidElementId && supportCutStyles) { IFCAnyHandle cutStyleHnd = exporterIFC.GetOrCreateFillPattern(fillPatternId, color, planScale); if (cutStyleHnd.HasValue) { styles.Add(cutStyleHnd); hasFill = true; } } IFCAnyHandle presStyleHnd = IFCInstanceExporter.CreatePresentationStyleAssignment(file, styles); HashSet<IFCAnyHandle> presStyleSet = new HashSet<IFCAnyHandle>(); presStyleSet.Add(presStyleHnd); IFCAnyHandle styledItemHnd = IFCInstanceExporter.CreateStyledItem(file, styledRepItem, presStyleSet, null); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle(""); string repId = "Style"; string repType = (hasFill) ? "Material and Cut Pattern" : "Material"; HashSet<IFCAnyHandle> repItems = new HashSet<IFCAnyHandle>(); repItems.Add(styledItemHnd); IFCAnyHandle styleRepHnd = IFCInstanceExporter.CreateStyledRepresentation(file, contextOfItems, repId, repType, repItems); List<IFCAnyHandle> repList = new List<IFCAnyHandle>(); repList.Add(styleRepHnd); IFCAnyHandle matDefRepHnd = IFCInstanceExporter.CreateMaterialDefinitionRepresentation(file, null, null, repList, materialNameHandle); } } } } return materialNameHandle; }
/// <summary> /// Exports a geometry element to boundary representation. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="exportBoundaryRep">True if to export boundary representation.</param> /// <param name="exportAsFacetation">True if to export the geometry as facetation.</param> /// <param name="bodyRep">Body representation.</param> /// <param name="boundaryRep">Boundary representation.</param> /// <returns>True if success, false if fail.</returns> public static bool ExportSurface(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, bool exportBoundaryRep, bool exportAsFacetation, ref IFCAnyHandle bodyRep, ref IFCAnyHandle boundaryRep) { if (geometryElement == null) { return(false); } IFCGeometryInfo ifcGeomInfo = null; Document doc = element.Document; Plane plane = GeometryUtil.CreateDefaultPlane(); XYZ projDir = new XYZ(0, 0, 1); double eps = UnitUtil.ScaleLength(doc.Application.VertexTolerance); ifcGeomInfo = IFCGeometryInfo.CreateFaceGeometryInfo(exporterIFC, plane, projDir, eps, exportBoundaryRep); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, ifcGeomInfo, geometryElement, XYZ.Zero, true); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle surface; // Use tessellated geometry for surface in IFC Reference View if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { BodyExporterOptions options = new BodyExporterOptions(false, ExportOptionsCache.ExportTessellationLevel.ExtraLow); surface = BodyExporter.ExportBodyAsTriangulatedFaceSet(exporterIFC, element, options, geometryElement); } else { HashSet <IFCAnyHandle> faceSets = new HashSet <IFCAnyHandle>(); IList <ICollection <IFCAnyHandle> > faceList = ifcGeomInfo.GetFaces(); foreach (ICollection <IFCAnyHandle> faces in faceList) { // no faces, don't complain. if (faces.Count == 0) { continue; } HashSet <IFCAnyHandle> faceSet = new HashSet <IFCAnyHandle>(faces); faceSets.Add(IFCInstanceExporter.CreateConnectedFaceSet(file, faceSet)); } if (faceSets.Count == 0) { return(false); } surface = IFCInstanceExporter.CreateFaceBasedSurfaceModel(file, faceSets); } if (IFCAnyHandleUtil.IsNullOrHasNoValue(surface)) { return(false); } BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, doc, surface, BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, element)); ISet <IFCAnyHandle> surfaceItems = new HashSet <IFCAnyHandle>(); surfaceItems.Add(surface); ElementId catId = CategoryUtil.GetSafeCategoryId(element); bodyRep = RepresentationUtil.CreateSurfaceRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("Body"), surfaceItems, exportAsFacetation, bodyRep); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { return(false); } ICollection <IFCAnyHandle> boundaryRepresentations = ifcGeomInfo.GetRepresentations(); if (exportBoundaryRep && boundaryRepresentations.Count > 0) { HashSet <IFCAnyHandle> boundaryRepresentationSet = new HashSet <IFCAnyHandle>(); boundaryRepresentationSet.UnionWith(boundaryRepresentations); boundaryRep = RepresentationUtil.CreateBoundaryRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("FootPrint"), boundaryRepresentationSet, boundaryRep); } return(true); }
private static IFCAnyHandle TryToCreateAsExtrusion(ExporterIFC exporterIFC, Wall wallElement, IList<IList<IFCConnectedWallData>> connectedWalls, IList<Solid> solids, IList<Mesh> meshes, double baseWallElevation, ElementId catId, Curve baseCurve, Curve trimmedCurve, Plane wallLCS, double scaledDepth, IFCRange zSpan, IFCRange range, PlacementSetter setter, out IList<IFCExtrusionData> cutPairOpenings, out bool isCompletelyClipped, out double scaledFootprintArea, out double scaledLength) { cutPairOpenings = new List<IFCExtrusionData>(); IFCAnyHandle bodyRep; scaledFootprintArea = 0; double unscaledLength = trimmedCurve != null ? trimmedCurve.Length : 0; scaledLength = UnitUtil.ScaleLength(unscaledLength); XYZ localOrig = wallLCS.Origin; // Check to see if the wall has geometry given the specified range. if (!WallHasGeometryToExport(wallElement, solids, meshes, range, out isCompletelyClipped)) return null; // This is our major check here that goes into internal code. If we have enough information to faithfully reproduce // the wall as an extrusion with clippings and openings, we will continue. Otherwise, export it as a BRep. if (!CanExportWallGeometryAsExtrusion(wallElement, range)) return null; // extrusion direction. XYZ extrusionDir = GetWallHeightDirection(wallElement); // create extrusion boundary. bool alwaysThickenCurve = IsWallBaseRectangular(wallElement, trimmedCurve); double unscaledWidth = wallElement.Width; IList<CurveLoop> boundaryLoops = GetBoundaryLoopsFromWall(exporterIFC, wallElement, alwaysThickenCurve, trimmedCurve, unscaledWidth); if (boundaryLoops == null || boundaryLoops.Count == 0) return null; double fullUnscaledLength = baseCurve.Length; double unscaledFootprintArea = ExporterIFCUtils.ComputeAreaOfCurveLoops(boundaryLoops); scaledFootprintArea = UnitUtil.ScaleArea(unscaledFootprintArea); // We are going to do a little sanity check here. If the scaledFootprintArea is significantly less than the // width * length of the wall footprint, we probably calculated the area wrong, and will abort. // This could occur because of a door or window that cuts a corner of the wall (i.e., has no wall material on one side). // We want the scaledFootprintArea to be at least (95% of approximateBaseArea - 2 * side wall area). // The "side wall area" is an approximate value that takes into account potential wall joins. // This prevents us from doing extra work for many small walls because of joins. We'll allow 1' (~30 cm) per side for this. double approximateUnscaledBaseArea = unscaledWidth * fullUnscaledLength; if (unscaledFootprintArea < (approximateUnscaledBaseArea * .95 - 2 * unscaledWidth)) { // Can't handle the case where we don't have a simple extrusion to begin with. if (!alwaysThickenCurve) return null; boundaryLoops = GetBoundaryLoopsFromBaseCurve(wallElement, connectedWalls, baseCurve, trimmedCurve, unscaledWidth, scaledDepth); if (boundaryLoops == null || boundaryLoops.Count == 0) return null; } // origin gets scaled later. double baseWallZOffset = localOrig[2] - ((range == null) ? baseWallElevation : Math.Min(range.Start, baseWallElevation)); XYZ modifiedSetterOffset = new XYZ(0, 0, setter.Offset + baseWallZOffset); IFCAnyHandle baseBodyItemHnd = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, boundaryLoops, wallLCS, extrusionDir, scaledDepth); if (IFCAnyHandleUtil.IsNullOrHasNoValue(baseBodyItemHnd)) return null; IFCAnyHandle bodyItemHnd = AddClippingsToBaseExtrusion(exporterIFC, wallElement, modifiedSetterOffset, range, zSpan, baseBodyItemHnd, out cutPairOpenings); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyItemHnd)) return null; bool hasClipping = bodyItemHnd.Id != baseBodyItemHnd.Id; ElementId matId = HostObjectExporter.GetFirstLayerMaterialId(wallElement); IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, wallElement.Document, baseBodyItemHnd, matId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(bodyItemHnd); // Check whether wall has opening. If it has, exporting it in the Reference View will need to be in a tessellated geometry that includes the opening cut IList<IFCOpeningData> openingDataList = ExporterIFCUtils.GetOpeningData(exporterIFC, wallElement, wallLCS, range); bool wallHasOpening = openingDataList.Count > 0; BodyExporterOptions options = new BodyExporterOptions(true); IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); if (!hasClipping) { // Check whether wall has opening. If it has, exporting it in Reference View will need to be in a tesselated geometry that includes the opening cut if (ExporterUtil.IsReferenceView() && wallHasOpening) { List<GeometryObject> geomList = new List<GeometryObject>(); bodyItems.Clear(); // Since we will change the geometry, clear existing extrusion data first if (solids.Count > 0) foreach (GeometryObject solid in solids) geomList.Add(solid); if (meshes.Count > 0) foreach (GeometryObject mesh in meshes) geomList.Add(mesh); foreach (GeometryObject geom in geomList) { IFCAnyHandle triangulatedBodyItem = BodyExporter.ExportBodyAsTriangulatedFaceSet(exporterIFC, wallElement, options, geom); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(triangulatedBodyItem)) bodyItems.Add(triangulatedBodyItem); } bodyRep = RepresentationUtil.CreateTessellatedRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems, null); } else bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems, null); } else { // Create TessellatedRep geometry if it is Reference View. if (ExporterUtil.IsReferenceView()) { List<GeometryObject> geomList = new List<GeometryObject>(); // The native function AddClippingsToBaseExtrusion will create the IfcBooleanClippingResult entity and therefore here we need to delete it foreach (IFCAnyHandle item in bodyItems) { item.Dispose(); //Still DOES NOT work, the IfcBooleanClippingResult is still orphaned in the IFC file! } bodyItems.Clear(); // Since we will change the geometry, clear existing extrusion data first if (solids.Count > 0) foreach (GeometryObject solid in solids) geomList.Add(solid); if (meshes.Count > 0) foreach (GeometryObject mesh in meshes) geomList.Add(mesh); foreach (GeometryObject geom in geomList) { IFCAnyHandle triangulatedBodyItem = BodyExporter.ExportBodyAsTriangulatedFaceSet(exporterIFC, wallElement, options, geom); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(triangulatedBodyItem)) bodyItems.Add(triangulatedBodyItem); } bodyRep = RepresentationUtil.CreateTessellatedRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems, null); } else bodyRep = RepresentationUtil.CreateClippingRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems); } return bodyRep; }
/// <summary> /// Exports list of geometries to IFC body representation. /// </summary> /// <param name="application">The Revit application.</param> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="categoryId">The category id.</param> /// <param name="geometryList">The geometry list.</param> /// <param name="tryToExportAsExtrusion">True if try to export as extrusion.</param> /// <param name="exportBodyParams">The extrusion creation data.</param> /// <returns>The representation handle.</returns> public static IFCAnyHandle ExportBody(Autodesk.Revit.ApplicationServices.Application application, ExporterIFC exporterIFC, ElementId categoryId, IList<GeometryObject> geometryList, bool tryToExportAsExtrusion, IFCExtrusionCreationData exportBodyParams) { IFCAnyHandle body = IFCAnyHandle.Create(); int sizeOfGeometry = geometryList.Count; if (sizeOfGeometry == 0) return body; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle(); double scale = exporterIFC.LinearScale; double eps = application.VertexTolerance * scale; HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); if (tryToExportAsExtrusion) { // Check to see if we have Geometries or GFaces. // We will have the specific all GFaces case and then the generic case. IList<Face> faces = new List<Face>(); bool allFaces = true; foreach (GeometryObject geometryObject in geometryList) { if (geometryObject is Face) faces.Add(geometryObject as Face); else { allFaces = false; break; } } int numExtrusionsToCreate = allFaces ? 1 : sizeOfGeometry; try { for (int ii = 0; ii < numExtrusionsToCreate && tryToExportAsExtrusion; ii++) { SetBestMaterialIdInExporter(geometryList[ii], exporterIFC); IList<IFCExtrusionData> extrusionList = new List<IFCExtrusionData>(); IFCExtrusionAxes axesToExtrudeIn = exportBodyParams != null ? exportBodyParams.PossibleExtrusionAxes : IFCExtrusionAxes.TryDefault; XYZ directionToExtrudeIn = XYZ.Zero; if (exportBodyParams != null && exportBodyParams.HasCustomAxis) directionToExtrudeIn = exportBodyParams.CustomAxis; IFCExtrusionCalculatorOptions extrusionOptions = new IFCExtrusionCalculatorOptions(exporterIFC, axesToExtrudeIn, directionToExtrudeIn, scale); bool canExportAsExtrusion = false; if (allFaces) extrusionList = IFCExtrusionCalculatorUtils.CalculateExtrusionData(extrusionOptions, faces); else extrusionList = IFCExtrusionCalculatorUtils.CalculateExtrusionData(extrusionOptions, geometryList[ii]); if (extrusionList.Count > 0) { if (exportBodyParams != null && exportBodyParams.AreInnerRegionsOpenings) { IList<CurveLoop> curveLoops = extrusionList[0].GetLoops(); XYZ extrudedDirection = extrusionList[0].ExtrusionDirection; int numLoops = curveLoops.Count; for (int jj = numLoops - 1; jj > 0; jj--) { AddOpeningData(exportBodyParams, extrusionList[0], curveLoops[jj]); } extrusionList[0].ClearLoops(); } canExportAsExtrusion = false; IFCAnyHandle extrusionHandle = CreateExtrudedSolidFromExtrusionData(exporterIFC, categoryId, extrusionList[0]); if (extrusionHandle.HasValue) { bodyItems.Add(extrusionHandle); IFCExtrusionBasis whichBasis = extrusionList[0].ExtrusionBasis; IList<CurveLoop> curveLoops = extrusionList[0].GetLoops(); XYZ extrusionDirection = extrusionList[0].ExtrusionDirection; canExportAsExtrusion = (whichBasis >= 0); if (exportBodyParams != null) { double zOff = (whichBasis == IFCExtrusionBasis.BasisZ) ? (1.0 - Math.Abs(extrusionDirection[2])) : Math.Abs(extrusionDirection[2]); double scaledAngle = Math.Asin(zOff) * 180 / Math.PI; exportBodyParams.Slope = scaledAngle; exportBodyParams.ScaledLength = extrusionList[0].ScaledExtrusionLength; exportBodyParams.CustomAxis = extrusionDirection; for (int kk = 1; kk < extrusionList.Count; kk++) { AddOpeningData(exportBodyParams, extrusionList[kk]); } Plane plane = null; double height = 0.0, width = 0.0; if (ComputeHeightWidthOfCurveLoop(curveLoops[0], plane, out height, out width)) { exportBodyParams.ScaledHeight = height * scale; exportBodyParams.ScaledWidth = width * scale; } double area = ExporterIFCUtils.ComputeAreaOfCurveLoops(curveLoops); if (area > 0.0) { exportBodyParams.ScaledArea = area * scale * scale; } double innerPerimeter = ComputeInnerPerimeterOfCurveLoops(curveLoops); double outerPerimeter = ComputeOuterPerimeterOfCurveLoops(curveLoops); if (innerPerimeter > 0.0) exportBodyParams.ScaledInnerPerimeter = innerPerimeter * scale; if (outerPerimeter > 0.0) exportBodyParams.ScaledOuterPerimeter = outerPerimeter * scale; } } else { if (exportBodyParams != null) exportBodyParams.ClearOpenings(); } } else { tryToExportAsExtrusion = false; } } } catch { tryToExportAsExtrusion = false; } if (tryToExportAsExtrusion) { body = RepresentationUtil.CreateSweptSolidRep(exporterIFC, categoryId, contextOfItems, bodyItems, body); return body; } } // We couldn't export it as an extrusion; export as a faceted solid or a surface model. DeleteHandles(bodyItems); bodyItems.Clear(); // generate "bottom corner" of bbox; create new local placement if passed in. // need to transform, but not scale, this point to make it the new origin. using (IFCTransformSetter transformSetter = IFCTransformSetter.Create()) { if (exportBodyParams != null) transformSetter.InitializeFromBoundingBox(exporterIFC, geometryList, exportBodyParams); HashSet<IFCAnyHandle> faceSet = new HashSet<IFCAnyHandle>(); // for export as surface. bool exportAsBReps = true; foreach (GeometryObject geometryObject in geometryList) { SetBestMaterialIdInExporter(geometryObject, exporterIFC); IFCGeometryInfo faceListInfo = IFCGeometryInfo.CreateFaceGeometryInfo(eps); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, faceListInfo, geometryObject, XYZ.Zero, false); IList<ICollection<IFCAnyHandle>> faceSetList = faceListInfo.GetFaces(); int numBReps = faceSetList.Count; if (numBReps == 0) continue; foreach (ICollection<IFCAnyHandle> currentFaceSet in faceSetList) { if (currentFaceSet.Count == 0) continue; if (exportAsBReps) { if ((currentFaceSet.Count < 4) || !CanCreateClosedShell(currentFaceSet)) { // fix all previous bodyItems. exportAsBReps = false; foreach (IFCAnyHandle bodyItem in bodyItems) { if (bodyItem.HasValue) { IFCAnyHandle closedShellHnd = IFCGeometryUtils.GetFaceOuterBoundary(bodyItem); if (closedShellHnd.HasValue) { ICollection<IFCAnyHandle> faces = IFCGeometryUtils.GetClosedShellFaces(closedShellHnd); IFCAnyHandle faceSetHnd = file.CreateConnectedFaceSet(faces); faceSet.Add(faceSetHnd); // only one item. closedShellHnd.Delete(); } bodyItem.Delete(); } } bodyItems.Clear(); } } if (exportAsBReps) { IFCAnyHandle faceOuter = file.CreateClosedShell(currentFaceSet); IFCAnyHandle brepHnd = RepresentationUtil.CreateFacetedBRep(exporterIFC, faceOuter); if (brepHnd.HasValue) bodyItems.Add(brepHnd); // only one item. } else { // TODO: add layer assignment info. IFCAnyHandle faceSetHnd = file.CreateConnectedFaceSet(currentFaceSet); faceSet.Add(faceSetHnd); // only one item. } } } if (faceSet.Count > 0) { IFCAnyHandle surfaceModel = file.CreateFaceBasedSurfaceModel(faceSet); bodyItems.Add(surfaceModel); // only one item. } if (bodyItems.Count == 0) return body; if (exportAsBReps) body = RepresentationUtil.CreateBRepRep(exporterIFC, categoryId, contextOfItems, bodyItems); else body = RepresentationUtil.CreateSurfaceRep(exporterIFC, categoryId, contextOfItems, bodyItems, false); return body; } }
/// <summary> /// Create the handle corresponding to the "Axis" IfcRepresentation for a beam, if possible. /// </summary> /// <param name="exporterIFC">The ExporterIFC class.</param> /// <param name="element">The beam element.</param> /// <param name="catId">The beam category id.</param> /// <param name="axisInfo">The optional beam axis information.</param> /// <param name="offsetTransform">The optional offset transform applied to the "Body" representation.</param> /// <returns>The handle, or null if not created.</returns> private static IFCAnyHandle CreateBeamAxis(ExporterIFC exporterIFC, Element element, ElementId catId, BeamAxisInfo axisInfo, Transform offsetTransform) { if (axisInfo == null) { return(null); } Curve curve = axisInfo.Axis; XYZ projDir = axisInfo.AxisNormal; Transform lcs = axisInfo.LCSAsTransform; string representationTypeOpt = "Curve2D"; // This is by IFC2x2+ convention. XYZ curveOffset = XYZ.Zero; if (offsetTransform != null) { curveOffset = -UnitUtil.UnscaleLength(offsetTransform.Origin); } else { // Note that we do not have to have any scaling adjustment here, since the curve origin is in the // same internal coordinate system as the curve. curveOffset = -lcs.Origin; } Transform offsetLCS = new Transform(lcs); offsetLCS.Origin = XYZ.Zero; IList <IFCAnyHandle> axis_items = null; if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { IFCAnyHandle axisHnd = GeometryUtil.CreatePolyCurveFromCurve(exporterIFC, curve); axis_items = new List <IFCAnyHandle>(); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(axisHnd)) { axis_items.Add(axisHnd); representationTypeOpt = "Curve3D"; // We use Curve3D for IFC4RV Axis } } else { IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, offsetLCS, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, curveOffset, true); axis_items = info.GetCurves(); } if (axis_items.Count > 0) { string identifierOpt = "Axis"; // This is by IFC2x2+ convention. IFCAnyHandle axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); return(axisRep); } return(null); }
/// <summary> /// Exports a Rebar to IFC ReinforcingBar. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element to be exported.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>The list of IfcReinforcingBar handles created.</returns> public static ISet <IFCAnyHandle> ExportRebar(ExporterIFC exporterIFC, Element element, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); HashSet <IFCAnyHandle> createdRebars = new HashSet <IFCAnyHandle>(); using (IFCTransaction transaction = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { if (element is Rebar) { GeometryElement rebarGeometry = ExporterIFCUtils.GetRebarGeometry(element as Rebar, ExporterCacheManager.ExportOptionsCache.FilterViewForExport); // only options are: Not Export, BuildingElementProxy, or ReinforcingBar/Mesh, depending on layout. // Not Export is handled previously, and ReinforcingBar vs Mesh will be determined below. string ifcEnumType; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType); if (exportType == IFCExportType.IfcBuildingElementProxy || exportType == IFCExportType.IfcBuildingElementProxyType) { if (rebarGeometry != null) { ProxyElementExporter.ExportBuildingElementProxy(exporterIFC, element, rebarGeometry, productWrapper); transaction.Commit(); } return(null); } } IFCAnyHandle prodRep = null; double totalBarLengthUnscale = GetRebarTotalLength(element); double volumeUnscale = GetRebarVolume(element); double totalBarLength = UnitUtil.ScaleLength(totalBarLengthUnscale); if (MathUtil.IsAlmostZero(totalBarLength)) { return(null); } ElementId materialId = ElementId.InvalidElementId; ParameterUtil.GetElementIdValueFromElementOrSymbol(element, BuiltInParameter.MATERIAL_ID_PARAM, out materialId); Document doc = element.Document; ElementId typeId = element.GetTypeId(); RebarBarType elementType = doc.GetElement(element.GetTypeId()) as RebarBarType; double diameter = UnitUtil.ScaleLength(elementType == null ? 1.0 / 12.0 : elementType.BarDiameter); double radius = diameter / 2.0; double longitudinalBarNominalDiameter = diameter; double longitudinalBarCrossSectionArea = UnitUtil.ScaleArea(volumeUnscale / totalBarLengthUnscale); double barLength = totalBarLength / GetRebarQuantity(element); IList <Curve> baseCurves = GetRebarCenterlineCurves(element, true, false, false); int numberOfBarPositions = GetNumberOfBarPositions(element); string steelGrade = NamingUtil.GetOverrideStringValue(element, "SteelGrade", null); // Allow use of IFC2x3 or IFC4 naming. string predefinedType = NamingUtil.GetOverrideStringValue(element, "BarRole", null); if (string.IsNullOrWhiteSpace(predefinedType)) { predefinedType = NamingUtil.GetOverrideStringValue(element, "PredefinedType", null); } IFCReinforcingBarRole role = GetReinforcingBarRole(predefinedType); string origRebarName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string rebarDescription = NamingUtil.GetDescriptionOverride(element, null); string rebarObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string rebarTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); const int maxBarGUIDS = IFCReinforcingBarSubElements.BarEnd - IFCReinforcingBarSubElements.BarStart + 1; ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); IFCAnyHandle originalPlacement = setter.LocalPlacement; for (int i = 0; i < numberOfBarPositions; i++) { if (!DoesBarExistAtPosition(element, i)) { continue; } string rebarName = NamingUtil.GetNameOverride(element, origRebarName + ": " + i); Transform barTrf = GetBarPositionTransform(element, i); 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, element, categoryId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(shapeRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle copyLevelPlacement = (i == 0) ? originalPlacement : ExporterUtil.CopyLocalPlacement(file, originalPlacement); string rebarGUID = (i < maxBarGUIDS) ? GUIDUtil.CreateSubElementGUID(element, i + (int)IFCReinforcingBarSubElements.BarStart) : GUIDUtil.CreateGUID(); IFCAnyHandle elemHnd = IFCInstanceExporter.CreateReinforcingBar(file, rebarGUID, exporterIFC.GetOwnerHistoryHandle(), rebarName, rebarDescription, rebarObjectType, copyLevelPlacement, prodRep, rebarTag, steelGrade, longitudinalBarNominalDiameter, longitudinalBarCrossSectionArea, barLength, role, null); createdRebars.Add(elemHnd); productWrapper.AddElement(element, elemHnd, setter.LevelInfo, null, true); ExporterCacheManager.HandleToElementCache.Register(elemHnd, element.Id); CategoryUtil.CreateMaterialAssociation(exporterIFC, elemHnd, materialId); } } transaction.Commit(); } return(createdRebars); }
/// <summary> /// Exports curtain object as one Brep. /// </summary> /// <param name="allSubElements"> /// Collection of elements contained in the host curtain element. /// </param> /// <param name="wallElement"> /// The curtain wall element. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="setter"> /// The PlacementSetter object. /// </param> /// <param name="localPlacement"> /// The local placement handle. /// </param> /// <returns> /// The handle. /// </returns> public static IFCAnyHandle ExportCurtainObjectCommonAsOneBRep(ICollection <ElementId> allSubElements, Element wallElement, ExporterIFC exporterIFC, PlacementSetter setter, IFCAnyHandle localPlacement) { IFCAnyHandle prodDefRep = null; Document document = wallElement.Document; double eps = UnitUtil.ScaleLength(document.Application.VertexTolerance); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); IFCGeometryInfo info = IFCGeometryInfo.CreateFaceGeometryInfo(eps); ISet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); // Want to make sure we don't accidentally add a mullion or curtain line more than once. HashSet <ElementId> alreadyVisited = new HashSet <ElementId>(); bool useFallbackBREP = true; Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); foreach (ElementId subElemId in allSubElements) { Element subElem = wallElement.Document.GetElement(subElemId); GeometryElement geomElem = subElem.get_Geometry(geomOptions); if (geomElem == null) { continue; } if (alreadyVisited.Contains(subElem.Id)) { continue; } alreadyVisited.Add(subElem.Id); // Export tessellated geometry when IFC4 Reference View is selected if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(false, ExportOptionsCache.ExportTessellationLevel.ExtraLow); IFCAnyHandle triFaceSet = BodyExporter.ExportBodyAsTriangulatedFaceSet(exporterIFC, subElem, bodyExporterOptions, geomElem); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(triFaceSet)) { bodyItems.Add(triFaceSet); useFallbackBREP = false; // no need to do Brep since it is successful } } // Export AdvancedFace before use fallback BREP else if (ExporterCacheManager.ExportOptionsCache.ExportAs4DesignTransferView) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(false, ExportOptionsCache.ExportTessellationLevel.ExtraLow); IFCAnyHandle advancedBRep = BodyExporter.ExportBodyAsAdvancedBrep(exporterIFC, subElem, bodyExporterOptions, geomElem); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(advancedBRep)) { bodyItems.Add(advancedBRep); useFallbackBREP = false; // no need to do Brep since it is successful } } if (useFallbackBREP) { ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, geomElem, XYZ.Zero, false); HashSet <IFCAnyHandle> faces = new HashSet <IFCAnyHandle>(info.GetSurfaces()); IFCAnyHandle outer = IFCInstanceExporter.CreateClosedShell(file, faces); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(outer)) { bodyItems.Add(RepresentationUtil.CreateFacetedBRep(exporterIFC, document, outer, ElementId.InvalidElementId)); } } } if (bodyItems.Count == 0) { return(prodDefRep); } ElementId catId = CategoryUtil.GetSafeCategoryId(wallElement); IFCAnyHandle shapeRep; // Use tessellated geometry in Reference View if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView && !useFallbackBREP) { shapeRep = RepresentationUtil.CreateTessellatedRep(exporterIFC, wallElement, catId, contextOfItems, bodyItems, null); } else if (ExporterCacheManager.ExportOptionsCache.ExportAs4DesignTransferView && !useFallbackBREP) { shapeRep = RepresentationUtil.CreateAdvancedBRepRep(exporterIFC, wallElement, catId, contextOfItems, bodyItems, null); } else { shapeRep = RepresentationUtil.CreateBRepRep(exporterIFC, wallElement, catId, contextOfItems, bodyItems); } if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) { return(prodDefRep); } IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, wallElement.get_Geometry(geomOptions), Transform.Identity); if (boundingBoxRep != null) { shapeReps.Add(boundingBoxRep); } prodDefRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); return(prodDefRep); }
/// <summary> /// Create the handle corresponding to the "Axis" IfcRepresentation for a structural member objects, if possible. /// </summary> /// <param name="exporterIFC">The ExporterIFC class.</param> /// <param name="element">The structural member element.</param> /// <param name="catId">The structural member category id.</param> /// <param name="axisInfo">The optional structural member axis information.</param> /// <param name="offsetTransform">The optional offset transform applied to the "Body" representation.</param> /// <returns>The handle, or null if not created.</returns> public static IFCAnyHandle CreateStructuralMemberAxis(ExporterIFC exporterIFC, Element element, ElementId catId, StructuralMemberAxisInfo axisInfo, Transform newTransformLCS) { if (axisInfo == null) { return(null); } // This Axis should have been transformed into its ECS position previously (in GetStructuralMemberAxisTransform()) Curve curve = axisInfo.Axis; Transform offset = Transform.Identity; if (newTransformLCS != null) { // We need to flip the Left-handed transform to the right-hand one as IFC only support right-handed coordinate system if (newTransformLCS.Determinant < 0) { XYZ orig = newTransformLCS.Origin; newTransformLCS.Origin = XYZ.Zero; offset = FlipYTrf().Multiply(newTransformLCS); offset.Origin = orig; } else { offset = newTransformLCS; } } // Calculate the transformation matrix to tranform the original Axis Curve at its ECS into the new ECS assigned in the offset curve = curve.CreateTransformed(offset.Inverse.Multiply(axisInfo.LCSAsTransform)); IDictionary <IFCFuzzyXYZ, IFCAnyHandle> cachePoints = new Dictionary <IFCFuzzyXYZ, IFCAnyHandle>(); IFCAnyHandle ifcCurveHnd = GeometryUtil.CreateIFCCurveFromRevitCurve(exporterIFC.GetFile(), exporterIFC, curve, true, cachePoints); IList <IFCAnyHandle> axis_items = new List <IFCAnyHandle>(); if (!(IFCAnyHandleUtil.IsNullOrHasNoValue(ifcCurveHnd))) { axis_items.Add(ifcCurveHnd); } if (axis_items.Count > 0) { string identifierOpt = "Axis"; // This is by IFC2x2+ convention. string representationTypeOpt = "Curve3D"; // This is by IFC2x2+ convention. IFCAnyHandle axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); return(axisRep); } return(null); }
/// <summary> /// Exports a geometry element to boundary representation. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="exportBoundaryRep">True if to export boundary representation.</param> /// <param name="exportAsFacetation">True if to export the geometry as facetation.</param> /// <param name="bodyRep">Body representation.</param> /// <param name="boundaryRep">Boundary representation.</param> /// <returns>True if success, false if fail.</returns> public static bool ExportSurface(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, bool exportBoundaryRep, bool exportAsFacetation, ref IFCAnyHandle bodyRep, ref IFCAnyHandle boundaryRep) { if (geometryElement == null) { return(false); } IFCGeometryInfo ifcGeomInfo = null; Document doc = element.Document; Plane plane = GeometryUtil.CreateDefaultPlane(); XYZ projDir = new XYZ(0, 0, 1); double eps = UnitUtil.ScaleLength(doc.Application.VertexTolerance); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle surface; ICollection <IFCAnyHandle> boundaryRepresentations = new List <IFCAnyHandle>(); // Use tessellated geometry for surface in IFC Reference View if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { BodyExporterOptions options = new BodyExporterOptions(false, ExportOptionsCache.ExportTessellationLevel.ExtraLow); surface = BodyExporter.ExportBodyAsTessellatedFaceSet(exporterIFC, element, options, geometryElement); if (element is Autodesk.Revit.DB.Architecture.TopographySurface) { // TODO: need to find a good way to create the right boundary outline! //IList<XYZ> boundaryPoints = (element as Autodesk.Revit.DB.Architecture.TopographySurface).GetBoundaryPoints(); //if (boundaryPoints != null && boundaryPoints.Count > 0) //{ // IList<IFCAnyHandle> coords = new List<IFCAnyHandle>(); // foreach (XYZ point in boundaryPoints) // { // XYZ scPoint = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, point); // IList<double> uvPoint = new List<double>(); // // SInce the projection direction is on Z-axis, simply ignoring the Z-value will do for this. And also the Site reference will follow the WCS // uvPoint.Add(scPoint.X); // uvPoint.Add(scPoint.Y); // IFCAnyHandle ifcCartesianPoint = IFCInstanceExporter.CreateCartesianPoint(file, uvPoint); // coords.Add(ifcCartesianPoint); // } // if (coords.Count >= 2) // { // IFCAnyHandle boundaryLines = IFCInstanceExporter.CreatePolyline(file, coords); // boundaryRepresentations.Add(boundaryLines); // } //} } } else { ifcGeomInfo = IFCGeometryInfo.CreateFaceGeometryInfo(exporterIFC, plane, projDir, eps, exportBoundaryRep); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, ifcGeomInfo, geometryElement, XYZ.Zero, true); HashSet <IFCAnyHandle> faceSets = new HashSet <IFCAnyHandle>(); IList <ICollection <IFCAnyHandle> > faceList = ifcGeomInfo.GetFaces(); foreach (ICollection <IFCAnyHandle> faces in faceList) { // no faces, don't complain. if (faces.Count == 0) { continue; } HashSet <IFCAnyHandle> faceSet = new HashSet <IFCAnyHandle>(faces); faceSets.Add(IFCInstanceExporter.CreateConnectedFaceSet(file, faceSet)); } if (faceSets.Count == 0) { return(false); } surface = IFCInstanceExporter.CreateFaceBasedSurfaceModel(file, faceSets); // Collect Footprint data boundaryRepresentations = ifcGeomInfo.GetRepresentations(); } if (IFCAnyHandleUtil.IsNullOrHasNoValue(surface)) { return(false); } BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, doc, surface, BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, element)); ISet <IFCAnyHandle> surfaceItems = new HashSet <IFCAnyHandle>(); surfaceItems.Add(surface); ElementId catId = CategoryUtil.GetSafeCategoryId(element); bodyRep = RepresentationUtil.CreateSurfaceRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("Body"), surfaceItems, exportAsFacetation, bodyRep); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { return(false); } if (exportBoundaryRep && boundaryRepresentations.Count > 0) { HashSet <IFCAnyHandle> boundaryRepresentationSet = new HashSet <IFCAnyHandle>(); boundaryRepresentationSet.UnionWith(boundaryRepresentations); boundaryRep = RepresentationUtil.CreateBoundaryRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("FootPrint"), boundaryRepresentationSet, boundaryRep); } return(true); }
/// <summary> /// Exports a gutter element. /// </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> public static void ExportGutter(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, 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.IfcPipeSegmentType; if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum)) { 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); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); IFCAnyHandle bodyRep = BodyExporter.ExportBody(exporterIFC, element, categoryId, ElementId.InvalidElementId, geometryElement, bodyExporterOptions, ecData).RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { if (ecData != null) { ecData.ClearOpenings(); } return; } string originalTag = NamingUtil.CreateIFCElementId(element); // In Revit, we don't have a corresponding type, so we create one for every gutter. IFCAnyHandle origin = ExporterUtil.CreateAxis2Placement3D(file); IFCAnyHandle repMap3dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyRep); List <IFCAnyHandle> repMapList = new List <IFCAnyHandle>(); repMapList.Add(repMap3dHnd); string elementTypeName = NamingUtil.CreateIFCObjectName(exporterIFC, element); string typeGuid = GUIDUtil.CreateSubElementGUID(element, (int)IFCHostedSweepSubElements.PipeSegmentType); IFCAnyHandle style = IFCInstanceExporter.CreatePipeSegmentType(file, null, null, repMapList, IFCPipeSegmentType.Gutter); IFCAnyHandleUtil.OverrideNameAttribute(style, elementTypeName); IFCAnyHandleUtil.SetAttribute(style, "Tag", originalTag); ExporterUtil.SetGlobalId(style, typeGuid); IFCAnyHandleUtil.SetAttribute(style, "ElementType", elementTypeName); List <IFCAnyHandle> representationMaps = GeometryUtil.GetRepresentationMaps(style); IFCAnyHandle mappedItem = ExporterUtil.CreateDefaultMappedItem(file, representationMaps[0]); ISet <IFCAnyHandle> representations = new HashSet <IFCAnyHandle>(); representations.Add(mappedItem); IFCAnyHandle bodyMappedItemRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, element, categoryId, exporterIFC.Get3DContextHandle("Body"), representations); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyMappedItemRep)) { return; } List <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(bodyMappedItemRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) { shapeReps.Add(boundingBoxRep); } IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); if (roomId == ElementId.InvalidElementId) { localPlacementToUse = ecData.GetLocalPlacement(); } string guid = GUIDUtil.CreateGUID(element); IFCAnyHandle elemHnd = IFCInstanceExporter.CreateFlowSegment(exporterIFC, element, guid, ExporterCacheManager.OwnerHistoryHandle, localPlacementToUse, prodRep); bool containedInSpace = (roomId != ElementId.InvalidElementId); productWrapper.AddElement(element, elemHnd, setter.LevelInfo, ecData, !containedInSpace); if (containedInSpace) { ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, elemHnd); } // Associate segment with type. ExporterCacheManager.TypeRelationsCache.Add(style, elemHnd); OpeningUtil.CreateOpeningsIfNecessary(elemHnd, element, ecData, null, exporterIFC, localPlacementToUse, setter, productWrapper); } tr.Commit(); } } }
/// <summary> /// Exports a gutter element. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The IFCProductWrapper.</param> public static void ExportGutter(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(setter.GetPlacement()); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(); IFCAnyHandle bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, categoryId, geometryElement, bodyExporterOptions, ecData).RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { if (ecData != null) { ecData.ClearOpenings(); } return; } IFCAnyHandle origin = ExporterUtil.CreateAxis2Placement3D(file); IFCAnyHandle repMap3dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyRep); List <IFCAnyHandle> repMapList = new List <IFCAnyHandle>(); repMapList.Add(repMap3dHnd); string elementTypeName = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle style = IFCInstanceExporter.CreatePipeSegmentType(file, ExporterIFCUtils.CreateGUID(element), exporterIFC.GetOwnerHistoryHandle(), elementTypeName, null, null, null, repMapList, NamingUtil.CreateIFCElementId(element), elementTypeName, IFCPipeSegmentType.Gutter); List <IFCAnyHandle> representationMaps = GeometryUtil.GetRepresentationMaps(style); IFCAnyHandle mappedItem = ExporterUtil.CreateDefaultMappedItem(file, representationMaps[0]); IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); representations.Add(mappedItem); IFCAnyHandle bodyMappedItemRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, element, categoryId, exporterIFC.Get3DContextHandle("Body"), representations); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyMappedItemRep)) { return; } List <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(bodyMappedItemRep); IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); if (roomId == ElementId.InvalidElementId) { localPlacementToUse = ecData.GetLocalPlacement(); } string name = NamingUtil.GetNameOverride(element, NamingUtil.CreateIFCName(exporterIFC, -1)); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, elementTypeName); IFCAnyHandle elemHnd = IFCInstanceExporter.CreateFlowSegment(file, ExporterIFCUtils.CreateGUID(element), exporterIFC.GetOwnerHistoryHandle(), name, description, objectType, localPlacementToUse, prodRep, NamingUtil.CreateIFCElementId(element)); if (roomId == ElementId.InvalidElementId) { productWrapper.AddElement(elemHnd, setter.GetLevelInfo(), ecData, true); } else { exporterIFC.RelateSpatialElement(roomId, elemHnd); productWrapper.AddElement(elemHnd, setter.GetLevelInfo(), ecData, false); } OpeningUtil.CreateOpeningsIfNecessary(elemHnd, element, ecData, exporterIFC, localPlacementToUse, setter, productWrapper); } tr.Commit(); } } }
/// <summary> /// Exports a CeilingAndFloor element to IFC. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="floor">The floor element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportCeilingAndFloorElement(ExporterIFC exporterIFC, CeilingAndFloor floorElement, GeometryElement geometryElement, ProductWrapper productWrapper) { if (geometryElement == null) { return; } // export parts or not bool exportParts = PartExporter.CanExportParts(floorElement); if (exportParts && !PartExporter.CanExportElementInPartExport(floorElement, floorElement.LevelId, false)) { return; } IFCFile file = exporterIFC.GetFile(); string ifcEnumType; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, floorElement, out ifcEnumType); using (IFCTransaction tr = new IFCTransaction(file)) { bool canExportAsContainerOrWithExtrusionAnalyzer = (!exportParts && (floorElement is Floor)); if (canExportAsContainerOrWithExtrusionAnalyzer) { // Try to export the Floor slab as a container. If that succeeds, we are done. // If we do export the floor as a container, it will take care of the local placement and transform there, so we need to leave // this out of the IFCTransformSetter and PlacementSetter scopes below, or else we'll get double transforms. IFCAnyHandle floorHnd = RoofExporter.ExportRoofOrFloorAsContainer(exporterIFC, ifcEnumType, floorElement, geometryElement, productWrapper); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(floorHnd)) { tr.Commit(); return; } } IList <IFCAnyHandle> slabHnds = new List <IFCAnyHandle>(); IList <IFCAnyHandle> brepSlabHnds = new List <IFCAnyHandle>(); IList <IFCAnyHandle> nonBrepSlabHnds = new List <IFCAnyHandle>(); using (IFCTransformSetter transformSetter = IFCTransformSetter.Create()) { using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, floorElement)) { IFCAnyHandle localPlacement = placementSetter.LocalPlacement; IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; // The routine ExportExtrudedSlabOpenings is called if exportedAsInternalExtrusion is true, and it requires having a valid level association. // Disable calling ExportSlabAsExtrusion if we can't handle potential openings. bool canExportAsInternalExtrusion = placementSetter.LevelInfo != null; bool exportedAsInternalExtrusion = false; ElementId catId = CategoryUtil.GetSafeCategoryId(floorElement); IList <IFCAnyHandle> prodReps = new List <IFCAnyHandle>(); IList <ShapeRepresentationType> repTypes = new List <ShapeRepresentationType>(); IList <IList <CurveLoop> > extrusionLoops = new List <IList <CurveLoop> >(); IList <IFCExtrusionCreationData> loopExtraParams = new List <IFCExtrusionCreationData>(); Plane floorPlane = GeometryUtil.CreateDefaultPlane(); IList <IFCAnyHandle> localPlacements = new List <IFCAnyHandle>(); if (canExportAsContainerOrWithExtrusionAnalyzer) { Floor floor = floorElement as Floor; // Next, try to use the ExtrusionAnalyzer for the limited cases it handles - 1 solid, no openings, end clippings only. // Also limited to cases with line and arc boundaries. // SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); IList <Solid> solids = solidMeshInfo.GetSolids(); IList <Mesh> meshes = solidMeshInfo.GetMeshes(); if (solids.Count == 1 && meshes.Count == 0) { bool completelyClipped; // floorExtrusionDirection is set to (0, 0, -1) because extrusionAnalyzerFloorPlane is computed from the top face of the floor XYZ floorExtrusionDirection = new XYZ(0, 0, -1); XYZ modelOrigin = XYZ.Zero; XYZ floorOrigin = floor.GetVerticalProjectionPoint(modelOrigin, FloorFace.Top); if (floorOrigin == null) { // GetVerticalProjectionPoint may return null if FloorFace.Top is an edited face that doesn't // go through the Revit model origin. We'll try the midpoint of the bounding box instead. BoundingBoxXYZ boundingBox = floorElement.get_BoundingBox(null); modelOrigin = (boundingBox.Min + boundingBox.Max) / 2.0; floorOrigin = floor.GetVerticalProjectionPoint(modelOrigin, FloorFace.Top); } if (floorOrigin != null) { XYZ floorDir = floor.GetNormalAtVerticalProjectionPoint(floorOrigin, FloorFace.Top); Plane extrusionAnalyzerFloorPlane = new Plane(floorDir, floorOrigin); GenerateAdditionalInfo additionalInfo = ExporterCacheManager.ExportOptionsCache.ExportAs4 ? GenerateAdditionalInfo.GenerateFootprint : GenerateAdditionalInfo.None; HandleAndData floorAndProperties = ExtrusionExporter.CreateExtrusionWithClippingAndProperties(exporterIFC, floorElement, catId, solids[0], extrusionAnalyzerFloorPlane, floorExtrusionDirection, null, out completelyClipped, addInfo: additionalInfo); if (completelyClipped) { return; } if (floorAndProperties.Handle != null) { IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); representations.Add(floorAndProperties.Handle); // Footprint representation will only be exported in export to IFC4 if (((additionalInfo & GenerateAdditionalInfo.GenerateFootprint) != 0) && (floorAndProperties.FootprintRepHandle != null)) { representations.Add(floorAndProperties.FootprintRepHandle); } IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); prodReps.Add(prodRep); repTypes.Add(ShapeRepresentationType.SweptSolid); if (floorAndProperties.Data != null) { loopExtraParams.Add(floorAndProperties.Data); } } } } } // Use internal routine as backup that handles openings. if (prodReps.Count == 0 && canExportAsInternalExtrusion) { //IList<IFCAnyHandle> prodRepsTmp = new List<IFCAnyHandle>(); exportedAsInternalExtrusion = ExporterIFCUtils.ExportSlabAsExtrusion(exporterIFC, floorElement, geometryElement, transformSetter, localPlacement, out localPlacements, out prodReps, out extrusionLoops, out loopExtraParams, floorPlane); for (int ii = 0; ii < prodReps.Count; ii++) { // all are extrusions repTypes.Add(ShapeRepresentationType.SweptSolid); // Footprint representation will only be exported in export to IFC4 if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { // Get back the representations, we need to add the Footprint to it //IList<IFCAnyHandle> representations = IFCAnyHandleUtil.GetRepresentations(prodRepsTmp[ii]); if (extrusionLoops.Count > ii) { if (extrusionLoops[ii].Count > 0) { // Get the extrusion footprint using the first Curveloop. Transform needs to be obtained from the returned local placement Transform lcs = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, localPlacements[ii]); Plane plane = new Plane(lcs.BasisX, lcs.BasisY, lcs.Origin); IFCAnyHandle footprintGeomRepItem = GeometryUtil.CreateIFCCurveFromCurveLoop(exporterIFC, extrusionLoops[ii][0], plane, floorPlane.Normal); IFCAnyHandle contextOfItemsFootprint = exporterIFC.Get3DContextHandle("FootPrint"); ISet <IFCAnyHandle> repItem = new HashSet <IFCAnyHandle>(); repItem.Add(footprintGeomRepItem); IFCAnyHandle footprintShapeRepresentation = RepresentationUtil.CreateBaseShapeRepresentation(exporterIFC, contextOfItemsFootprint, "FootPrint", "Curve2D", repItem); //representations.Add(footprintShapeRepresentation); IList <IFCAnyHandle> reps = new List <IFCAnyHandle>(); reps.Add(footprintShapeRepresentation); IFCAnyHandleUtil.AddRepresentations(prodReps[ii], reps); } } //IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); //prodReps.Add(prodRep); } else { //prodReps.Add(prodRepsTmp[ii]); } // We do not need the prodRepsTmp anymore, delete the handle: //prodRepsTmp[ii].Delete(); } } if (prodReps.Count == 0) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { // Brep representation using tesellation after ExportSlabAsExtrusion does not return prodReps BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.Medium); BodyData bodyData; IFCAnyHandle prodDefHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, floorElement, catId, geometryElement, bodyExporterOptions, null, ecData, out bodyData); if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodDefHnd)) { ecData.ClearOpenings(); return; } prodReps.Add(prodDefHnd); repTypes.Add(bodyData.ShapeRepresentationType); } } // Create the slab from either the extrusion or the BRep information. string ifcGUID = GUIDUtil.CreateGUID(floorElement); int numReps = exportParts ? 1 : prodReps.Count; string entityType = null; switch (exportType) { case IFCExportType.IfcFooting: if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { entityType = IFCValidateEntry.GetValidIFCType <Revit.IFC.Export.Toolkit.IFC4.IFCFootingType>(floorElement, ifcEnumType, null); } else { entityType = IFCValidateEntry.GetValidIFCType <IFCFootingType>(floorElement, ifcEnumType, null); } break; case IFCExportType.IfcCovering: entityType = IFCValidateEntry.GetValidIFCType <IFCCoveringType>(floorElement, ifcEnumType, "FLOORING"); break; case IFCExportType.IfcRamp: if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { entityType = IFCValidateEntry.GetValidIFCType <Revit.IFC.Export.Toolkit.IFC4.IFCRampType>(floorElement, ifcEnumType, null); } else { entityType = IFCValidateEntry.GetValidIFCType <IFCRampType>(floorElement, ifcEnumType, null); } break; default: bool isBaseSlab = false; AnalyticalModel analyticalModel = floorElement.GetAnalyticalModel(); if (analyticalModel != null) { AnalyzeAs slabFoundationType = analyticalModel.GetAnalyzeAs(); isBaseSlab = (slabFoundationType == AnalyzeAs.SlabOnGrade) || (slabFoundationType == AnalyzeAs.Mat); } entityType = IFCValidateEntry.GetValidIFCType <IFCSlabType>(floorElement, ifcEnumType, isBaseSlab ? "BASESLAB" : "FLOOR"); break; } for (int ii = 0; ii < numReps; ii++) { string ifcName = NamingUtil.GetNameOverride(floorElement, NamingUtil.GetIFCNamePlusIndex(floorElement, ii == 0 ? -1 : ii + 1)); string ifcDescription = NamingUtil.GetDescriptionOverride(floorElement, null); string ifcObjectType = NamingUtil.GetObjectTypeOverride(floorElement, exporterIFC.GetFamilyName()); string ifcTag = NamingUtil.GetTagOverride(floorElement, NamingUtil.CreateIFCElementId(floorElement)); string currentGUID = (ii == 0) ? ifcGUID : GUIDUtil.CreateGUID(); IFCAnyHandle localPlacementHnd = exportedAsInternalExtrusion ? localPlacements[ii] : localPlacement; IFCAnyHandle slabHnd = null; // TODO: replace with CreateGenericBuildingElement. switch (exportType) { case IFCExportType.IfcFooting: slabHnd = IFCInstanceExporter.CreateFooting(file, currentGUID, ownerHistory, ifcName, ifcDescription, ifcObjectType, localPlacementHnd, exportParts ? null : prodReps[ii], ifcTag, entityType); break; case IFCExportType.IfcCovering: slabHnd = IFCInstanceExporter.CreateCovering(file, currentGUID, ownerHistory, ifcName, ifcDescription, ifcObjectType, localPlacementHnd, exportParts ? null : prodReps[ii], ifcTag, entityType); break; case IFCExportType.IfcRamp: slabHnd = IFCInstanceExporter.CreateRamp(file, currentGUID, ownerHistory, ifcName, ifcDescription, ifcObjectType, localPlacementHnd, exportParts ? null : prodReps[ii], ifcTag, entityType); break; default: //if ((canExportAsInternalExtrusion || exportedAsInternalExtrusion) && ExporterCacheManager.ExportOptionsCache.ExportAs4) //{ // slabHnd = IFCInstanceExporter.CreateSlabStandardCase(file, currentGUID, ownerHistory, ifcName, // ifcDescription, ifcObjectType, localPlacementHnd, exportParts ? null : prodReps[ii], // ifcTag, entityType); //} //else slabHnd = IFCInstanceExporter.CreateSlab(file, currentGUID, ownerHistory, ifcName, ifcDescription, ifcObjectType, localPlacementHnd, exportParts ? null : prodReps[ii], ifcTag, entityType); break; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(slabHnd)) { return; } if (exportParts) { PartExporter.ExportHostPart(exporterIFC, floorElement, slabHnd, productWrapper, placementSetter, localPlacementHnd, null); } slabHnds.Add(slabHnd); if (!exportParts) { if (repTypes[ii] == ShapeRepresentationType.Brep) { brepSlabHnds.Add(slabHnd); } else { nonBrepSlabHnds.Add(slabHnd); } } } for (int ii = 0; ii < numReps; ii++) { IFCExtrusionCreationData loopExtraParam = ii < loopExtraParams.Count ? loopExtraParams[ii] : null; productWrapper.AddElement(floorElement, slabHnds[ii], placementSetter, loopExtraParam, true); } // This call to the native function appears to create Brep opening also when appropriate. But the creation of the IFC instances is not // controllable from the managed code. Therefore in some cases BRep geometry for Opening will still be exported even in the Reference View if (exportedAsInternalExtrusion) { ExporterIFCUtils.ExportExtrudedSlabOpenings(exporterIFC, floorElement, placementSetter.LevelInfo, localPlacements[0], slabHnds, extrusionLoops, floorPlane, productWrapper.ToNative()); } //// For now we have to be content without IfcOpeningStandardCase from the openings created by this native call because it is too much to //// "reverse engineer" the IFChandle //foreach (IFCAnyHandle slabHandle in slabHnds) //{ // updateOpeningProfileRep(exporterIFC, slabHandle); //} } if (!exportParts) { if (nonBrepSlabHnds.Count > 0) { HostObjectExporter.ExportHostObjectMaterials(exporterIFC, floorElement, nonBrepSlabHnds, geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, false); } if (brepSlabHnds.Count > 0) { HostObjectExporter.ExportHostObjectMaterials(exporterIFC, floorElement, brepSlabHnds, geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, true); } } } tr.Commit(); return; } }
/// <summary> /// Exports list of geometries to IFC body representation. /// </summary> /// <param name="application">The Revit application.</param> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="categoryId">The category id.</param> /// <param name="geometryListIn">The geometry list.</param> /// <param name="options">The settings for how to export the body.</param> /// <param name="exportBodyParams">The extrusion creation data.</param> /// <returns>The BodyData containing the handle, offset and material ids.</returns> public static BodyData ExportBody(Autodesk.Revit.ApplicationServices.Application application, ExporterIFC exporterIFC, Element element, ElementId categoryId, IList<GeometryObject> geometryListIn, BodyExporterOptions options, IFCExtrusionCreationData exportBodyParams) { BodyData bodyData = new BodyData(); if (geometryListIn.Count == 0) return bodyData; Document document = element.Document; bool tryToExportAsExtrusion = options.TryToExportAsExtrusion; bool canExportSolidModelRep = false; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); double scale = exporterIFC.LinearScale; double eps = application.VertexTolerance * scale; IList<GeometryObject> splitGeometryList = new List<GeometryObject>(); bool allFaces = true; foreach (GeometryObject geomObject in geometryListIn) { try { bool split = false; if (geomObject is Solid) { Solid solid = geomObject as Solid; IList<Solid> splitVolumes = SolidUtils.SplitVolumes(solid); allFaces = false; if (splitVolumes != null && splitVolumes.Count != 0) { split = true; foreach (Solid currSolid in splitVolumes) { splitGeometryList.Add(currSolid); // The geometry element created by SplitVolumesis a copy which will have its own allocated // membership - this needs to be stored and disposed of (see AllocatedGeometryObjectCache // for details) ExporterCacheManager.AllocatedGeometryObjectCache.AddGeometryObject(currSolid); } } } else if (allFaces && !(geomObject is Face)) allFaces = false; if (!split) splitGeometryList.Add(geomObject); } catch { splitGeometryList.Add(geomObject); } } IList<IFCAnyHandle> bodyItems = new List<IFCAnyHandle>(); IList<ElementId> materialIdsForExtrusions = new List<ElementId>(); IList<int> exportAsBRep = new List<int>(); IList<int> exportAsExtrusion = new List<int>(); using (IFCTransaction tr = new IFCTransaction(file)) { if (tryToExportAsExtrusion) { // Check to see if we have Geometries or GFaces. // We will have the specific all GFaces case and then the generic case. IList<Face> faces = null; if (allFaces) { faces = new List<Face>(); foreach (GeometryObject geometryObject in splitGeometryList) { faces.Add(geometryObject as Face); } } int numExtrusionsToCreate = allFaces ? 1 : splitGeometryList.Count; IList<IList<IFCExtrusionData>> extrusionLists = new List<IList<IFCExtrusionData>>(); for (int ii = 0; ii < numExtrusionsToCreate && tryToExportAsExtrusion; ii++) { IList<IFCExtrusionData> extrusionList = new List<IFCExtrusionData>(); IFCExtrusionAxes axesToExtrudeIn = exportBodyParams != null ? exportBodyParams.PossibleExtrusionAxes : IFCExtrusionAxes.TryDefault; XYZ directionToExtrudeIn = XYZ.Zero; if (exportBodyParams != null && exportBodyParams.HasCustomAxis) directionToExtrudeIn = exportBodyParams.CustomAxis; IFCExtrusionCalculatorOptions extrusionOptions = new IFCExtrusionCalculatorOptions(exporterIFC, axesToExtrudeIn, directionToExtrudeIn, scale); if (allFaces) extrusionList = IFCExtrusionCalculatorUtils.CalculateExtrusionData(extrusionOptions, faces); else extrusionList = IFCExtrusionCalculatorUtils.CalculateExtrusionData(extrusionOptions, splitGeometryList[ii]); if (extrusionList.Count == 0) { if (!canExportSolidModelRep) { tryToExportAsExtrusion = false; break; } exportAsBRep.Add(ii); } else { extrusionLists.Add(extrusionList); exportAsExtrusion.Add(ii); } } int numCreatedExtrusions = extrusionLists.Count; for (int ii = 0; (ii < numCreatedExtrusions) && tryToExportAsExtrusion; ii++) { int geomIndex = exportAsExtrusion[ii]; bodyData.AddMaterial(SetBestMaterialIdInExporter(splitGeometryList[geomIndex], exporterIFC)); if (exportBodyParams != null && exportBodyParams.AreInnerRegionsOpenings) { IList<CurveLoop> curveLoops = extrusionLists[ii][0].GetLoops(); XYZ extrudedDirection = extrusionLists[ii][0].ExtrusionDirection; int numLoops = curveLoops.Count; for (int jj = numLoops - 1; jj > 0; jj--) { ExtrusionExporter.AddOpeningData(exportBodyParams, extrusionLists[ii][0], curveLoops[jj]); extrusionLists[ii][0].RemoveLoopAt(jj); } } bool exportedAsExtrusion = false; IFCExtrusionBasis whichBasis = extrusionLists[ii][0].ExtrusionBasis; if (whichBasis >= 0) { IFCAnyHandle extrusionHandle = ExtrusionExporter.CreateExtrudedSolidFromExtrusionData(exporterIFC, element, extrusionLists[ii][0]); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(extrusionHandle)) { bodyItems.Add(extrusionHandle); materialIdsForExtrusions.Add(exporterIFC.GetMaterialIdForCurrentExportState()); IList<CurveLoop> curveLoops = extrusionLists[ii][0].GetLoops(); XYZ extrusionDirection = extrusionLists[ii][0].ExtrusionDirection; if (exportBodyParams != null) { double zOff = (whichBasis == IFCExtrusionBasis.BasisZ) ? (1.0 - Math.Abs(extrusionDirection[2])) : Math.Abs(extrusionDirection[2]); double scaledAngle = Math.Asin(zOff) * 180 / Math.PI; exportBodyParams.Slope = scaledAngle; exportBodyParams.ScaledLength = extrusionLists[ii][0].ScaledExtrusionLength; exportBodyParams.ExtrusionDirection = extrusionDirection; for (int kk = 1; kk < extrusionLists[ii].Count; kk++) { ExtrusionExporter.AddOpeningData(exportBodyParams, extrusionLists[ii][kk]); } Plane plane = null; double height = 0.0, width = 0.0; if (ExtrusionExporter.ComputeHeightWidthOfCurveLoop(curveLoops[0], plane, out height, out width)) { exportBodyParams.ScaledHeight = height * scale; exportBodyParams.ScaledWidth = width * scale; } double area = ExporterIFCUtils.ComputeAreaOfCurveLoops(curveLoops); if (area > 0.0) { exportBodyParams.ScaledArea = area * scale * scale; } double innerPerimeter = ExtrusionExporter.ComputeInnerPerimeterOfCurveLoops(curveLoops); double outerPerimeter = ExtrusionExporter.ComputeOuterPerimeterOfCurveLoops(curveLoops); if (innerPerimeter > 0.0) exportBodyParams.ScaledInnerPerimeter = innerPerimeter * scale; if (outerPerimeter > 0.0) exportBodyParams.ScaledOuterPerimeter = outerPerimeter * scale; } exportedAsExtrusion = true; } } if (!exportedAsExtrusion) { if (!canExportSolidModelRep) { tryToExportAsExtrusion = false; break; } exportAsBRep.Add(ii); } } } if ((exportAsBRep.Count == 0) && tryToExportAsExtrusion) { int sz = bodyItems.Count(); for (int ii = 0; ii < sz; ii++) BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, bodyItems[ii], materialIdsForExtrusions[ii]); bodyData.RepresentationHnd = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, categoryId, contextOfItems, bodyItems, bodyData.RepresentationHnd); } if (tryToExportAsExtrusion) tr.Commit(); else tr.RollBack(); if ((exportAsBRep.Count == 0) && tryToExportAsExtrusion) return bodyData; } // We couldn't export it as an extrusion; export as a solid, brep, or a surface model. if (!canExportSolidModelRep) { exportAsExtrusion.Clear(); bodyItems.Clear(); if (exportBodyParams != null) exportBodyParams.ClearOpenings(); } if (exportAsExtrusion.Count == 0) exportAsBRep.Clear(); // generate "bottom corner" of bbox; create new local placement if passed in. // need to transform, but not scale, this point to make it the new origin. // We will only do this if we didn't create any extrusions at all. using (IFCTransformSetter transformSetter = IFCTransformSetter.Create()) { if (exportBodyParams != null && (exportAsBRep.Count == 0)) bodyData.BrepOffsetTransform = transformSetter.InitializeFromBoundingBox(exporterIFC, splitGeometryList, exportBodyParams); return ExportBodyAsBRep(exporterIFC, splitGeometryList, exportAsBRep, bodyItems, element, categoryId, contextOfItems, eps, options, bodyData); } }
/// <summary> /// Exports curtain object as one Brep. /// </summary> /// <param name="allSubElements"> /// Collection of elements contained in the host curtain element. /// </param> /// <param name="wallElement"> /// The curtain wall element. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="setter"> /// The PlacementSetter object. /// </param> /// <param name="localPlacement"> /// The local placement handle. /// </param> /// <returns> /// The handle. /// </returns> public static IFCAnyHandle ExportCurtainObjectCommonAsOneBRep(ICollection <ElementId> allSubElements, Element wallElement, ExporterIFC exporterIFC, PlacementSetter setter, IFCAnyHandle localPlacement) { IFCAnyHandle prodDefRep = null; Document document = wallElement.Document; double eps = UnitUtil.ScaleLength(document.Application.VertexTolerance); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); IFCGeometryInfo info = IFCGeometryInfo.CreateFaceGeometryInfo(eps); ISet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); // Want to make sure we don't accidentally add a mullion or curtain line more than once. HashSet <ElementId> alreadyVisited = new HashSet <ElementId>(); Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); foreach (ElementId subElemId in allSubElements) { Element subElem = wallElement.Document.GetElement(subElemId); GeometryElement geomElem = subElem.get_Geometry(geomOptions); if (geomElem == null) { continue; } if (alreadyVisited.Contains(subElem.Id)) { continue; } alreadyVisited.Add(subElem.Id); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, geomElem, XYZ.Zero, false); HashSet <IFCAnyHandle> faces = new HashSet <IFCAnyHandle>(info.GetSurfaces()); IFCAnyHandle outer = IFCInstanceExporter.CreateClosedShell(file, faces); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(outer)) { bodyItems.Add(RepresentationUtil.CreateFacetedBRep(exporterIFC, document, outer, ElementId.InvalidElementId)); } } if (bodyItems.Count == 0) { return(prodDefRep); } ElementId catId = CategoryUtil.GetSafeCategoryId(wallElement); IFCAnyHandle shapeRep = RepresentationUtil.CreateBRepRep(exporterIFC, wallElement, catId, contextOfItems, bodyItems); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) { return(prodDefRep); } IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, wallElement.get_Geometry(geomOptions), Transform.Identity); if (boundingBoxRep != null) { shapeReps.Add(boundingBoxRep); } prodDefRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); return(prodDefRep); }
/// <summary> /// Creates IFC room/space/area item, not include boundaries. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> /// <param name="setter"> /// The IFCPlacementSetter. /// </param> /// <returns> /// True if created successfully, false otherwise. /// </returns> static bool CreateIFCSpace(ExporterIFC exporterIFC, SpatialElement spatialElement, ProductWrapper productWrapper, IFCPlacementSetter setter) { IList<CurveLoop> curveLoops = null; try { SpatialElementBoundaryOptions options = ExporterIFCUtils.GetSpatialElementBoundaryOptions(exporterIFC, spatialElement); curveLoops = ExporterIFCUtils.GetRoomBoundaryAsCurveLoopArray(spatialElement, options, true); } catch (Autodesk.Revit.Exceptions.InvalidOperationException) { //Some spatial elements are not placed that have no boundary loops. Don't export them. return false; } Autodesk.Revit.DB.Document document = spatialElement.Document; ElementId levelId = spatialElement.Level != null ? spatialElement.Level.Id : ElementId.InvalidElementId; double scale = exporterIFC.LinearScale; ElementId catId = spatialElement.Category != null ? spatialElement.Category.Id : ElementId.InvalidElementId; double dArea = 0.0; if (ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_AREA, out dArea)) dArea *= (scale * scale); IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); string strSpaceNumber = null; string strSpaceName = null; string strSpaceDesc = null; bool isArea = spatialElement is Area; if (!isArea) { if (!ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ROOM_NUMBER, out strSpaceNumber)) strSpaceNumber = null; if (!ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ROOM_NAME, out strSpaceName)) strSpaceName = null; if (!ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS, out strSpaceDesc)) strSpaceDesc = null; } else { // Default to true to preserve previous behavior. bool? exportGSADesignGrossArea = ExporterCacheManager.ExportOptionsCache.ExportGSAGrossDesignArea; if (!exportGSADesignGrossArea.HasValue || exportGSADesignGrossArea.Value) { Element level = document.GetElement(levelId); if (level != null) { strSpaceNumber = level.Name + " GSA Design Gross Area"; } } } string name = strSpaceNumber; string longName = strSpaceName; string desc = strSpaceDesc; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle localPlacement = setter.GetPlacement(); ElementType elemType = document.GetElement(spatialElement.GetTypeId()) as ElementType; IFCInternalOrExternal internalOrExternal = CategoryUtil.IsElementExternal(spatialElement, true) ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal; double roomHeight = 0.0; roomHeight = GetHeight(spatialElement, scale, levelId, levelInfo); if (roomHeight <= 0.0) return false; double bottomOffset; ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_LOWER_OFFSET, out bottomOffset); XYZ zDir = new XYZ(0, 0, 1); XYZ orig = new XYZ(0, 0, levelInfo.Elevation + bottomOffset); Plane plane = new Plane(zDir, orig); // room calculated as level offset. GeometryElement geomElem = null; if (spatialElement is Autodesk.Revit.DB.Architecture.Room) { Autodesk.Revit.DB.Architecture.Room room = spatialElement as Autodesk.Revit.DB.Architecture.Room; geomElem = room.ClosedShell; } else if (spatialElement is Autodesk.Revit.DB.Mechanical.Space) { Autodesk.Revit.DB.Mechanical.Space space = spatialElement as Autodesk.Revit.DB.Mechanical.Space; geomElem = space.ClosedShell; } IFCAnyHandle spaceHnd = null; using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { extraParams.SetLocalPlacement(localPlacement); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; using (IFCTransaction transaction2 = new IFCTransaction(file)) { IFCAnyHandle repHnd = null; if (!ExporterCacheManager.ExportOptionsCache.Use2DRoomBoundaryForRoomVolumeCreation && geomElem != null) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); bodyExporterOptions.TessellationLevel = BodyExporterOptions.BodyTessellationLevel.Coarse; repHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, spatialElement, catId, geomElem, bodyExporterOptions, null, extraParams); if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) extraParams.ClearOpenings(); } else { IFCAnyHandle shapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, plane, zDir, roomHeight); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return false; IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, shapeRep, ElementId.InvalidElementId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(shapeRep); shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, spatialElement, catId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomElem, Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); repHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); } extraParams.ScaledHeight = roomHeight; extraParams.ScaledArea = dArea; string spatialElementName = NamingUtil.GetNameOverride(spatialElement, name); string spatialElementDescription = NamingUtil.GetDescriptionOverride(spatialElement, desc); string spatialElementObjectType = NamingUtil.GetObjectTypeOverride(spatialElement, null); double? spaceElevationWithFlooring = null; double elevationWithFlooring = 0.0; if (ParameterUtil.GetDoubleValueFromElement(spatialElement, "IfcElevationWithFlooring", out elevationWithFlooring) == true) spaceElevationWithFlooring = elevationWithFlooring; spaceHnd = IFCInstanceExporter.CreateSpace(file, GUIDUtil.CreateGUID(spatialElement), exporterIFC.GetOwnerHistoryHandle(), spatialElementName,spatialElementDescription, spatialElementObjectType, extraParams.GetLocalPlacement(), repHnd, longName, Toolkit.IFCElementComposition.Element, internalOrExternal, spaceElevationWithFlooring); transaction2.Commit(); } productWrapper.AddSpace(spaceHnd, levelInfo, extraParams, true); } // Save room handle for later use/relationships ExporterCacheManager.SpatialElementHandleCache.Register(spatialElement.Id, spaceHnd); exporterIFC.RegisterSpatialElementHandle(spatialElement.Id, spaceHnd); // Find Ceiling as a Space boundary and keep the relationship in a cache for use later Boolean ret = getCeilingSpaceBoundary(spatialElement); if (!MathUtil.IsAlmostZero(dArea) && !(ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE) && !ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 && !ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { ExporterIFCUtils.CreatePreCOBIEGSAQuantities(exporterIFC, spaceHnd, "GSA Space Areas", (isArea ? "GSA Design Gross Area" : "GSA BIM Area"), dArea); } // Export BaseQuantities for SpatialElement if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities && !(ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE)) { // Skip this step. The "standard" quantities will be exported at the end of export element process in exportElement (Exporter.cs) // ExporterIFCUtils.CreateNonCOBIERoomQuantities(exporterIFC, spaceHnd, spatialElement, dArea, roomHeight); } // Create general classification for Spatial element from ClassificationCode(s). This is not done here but rather at the end of exportElement process // ClassificationUtil.CreateClassification(exporterIFC, file, spatialElement, spaceHnd, ""); // Export Classifications for SpatialElement for GSA/COBIE. if (ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE) { CreateCOBIESpaceClassifications(exporterIFC, file, spaceHnd, document.ProjectInformation, spatialElement); } return true; }
/// <summary> /// Main implementation to export walls. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="origWrapper"> /// The ProductWrapper. /// </param> /// <param name="overrideLevelId"> /// The level id. /// </param> /// <param name="range"> /// The range to be exported for the element. /// </param> /// <returns> /// The exported wall handle. /// </returns> public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (ProductWrapper localWrapper = ProductWrapper.Create(origWrapper)) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; FamilyInstance famInstWallElem = element as FamilyInstance; FaceWall faceWall = element as FaceWall; if (wallElement == null && famInstWallElem == null && faceWall == null) return null; if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return null; Document doc = element.Document; double scale = exporterIFC.LinearScale; double baseWallElevation = 0.0; ElementId baseLevelId = ExporterUtil.GetBaseLevelIdForElement(element); if (baseLevelId != ElementId.InvalidElementId) { Element baseLevel = doc.GetElement(baseLevelId); if (baseLevel is Level) baseWallElevation = (baseLevel as Level).Elevation; } IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis"); IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); IFCRange zSpan = new IFCRange(); double depth = 0.0; bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, validRange ? overrideLevelId : element.Level.Id, validRange)) return null; // get bounding box height so that we can subtract out pieces properly. // only for Wall, not FamilyInstance. if (wallElement != null && geometryElement != null) { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox == null) return null; zSpan = new IFCRange(boundingBox.Min.Z, boundingBox.Max.Z); // if we have a top clipping plane, modify depth accordingly. double bottomHeight = validRange ? Math.Max(zSpan.Start, range.Start) : zSpan.Start; double topHeight = validRange ? Math.Min(zSpan.End, range.End) : zSpan.End; depth = topHeight - bottomHeight; if (MathUtil.IsAlmostZero(depth)) return null; depth *= scale; } IFCAnyHandle axisRep = null; IFCAnyHandle bodyRep = null; bool exportingAxis = false; Curve curve = null; bool exportedAsWallWithAxis = false; bool exportedBodyDirectly = false; bool exportingInplaceOpenings = false; Curve centerCurve = GetWallAxis(wallElement); XYZ localXDir = new XYZ(1, 0, 0); XYZ localYDir = new XYZ(0, 1, 0); XYZ localZDir = new XYZ(0, 0, 1); XYZ localOrig = new XYZ(0, 0, 0); double eps = MathUtil.Eps(); if (centerCurve != null) { Curve baseCurve = GetWallAxisAtBaseHeight(wallElement); curve = GetWallTrimmedCurve(wallElement, baseCurve); IFCRange curveBounds; XYZ oldOrig; GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig); localOrig = oldOrig; if (baseCurve != null) { if (!validRange || (MathUtil.IsAlmostEqual(range.Start, zSpan.Start))) { XYZ newOrig = baseCurve.Evaluate(curveBounds.Start, false); if (!validRange && (zSpan.Start < newOrig[2] - eps)) localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan.Start); else localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]); } else { localOrig = new XYZ(localOrig.X, localOrig.Y, range.Start); } } double dist = localOrig[2] - oldOrig[2]; if (!MathUtil.IsAlmostZero(dist)) { XYZ moveVec = new XYZ(0, 0, dist); curve = GeometryUtil.MoveCurve(curve, moveVec); } localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } else { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox != null) { XYZ bBoxMin = boundingBox.Min; XYZ bBoxMax = boundingBox.Max; if (validRange) localOrig = new XYZ(bBoxMin.X, bBoxMin.Y, range.Start); else localOrig = boundingBox.Min; XYZ localXDirMax = null; Transform bTrf = boundingBox.Transform; XYZ localXDirMax1 = new XYZ(bBoxMax.X, localOrig.Y, localOrig.Z); localXDirMax1 = bTrf.OfPoint(localXDirMax1); XYZ localXDirMax2 = new XYZ(localOrig.X, bBoxMax.Y, localOrig.Z); localXDirMax2 = bTrf.OfPoint(localXDirMax2); if (localXDirMax1.DistanceTo(localOrig) >= localXDirMax2.DistanceTo(localOrig)) localXDirMax = localXDirMax1; else localXDirMax = localXDirMax2; localXDir = localXDirMax.Subtract(localOrig); localXDir = localXDir.Normalize(); localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } } Transform orientationTrf = Transform.Identity; orientationTrf.BasisX = localXDir; orientationTrf.BasisY = localYDir; orientationTrf.BasisZ = localZDir; orientationTrf.Origin = localOrig; if (overrideLevelId == ElementId.InvalidElementId) overrideLevelId = ExporterUtil.GetBaseLevelIdForElement(element); using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.GetPlacement(); Plane plane = new Plane(localXDir, localYDir, localOrig); // project curve to XY plane. XYZ projDir = XYZ.BasisZ; // two representations: axis, body. { if (!exportParts && (centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve))) { exportingAxis = true; string identifierOpt = "Axis"; // IFC2x2 convention string representationTypeOpt = "Curve2D"; // IFC2x2 convention IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true); IList<IFCAnyHandle> axisItems = info.GetCurves(); if (axisItems.Count == 0) { exportingAxis = false; } else { HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>(); foreach (IFCAnyHandle axisItem in axisItems) axisItemSet.Add(axisItem); axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItemsAxis, identifierOpt, representationTypeOpt, axisItemSet); } } } IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>(); Document document = element.Document; IList<Solid> solids = new List<Solid>(); IList<Mesh> meshes = new List<Mesh>(); if (!exportParts && wallElement != null && exportingAxis && curve != null) { SolidMeshGeometryInfo solidMeshInfo = (range == null) ? GeometryUtil.GetSplitSolidMeshGeometry(geometryElement) : GeometryUtil.GetSplitClippedSolidMeshGeometry(geometryElement, range); solids = solidMeshInfo.GetSolids(); meshes = solidMeshInfo.GetMeshes(); if (solids.Count == 0 && meshes.Count == 0) return null; bool useNewCode = false; if (useNewCode && solids.Count == 1 && meshes.Count == 0) { bool completelyClipped; bodyRep = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, wallElement, catId, solids[0], plane, projDir, range, out completelyClipped); if (completelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { exportedAsWallWithAxis = true; exportedBodyDirectly = true; } else { exportedAsWallWithAxis = false; exportedBodyDirectly = false; } } if (!exportedAsWallWithAxis) { // Fallback - use native routines to try to export wall. bool isCompletelyClipped; bodyRep = FallbackTryToCreateAsExtrusion(exporterIFC, wallElement, solidMeshInfo, baseWallElevation, catId, curve, plane, depth, zSpan, range, setter, out cutPairOpenings, out isCompletelyClipped); if (isCompletelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) exportedAsWallWithAxis = true; } } using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { BodyData bodyData = null; if (!exportedAsWallWithAxis) { SolidMeshGeometryInfo solidMeshCapsule = null; if (wallElement != null || faceWall != null) { if (validRange) { solidMeshCapsule = GeometryUtil.GetSplitClippedSolidMeshGeometry(geometryElement, range); } else { solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); } if (solidMeshCapsule.SolidsCount() == 0 && solidMeshCapsule.MeshesCount() == 0) { return null; } } else { GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem); if (geomElemToUse != null) { exportingInplaceOpenings = true; } else { exportingInplaceOpenings = false; geomElemToUse = geometryElement; } Transform trf = Transform.Identity; if (geomElemToUse != geometryElement) trf = famInstWallElem.GetTransform(); solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geomElemToUse, trf); } solids = solidMeshCapsule.GetSolids(); meshes = solidMeshCapsule.GetMeshes(); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); // Swept solids are not natively exported as part of CV2.0. // We have removed the UI toggle for this, so that it is by default false, but keep for possible future use. if (ExporterCacheManager.ExportOptionsCache.ExportAdvancedSweptSolids) bodyExporterOptions.TryToExportAsSweptSolid = true; ElementId overrideMaterialId = ElementId.InvalidElementId; if (wallElement != null) overrideMaterialId = HostObjectExporter.GetFirstLayerMaterialId(wallElement); if (!exportParts) { if ((solids.Count > 0) || (meshes.Count > 0)) { bodyRep = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId, solids, meshes, bodyExporterOptions, extraParams).RepresentationHnd; } else { IList<GeometryObject> geomElemList = new List<GeometryObject>(); geomElemList.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId, geomElemList, bodyExporterOptions, extraParams); bodyRep = bodyData.RepresentationHnd; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { extraParams.ClearOpenings(); return null; } } // We will be able to export as a IfcWallStandardCase as long as we have an axis curve. XYZ extrDirUsed = XYZ.Zero; if (extraParams.HasExtrusionDirection) { extrDirUsed = extraParams.ExtrusionDirection; if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0)) { if ((solids.Count == 1) && (meshes.Count == 0)) exportedAsWallWithAxis = exportingAxis; exportedBodyDirectly = true; } } } IFCAnyHandle prodRep = null; if (!exportParts) { IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (exportingAxis) representations.Add(axisRep); representations.Add(bodyRep); IFCAnyHandle boundingBoxRep = null; if ((solids.Count > 0) || (meshes.Count > 0)) boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, solids, meshes, Transform.Identity); else boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) representations.Add(boundingBoxRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); } ElementId matId = ElementId.InvalidElementId; string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = null; string elemGUID = (validRange) ? GUIDUtil.CreateGUID() : GUIDUtil.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); // For Foundation and Retaining walls, allow exporting as IfcFooting instead. bool exportAsFooting = false; string enumTypeValue = null; if (wallElement != null) { WallType wallType = wallElement.WallType; if (wallType != null) { int wallFunction; if (ParameterUtil.GetIntValueFromElement(wallType, BuiltInParameter.FUNCTION_PARAM, out wallFunction) != null) { if (wallFunction == (int)WallFunction.Retaining || wallFunction == (int)WallFunction.Foundation) { // In this case, allow potential to export foundation and retaining walls as footing. IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, wallElement, out enumTypeValue); if (exportType == IFCExportType.ExportFooting) exportAsFooting = true; } } } } if (exportedAsWallWithAxis) { if (exportAsFooting) { Toolkit.IFCFootingType footingType = FootingExporter.GetIFCFootingType(element, enumTypeValue); wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, footingType); } else if (exportParts) { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, null, elemTag); } else { wallHnd = IFCInstanceExporter.CreateWallStandardCase(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, prodRep, elemTag); } if (exportParts) PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(element, wallHnd, setter, extraParams, true); if (!exportParts) { OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, null, exporterIFC, localPlacement, setter, localWrapper); if (exportedBodyDirectly) { Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform, exporterIFC, localPlacement, setter, localWrapper); } else { ICollection<IFCAnyHandle> beforeOpenings = localWrapper.GetAllObjects(); double scaledWidth = wallElement.Width * scale; ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper.ToNative()); ICollection<IFCAnyHandle> afterOpenings = localWrapper.GetAllObjects(); if (beforeOpenings.Count != afterOpenings.Count) { foreach (IFCAnyHandle before in beforeOpenings) afterOpenings.Remove(before); foreach (IFCAnyHandle potentiallyBadOpening in afterOpenings) { PotentiallyCorrectOpeningOrientationAndOpeningType(potentiallyBadOpening, localPlacement, scaledWidth); } } } } // export Base Quantities if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth); } } else { if (exportAsFooting) { Toolkit.IFCFootingType footingType = FootingExporter.GetIFCFootingType(element, enumTypeValue); wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, footingType); } else { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag); } if (exportParts) PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(element, wallHnd, setter, extraParams, true); if (!exportParts) { // Only export one material for 2x2; for future versions, export the whole list. if (exporterIFC.ExportAs2x2 || famInstWallElem != null) { matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids, meshes, element); if (matId != ElementId.InvalidElementId) CategoryUtil.CreateMaterialAssociation(exporterIFC, wallHnd, matId); } if (exportingInplaceOpenings) { ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, famInstWallElem, 0.0, range, setter, localPlacement, localWrapper.ToNative()); } if (exportedBodyDirectly) { Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform, exporterIFC, localPlacement, setter, localWrapper); } } } ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; if ((wallElement != null || faceWall != null) && !exportParts) { HostObject hostObject = null; if (wallElement != null) hostObject = wallElement; else hostObject = faceWall; if (!exporterIFC.ExportAs2x2 || exportedAsWallWithAxis) HostObjectExporter.ExportHostObjectMaterials(exporterIFC, hostObject, localWrapper.GetAnElement(), geometryElement, localWrapper, wallLevelId, Toolkit.IFCLayerSetDirection.Axis2, !exportedAsWallWithAxis); } ExportWallType(exporterIFC, localWrapper, wallHnd, element, matId, exportedAsWallWithAxis, exportAsFooting); exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId); tr.Commit(); return wallHnd; } } } } }
/// <summary> /// Creates a extruded product definition shape representation. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The base element.</param> /// <param name="categoryId">The category of the element.</param> /// <param name="curveLoops">The curve loops defining the extruded surface.</param> /// <param name="plane">The extrusion base plane.</param> /// <param name="extrDirVec">The extrusion direction.</param> /// <param name="extrusionSize">The scaled extrusion length.</param> /// <returns>The handle.</returns> public static IFCAnyHandle CreateExtrudedProductDefShape(ExporterIFC exporterIFC, Element element, ElementId categoryId, IList<CurveLoop> curveLoops, Plane plane, XYZ extrDirVec, double extrusionSize) { IFCFile file = exporterIFC.GetFile(); IFCAnyHandle extrusionHnd = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, plane, extrDirVec, extrusionSize); if (IFCAnyHandleUtil.IsNullOrHasNoValue(extrusionHnd)) return null; ISet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(extrusionHnd); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); IFCAnyHandle shapeRepHnd = CreateSweptSolidRep(exporterIFC, element, categoryId, contextOfItems, bodyItems, null); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRepHnd); return IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); }
/// <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 = Common.Enums.IFCEntityType.IfcRamp; if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum)) { return; } // TESTING foreach (GeometryObject geomObj in geometryElement) { Visibility visibility = geomObj.Visibility; } IFCFile file = exporterIFC.GetFile(); ElementId categoryId = CategoryUtil.GetSafeCategoryId(ramp); using (IFCTransaction tr = new IFCTransaction(file)) { using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, ramp)) { IFCAnyHandle contextOfItemsFootPrint = exporterIFC.Get3DContextHandle("FootPrint"); IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis"); Transform trf = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, placementSetter.LocalPlacement); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; IList <(Solid body, Face largestTopFace)> rampFlights = null; IList <Solid> landings = null; if (IdentifyRampFlightAndLanding(geometryElement, out rampFlights, out landings)) { string rampGUID = GUIDUtil.CreateGUID(ramp); IFCAnyHandle rampLocalPlacement = placementSetter.LocalPlacement; string predefType = "NOTDEFINED"; //Temporary IFCAnyHandle rampContainerHnd = IFCInstanceExporter.CreateRamp(exporterIFC, ramp, rampGUID, ownerHistory, rampLocalPlacement, null, predefType); // Create appropriate type IFCExportInfoPair exportType = new IFCExportInfoPair(); exportType.SetValueWithPair(IFCEntityType.IfcRamp); IFCAnyHandle rampTypeHnd = ExporterUtil.CreateGenericTypeFromElement(ramp, exportType, exporterIFC.GetFile(), ownerHistory, predefType, productWrapper); ExporterCacheManager.TypeRelationsCache.Add(rampTypeHnd, rampContainerHnd); productWrapper.AddElement(ramp, rampContainerHnd, placementSetter.LevelInfo, null, true); //Breakdown the Ramp into its components: RampFlights and Landings int rampFlightIndex = 0; int landingIndex = 0; HashSet <IFCAnyHandle> rampComponents = new HashSet <IFCAnyHandle>(); foreach ((Solid body, Face topFace)rampFlight in rampFlights) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.AllowVerticalOffsetOfBReps = false; ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, placementSetter.LocalPlacement, null)); ecData.ReuseLocalPlacement = true; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); BodyData bodyData = BodyExporter.ExportBody(exporterIFC, ramp, categoryId, ElementId.InvalidElementId, rampFlight.body, bodyExporterOptions, ecData); IFCAnyHandle bodyRep = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { ecData.ClearOpenings(); continue; } IList <IFCAnyHandle> reps = new List <IFCAnyHandle>(); reps.Add(bodyRep); //if (!ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2) //{ // CreateWalkingLineAndFootprint(exporterIFC, run, bodyData, categoryId, trf, ref reps); //} Transform boundingBoxTrf = (bodyData.OffsetTransform == null) ? Transform.Identity : bodyData.OffsetTransform.Inverse; IList <GeometryObject> solidList = new List <GeometryObject>(); solidList.Add(rampFlight.body); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, solidList, boundingBoxTrf); if (boundingBoxRep != null) { reps.Add(boundingBoxRep); } IFCAnyHandle representation = IFCInstanceExporter.CreateProductDefinitionShape(exporterIFC.GetFile(), null, null, reps); rampFlightIndex++; string flightGUID = GUIDUtil.CreateSubElementGUID(ramp, rampFlightIndex); string origFlightName = IFCAnyHandleUtil.GetStringAttribute(rampContainerHnd, "Name") + " " + rampFlightIndex; string flightName = NamingUtil.GetOverrideStringValue(ramp, "IfcRampFlight.Name (" + rampFlightIndex + ")", origFlightName); IFCAnyHandle flightLocalPlacement = ecData.GetLocalPlacement(); string flightPredefType = NamingUtil.GetOverrideStringValue(ramp, "IfcRampFlight.PredefinedType (" + rampFlightIndex + ")", null); IFCAnyHandle rampFlightHnd = IFCInstanceExporter.CreateRampFlight(exporterIFC, null, flightGUID, ownerHistory, flightLocalPlacement, representation, flightPredefType); IFCAnyHandleUtil.OverrideNameAttribute(rampFlightHnd, flightName); rampComponents.Add(rampFlightHnd); // Create type IFCExportInfoPair flightEportType = new IFCExportInfoPair(); flightEportType.SetValueWithPair(IFCEntityType.IfcRampFlight); IFCAnyHandle flightTypeHnd = IFCInstanceExporter.CreateGenericIFCType(flightEportType, null, exporterIFC.GetFile(), null, null, flightPredefType); IFCAnyHandleUtil.OverrideNameAttribute(flightTypeHnd, flightName); ExporterCacheManager.TypeRelationsCache.Add(flightTypeHnd, rampFlightHnd); CategoryUtil.CreateMaterialAssociation(exporterIFC, rampFlightHnd, bodyData.MaterialIds); IFCAnyHandle psetRampFlightCommonHnd = CreatePSetRampFlightCommon(exporterIFC, file, ramp, rampFlightIndex, rampFlight.topFace); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(psetRampFlightCommonHnd)) { HashSet <IFCAnyHandle> relatedObjects = new HashSet <IFCAnyHandle>() { rampFlightHnd }; ExporterUtil.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, relatedObjects, psetRampFlightCommonHnd); } } } foreach (Solid landing in landings) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.AllowVerticalOffsetOfBReps = false; ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, placementSetter.LocalPlacement, null)); ecData.ReuseLocalPlacement = true; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); BodyData bodyData = BodyExporter.ExportBody(exporterIFC, ramp, categoryId, ElementId.InvalidElementId, landing, bodyExporterOptions, ecData); IFCAnyHandle bodyRep = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { ecData.ClearOpenings(); continue; } IList <IFCAnyHandle> reps = new List <IFCAnyHandle>(); reps.Add(bodyRep); //if (!ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2) //{ // CreateWalkingLineAndFootprint(exporterIFC, run, bodyData, categoryId, trf, ref reps); //} Transform boundingBoxTrf = (bodyData.OffsetTransform == null) ? Transform.Identity : bodyData.OffsetTransform.Inverse; IList <GeometryObject> solidList = new List <GeometryObject>(); solidList.Add(landing); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, solidList, boundingBoxTrf); if (boundingBoxRep != null) { reps.Add(boundingBoxRep); } IFCAnyHandle representation = IFCInstanceExporter.CreateProductDefinitionShape(exporterIFC.GetFile(), null, null, reps); landingIndex++; string landingGUID = GUIDUtil.CreateSubElementGUID(ramp, landingIndex); string origLandingName = IFCAnyHandleUtil.GetStringAttribute(rampContainerHnd, "Name") + " " + landingIndex; string landingName = NamingUtil.GetOverrideStringValue(ramp, "IfcRampLanding.Name (" + landingIndex + ")", origLandingName); IFCAnyHandle landingLocalPlacement = ecData.GetLocalPlacement(); string landingPredefType = "LANDING"; IFCAnyHandle rampLandingHnd = IFCInstanceExporter.CreateSlab(exporterIFC, ramp, landingGUID, ownerHistory, landingLocalPlacement, representation, landingPredefType); IFCAnyHandleUtil.OverrideNameAttribute(rampLandingHnd, landingName); rampComponents.Add(rampLandingHnd); // Create type IFCExportInfoPair landingEportType = new IFCExportInfoPair(); landingEportType.SetValueWithPair(IFCEntityType.IfcSlab); IFCAnyHandle landingTypeHnd = IFCInstanceExporter.CreateGenericIFCType(landingEportType, null, exporterIFC.GetFile(), null, null, landingPredefType); IFCAnyHandleUtil.OverrideNameAttribute(landingTypeHnd, landingName); ExporterCacheManager.TypeRelationsCache.Add(landingTypeHnd, rampLandingHnd); CategoryUtil.CreateMaterialAssociation(exporterIFC, rampLandingHnd, bodyData.MaterialIds); IFCAnyHandle psetSlabCommonHnd = CreatePSetRampLandingCommon(exporterIFC, file, ramp, landingIndex); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(psetSlabCommonHnd)) { HashSet <IFCAnyHandle> relatedObjects = new HashSet <IFCAnyHandle>() { rampLandingHnd }; ExporterUtil.CreateRelDefinesByProperties(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, relatedObjects, psetSlabCommonHnd); } } } if (rampComponents.Count > 0) { IFCInstanceExporter.CreateRelAggregates(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, rampContainerHnd, rampComponents); } } else { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(placementSetter.LocalPlacement); ecData.ReuseLocalPlacement = false; GeometryElement rampGeom = GeometryUtil.GetOneLevelGeometryElement(geometryElement, numFlights); BodyData bodyData; 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 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> /// Main implementation to export walls. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="origWrapper"> /// The IFCProductWrapper. /// </param> /// <param name="overrideLevelId"> /// The level id. /// </param> /// <param name="range"> /// The range to be exported for the element. /// </param> /// <returns> /// The exported wall handle. /// </returns> public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range) { using (IFCProductWrapper localWrapper = IFCProductWrapper.Create(origWrapper)) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; FamilyInstance famInstWallElem = element as FamilyInstance; if (wallElement == null && famInstWallElem == null) return null; if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return null; // get global values. Document doc = element.Document; double scale = exporterIFC.LinearScale; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis"); IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); IFCRange zSpan = new IFCRange(); double depth = 0.0; bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); bool exportParts = PartExporter.CanExportParts(wallElement); if (exportParts && !PartExporter.CanExportElementInPartExport(wallElement, validRange? overrideLevelId : wallElement.Level.Id, validRange)) return null; // get bounding box height so that we can subtract out pieces properly. // only for Wall, not FamilyInstance. if (wallElement != null && geometryElement != null) { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox == null) return null; zSpan = new IFCRange(boundingBox.Min.Z, boundingBox.Max.Z); // if we have a top clipping plane, modify depth accordingly. double bottomHeight = validRange ? Math.Max(zSpan.Start, range.Start) : zSpan.Start; double topHeight = validRange ? Math.Min(zSpan.End, range.End) : zSpan.End; depth = topHeight - bottomHeight; if (MathUtil.IsAlmostZero(depth)) return null; depth *= scale; } IFCAnyHandle axisRep = null; IFCAnyHandle bodyRep = null; bool exportingAxis = false; Curve curve = null; bool exportedAsWallWithAxis = false; bool exportedBodyDirectly = false; bool exportingInplaceOpenings = false; Curve centerCurve = GetWallAxis(wallElement); XYZ localXDir = new XYZ(1, 0, 0); XYZ localYDir = new XYZ(0, 1, 0); XYZ localZDir = new XYZ(0, 0, 1); XYZ localOrig = new XYZ(0, 0, 0); double eps = MathUtil.Eps(); if (centerCurve != null) { Curve baseCurve = GetWallAxisAtBaseHeight(wallElement); curve = GetWallTrimmedCurve(wallElement, baseCurve); IFCRange curveBounds; XYZ oldOrig; GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig); localOrig = oldOrig; if (baseCurve != null) { if (!validRange || (MathUtil.IsAlmostEqual(range.Start, zSpan.Start))) { XYZ newOrig = baseCurve.Evaluate(curveBounds.Start, false); if (!validRange && (zSpan.Start < newOrig[2] - eps)) localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan.Start); else localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]); } else { localOrig = new XYZ(localOrig.X, localOrig.Y, range.Start); } } double dist = localOrig[2] - oldOrig[2]; if (!MathUtil.IsAlmostZero(dist)) { XYZ moveVec = new XYZ(0, 0, dist); curve = GeometryUtil.MoveCurve(curve, moveVec); } localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } Transform orientationTrf = Transform.Identity; orientationTrf.BasisX = localXDir; orientationTrf.BasisY = localYDir; orientationTrf.BasisZ = localZDir; orientationTrf.Origin = localOrig; using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.GetPlacement(); Plane plane = new Plane(localXDir, localYDir, localOrig); // project curve to XY plane. XYZ projDir = XYZ.BasisZ; // two representations: axis, body. { if ((centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve))) { exportingAxis = true; string identifierOpt = "Axis"; // IFC2x2 convention string representationTypeOpt = "Curve2D"; // IFC2x2 convention IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true); IList<IFCAnyHandle> axisItems = info.GetCurves(); if (axisItems.Count == 0) { exportingAxis = false; } else { HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>(); foreach (IFCAnyHandle axisItem in axisItems) axisItemSet.Add(axisItem); axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItemsAxis, identifierOpt, representationTypeOpt, axisItemSet); } } } IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>(); Document document = element.Document; if (wallElement != null && exportingAxis && curve != null) { SolidMeshGeometryInfo solidMeshInfo = (range == null) ? GeometryUtil.GetSolidMeshGeometry(geometryElement, Transform.Identity) : GeometryUtil.GetClippedSolidMeshGeometry(geometryElement, range); IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> meshes = solidMeshInfo.GetMeshes(); if (solids.Count == 0 && meshes.Count == 0) return null; bool useNewCode = false; if (useNewCode && solids.Count == 1 && meshes.Count == 0) { bool completelyClipped; bodyRep = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, wallElement, catId, solids[0], plane, projDir, range, out completelyClipped); if (completelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { exportedAsWallWithAxis = true; exportedBodyDirectly = true; } else { exportedAsWallWithAxis = false; exportedBodyDirectly = false; } } if (!exportedAsWallWithAxis) { // Fallback - use native routines to try to export wall. bool isCompletelyClipped; bodyRep = FallbackTryToCreateAsExtrusion(exporterIFC, wallElement, solidMeshInfo, catId, curve, plane, depth, zSpan, range, setter, out cutPairOpenings, out isCompletelyClipped); if (isCompletelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) exportedAsWallWithAxis = true; } } using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { ElementId matId = ElementId.InvalidElementId; if (!exportedAsWallWithAxis) { SolidMeshGeometryInfo solidMeshCapsule = null; if (wallElement != null) { if (validRange) { solidMeshCapsule = GeometryUtil.GetClippedSolidMeshGeometry(geometryElement, range); } else { solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); } if (solidMeshCapsule.SolidsCount() == 0 && solidMeshCapsule.MeshesCount() == 0) { return null; } } else { GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem); if (geomElemToUse != null) { exportingInplaceOpenings = true; } else { exportingInplaceOpenings = false; geomElemToUse = geometryElement; } Transform trf = Transform.Identity; if (geomElemToUse != geometryElement) trf = famInstWallElem.GetTransform(); solidMeshCapsule = GeometryUtil.GetSolidMeshGeometry(geomElemToUse, trf); } IList<Solid> solids = solidMeshCapsule.GetSolids(); IList<Mesh> meshes = solidMeshCapsule.GetMeshes(); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); if ((solids.Count > 0) || (meshes.Count > 0)) { matId = BodyExporter.GetBestMaterialIdForGeometry(solids, meshes); bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, catId, solids, meshes, bodyExporterOptions, extraParams).RepresentationHnd; } else { IList<GeometryObject> geomElemList = new List<GeometryObject>(); geomElemList.Add(geometryElement); BodyData bodyData = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, catId, geomElemList, bodyExporterOptions, extraParams); bodyRep = bodyData.RepresentationHnd; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { extraParams.ClearOpenings(); return null; } // We will be able to export as a IfcWallStandardCase as long as we have an axis curve. XYZ extrDirUsed = XYZ.Zero; if (extraParams.HasExtrusionDirection) { extrDirUsed = extraParams.ExtrusionDirection; if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0)) { if ((solids.Count == 1) && (meshes.Count == 0)) exportedAsWallWithAxis = exportingAxis; exportedBodyDirectly = true; } } } IFCAnyHandle prodRep = null; IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (exportingAxis) representations.Add(axisRep); representations.Add(bodyRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = null; string elemGUID = (validRange) ? ExporterIFCUtils.CreateGUID() : ExporterIFCUtils.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, exporterIFC.GetName()); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemId = NamingUtil.CreateIFCElementId(element); if (exportedAsWallWithAxis) { wallHnd = IFCInstanceExporter.CreateWallStandardCase(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemId); if (exportParts) PartExporter.ExportHostPart(exporterIFC, wallElement, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(wallHnd, setter, extraParams, true); OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, exporterIFC, localPlacement, setter, localWrapper); if (exportedBodyDirectly) { OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper); } else { double scaledWidth = wallElement.Width * scale; ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper); } // export Base Quantities if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth); } } else { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemId); if (exportParts) PartExporter.ExportHostPart(exporterIFC, wallElement, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(wallHnd, setter, extraParams, true); // Only export one material for 2x2; for future versions, export the whole list. if (exporterIFC.ExportAs2x2 && (matId != ElementId.InvalidElementId) && !exportParts) { CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, wallHnd, matId); } if (exportingInplaceOpenings) { ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, famInstWallElem, 0.0, range, setter, localPlacement, localWrapper); } if (exportedBodyDirectly) OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper); } PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, localWrapper); ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; if (wallElement != null && !exportParts) { if (!exporterIFC.ExportAs2x2 || exportedAsWallWithAxis) //will move this check into ExportHostObject HostObjectExporter.ExportHostObjectMaterials(exporterIFC, wallElement, localWrapper.GetAnElement(), geometryElement, localWrapper, wallLevelId, Toolkit.IFCLayerSetDirection.Axis2); } exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId); return wallHnd; } } } }
/// <summary> /// Exports a Rebar Coupler, /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="coupler">The RebarCoupler element.</param> /// <param name="productWrapper">The product wrapper.</param> public static void ExportCoupler(ExporterIFC exporterIFC, RebarCoupler coupler, ProductWrapper productWrapper) { if (coupler == null) { return; } FamilySymbol familySymbol = ExporterCacheManager.Document.GetElement(coupler.GetTypeId()) as FamilySymbol; if (familySymbol == 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>("IfcMechanicalFastener", out elementClassTypeEnum)) { if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum)) { return; } } ElementId categoryId = CategoryUtil.GetSafeCategoryId(coupler); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; Options options = GeometryUtil.GetIFCExportGeometryOptions();; string ifcEnumType; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, coupler, out ifcEnumType); using (IFCTransaction tr = new IFCTransaction(file)) { FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(coupler.GetTypeId(), false, exportType); bool found = currentTypeInfo.IsValid(); if (!found) { string typeGUID = GUIDUtil.CreateGUID(familySymbol); string typeName = NamingUtil.GetIFCName(familySymbol); string typeObjectType = NamingUtil.CreateIFCObjectName(exporterIFC, familySymbol); string applicableOccurance = NamingUtil.GetObjectTypeOverride(familySymbol, typeObjectType); string typeDescription = NamingUtil.GetDescriptionOverride(familySymbol, null); string typeElemId = NamingUtil.CreateIFCElementId(familySymbol); HashSet <IFCAnyHandle> propertySetsOpt = new HashSet <IFCAnyHandle>(); GeometryElement exportGeometry = familySymbol.get_Geometry(options); BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.ExtraLow); bodyData = BodyExporter.ExportBody(exporterIFC, coupler, categoryId, ElementId.InvalidElementId, exportGeometry, bodyExporterOptions, null); List <IFCAnyHandle> repMap = new List <IFCAnyHandle>(); IFCAnyHandle origin = ExporterUtil.CreateAxis2Placement3D(file);; repMap.Add(IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyData.RepresentationHnd)); IFCAnyHandle styleHandle = FamilyExporterUtil.ExportGenericType(exporterIFC, exportType, ifcEnumType, typeGUID, typeName, typeDescription, applicableOccurance, propertySetsOpt, repMap, typeElemId, typeName, coupler, familySymbol); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle)) { currentTypeInfo.Style = styleHandle; ExporterCacheManager.TypeObjectsCache.Register(coupler.GetTypeId(), false, exportType, currentTypeInfo); } } int nCouplerQuantity = coupler.GetCouplerQuantity(); if (nCouplerQuantity <= 0) { return; } ISet <IFCAnyHandle> createdRebarCouplerHandles = new HashSet <IFCAnyHandle>(); string origInstanceName = NamingUtil.GetNameOverride(coupler, NamingUtil.GetIFCName(coupler)); for (int idx = 0; idx < nCouplerQuantity; idx++) { string instanceGUID = GUIDUtil.CreateSubElementGUID(coupler, idx); string instanceName = NamingUtil.GetNameOverride(coupler, origInstanceName + ": " + idx); string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, coupler); string instanceObjectType = NamingUtil.GetObjectTypeOverride(coupler, objectType); string instanceDescription = NamingUtil.GetDescriptionOverride(coupler, null); string instanceElemId = NamingUtil.CreateIFCElementId(coupler); string instanceTag = NamingUtil.GetTagOverride(coupler, NamingUtil.CreateIFCElementId(coupler)); IFCAnyHandle style = currentTypeInfo.Style; if (IFCAnyHandleUtil.IsNullOrHasNoValue(style)) { return; } IList <IFCAnyHandle> repMapList = GeometryUtil.GetRepresentationMaps(style); if (repMapList == null) { return; } if (repMapList.Count == 0) { return; } IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); IFCAnyHandle contextOfItems3d = exporterIFC.Get3DContextHandle("Body"); ISet <IFCAnyHandle> representations = new HashSet <IFCAnyHandle>(); representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMapList[0], XYZ.Zero)); IFCAnyHandle shapeRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, coupler, categoryId, contextOfItems3d, representations); shapeReps.Add(shapeRep); IFCAnyHandle productRepresentation = IFCInstanceExporter.CreateProductDefinitionShape(exporterIFC.GetFile(), null, null, shapeReps); Transform trf = coupler.GetCouplerPositionTransform(idx); using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, coupler, trf, null)) { IFCAnyHandle instanceHandle = null; instanceHandle = IFCInstanceExporter.CreateGenericIFCEntity(Common.Enums.IFCEntityType.IfcMechanicalFastener, file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, setter.LocalPlacement, productRepresentation, instanceTag); if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { // In IFC4 NominalDiameter and NominalLength attributes have been deprecated. PredefinedType attribute was added. IFCAnyHandleUtil.SetAttribute(instanceHandle, "PredefinedType", Revit.IFC.Export.Toolkit.IFC4.IFCMechanicalFastenerType.USERDEFINED); } else { IFCAnyHandleUtil.SetAttribute(instanceHandle, "NominalDiameter", familySymbol.get_Parameter(BuiltInParameter.COUPLER_WIDTH).AsDouble()); IFCAnyHandleUtil.SetAttribute(instanceHandle, "NominalLength", familySymbol.get_Parameter(BuiltInParameter.COUPLER_LENGTH).AsDouble()); } createdRebarCouplerHandles.Add(instanceHandle); productWrapper.AddElement(coupler, instanceHandle, setter, null, true); } } string couplerGUID = GUIDUtil.CreateGUID(coupler); if (nCouplerQuantity > 1) { // Create a group to hold all of the created IFC entities, if the coupler aren't already in an assembly. // We want to avoid nested groups of groups of couplers. if (coupler.AssemblyInstanceId == ElementId.InvalidElementId) { string revitObjectType = exporterIFC.GetFamilyName(); string name = NamingUtil.GetNameOverride(coupler, revitObjectType); string description = NamingUtil.GetDescriptionOverride(coupler, null); string objectType = NamingUtil.GetObjectTypeOverride(coupler, revitObjectType); IFCAnyHandle rebarGroup = IFCInstanceExporter.CreateGroup(file, couplerGUID, ownerHistory, name, description, objectType); productWrapper.AddElement(coupler, rebarGroup); IFCInstanceExporter.CreateRelAssignsToGroup(file, GUIDUtil.CreateGUID(), ownerHistory, null, null, createdRebarCouplerHandles, null, rebarGroup); } } else { // We will update the GUID of the one created element to be the element GUID. // This will allow the IfcGUID parameter to be use/set if appropriate. ExporterUtil.SetGlobalId(createdRebarCouplerHandles.ElementAt(0), couplerGUID); } tr.Commit(); } }
/// <summary> /// Exports curtain object as one Brep. /// </summary> /// <param name="allSubElements"> /// Collection of elements contained in the host curtain element. /// </param> /// <param name="wallElement"> /// The curtain wall element. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="setter"> /// The IFCPlacementSetter object. /// </param> /// <param name="localPlacement"> /// The local placement handle. /// </param> /// <returns> /// The handle. /// </returns> public static IFCAnyHandle ExportCurtainObjectCommonAsOneBRep(ElementSet allSubElements, Element wallElement, ExporterIFC exporterIFC, IFCPlacementSetter setter, IFCAnyHandle localPlacement) { IFCAnyHandle prodDefRep = IFCAnyHandle.Create(); double eps = wallElement.Document.Application.VertexTolerance * exporterIFC.LinearScale; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle(); IFCGeometryInfo info = IFCGeometryInfo.CreateSurfaceGeometryInfo(eps); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); // Want to make sure we don't accidentally add a mullion or curtain line more than once. HashSet<ElementId> alreadyVisited = new HashSet<ElementId>(); Options geomOptions = new Options(); foreach (Element subElem in allSubElements) { GeometryElement geometryElement = subElem.get_Geometry(geomOptions); if (geometryElement == null) continue; if (alreadyVisited.Contains(subElem.Id)) continue; alreadyVisited.Add(subElem.Id); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, geometryElement, XYZ.Zero, false); IFCAnyHandle outer = file.CreateClosedShell(info.GetSurfaces()); if (outer.HasValue) bodyItems.Add(RepresentationUtil.CreateFacetedBRep(exporterIFC, outer)); } if (bodyItems.Count == 0) return prodDefRep; ElementId catId = CategoryUtil.GetSafeCategoryId(wallElement); IFCAnyHandle shapeRep = RepresentationUtil.CreateBRepRep(exporterIFC, catId, contextOfItems, bodyItems); if (!shapeRep.HasValue) return prodDefRep; IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); prodDefRep = file.CreateProductDefinitionShape(IFCLabel.Create(), IFCLabel.Create(), shapeReps); return prodDefRep; }
/// <summary> /// Exports a family instance as a mapped item. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="familyInstance"> /// The family instance to be exported. /// </param> /// <param name="exportType"> /// The export type. /// </param> /// <param name="ifcEnumType"> /// The string value represents the IFC type. /// </param> /// <param name="wrapper"> /// The IFCProductWrapper. /// </param> /// <param name="overrideLevelId"> /// The level id. /// </param> /// <param name="range"> /// The range of this family instance to be exported. /// </param> public static void ExportFamilyInstanceAsMappedItem(ExporterIFC exporterIFC, FamilyInstance familyInstance, IFCExportType exportType, string ifcEnumType, IFCProductWrapper wrapper, ElementId overrideLevelId, UV range) { Document doc = familyInstance.Document; IFCFile file = exporterIFC.GetFile(); FamilySymbol familySymbol = ExporterIFCUtils.GetOriginalSymbol(familyInstance); if (familySymbol == null) return; IFCProductWrapper familyProductWrapper = IFCProductWrapper.Create(wrapper); double scale = exporterIFC.LinearScale; IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); HostObject hostElement = familyInstance.Host as HostObject; //hostElement could be null ElementId categoryId = CategoryUtil.GetSafeCategoryId(familySymbol); //string emptyString = ""; string familyName = familySymbol.Name; IFCLabel objectType = IFCLabel.Create(familyName); // A Family Instance can have its own copy of geometry, or use the symbol's copy with a transform. // The routine below tells us whether to use the Instance's copy or the Symbol's copy. bool useInstanceGeometry = ExporterIFCUtils.UsesInstanceGeometry(familyInstance); IList<IFCExtrusionData> cutPairOpeningsForColumns = new List<IFCExtrusionData>(); IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData(); Transform trf = familyInstance.GetTransform(); // Extra information if we are exporting a door or a window. IFCDoorWindowInfo doorWindowInfo = null; if (exportType == IFCExportType.ExportDoorType) doorWindowInfo = IFCDoorWindowInfo.CreateDoorInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf); else if (exportType == IFCExportType.ExportWindowType) doorWindowInfo = IFCDoorWindowInfo.CreateWindowInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf); IFCTypeInfo typeInfo = new IFCTypeInfo(); XYZ extraOffset = XYZ.Zero; bool flipped = doorWindowInfo != null ? doorWindowInfo.IsSymbolFlipped : false; IFCTypeInfo currentTypeInfo = exporterIFC.FindType(familySymbol.Id, flipped); bool found = currentTypeInfo.IsValid(); Family family = familySymbol.Family; // TODO: this code to be removed by ExtrusionAnalyzer code. bool trySpecialColumnCreation = ((exportType == IFCExportType.ExportColumnType) && (!family.IsInPlace)); // We will create a new mapped type if: // 1. We are exporting part of a column or in-place wall (range != null), OR // 2. We are using the instance's copy of the geometry (that it, it has unique geometry), OR // 3. We haven't already created the type. bool creatingType = ((range != null) || useInstanceGeometry || !found); if (creatingType) { IFCAnyHandle bodyRepresentation = IFCAnyHandle.Create(); IFCAnyHandle planRepresentation = IFCAnyHandle.Create(); // If we are using the instance geometry, ignore the transformation. if (useInstanceGeometry) trf = Transform.Identity; // TODO: this code to be removed by ExtrusionAnalyzer code. if (trySpecialColumnCreation) { XYZ rangeOffset = trf.Origin; IFCFamilyInstanceExtrusionExportResults results; if (range != null) { results = ExporterIFCUtils.ExportFamilyInstanceAsExtrusion(exporterIFC, familyInstance, useInstanceGeometry, range, overrideLevelId, extraParams); } else { results = ExporterIFCUtils.ExportFamilyInstanceAsExtrusion(exporterIFC, familyInstance, useInstanceGeometry, overrideLevelId, extraParams); } bodyRepresentation = results.GetExtrusionHandle(); extraOffset = results.ExtraOffset; cutPairOpeningsForColumns = results.GetCutPairOpenings(); if (bodyRepresentation.HasValue) { typeInfo.MaterialId = results.MaterialId; // add in level for real columns, not in-place ones. Element actualLevel = (overrideLevelId == ElementId.InvalidElementId) ? familyInstance.Level : doc.get_Element(overrideLevelId); if (actualLevel != null) { IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(actualLevel.Id); double nonStoryLevelOffset = LevelUtil.GetNonStoryLevelOffsetIfAny(exporterIFC, actualLevel as Level); if (range != null) { rangeOffset = new XYZ(rangeOffset.X, rangeOffset.Y, levelInfo.Elevation + nonStoryLevelOffset); } } } rangeOffset += extraOffset; trf.Origin = rangeOffset; } Transform doorWindowTrf = Transform.Identity; IFCAnyHandle dummyPlacement = IFCAnyHandle.Create(); if (doorWindowInfo != null) { doorWindowTrf = ExporterIFCUtils.GetTransformForDoorOrWindow(familyInstance, familySymbol, doorWindowInfo); } else { dummyPlacement = file.CreateLocalPlacement(IFCAnyHandle.Create(), file.CreateAxis2Placement3D()); extraParams.SetLocalPlacement(dummyPlacement); } bool needToCreate2d = (!exporterIFC.ExportAs2x2); bool needToCreate3d = (!bodyRepresentation.HasValue); if (needToCreate2d || needToCreate3d) { using (IFCTransformSetter trfSetter = IFCTransformSetter.Create()) { if (doorWindowInfo != null) { trfSetter.Initialize(exporterIFC, doorWindowTrf); } Options options = new Options(); GeometryElement exportGeometry = useInstanceGeometry ? familyInstance.get_Geometry(options) : familySymbol.get_Geometry(options); if (exportGeometry == null) return; if (needToCreate3d) { IFCSolidMeshGeometryInfo solidMeshInfo; if (range == null) solidMeshInfo = ExporterIFCUtils.GetSolidMeshGeometry(exporterIFC, exportGeometry, Transform.Identity); else solidMeshInfo = ExporterIFCUtils.GetClippedSolidMeshGeometry(exporterIFC, range, exportGeometry); IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> polyMeshes = solidMeshInfo.GetMeshes(); bool tryToExportAsExtrusion = (!exporterIFC.ExportAs2x2 || (exportType == IFCExportType.ExportColumnType)); if (exportType == IFCExportType.ExportColumnType) { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; } else { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryXYZ; } if (solids.Count > 0 || polyMeshes.Count > 0) { bodyRepresentation = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, categoryId, solids, polyMeshes, tryToExportAsExtrusion, extraParams); typeInfo.MaterialId = BodyExporter.GetBestMaterialIdForGeometry(solids, polyMeshes); } else { IList<GeometryObject> exportedGeometries = new List<GeometryObject>(); exportedGeometries.Add(exportGeometry); bodyRepresentation = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, categoryId, exportedGeometries, tryToExportAsExtrusion, extraParams); } if (!bodyRepresentation.HasValue) { extraParams.ClearOpenings(); return; } } // if exporting IFC2x3 (or later), export 2D plan rep of family (if it exists). if (needToCreate2d) { HashSet<IFCAnyHandle> curveSet = new HashSet<IFCAnyHandle>(); { Transform planeTrf = doorWindowTrf.Inverse; Plane plane = new Plane(planeTrf.get_Basis(0), planeTrf.get_Basis(1), planeTrf.Origin); XYZ projDir = new XYZ(0, 0, 1); IFCGeometryInfo IFCGeometryInfo = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, true); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, IFCGeometryInfo, exportGeometry, planeTrf.Origin, false); IList<IFCAnyHandle> curves = IFCGeometryInfo.GetCurves(); foreach (IFCAnyHandle curve in curves) curveSet.Add(curve); if (curveSet.Count > 0) { IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle(); IFCAnyHandle curveRepresentationItem = file.CreateGeometricSet(curveSet); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(curveRepresentationItem); planRepresentation = RepresentationUtil.CreateGeometricSetRep(exporterIFC, categoryId, "Annotation", contextOfItems2d, bodyItems); } } } } } if (doorWindowInfo != null) { typeInfo.SetStyleTransform(doorWindowTrf.Inverse); } else { if (!MathUtil.IsAlmostZero(extraOffset.DotProduct(extraOffset))) { Transform newTransform = typeInfo.GetStyleTransform(); XYZ newOrig = newTransform.Origin + extraOffset; newTransform.Origin = newOrig; typeInfo.SetStyleTransform(newTransform); } typeInfo.SetStyleTransform(ExporterIFCUtils.GetUnscaledTransform(exporterIFC, extraParams.GetLocalPlacement())); } IFCLabel descriptionOpt = IFCLabel.Create(); IFCLabel applicableOccurrenceOpt = IFCLabel.Create(); IFCAnyHandle origin = file.CreateAxis2Placement3D(); IFCAnyHandle repMap2dHnd = IFCAnyHandle.Create(); IFCAnyHandle repMap3dHnd = file.CreateRepresentationMap(origin, bodyRepresentation); IList<IFCAnyHandle> repMapList = new List<IFCAnyHandle>(); repMapList.Add(repMap3dHnd); if (planRepresentation.HasValue) { repMap2dHnd = file.CreateRepresentationMap(origin, planRepresentation); repMapList.Add(repMap2dHnd); } // for Door, Window bool paramTakesPrecedence = false; // For Revit, this is currently always false. bool sizeable = false; // for many HashSet<IFCAnyHandle> propertySets = new HashSet<IFCAnyHandle>(); IFCLabel guid = IFCLabel.CreateGUID(familySymbol); IFCLabel symIdAsLabel = NamingUtil.CreateIFCElementId(familySymbol); // This covers many generic types. If we can't find it in the list here, do custom exports. IFCAnyHandle typeStyle = FamilyExporterUtil.ExportGenericType(file, exportType, ifcEnumType, guid, ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, symIdAsLabel, objectType, familyInstance, familySymbol); // Cover special cases not covered above. if (!typeStyle.HasValue) { switch (exportType) { case IFCExportType.ExportColumnType: { // If we are using the instance GRep, then we have to create a generic GUID for the // column type, as they share the same ElementId. IFCLabel colGUID = IFCLabel.Create(); IFCLabel colElemId = IFCLabel.Create(); if (useInstanceGeometry) { colGUID = IFCLabel.CreateGUID(); colElemId = NamingUtil.CreateIFCElementId(familyInstance); } else { colGUID = guid; colElemId = NamingUtil.CreateIFCElementId(familySymbol); } string columnType = "Column"; typeStyle = file.CreateColumnType(columnType, colGUID, ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, colElemId, objectType, familyInstance, familySymbol); break; } case IFCExportType.ExportDoorType: { string constructionType = string.Empty; ParameterUtil.GetStringValueFromElementOrSymbol(familyInstance, "Construction", out constructionType); IFCAnyHandle doorLining = DoorWindowUtil.CreateDoorLiningProperties(exporterIFC, familyInstance); if (doorLining.HasValue) propertySets.Add(doorLining); IList<IFCAnyHandle> doorPanels = DoorWindowUtil.CreateDoorPanelProperties(exporterIFC, doorWindowInfo, familyInstance); propertySets.UnionWith(doorPanels); IFCLabel doorStyleGUID = IFCLabel.CreateGUID(); IFCLabel doorStyleElemId = NamingUtil.CreateIFCElementId(familyInstance); typeStyle = file.CreateDoorStyle(doorStyleGUID, ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, doorStyleElemId, doorWindowInfo.DoorOperationType, constructionType, paramTakesPrecedence, sizeable); break; } case IFCExportType.ExportSystemFurnitureElementType: { IFCLabel furnitureId = NamingUtil.CreateIFCElementId(familyInstance); typeStyle = file.CreateSystemFurnitureElementType(guid, ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, furnitureId, objectType); break; } case IFCExportType.ExportWindowType: { IFCWindowStyleOperation operationType = DoorWindowUtil.GetIFCWindowStyleOperation(familySymbol); string constructionType = DoorWindowUtil.GetIFCWindowStyleConstruction(familyInstance, ""); IFCAnyHandle windowLining = DoorWindowUtil.CreateWindowLiningProperties(exporterIFC, familyInstance, descriptionOpt); if (windowLining.HasValue) propertySets.Add(windowLining); IList<IFCAnyHandle> windowPanels = DoorWindowUtil.CreateWindowPanelProperties(exporterIFC, familyInstance, descriptionOpt); propertySets.UnionWith(windowPanels); IFCLabel windowStyleGUID = IFCLabel.CreateGUID(); IFCLabel windowStyleElemId = NamingUtil.CreateIFCElementId(familyInstance); typeStyle = file.CreateWindowStyle(windowStyleGUID, ownerHistory, objectType, descriptionOpt, applicableOccurrenceOpt, propertySets, repMapList, windowStyleElemId, operationType, constructionType, paramTakesPrecedence, sizeable); break; } case IFCExportType.ExportBuildingElementProxy: default: { typeInfo.Set2DMapHandle(repMap2dHnd); typeInfo.Set3DMapHandle(repMap3dHnd); break; } } } typeInfo.SetStyle(typeStyle); // Transfer extraParams information for certain types. if (typeStyle.HasValue) { if (((exportType == IFCExportType.ExportColumnType) && trySpecialColumnCreation) || (exportType == IFCExportType.ExportMemberType)) { typeInfo.ScaledArea = extraParams.ScaledArea; typeInfo.ScaledDepth = extraParams.ScaledLength; typeInfo.ScaledInnerPerimeter = extraParams.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extraParams.ScaledOuterPerimeter; } } } else if (!creatingType && (trySpecialColumnCreation)) { // still need to modify instance trf for columns. trf.Origin += GetLevelOffsetForExtrudedColumns(exporterIFC, familyInstance, overrideLevelId, extraParams); } if (found && !typeInfo.GetStyle().HasValue) { typeInfo = currentTypeInfo; } // we'll pretend we succeeded, but we'll do nothing. if (!typeInfo.GetStyle().HasValue && !typeInfo.Get2DMapHandle().HasValue && !typeInfo.Get3DMapHandle().HasValue) return; // add to the map, as long as we are not using range, not using instance geometry, and don't have extra openings. if ((range == null) && !useInstanceGeometry && (extraParams.GetOpenings().Count == 0)) exporterIFC.AddType(familySymbol.Id, flipped, typeInfo); Transform oldTrf = new Transform(trf); XYZ scaledMapOrigin = XYZ.Zero; trf = trf.Multiply(typeInfo.GetStyleTransform()); // create instance. IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); { IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle(); IFCAnyHandle contextOfItems3d = exporterIFC.Get3DContextHandle(); // for proxies, we store the IfcRepresentationMap directly since there is no style. IList<IFCAnyHandle> repMapList = IFCGeometryUtils.GetRepresentationMaps(typeInfo.GetStyle()); int numReps = repMapList.Count; IFCAnyHandle repMap2dHnd = typeInfo.Get2DMapHandle(); IFCAnyHandle repMap3dHnd = typeInfo.Get3DMapHandle(); if (!repMap3dHnd.HasValue && (numReps > 0)) repMap3dHnd = repMapList[0]; if (!repMap2dHnd.HasValue && (numReps > 1)) repMap2dHnd = repMapList[1]; if (repMap3dHnd.HasValue) { HashSet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>(); representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap3dHnd, scaledMapOrigin)); IFCAnyHandle shapeRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, categoryId, contextOfItems3d, representations); if (!shapeRep.HasValue) return; shapeReps.Add(shapeRep); } if (repMap2dHnd.HasValue) { HashSet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>(); representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap2dHnd, scaledMapOrigin)); IFCAnyHandle shapeRep = RepresentationUtil.CreatePlanMappedItemRep(exporterIFC, categoryId, contextOfItems2d, representations); if (!shapeRep.HasValue) return; shapeReps.Add(shapeRep); } } IFCLabel noDescriptionOpt = IFCLabel.Create(); IFCLabel noNameOpt = IFCLabel.Create(); IFCAnyHandle rep = file.CreateProductDefinitionShape(noNameOpt, noDescriptionOpt, shapeReps); IFCAnyHandle instanceHandle = IFCAnyHandle.Create(); using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, familyInstance, trf, null, overrideLevelId)) { IFCLabel instanceGUID = IFCLabel.CreateGUID(familyInstance); IFCLabel origInstanceName = NamingUtil.CreateIFCName(exporterIFC, -1); IFCLabel instanceName = NamingUtil.GetNameOverride(familyInstance, origInstanceName); IFCLabel instanceDescription = NamingUtil.GetDescriptionOverride(familyInstance, noDescriptionOpt); IFCLabel instanceObjectType = NamingUtil.GetObjectTypeOverride(familyInstance, objectType); IFCLabel instanceElemId = NamingUtil.CreateIFCElementId(familyInstance); IFCAnyHandle localPlacement = setter.GetPlacement(); instanceHandle = FamilyExporterUtil.ExportGenericInstance(exportType, exporterIFC, familyInstance, wrapper, setter, extraParams, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, rep, instanceElemId); switch (exportType) { case IFCExportType.ExportColumnType: { IFCAnyHandle placementToUse = localPlacement; if (!useInstanceGeometry) { Transform openingTrf = new Transform(oldTrf); Transform extraRot = new Transform(oldTrf); extraRot.Origin = XYZ.Zero; openingTrf = openingTrf.Multiply(extraRot); openingTrf = openingTrf.Multiply(typeInfo.GetStyleTransform()); IFCAnyHandle openingRelativePlacement = file.CreateAxis2Placement3D(openingTrf.Origin * scale, openingTrf.get_Basis(2), openingTrf.get_Basis(0)); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement); IFCGeometryUtils.SetRelativePlacement(openingPlacement, openingRelativePlacement); placementToUse = openingPlacement; } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, cutPairOpeningsForColumns, exporterIFC, placementToUse, setter, wrapper); OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, placementToUse, setter, wrapper); //export Base Quantities. ExporterIFCUtils.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo); CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, instanceHandle, typeInfo.MaterialId); ExporterIFCUtils.CreateColumnPropertySet(exporterIFC, familyInstance, extraParams, wrapper); break; } case IFCExportType.ExportDoorType: case IFCExportType.ExportWindowType: { double doorHeight = doorWindowInfo.OpeningHeight; if (doorHeight < MathUtil.Eps()) doorHeight = GetMinSymbolHeight(familySymbol); double doorWidth = doorWindowInfo.OpeningWidth; if (doorWidth < MathUtil.Eps()) doorWidth = GetMinSymbolWidth(familySymbol); IFCMeasureValue height = IFCMeasureValue.Create(doorHeight * scale); IFCMeasureValue width = IFCMeasureValue.Create(doorWidth * scale); if (!doorWindowInfo.GetLocalPlacement().HasValue) doorWindowInfo.SetLocalPlacement(localPlacement); IFCAnyHandle doorWindowOrigLocalPlacement = doorWindowInfo.GetLocalPlacement(); Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(localPlacement, doorWindowOrigLocalPlacement); IFCAnyHandle doorWindowRelativePlacement = file.CreateAxis2Placement3D(relTrf); IFCAnyHandle doorWindowLocalPlacement = file.CreateLocalPlacement(doorWindowOrigLocalPlacement, doorWindowRelativePlacement); if (exportType == IFCExportType.ExportDoorType) instanceHandle = file.CreateDoor(instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, rep, instanceElemId, height, width); else if (exportType == IFCExportType.ExportWindowType) instanceHandle = file.CreateWindow(instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, rep, instanceElemId, height, width); wrapper.AddElement(instanceHandle, setter, extraParams, true); exporterIFC.RegisterSpaceBoundingElementHandle(instanceHandle, familyInstance.Id, setter.LevelId); // only necessary when exporting as possible breps. OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, doorWindowLocalPlacement, setter, wrapper); if (exporterIFC.ExportBaseQuantities) ExporterIFCUtils.CreateDoorWindowBaseQuantities(exporterIFC, instanceHandle, (doorHeight * scale), (doorWidth * scale)); if (exportType == IFCExportType.ExportDoorType) ExporterIFCUtils.CreateDoorPropertySet(exporterIFC, familyInstance, wrapper); else ExporterIFCUtils.CreateWindowPropertySet(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportMemberType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, instanceHandle, typeInfo.MaterialId); //export Base Quantities. ExporterIFCUtils.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo); // TODO: create PropertySet! //createMemberPropertySet(exporter, pFamInst, pWrapper, extraParams); ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportPlateType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, instanceHandle, typeInfo.MaterialId); // TODO: create PropertySet! //createPlatePropertySet(exporter, pFamInst, pWrapper, extraParams); ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportTransportElementType: { string operationTypeOpt = ""; IFCMeasureValue capByWeightOpt = IFCMeasureValue.Create(); IFCMeasureValue capByNumOpt = IFCMeasureValue.Create(); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); instanceHandle = file.CreateTransportElement(instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, rep, instanceElemId, operationTypeOpt, capByWeightOpt, capByNumOpt, familyInstance, familySymbol); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportBuildingElementProxy: default: { bool isBuildingElementProxy = (exportType == IFCExportType.ExportBuildingElementProxy); if (!isBuildingElementProxy) { if (FamilyExporterUtil.IsDistributionControlElementSubType(exportType)) { IFCLabel controlElementId = IFCLabel.Create(); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); instanceHandle = file.CreateDistributionControlElement(instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacement, rep, instanceElemId, controlElementId); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); } else if (!instanceHandle.HasValue) { isBuildingElementProxy = true; } } if (isBuildingElementProxy) { IFCElementComposition proxyType = IFCElementComposition.Element; IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); instanceHandle = file.CreateBuildingElementProxy(instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, rep, instanceElemId, proxyType); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); } ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, familyInstance, wrapper); break; } } if (instanceHandle.HasValue) { if (doorWindowInfo != null) { if (doorWindowInfo.GetOpening().HasValue) { IFCLabel relGUID = IFCLabel.CreateGUID(); file.CreateRelFillsElement(relGUID, ownerHistory, IFCLabel.Create(), IFCLabel.Create(), doorWindowInfo.GetOpening(), instanceHandle); } else if (doorWindowInfo.NeedsOpening) { bool added = doorWindowInfo.SetDelayedFamilyInstance(instanceHandle, localPlacement, doorWindowInfo.AssignedLevelId); if (added) exporterIFC.RegisterDoorWindowForOpeningUpdate(doorWindowInfo); else { // we need to fill a later opening. exporterIFC.RegisterDoorWindowForUncreatedOpening(familyInstance.Id, instanceHandle); } } } if (typeInfo.GetStyle().HasValue) exporterIFC.AddTypeRelation(typeInfo.GetStyle(), instanceHandle); } } }
/// <summary> /// Creates openings if there is necessary. /// </summary> /// <param name="elementHandle"> /// The element handle to create openings. /// </param> /// <param name="element"> /// The element to create openings. /// </param> /// <param name="info"> /// The extrusion datas. /// </param> /// <param name="extraParams"> /// The extrusion creation data. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="originalPlacement"> /// The original placement handle. /// </param> /// <param name="setter"> /// The IFCPlacementSetter. /// </param> /// <param name="wrapper"> /// The IFCProductWrapper. /// </param> private static void CreateOpeningsIfNecessaryBase(IFCAnyHandle elementHandle, Element element, IList <IFCExtrusionData> info, IFCExtrusionCreationData extraParams, ExporterIFC exporterIFC, IFCAnyHandle originalPlacement, IFCPlacementSetter setter, IFCProductWrapper wrapper) { if (IFCAnyHandleUtil.IsNullOrHasNoValue(elementHandle)) { return; } int sz = info.Count; if (sz == 0) { return; } IFCFile file = exporterIFC.GetFile(); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); Document document = element.Document; string openingObjectType = "Opening"; int openingNumber = 1; for (int curr = info.Count - 1; curr >= 0; curr--) { IFCAnyHandle extrusionHandle = ExtrusionExporter.CreateExtrudedSolidFromExtrusionData(exporterIFC, element, info[curr]); if (IFCAnyHandleUtil.IsNullOrHasNoValue(extrusionHandle)) { continue; } IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, extrusionHandle, ElementId.InvalidElementId); HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); bodyItems.Add(extrusionHandle); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); IFCAnyHandle bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, categoryId, contextOfItems, bodyItems, null); IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); representations.Add(bodyRep); IFCAnyHandle openingRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, originalPlacement); string guid = ExporterIFCUtils.CreateGUID(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string openingName = NamingUtil.GetNameOverride(element, NamingUtil.CreateIFCName(exporterIFC, openingNumber++)); string elementId = NamingUtil.CreateIFCElementId(element); IFCAnyHandle openingElement = IFCInstanceExporter.CreateOpeningElement(file, guid, ownerHistory, openingName, null, openingObjectType, openingPlacement, openingRep, elementId); wrapper.AddElement(openingElement, setter, extraParams, true); if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities && (extraParams != null)) { ExporterIFCUtils.CreateOpeningQuantities(exporterIFC, openingElement, extraParams); } string voidGuid = ExporterIFCUtils.CreateGUID(); IFCInstanceExporter.CreateRelVoidsElement(file, voidGuid, ownerHistory, null, null, elementHandle, openingElement); } }
/// <summary> /// Gets material handle from material id or creates one if there is none. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="materialId">The material id.</param> /// <returns>The handle.</returns> public static IFCAnyHandle GetOrCreateMaterialHandle(ExporterIFC exporterIFC, ElementId materialId) { Document document = ExporterCacheManager.Document; IFCAnyHandle materialNameHandle = ExporterCacheManager.MaterialHandleCache.Find(materialId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialNameHandle)) { string materialName = "<Unnamed>"; string description = null; string category = null; if (materialId != ElementId.InvalidElementId) { Material material = document.GetElement(materialId) as Material; if (material != null) { materialName = NamingUtil.GetMaterialName(material); if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { category = NamingUtil.GetMaterialCategoryName(material); description = NamingUtil.GetOverrideStringValue(material, "IfcDescription", null); } } } IFCFile file = exporterIFC.GetFile(); materialNameHandle = IFCInstanceExporter.CreateMaterial(file, materialName, description: description, category: category); ExporterCacheManager.MaterialHandleCache.Register(materialId, materialNameHandle); // associate Material with SurfaceStyle if necessary. if (materialId != ElementId.InvalidElementId && !ExporterCacheManager.ExportOptionsCache.ExportAs2x2 && materialNameHandle.HasValue) { HashSet <IFCAnyHandle> matRepHandles = IFCAnyHandleUtil.GetHasRepresentation(materialNameHandle); if (matRepHandles.Count == 0) { Material matElem = document.GetElement(materialId) as Material; // TODO_DOUBLE_PATTERN - deal with background pattern ElementId fillPatternId = (matElem != null) ? matElem.CutForegroundPatternId : ElementId.InvalidElementId; Color color = (matElem != null) ? GetSafeColor(matElem.CutForegroundPatternColor) : new Color(0, 0, 0); double planScale = 100.0; HashSet <IFCAnyHandle> styles = new HashSet <IFCAnyHandle>(); bool hasFill = false; IFCAnyHandle styledRepItem = null; IFCAnyHandle matStyleHnd = GetOrCreateMaterialStyle(document, file, materialId); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(matStyleHnd) && !ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { styles.Add(matStyleHnd); bool supportCutStyles = !ExporterCacheManager.ExportOptionsCache.ExportAsCoordinationView2; if (fillPatternId != ElementId.InvalidElementId && supportCutStyles) { IFCAnyHandle cutStyleHnd = exporterIFC.GetOrCreateFillPattern(fillPatternId, color, planScale); if (cutStyleHnd.HasValue) { styles.Add(cutStyleHnd); hasFill = true; } } IFCAnyHandle styledItemHnd; if (ExporterCacheManager.ExportOptionsCache.ExportAsOlderThanIFC4) { IFCAnyHandle presStyleHnd = IFCInstanceExporter.CreatePresentationStyleAssignment(file, styles); HashSet <IFCAnyHandle> presStyleSet = new HashSet <IFCAnyHandle>(); presStyleSet.Add(presStyleHnd); styledItemHnd = IFCInstanceExporter.CreateStyledItem(file, styledRepItem, presStyleSet, null); } else { styledItemHnd = IFCInstanceExporter.CreateStyledItem(file, styledRepItem, styles, null); } IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle(""); string repId = "Style"; string repType = (hasFill) ? "Material and Cut Pattern" : "Material"; HashSet <IFCAnyHandle> repItems = new HashSet <IFCAnyHandle>(); repItems.Add(styledItemHnd); IFCAnyHandle styleRepHnd = IFCInstanceExporter.CreateStyledRepresentation(file, contextOfItems, repId, repType, repItems); List <IFCAnyHandle> repList = new List <IFCAnyHandle>(); repList.Add(styleRepHnd); IFCAnyHandle matDefRepHnd = IFCInstanceExporter.CreateMaterialDefinitionRepresentation(file, null, null, repList, materialNameHandle); } } } } return(materialNameHandle); }
/// <summary> /// Exports a geometry element to boundary representation. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="exportBoundaryRep">True if to export boundary representation.</param> /// <param name="exportAsFacetation">True if to export the geometry as facetation.</param> /// <param name="bodyRep">Body representation.</param> /// <param name="boundaryRep">Boundary representation.</param> /// <returns>True if success, false if fail.</returns> public static bool ExportSurface(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, bool exportBoundaryRep, bool exportAsFacetation, ref IFCAnyHandle bodyRep, ref IFCAnyHandle boundaryRep) { if (geometryElement == null) { return(false); } IFCGeometryInfo ifcGeomInfo = null; Document doc = element.Document; Plane plane = GeometryUtil.CreateDefaultPlane(); XYZ projDir = new XYZ(0, 0, 1); double eps = doc.Application.VertexTolerance * exporterIFC.LinearScale; ifcGeomInfo = IFCGeometryInfo.CreateFaceGeometryInfo(exporterIFC, plane, projDir, eps, exportBoundaryRep); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, ifcGeomInfo, geometryElement, XYZ.Zero, true); IFCFile file = exporterIFC.GetFile(); HashSet <IFCAnyHandle> faceSets = new HashSet <IFCAnyHandle>(); IList <ICollection <IFCAnyHandle> > faceList = ifcGeomInfo.GetFaces(); foreach (ICollection <IFCAnyHandle> faces in faceList) { // no faces, don't complain. if (faces.Count == 0) { continue; } HashSet <IFCAnyHandle> faceSet = new HashSet <IFCAnyHandle>(faces); faceSets.Add(IFCInstanceExporter.CreateConnectedFaceSet(file, faceSet)); } if (faceSets.Count == 0) { return(false); } IFCAnyHandle surface = IFCInstanceExporter.CreateFaceBasedSurfaceModel(file, faceSets); BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, doc, surface, BodyExporter.GetBestMaterialIdFromGeometryOrParameter(geometryElement, exporterIFC, element)); IList <IFCAnyHandle> surfaceItems = new List <IFCAnyHandle>(); surfaceItems.Add(surface); ElementId catId = CategoryUtil.GetSafeCategoryId(element); bodyRep = RepresentationUtil.CreateSurfaceRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("Body"), surfaceItems, exportAsFacetation, bodyRep); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { return(false); } ICollection <IFCAnyHandle> boundaryRepresentations = ifcGeomInfo.GetRepresentations(); if (exportBoundaryRep && boundaryRepresentations.Count > 0) { boundaryRep = RepresentationUtil.CreateBoundaryRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("FootPrint"), boundaryRepresentations, boundaryRep); } return(true); }
/// <summary> /// Creates openings if there is necessary. /// </summary> /// <param name="elementHandle">The element handle to create openings.</param> /// <param name="element">The element to create openings.</param> /// <param name="info">The extrusion data.</param> /// <param name="extraParams">The extrusion creation data.</param> /// <param name="offsetTransform">The offset transform from ExportBody, or the identity transform.</param> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="originalPlacement">The original placement handle.</param> /// <param name="setter">The PlacementSetter.</param> /// <param name="wrapper">The ProductWrapper.</param> private static void CreateOpeningsIfNecessaryBase(IFCAnyHandle elementHandle, Element element, IList <IFCExtrusionData> info, IFCExtrusionCreationData extraParams, Transform offsetTransform, ExporterIFC exporterIFC, IFCAnyHandle originalPlacement, PlacementSetter setter, ProductWrapper wrapper) { if (IFCAnyHandleUtil.IsNullOrHasNoValue(elementHandle)) { return; } int sz = info.Count; if (sz == 0) { return; } using (TransformSetter transformSetter = TransformSetter.Create()) { if (offsetTransform != null) { transformSetter.Initialize(exporterIFC, offsetTransform.Inverse); } IFCFile file = exporterIFC.GetFile(); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); Document document = element.Document; string openingObjectType = "Opening"; int openingNumber = 1; for (int curr = info.Count - 1; curr >= 0; curr--) { Transform extrusionTrf = Transform.Identity; IFCAnyHandle extrusionHandle = ExtrusionExporter.CreateExtrudedSolidFromExtrusionData(exporterIFC, element, info[curr], out extrusionTrf); if (IFCAnyHandleUtil.IsNullOrHasNoValue(extrusionHandle)) { continue; } BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, extrusionHandle, ElementId.InvalidElementId); HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); bodyItems.Add(extrusionHandle); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); IFCAnyHandle bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, categoryId, contextOfItems, bodyItems, null); IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); representations.Add(bodyRep); IFCAnyHandle openingRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, originalPlacement); string guid = GUIDUtil.CreateGUID(); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; string openingName = NamingUtil.GetIFCNamePlusIndex(element, openingNumber++); string openingDescription = NamingUtil.GetDescriptionOverride(element, null); string openingTag = NamingUtil.GetTagOverride(element); IFCAnyHandle openingElement = IFCInstanceExporter.CreateOpeningElement(exporterIFC, guid, ownerHistory, openingName, openingDescription, openingObjectType, openingPlacement, openingRep, openingTag); IFCExportInfoPair exportInfo = new IFCExportInfoPair(IFCEntityType.IfcOpeningElement); wrapper.AddElement(null, openingElement, setter, extraParams, true, exportInfo); if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities && (extraParams != null)) { PropertyUtil.CreateOpeningQuantities(exporterIFC, openingElement, extraParams); } string voidGuid = GUIDUtil.CreateGUID(); IFCInstanceExporter.CreateRelVoidsElement(file, voidGuid, ownerHistory, null, null, elementHandle, openingElement); } } }
/// <summary> /// Exports a gutter element. /// </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> public static void ExportGutter(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { 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); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(); IFCAnyHandle bodyRep = BodyExporter.ExportBody(exporterIFC, element, categoryId, ElementId.InvalidElementId, geometryElement, bodyExporterOptions, ecData).RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { if (ecData != null) { ecData.ClearOpenings(); } return; } IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string originalTag = NamingUtil.CreateIFCElementId(element); // In Revit, we don't have a corresponding type, so we create one for every gutter. IFCAnyHandle origin = ExporterUtil.CreateAxis2Placement3D(file); IFCAnyHandle repMap3dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyRep); List <IFCAnyHandle> repMapList = new List <IFCAnyHandle>(); repMapList.Add(repMap3dHnd); string elementTypeName = NamingUtil.CreateIFCObjectName(exporterIFC, element); string typeGuid = GUIDUtil.CreateSubElementGUID(element, (int)IFCHostedSweepSubElements.PipeSegmentType); IFCAnyHandle style = IFCInstanceExporter.CreatePipeSegmentType(file, typeGuid, ownerHistory, elementTypeName, null, null, null, repMapList, originalTag, elementTypeName, IFCPipeSegmentType.Gutter); List <IFCAnyHandle> representationMaps = GeometryUtil.GetRepresentationMaps(style); IFCAnyHandle mappedItem = ExporterUtil.CreateDefaultMappedItem(file, representationMaps[0]); ISet <IFCAnyHandle> representations = new HashSet <IFCAnyHandle>(); representations.Add(mappedItem); IFCAnyHandle bodyMappedItemRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, element, categoryId, exporterIFC.Get3DContextHandle("Body"), representations); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyMappedItemRep)) { return; } List <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(bodyMappedItemRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) { shapeReps.Add(boundingBoxRep); } IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); if (roomId == ElementId.InvalidElementId) { localPlacementToUse = ecData.GetLocalPlacement(); } string guid = GUIDUtil.CreateGUID(element); string name = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, elementTypeName); string tag = NamingUtil.GetTagOverride(element, originalTag); IFCAnyHandle elemHnd = IFCInstanceExporter.CreateFlowSegment(file, guid, ownerHistory, name, description, objectType, localPlacementToUse, prodRep, tag); bool containedInSpace = (roomId != ElementId.InvalidElementId); productWrapper.AddElement(element, elemHnd, setter.LevelInfo, ecData, !containedInSpace); if (containedInSpace) { ExporterCacheManager.SpaceInfoCache.RelateToSpace(roomId, elemHnd); } // Associate segment with type. ExporterCacheManager.TypeRelationsCache.Add(style, elemHnd); OpeningUtil.CreateOpeningsIfNecessary(elemHnd, element, ecData, null, exporterIFC, localPlacementToUse, setter, productWrapper); } tr.Commit(); } } }
/// <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 = exporterIFC.GetOwnerHistoryHandle(); 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 = CreateSweptDiskSolid(exporterIFC, file, wireCenterline, longitudinalBarNominalDiameter); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyItem)) { bodyItems.Add(bodyItem); } } wireCenterlines = sheet.GetWireCenterlines(WireDistributionDirection.Minor); foreach (Curve wireCenterline in wireCenterlines) { IFCAnyHandle bodyItem = CreateSweptDiskSolid(exporterIFC, file, wireCenterline, transverseBarNominalDiameter); 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 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="ifcEnumType">The roof type.</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, string ifcEnumType, 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); } Common.Enums.IFCEntityType elementClassTypeEnum = Common.Enums.IFCEntityType.IfcRoof; if (elementIsFloor) { elementClassTypeEnum = Common.Enums.IFCEntityType.IfcSlab; } // Check the intended IFC entity or type name is in the exclude list specified in the UI if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum)) { return(null); } using (IFCTransaction transaction = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { IFCAnyHandle localPlacement = setter.LocalPlacement; 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); } 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); string elementName = NamingUtil.GetIFCName(element); string elementDescription = NamingUtil.GetDescriptionOverride(element, null); string elementObjectType = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName()); string elementId = NamingUtil.CreateIFCElementId(element); string hostObjectType = IFCValidateEntry.GetValidIFCType(element, ifcEnumType); IFCAnyHandle hostObjectHandle = null; if (elementIsRoof) { hostObjectHandle = IFCInstanceExporter.CreateRoof(file, elementGUID, ownerHistory, elementName, elementDescription, elementObjectType, localPlacement, prodRepHnd, elementId, hostObjectType); } else { hostObjectHandle = IFCInstanceExporter.CreateSlab(file, elementGUID, ownerHistory, elementName, elementDescription, elementObjectType, localPlacement, prodRepHnd, elementId, hostObjectType); } 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 = elementIsRoof ? "ROOF" : hostObjectType; 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; IFCAnyHandle shapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, lcs, extrusionDir, scaledExtrusionDepth, false); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) { return(null); } ElementId matId = HostObjectExporter.GetFirstLayerMaterialId(element as HostObject); BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, element.Document, shapeRep, matId); HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); bodyItems.Add(shapeRep); shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle repHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, 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(file, slabGUID, ownerHistory, elementName, elementDescription, elementObjectType, slabPlacement, repHnd, elementId, 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))); productWrapper.AddElement(null, slabHnd, setter, slabExtrusionCreationData, false); elementHandles.Add(slabHnd); slabHandles.Add(slabHnd); hostObjectOpeningLoops.Add(slabCurveLoop); maximumScaledDepth = Math.Max(maximumScaledDepth, scaledDepth); loopNum++; } } productWrapper.AddElement(element, hostObjectHandle, setter, extrusionCreationData, true); ExporterUtil.RelateObjects(exporterIFC, null, hostObjectHandle, slabHandles); OpeningUtil.AddOpeningsToElement(exporterIFC, elementHandles, hostObjectOpeningLoops, element, null, maximumScaledDepth, null, setter, localPlacement, productWrapper); transaction.Commit(); return(hostObjectHandle); } } } finally { exporterIFC.ClearFaceWithElementHandleMap(); } } } }
/// <summary> /// Exports curtain object as one Brep. /// </summary> /// <param name="allSubElements"> /// Collection of elements contained in the host curtain element. /// </param> /// <param name="wallElement"> /// The curtain wall element. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="setter"> /// The IFCPlacementSetter object. /// </param> /// <param name="localPlacement"> /// The local placement handle. /// </param> /// <returns> /// The handle. /// </returns> public static IFCAnyHandle ExportCurtainObjectCommonAsOneBRep(ICollection<ElementId> allSubElements, Element wallElement, ExporterIFC exporterIFC, IFCPlacementSetter setter, IFCAnyHandle localPlacement) { IFCAnyHandle prodDefRep = null; Document document = wallElement.Document; double eps = document.Application.VertexTolerance * exporterIFC.LinearScale; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); IFCGeometryInfo info = IFCGeometryInfo.CreateFaceGeometryInfo(eps); IList<IFCAnyHandle> bodyItems = new List<IFCAnyHandle>(); // Want to make sure we don't accidentally add a mullion or curtain line more than once. HashSet<ElementId> alreadyVisited = new HashSet<ElementId>(); Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); foreach (ElementId subElemId in allSubElements) { Element subElem = wallElement.Document.GetElement(subElemId); GeometryElement geomElem = subElem.get_Geometry(geomOptions); if (geomElem == null) continue; if (alreadyVisited.Contains(subElem.Id)) continue; alreadyVisited.Add(subElem.Id); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, geomElem, XYZ.Zero, false); HashSet<IFCAnyHandle> faces = new HashSet<IFCAnyHandle>(info.GetSurfaces()); IFCAnyHandle outer = IFCInstanceExporter.CreateClosedShell(file, faces); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(outer)) bodyItems.Add(RepresentationUtil.CreateFacetedBRep(exporterIFC, document, outer, ElementId.InvalidElementId)); } if (bodyItems.Count == 0) return prodDefRep; ElementId catId = CategoryUtil.GetSafeCategoryId(wallElement); IFCAnyHandle shapeRep = RepresentationUtil.CreateBRepRep(exporterIFC, wallElement, catId, contextOfItems, bodyItems); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return prodDefRep; IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, wallElement.get_Geometry(geomOptions), Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); prodDefRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); return prodDefRep; }
/// <summary> /// Exports a staircase to IfcStair, composing into separate runs and landings. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="ifcEnumType">The stairs type.</param> /// <param name="stair">The stairs element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="numFlights">The number of flights for a multistory staircase.</param> /// <param name="productWrapper">The IFCProductWrapper.</param> public static void ExportStairsAsContainer(ExporterIFC exporterIFC, string ifcEnumType, Stairs stair, GeometryElement geometryElement, int numFlights, IFCProductWrapper productWrapper) { if (stair == null || geometryElement == null) return; Document doc = stair.Document; Autodesk.Revit.ApplicationServices.Application app = doc.Application; IFCFile file = exporterIFC.GetFile(); Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); ElementId categoryId = CategoryUtil.GetSafeCategoryId(stair); using (IFCTransaction tr = new IFCTransaction(file)) { using (IFCPlacementSetter placementSetter = IFCPlacementSetter.Create(exporterIFC, stair)) { HashSet<ElementId> materialIds = new HashSet<ElementId>(); List<IFCAnyHandle> componentHandles = new List<IFCAnyHandle>(); IList<IFCExtrusionCreationData> componentExtrusionData = new List<IFCExtrusionCreationData>(); IFCAnyHandle contextOfItemsFootPrint = exporterIFC.Get3DContextHandle("FootPrint"); Transform trf = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, placementSetter.GetPlacement()); Plane boundaryPlane = new Plane(trf.BasisX, trf.BasisY, trf.Origin); XYZ boundaryProjDir = trf.BasisZ; IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string stairGUID = ExporterIFCUtils.CreateGUID(stair); string origStairName = exporterIFC.GetName(); string stairName = NamingUtil.GetNameOverride(stair, origStairName); string stairDescription = NamingUtil.GetDescriptionOverride(stair, null); string stairObjectType = NamingUtil.GetObjectTypeOverride(stair, NamingUtil.CreateIFCObjectName(exporterIFC, stair)); IFCAnyHandle stairLocalPlacement = placementSetter.GetPlacement(); string stairElementTag = NamingUtil.CreateIFCElementId(stair); IFCStairType stairType = GetIFCStairType(ifcEnumType); IFCAnyHandle stairContainerHnd = IFCInstanceExporter.CreateStair(file, stairGUID, ownerHistory, stairName, stairDescription, stairObjectType, stairLocalPlacement, null, stairElementTag, stairType); productWrapper.AddElement(stairContainerHnd, placementSetter.GetLevelInfo(), null, LevelUtil.AssociateElementToLevel(stair)); // Get List of runs to export their geometry. ICollection<ElementId> runIds = stair.GetStairsRuns(); int index = 0; foreach (ElementId runId in runIds) { index++; StairsRun run = doc.GetElement(runId) as StairsRun; using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.AllowVerticalOffsetOfBReps = false; ecData.SetLocalPlacement(placementSetter.GetPlacement()); ecData.ReuseLocalPlacement = false; GeometryElement runGeometryElement = run.get_Geometry(geomOptions); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); BodyData bodyData = BodyExporter.ExportBody(app, exporterIFC, run, categoryId, runGeometryElement, bodyExporterOptions, ecData); IFCAnyHandle bodyRep = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { ecData.ClearOpenings(); continue; } foreach (ElementId materialId in bodyData.MaterialIds) materialIds.Add(materialId); IList<IFCAnyHandle> reps = new List<IFCAnyHandle>(); reps.Add(bodyRep); Transform runBoundaryTrf = trf.Multiply(bodyData.BrepOffsetTransform); Plane runBoundaryPlane = new Plane(runBoundaryTrf.BasisX, runBoundaryTrf.BasisY, runBoundaryTrf.Origin); XYZ runBoundaryProjDir = runBoundaryTrf.BasisZ; CurveLoop boundary = run.GetFootprintBoundary(); IFCAnyHandle boundaryHnd = ExporterIFCUtils.CreateCurveFromCurveLoop(exporterIFC, boundary, runBoundaryPlane, runBoundaryProjDir); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(boundaryHnd)) { HashSet<IFCAnyHandle> geomSelectSet = new HashSet<IFCAnyHandle>(); geomSelectSet.Add(boundaryHnd); HashSet<IFCAnyHandle> boundaryItems = new HashSet<IFCAnyHandle>(); boundaryItems.Add(IFCInstanceExporter.CreateGeometricSet(file, geomSelectSet)); IFCAnyHandle boundaryRep = RepresentationUtil.CreateGeometricSetRep(exporterIFC, run, categoryId, "FootPrint", contextOfItemsFootPrint, boundaryItems); reps.Add(boundaryRep); } CurveLoop walkingLine = run.GetStairsPath(); IFCAnyHandle walkingLineHnd = ExporterIFCUtils.CreateCurveFromCurveLoop(exporterIFC, walkingLine, runBoundaryPlane, runBoundaryProjDir); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(walkingLineHnd)) { HashSet<IFCAnyHandle> geomSelectSet = new HashSet<IFCAnyHandle>(); geomSelectSet.Add(walkingLineHnd); HashSet<IFCAnyHandle> walkingLineItems = new HashSet<IFCAnyHandle>(); walkingLineItems.Add(IFCInstanceExporter.CreateGeometricSet(file, geomSelectSet)); IFCAnyHandle walkingLineRep = RepresentationUtil.CreateGeometricSetRep(exporterIFC, run, categoryId, "Axis", contextOfItemsFootPrint, walkingLineItems); reps.Add(walkingLineRep); } IFCAnyHandle representation = IFCInstanceExporter.CreateProductDefinitionShape(exporterIFC.GetFile(), null, null, reps); string runGUID = ExporterIFCUtils.CreateGUID(run); string origRunName = origStairName + " Run " + index; string runName = NamingUtil.GetNameOverride(run, origRunName); string runDescription = NamingUtil.GetDescriptionOverride(run, stairDescription); string runObjectType = NamingUtil.GetObjectTypeOverride(run, stairObjectType); IFCAnyHandle runLocalPlacement = ecData.GetLocalPlacement(); string runElementTag = NamingUtil.CreateIFCElementId(run); IFCAnyHandle stairFlightHnd = IFCInstanceExporter.CreateStairFlight(file, runGUID, ownerHistory, runName, runDescription, runObjectType, runLocalPlacement, representation, runElementTag, run.ActualRisersNumber, run.ActualTreadsNumber, stair.ActualRiserHeight, stair.ActualTreadDepth); componentHandles.Add(stairFlightHnd); componentExtrusionData.Add(ecData); productWrapper.AddElement(stairFlightHnd, placementSetter.GetLevelInfo(), ecData, false); ExporterCacheManager.HandleToElementCache.Register(stairFlightHnd, run.Id); } } // Get List of landings to export their geometry. ICollection<ElementId> landingIds = stair.GetStairsLandings(); index = 0; foreach (ElementId landingId in landingIds) { index++; StairsLanding landing = doc.GetElement(landingId) as StairsLanding; using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.AllowVerticalOffsetOfBReps = false; ecData.SetLocalPlacement(placementSetter.GetPlacement()); ecData.ReuseLocalPlacement = false; GeometryElement landingGeometryElement = landing.get_Geometry(geomOptions); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); BodyData bodyData = BodyExporter.ExportBody(app, exporterIFC, landing, categoryId, landingGeometryElement, bodyExporterOptions, ecData); IFCAnyHandle bodyRep = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { ecData.ClearOpenings(); continue; } foreach (ElementId materialId in bodyData.MaterialIds) materialIds.Add(materialId); // create Boundary rep. IList<IFCAnyHandle> reps = new List<IFCAnyHandle>(); reps.Add(bodyRep); Transform landingBoundaryTrf = trf.Multiply(bodyData.BrepOffsetTransform); Plane landingBoundaryPlane = new Plane(landingBoundaryTrf.BasisX, landingBoundaryTrf.BasisY, landingBoundaryTrf.Origin); XYZ landingBoundaryProjDir = landingBoundaryTrf.BasisZ; CurveLoop boundary = landing.GetFootprintBoundary(); IFCAnyHandle boundaryHnd = ExporterIFCUtils.CreateCurveFromCurveLoop(exporterIFC, boundary, landingBoundaryPlane, landingBoundaryProjDir); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(boundaryHnd)) { HashSet<IFCAnyHandle> geomSelectSet = new HashSet<IFCAnyHandle>(); geomSelectSet.Add(boundaryHnd); HashSet<IFCAnyHandle> boundaryItems = new HashSet<IFCAnyHandle>(); boundaryItems.Add(IFCInstanceExporter.CreateGeometricSet(file, geomSelectSet)); IFCAnyHandle boundaryRep = RepresentationUtil.CreateGeometricSetRep(exporterIFC, landing, categoryId, "FootPrint", contextOfItemsFootPrint, boundaryItems); reps.Add(boundaryRep); } CurveLoop walkingLine = landing.GetStairsPath(); IFCAnyHandle walkingLineHnd = ExporterIFCUtils.CreateCurveFromCurveLoop(exporterIFC, walkingLine, landingBoundaryPlane, landingBoundaryProjDir); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(walkingLineHnd)) { HashSet<IFCAnyHandle> geomSelectSet = new HashSet<IFCAnyHandle>(); geomSelectSet.Add(walkingLineHnd); HashSet<IFCAnyHandle> walkingLineItems = new HashSet<IFCAnyHandle>(); walkingLineItems.Add(IFCInstanceExporter.CreateGeometricSet(file, geomSelectSet)); IFCAnyHandle walkingLineRep = RepresentationUtil.CreateGeometricSetRep(exporterIFC, landing, categoryId, "Axis", contextOfItemsFootPrint, walkingLineItems); reps.Add(walkingLineRep); } string landingGUID = ExporterIFCUtils.CreateGUID(landing); string origLandingName = origStairName + " Landing " + index; string landingName = NamingUtil.GetNameOverride(landing, origLandingName); string landingDescription = NamingUtil.GetDescriptionOverride(landing, stairDescription); string landingObjectType = NamingUtil.GetObjectTypeOverride(landing, stairObjectType); IFCAnyHandle landingLocalPlacement = ecData.GetLocalPlacement(); string landingElementTag = NamingUtil.CreateIFCElementId(landing); IFCAnyHandle representation = IFCInstanceExporter.CreateProductDefinitionShape(exporterIFC.GetFile(), null, null, reps); IFCAnyHandle landingHnd = IFCInstanceExporter.CreateSlab(file, landingGUID, ownerHistory, landingName, landingDescription, landingObjectType, landingLocalPlacement, representation, landingElementTag, IFCSlabType.Landing); componentHandles.Add(landingHnd); componentExtrusionData.Add(ecData); productWrapper.AddElement(landingHnd, placementSetter.GetLevelInfo(), ecData, false); ExporterCacheManager.HandleToElementCache.Register(landingHnd, landing.Id); } } // Get List of supports to export their geometry. Supports are not exposed to API, so export as generic Element. ICollection<ElementId> supportIds = stair.GetStairsSupports(); index = 0; foreach (ElementId supportId in supportIds) { index++; Element support = doc.GetElement(supportId); using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(placementSetter.GetPlacement()); ecData.ReuseLocalPlacement = false; GeometryElement supportGeometryElement = support.get_Geometry(geomOptions); BodyData bodyData; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); IFCAnyHandle representation = RepresentationUtil.CreateBRepProductDefinitionShape(app, exporterIFC, support, categoryId, supportGeometryElement, bodyExporterOptions, null, ecData, out bodyData); if (IFCAnyHandleUtil.IsNullOrHasNoValue(representation)) { ecData.ClearOpenings(); continue; } foreach (ElementId materialId in bodyData.MaterialIds) materialIds.Add(materialId); string supportGUID = ExporterIFCUtils.CreateGUID(support); string origSupportName = origStairName + " Stringer " + index; string supportName = NamingUtil.GetNameOverride(support, origSupportName); string supportDescription = NamingUtil.GetDescriptionOverride(support, stairDescription); string supportObjectType = NamingUtil.GetObjectTypeOverride(support, stairObjectType); IFCAnyHandle supportLocalPlacement = ecData.GetLocalPlacement(); string supportElementTag = NamingUtil.CreateIFCElementId(support); IFCAnyHandle type = GetMemberTypeHandle(exporterIFC, support); IFCAnyHandle supportHnd = IFCInstanceExporter.CreateMember(file, supportGUID, ownerHistory, supportName, supportDescription, supportObjectType, supportLocalPlacement, representation, supportElementTag); componentHandles.Add(supportHnd); componentExtrusionData.Add(ecData); productWrapper.AddElement(supportHnd, placementSetter.GetLevelInfo(), ecData, false); ExporterCacheManager.TypeRelationsCache.Add(type, supportHnd); } } StairRampContainerInfo stairRampInfo = new StairRampContainerInfo(stairContainerHnd, componentHandles, null); ExporterCacheManager.StairRampContainerInfoCache.AddStairRampContainerInfo(stair.Id, stairRampInfo); CategoryUtil.CreateMaterialAssociations(stair.Document, exporterIFC, stairContainerHnd, materialIds); ExportMultistoryStair(exporterIFC, stair, numFlights, stairContainerHnd, componentHandles, componentExtrusionData, materialIds, placementSetter, productWrapper); } tr.Commit(); } }
/// <summary> /// Exports a Rebar to IFC ReinforcingBar. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element to be exported.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>The list of IfcReinforcingBar handles created.</returns> public static ISet<IFCAnyHandle> ExportRebar(ExporterIFC exporterIFC, Element element, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); HashSet<IFCAnyHandle> createdRebars = new HashSet<IFCAnyHandle>(); using (IFCTransaction transaction = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { if (element is Rebar) { GeometryElement rebarGeometry = ExporterIFCUtils.GetRebarGeometry(element as Rebar, ExporterCacheManager.ExportOptionsCache.FilterViewForExport); // only options are: Not Export, BuildingElementProxy, or ReinforcingBar/Mesh, depending on layout. // Not Export is handled previously, and ReinforcingBar vs Mesh will be determined below. string ifcEnumType; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType); if (exportType == IFCExportType.IfcBuildingElementProxy || exportType == IFCExportType.IfcBuildingElementProxyType) { if (rebarGeometry != null) { ProxyElementExporter.ExportBuildingElementProxy(exporterIFC, element, rebarGeometry, productWrapper); transaction.Commit(); } return null; } } IFCAnyHandle prodRep = null; double totalBarLengthUnscale = GetRebarTotalLength(element); double volumeUnscale = GetRebarVolume(element); double totalBarLength = UnitUtil.ScaleLength(totalBarLengthUnscale); if (MathUtil.IsAlmostZero(totalBarLength)) return null; ElementId materialId = ElementId.InvalidElementId; ParameterUtil.GetElementIdValueFromElementOrSymbol(element, BuiltInParameter.MATERIAL_ID_PARAM, out materialId); Document doc = element.Document; ElementId typeId = element.GetTypeId(); RebarBarType elementType = doc.GetElement(element.GetTypeId()) as RebarBarType; double diameter = UnitUtil.ScaleLength(elementType == null ? 1.0 / 12.0 : elementType.BarDiameter); double radius = diameter / 2.0; double longitudinalBarNominalDiameter = diameter; double longitudinalBarCrossSectionArea = UnitUtil.ScaleArea(volumeUnscale / totalBarLengthUnscale); double barLength = totalBarLength / GetRebarQuantity(element); IList<Curve> baseCurves = GetRebarCenterlineCurves(element, true, false, false); int numberOfBarPositions = GetNumberOfBarPositions(element); string steelGrade = NamingUtil.GetOverrideStringValue(element, "SteelGrade", null); // Allow use of IFC2x3 or IFC4 naming. string predefinedType = NamingUtil.GetOverrideStringValue(element, "BarRole", null); if (string.IsNullOrWhiteSpace(predefinedType)) predefinedType = NamingUtil.GetOverrideStringValue(element, "PredefinedType", null); IFCReinforcingBarRole role = GetReinforcingBarRole(predefinedType); string origRebarName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string rebarDescription = NamingUtil.GetDescriptionOverride(element, null); string rebarObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string rebarTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); const int maxBarGUIDS = IFCReinforcingBarSubElements.BarEnd - IFCReinforcingBarSubElements.BarStart + 1; ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); IFCAnyHandle originalPlacement = setter.LocalPlacement; for (int i = 0; i < numberOfBarPositions; i++) { if (!DoesBarExistAtPosition(element, i)) continue; string rebarName = NamingUtil.GetNameOverride(element, origRebarName + ": " + i); Transform barTrf = GetBarPositionTransform(element, i); 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, element, categoryId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle copyLevelPlacement = (i == 0) ? originalPlacement : ExporterUtil.CopyLocalPlacement(file, originalPlacement); string rebarGUID = (i < maxBarGUIDS) ? GUIDUtil.CreateSubElementGUID(element, i + (int)IFCReinforcingBarSubElements.BarStart) : GUIDUtil.CreateGUID(); IFCAnyHandle elemHnd = IFCInstanceExporter.CreateReinforcingBar(file, rebarGUID, exporterIFC.GetOwnerHistoryHandle(), rebarName, rebarDescription, rebarObjectType, copyLevelPlacement, prodRep, rebarTag, steelGrade, longitudinalBarNominalDiameter, longitudinalBarCrossSectionArea, barLength, role, null); createdRebars.Add(elemHnd); productWrapper.AddElement(element, elemHnd, setter.LevelInfo, null, true); ExporterCacheManager.HandleToElementCache.Register(elemHnd, element.Id); CategoryUtil.CreateMaterialAssociation(exporterIFC, elemHnd, materialId); } } transaction.Commit(); } return createdRebars; }
/// <summary> /// Create IFC room/space/area item, not include boundaries. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> /// <param name="setter"> /// The IFCPlacementSetter. /// </param> /// <returns> /// True if created successfully, false otherwise. /// </returns> static void CreateIFCSpace(ExporterIFC exporterIFC, SpatialElement spatialElement, IFCProductWrapper productWrapper, IFCPlacementSetter setter) { Autodesk.Revit.DB.Document document = spatialElement.Document; ElementId levelId = spatialElement.Level != null ? spatialElement.Level.Id : ElementId.InvalidElementId; double scale = exporterIFC.LinearScale; ElementId catId = spatialElement.Category != null ? spatialElement.Category.Id : ElementId.InvalidElementId; double dArea = 0.0; Parameter param = spatialElement.get_Parameter(BuiltInParameter.ROOM_AREA); if (param != null) { dArea = param.AsDouble(); dArea *= (scale * scale); } SpatialElementBoundaryOptions options = ExporterIFCUtils.GetSpatialElementBoundaryOptions(exporterIFC, spatialElement); IList<CurveLoop> curveLoops = ExporterIFCUtils.GetRoomBoundaryAsCurveLoopArray(spatialElement, options, true); IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); string strSpaceNumber = null; string strSpaceName = null; string strSpaceDesc = null; bool isArea = spatialElement is Area; if (!isArea) { Parameter paramRoomNum = spatialElement.get_Parameter(BuiltInParameter.ROOM_NUMBER); if (paramRoomNum != null) { strSpaceNumber = paramRoomNum.AsString(); } Parameter paramRoomName = spatialElement.get_Parameter(BuiltInParameter.ROOM_NAME); if (paramRoomName != null) { strSpaceName = paramRoomName.AsString(); } Parameter paramRoomComm = spatialElement.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS); if (paramRoomComm != null) { strSpaceDesc = paramRoomComm.AsString(); } } else { Element level = document.get_Element(levelId); if (level != null) { strSpaceNumber = level.Name + " GSA Design Gross Area"; } } //assign empty string if it is null if (strSpaceNumber == null) strSpaceNumber = ""; if (strSpaceName == null) strSpaceName = ""; if (strSpaceDesc == null) strSpaceDesc = ""; IFCLabel name = IFCLabel.Create(strSpaceNumber); IFCLabel longName = IFCLabel.Create(strSpaceName); IFCLabel desc = IFCLabel.Create(strSpaceDesc); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle localPlacement = setter.GetPlacement(); ElementType elemType = document.get_Element(spatialElement.GetTypeId()) as ElementType; bool isObjectExternal = CategoryUtil.IsElementExternal(spatialElement); IFCMeasureValue elevationWithFlooring = IFCMeasureValue.Create(); double roomHeight = 0.0; roomHeight = GetHeight(spatialElement, scale, levelInfo); double bottomOffset = 0.0; Parameter paramBottomOffset = spatialElement.get_Parameter(BuiltInParameter.ROOM_LOWER_OFFSET); bottomOffset = paramBottomOffset != null ? paramBottomOffset.AsDouble() : 0.0; XYZ zDir = new XYZ(0, 0, 1); XYZ orig = new XYZ(0, 0, levelInfo.Elevation + bottomOffset); Plane plane = new Plane(zDir, orig); // room calculated as level offset. GeometryElement geomElem = null; if (spatialElement is Autodesk.Revit.DB.Architecture.Room) { Autodesk.Revit.DB.Architecture.Room room = spatialElement as Autodesk.Revit.DB.Architecture.Room; geomElem = room.ClosedShell; } else if (spatialElement is Autodesk.Revit.DB.Mechanical.Space) { Autodesk.Revit.DB.Mechanical.Space space = spatialElement as Autodesk.Revit.DB.Mechanical.Space; geomElem = space.ClosedShell; } IFCAnyHandle spaceHnd = null; IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData(); extraParams.SetLocalPlacement(localPlacement); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; using (IFCTransaction tr2 = new IFCTransaction(file)) { IFCAnyHandle repHnd = null; if (!(exporterIFC.ExportAs2x2 || Use2DRoomBoundaryForRoomVolumeCalculation()) && geomElem != null) { IFCSolidMeshGeometryInfo solidMeshInfo = ExporterIFCUtils.GetSolidMeshGeometry(exporterIFC, geomElem, Transform.Identity); IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> polyMeshes = solidMeshInfo.GetMeshes(); bool tryToExportAsExtrusion = true; if (solids.Count != 1 || polyMeshes.Count != 0) tryToExportAsExtrusion = false; IList<GeometryObject> geomObjects = new List<GeometryObject>(); foreach (Solid solid in solids) geomObjects.Add(solid); IFCAnyHandle shapeRep = BodyExporter.ExportBody(spatialElement.Document.Application, exporterIFC, catId, geomObjects, tryToExportAsExtrusion, extraParams); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); repHnd = file.CreateProductDefinitionShape(IFCLabel.Create(), IFCLabel.Create(), shapeReps); } else { IFCAnyHandle shapeRep = file.CreateExtrudedSolidFromCurveLoop(exporterIFC, catId, curveLoops, plane, zDir, roomHeight); //pScaledOrig? HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(shapeRep); shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, catId, exporterIFC.Get3DContextHandle(), bodyItems, IFCAnyHandle.Create()); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); repHnd = file.CreateProductDefinitionShape(IFCLabel.Create(), IFCLabel.Create(), shapeReps); } extraParams.ScaledHeight = roomHeight; extraParams.ScaledArea = dArea; spaceHnd = file.CreateSpace(IFCLabel.CreateGUID(spatialElement), exporterIFC.GetOwnerHistoryHandle(), NamingUtil.GetNameOverride(spatialElement, name), NamingUtil.GetDescriptionOverride(spatialElement, desc), NamingUtil.GetObjectTypeOverride(spatialElement, IFCLabel.Create()), extraParams.GetLocalPlacement(), repHnd, longName, IFCElementComposition.Element , isObjectExternal, elevationWithFlooring); tr2.Commit(); } productWrapper.AddSpace(spaceHnd, levelInfo, extraParams, true); // Save room handle for later use/relationships exporterIFC.RegisterSpatialElementHandle(spatialElement.Id, spaceHnd); if (!MathUtil.IsAlmostZero(dArea) && !(exporterIFC.FileVersion == IFCVersion.IFCCOBIE)) { ExporterIFCUtils.CreatePreCOBIEGSAQuantities(exporterIFC, spaceHnd, "GSA Space Areas", (isArea ? "GSA Design Gross Area" : "GSA BIM Area"), dArea); } // Export BaseQuantities for RoomElem if (exporterIFC.ExportBaseQuantities && !(exporterIFC.FileVersion == IFCVersion.IFCCOBIE)) { ExporterIFCUtils.CreateNonCOBIERoomQuantities(exporterIFC, spaceHnd, spatialElement, dArea, roomHeight); } }
/// <summary> /// Exports a CeilingAndFloor element to IFC. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="floor">The floor element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void ExportCeilingAndFloorElement(ExporterIFC exporterIFC, CeilingAndFloor floorElement, ref GeometryElement geometryElement, ProductWrapper productWrapper) { if (geometryElement == null) { return; } IFCFile file = exporterIFC.GetFile(); string ifcEnumType; IFCExportInfoPair exportType = ExporterUtil.GetExportType(exporterIFC, floorElement, out ifcEnumType); IFCAnyHandle type = null; if (!ElementFilteringUtil.IsElementVisible(floorElement)) { 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>(exportType.ExportInstance.ToString(), out elementClassTypeEnum) || Enum.TryParse <Common.Enums.IFCEntityType>(exportType.ExportType.ToString(), out elementClassTypeEnum)) { if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum)) { return; } } Document doc = floorElement.Document; using (SubTransaction tempPartTransaction = new SubTransaction(doc)) { MaterialLayerSetInfo layersetInfo = new MaterialLayerSetInfo(exporterIFC, floorElement, productWrapper); // For IFC4RV export, Element will be split into its parts(temporarily) in order to export the wall by its parts // If Parts are created by code and not by user then their names should be equal to Material names. bool setMaterialNameToPartName = ExporterUtil.CreateParts(floorElement, layersetInfo.MaterialIds.Count, ref geometryElement); ExporterUtil.ExportPartAs exportPartAs = ExporterUtil.CanExportByComponentsOrParts(floorElement); bool exportByComponents = exportPartAs == ExporterUtil.ExportPartAs.ShapeAspect; bool exportParts = exportPartAs == ExporterUtil.ExportPartAs.Part; if (exportParts && !PartExporter.CanExportElementInPartExport(floorElement, floorElement.LevelId, false)) { return; } using (IFCTransaction tr = new IFCTransaction(file)) { bool canExportAsContainerOrWithExtrusionAnalyzer = (!exportParts && (floorElement is Floor)); if (canExportAsContainerOrWithExtrusionAnalyzer) { // Try to export the Floor slab as a container. If that succeeds, we are done. // If we do export the floor as a container, it will take care of the local placement and transform there, so we need to leave // this out of the IFCTransformSetter and PlacementSetter scopes below, or else we'll get double transforms. IFCAnyHandle floorHnd = RoofExporter.ExportRoofOrFloorAsContainer(exporterIFC, floorElement, geometryElement, productWrapper); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(floorHnd)) { tr.Commit(); return; } } IList <IFCAnyHandle> slabHnds = new List <IFCAnyHandle>(); IList <IFCAnyHandle> brepSlabHnds = new List <IFCAnyHandle>(); IList <IFCAnyHandle> nonBrepSlabHnds = new List <IFCAnyHandle>(); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; using (IFCTransformSetter transformSetter = IFCTransformSetter.Create()) { // Check for containment override IFCAnyHandle overrideContainerHnd = null; ElementId overrideContainerId = ParameterUtil.OverrideContainmentParameter(exporterIFC, floorElement, out overrideContainerHnd); using (PlacementSetter placementSetter = PlacementSetter.Create(exporterIFC, floorElement, null, null, overrideContainerId, overrideContainerHnd)) { IFCAnyHandle localPlacement = placementSetter.LocalPlacement; // The routine ExportExtrudedSlabOpenings is called if exportedAsInternalExtrusion is true, and it requires having a valid level association. // Disable calling ExportSlabAsExtrusion if we can't handle potential openings. bool canExportAsInternalExtrusion = placementSetter.LevelInfo != null && !ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView; bool exportedAsInternalExtrusion = false; ElementId catId = CategoryUtil.GetSafeCategoryId(floorElement); IList <IFCAnyHandle> prodReps = new List <IFCAnyHandle>(); IList <ShapeRepresentationType> repTypes = new List <ShapeRepresentationType>(); IList <IList <CurveLoop> > extrusionLoops = new List <IList <CurveLoop> >(); IList <IFCExtrusionCreationData> loopExtraParams = new List <IFCExtrusionCreationData>(); Plane floorPlane = GeometryUtil.CreateDefaultPlane(); IList <IFCAnyHandle> localPlacements = new List <IFCAnyHandle>(); if (!exportParts) { if (canExportAsContainerOrWithExtrusionAnalyzer) { Floor floor = floorElement as Floor; // Next, try to use the ExtrusionAnalyzer for the limited cases it handles - 1 solid, no openings, end clippings only. // Also limited to cases with line and arc boundaries. // SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); IList <Solid> solids = solidMeshInfo.GetSolids(); IList <Mesh> meshes = solidMeshInfo.GetMeshes(); IList <GeometryObject> gObjs = FamilyExporterUtil.RemoveInvisibleSolidsAndMeshes(floorElement.Document, exporterIFC, ref solids, ref meshes); if (solids.Count == 1 && meshes.Count == 0) { bool completelyClipped; // floorExtrusionDirection is set to (0, 0, -1) because extrusionAnalyzerFloorPlane is computed from the top face of the floor XYZ floorExtrusionDirection = new XYZ(0, 0, -1); XYZ modelOrigin = XYZ.Zero; XYZ floorOrigin = floor.GetVerticalProjectionPoint(modelOrigin, FloorFace.Top); if (floorOrigin == null) { // GetVerticalProjectionPoint may return null if FloorFace.Top is an edited face that doesn't // go through the Revit model origin. We'll try the midpoint of the bounding box instead. BoundingBoxXYZ boundingBox = floorElement.get_BoundingBox(null); modelOrigin = (boundingBox.Min + boundingBox.Max) / 2.0; floorOrigin = floor.GetVerticalProjectionPoint(modelOrigin, FloorFace.Top); } if (floorOrigin != null) { XYZ floorDir = floor.GetNormalAtVerticalProjectionPoint(floorOrigin, FloorFace.Top); Plane extrusionAnalyzerFloorBasePlane = GeometryUtil.CreatePlaneByNormalAtOrigin(floorDir); GenerateAdditionalInfo additionalInfo = GenerateAdditionalInfo.GenerateBody; additionalInfo |= ExporterCacheManager.ExportOptionsCache.ExportAs4 ? GenerateAdditionalInfo.GenerateFootprint : GenerateAdditionalInfo.None; // Skip generate body item for IFC4RV. It will be handled later in PartExporter.ExportHostPartAsShapeAspects() if (exportByComponents) { additionalInfo &= ~GenerateAdditionalInfo.GenerateBody; } HandleAndData floorAndProperties = ExtrusionExporter.CreateExtrusionWithClippingAndProperties(exporterIFC, floorElement, catId, solids[0], extrusionAnalyzerFloorBasePlane, floorOrigin, floorExtrusionDirection, null, out completelyClipped, addInfo: additionalInfo); if (completelyClipped) { return; } IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); if (floorAndProperties.Handle != null) { representations.Add(floorAndProperties.Handle); repTypes.Add(ShapeRepresentationType.SweptSolid); } // Footprint representation will only be exported in export to IFC4 if (((additionalInfo & GenerateAdditionalInfo.GenerateFootprint) != 0) && (floorAndProperties.FootprintInfo != null)) { IFCAnyHandle footprintShapeRep = floorAndProperties.FootprintInfo.CreateFootprintShapeRepresentation(exporterIFC); representations.Add(footprintShapeRep); } if (exportByComponents) { IFCAnyHandle prodRep = RepresentationUtil.CreateProductDefinitionShapeWithoutBodyRep(exporterIFC, floorElement, catId, geometryElement, representations); prodReps.Add(prodRep); } else if (representations.Count > 0 && floorAndProperties.Handle != null) // Only when at least the body rep exists will come here { IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); prodReps.Add(prodRep); } if (floorAndProperties.Data != null) { loopExtraParams.Add(floorAndProperties.Data); } } } } // Use internal routine as backup that handles openings. if (prodReps.Count == 0 && canExportAsInternalExtrusion && !exportByComponents) { exportedAsInternalExtrusion = ExporterIFCUtils.ExportSlabAsExtrusion(exporterIFC, floorElement, geometryElement, transformSetter, localPlacement, out localPlacements, out prodReps, out extrusionLoops, out loopExtraParams, floorPlane); PotentiallyFixPresentationLayerAssignment(floorElement, prodReps); for (int ii = 0; ii < prodReps.Count; ii++) { // all are extrusions repTypes.Add(ShapeRepresentationType.SweptSolid); // Footprint representation will only be exported in export to IFC4 if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { if (extrusionLoops.Count > ii) { if (extrusionLoops[ii].Count > 0) { // Get the extrusion footprint using the first Curveloop. Transform needs to be obtained from the returned local placement Transform lcs = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, localPlacements[ii]); IFCAnyHandle footprintGeomRepItem = GeometryUtil.CreateIFCCurveFromCurveLoop(exporterIFC, extrusionLoops[ii][0], lcs, floorPlane.Normal); IFCAnyHandle contextOfItemsFootprint = exporterIFC.Get3DContextHandle("FootPrint"); ISet <IFCAnyHandle> repItem = new HashSet <IFCAnyHandle>(); repItem.Add(footprintGeomRepItem); IFCAnyHandle footprintShapeRepresentation = RepresentationUtil.CreateBaseShapeRepresentation(exporterIFC, contextOfItemsFootprint, "FootPrint", "Curve2D", repItem); IList <IFCAnyHandle> reps = new List <IFCAnyHandle>(); reps.Add(footprintShapeRepresentation); IFCAnyHandleUtil.AddRepresentations(prodReps[ii], reps); } } } } } IFCAnyHandle prodDefHnd; if (prodReps.Count == 0) { if (exportByComponents) { prodDefHnd = RepresentationUtil.CreateProductDefinitionShapeWithoutBodyRep(exporterIFC, floorElement, catId, geometryElement, null); prodReps.Add(prodDefHnd); } else { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { // Brep representation using tesellation after ExportSlabAsExtrusion does not return prodReps BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true, ExportOptionsCache.ExportTessellationLevel.Medium); BodyData bodyData; prodDefHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, floorElement, catId, geometryElement, bodyExporterOptions, null, ecData, out bodyData); if (IFCAnyHandleUtil.IsNullOrHasNoValue(prodDefHnd)) { ecData.ClearOpenings(); return; } prodReps.Add(prodDefHnd); repTypes.Add(bodyData.ShapeRepresentationType); } } } } // Create the slab from either the extrusion or the BRep information. string ifcGUID = GUIDUtil.CreateGUID(floorElement); int numReps = exportParts ? 1 : prodReps.Count; // Deal with a couple of cases that have non-standard defaults. switch (exportType.ExportInstance) { case IFCEntityType.IfcCovering: exportType.ValidatedPredefinedType = IFCValidateEntry.GetValidIFCType <IFCCoveringType>(floorElement, ifcEnumType, "FLOORING"); break; case IFCEntityType.IfcSlab: bool isBaseSlab = false; AnalyticalModel analyticalModel = floorElement.GetAnalyticalModel(); if (analyticalModel != null) { AnalyzeAs slabFoundationType = analyticalModel.GetAnalyzeAs(); isBaseSlab = (slabFoundationType == AnalyzeAs.SlabOnGrade) || (slabFoundationType == AnalyzeAs.Mat); } exportType.ValidatedPredefinedType = IFCValidateEntry.GetValidIFCType <IFCSlabType>(floorElement, ifcEnumType, isBaseSlab ? "BASESLAB" : "FLOOR"); break; } for (int ii = 0; ii < numReps; ii++) { string ifcName = NamingUtil.GetNameOverride(floorElement, NamingUtil.GetIFCNamePlusIndex(floorElement, ii == 0 ? -1 : ii + 1)); string currentGUID = (ii == 0) ? ifcGUID : GUIDUtil.CreateGUID(); IFCAnyHandle localPlacementHnd = exportedAsInternalExtrusion ? localPlacements[ii] : localPlacement; IFCAnyHandle slabHnd = null; slabHnd = IFCInstanceExporter.CreateGenericIFCEntity(exportType, exporterIFC, floorElement, currentGUID, ownerHistory, localPlacementHnd, exportParts ? null : prodReps[ii]); if (IFCAnyHandleUtil.IsNullOrHasNoValue(slabHnd)) { return; } if (!string.IsNullOrEmpty(ifcName)) { IFCAnyHandleUtil.OverrideNameAttribute(slabHnd, ifcName); } // Pre IFC4 Slab does not have PredefinedType if (!string.IsNullOrEmpty(exportType.ValidatedPredefinedType) && !ExporterCacheManager.ExportOptionsCache.ExportAsOlderThanIFC4) { IFCAnyHandleUtil.SetAttribute(slabHnd, "PredefinedType", exportType.ValidatedPredefinedType, true); } if (exportParts) { PartExporter.ExportHostPart(exporterIFC, floorElement, slabHnd, productWrapper, placementSetter, localPlacementHnd, null, setMaterialNameToPartName); } else if (exportByComponents) { IFCExtrusionCreationData partECData = new IFCExtrusionCreationData(); IFCAnyHandle hostShapeRepFromParts = PartExporter.ExportHostPartAsShapeAspects(exporterIFC, floorElement, prodReps[ii], productWrapper, placementSetter, localPlacement, ElementId.InvalidElementId, layersetInfo, partECData); loopExtraParams.Add(partECData); } slabHnds.Add(slabHnd); // For IFC4RV, export of the geometry is already handled in PartExporter.ExportHostPartAsShapeAspects() if (!exportParts && !exportByComponents) { if (repTypes[ii] == ShapeRepresentationType.Brep || repTypes[ii] == ShapeRepresentationType.Tessellation) { brepSlabHnds.Add(slabHnd); } else { nonBrepSlabHnds.Add(slabHnd); } } } for (int ii = 0; ii < numReps; ii++) { IFCExtrusionCreationData loopExtraParam = ii < loopExtraParams.Count ? loopExtraParams[ii] : null; productWrapper.AddElement(floorElement, slabHnds[ii], placementSetter, loopExtraParam, true, exportType); type = ExporterUtil.CreateGenericTypeFromElement(floorElement, exportType, file, ownerHistory, exportType.ValidatedPredefinedType, productWrapper); ExporterCacheManager.TypeRelationsCache.Add(type, slabHnds[ii]); ExporterUtil.AddIntoComplexPropertyCache(slabHnds[ii], layersetInfo); } // This call to the native function appears to create Brep opening also when appropriate. But the creation of the IFC instances is not // controllable from the managed code. Therefore in some cases BRep geometry for Opening will still be exported even in the Reference View if (exportedAsInternalExtrusion) { ISet <IFCAnyHandle> oldCreatedObjects = productWrapper.GetAllObjects(); ExporterIFCUtils.ExportExtrudedSlabOpenings(exporterIFC, floorElement, placementSetter.LevelInfo, localPlacements[0], slabHnds, extrusionLoops, floorPlane, productWrapper.ToNative()); ISet <IFCAnyHandle> newCreatedObjects = productWrapper.GetAllObjects(); newCreatedObjects.ExceptWith(oldCreatedObjects); PotentiallyFixPresentationLayerAssignment(floorElement, newCreatedObjects); } } if (!exportParts) { if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { HostObjectExporter.ExportHostObjectMaterials(exporterIFC, floorElement, productWrapper.GetAnElement(), geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, false, type); } else { if (nonBrepSlabHnds.Count > 0) { HostObjectExporter.ExportHostObjectMaterials(exporterIFC, floorElement, nonBrepSlabHnds, geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, false, type); } if (brepSlabHnds.Count > 0) { HostObjectExporter.ExportHostObjectMaterials(exporterIFC, floorElement, brepSlabHnds, geometryElement, productWrapper, ElementId.InvalidElementId, Toolkit.IFCLayerSetDirection.Axis3, true, type); } } } } tr.Commit(); return; } } }
/// <summary> /// Exports a gutter element. /// </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> public static void ExportGutter(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element)) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(setter.GetPlacement()); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(); IFCAnyHandle bodyRep = BodyExporter.ExportBody(exporterIFC, element, categoryId, ElementId.InvalidElementId, geometryElement, bodyExporterOptions, ecData).RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { if (ecData != null) ecData.ClearOpenings(); return; } IFCAnyHandle origin = ExporterUtil.CreateAxis2Placement3D(file); IFCAnyHandle repMap3dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyRep); List<IFCAnyHandle> repMapList = new List<IFCAnyHandle>(); repMapList.Add(repMap3dHnd); string elementTypeName = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle style = IFCInstanceExporter.CreatePipeSegmentType(file, GUIDUtil.CreateGUID(element), exporterIFC.GetOwnerHistoryHandle(), elementTypeName, null, null, null, repMapList, NamingUtil.CreateIFCElementId(element), elementTypeName, IFCPipeSegmentType.Gutter); List<IFCAnyHandle> representationMaps = GeometryUtil.GetRepresentationMaps(style); IFCAnyHandle mappedItem = ExporterUtil.CreateDefaultMappedItem(file, representationMaps[0]); IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); representations.Add(mappedItem); IFCAnyHandle bodyMappedItemRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, element, categoryId, exporterIFC.Get3DContextHandle("Body"), representations); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyMappedItemRep)) return; List<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(bodyMappedItemRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); if (roomId == ElementId.InvalidElementId) localPlacementToUse = ecData.GetLocalPlacement(); string name = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string description = NamingUtil.GetDescriptionOverride(element, null); string objectType = NamingUtil.GetObjectTypeOverride(element, elementTypeName); string Tag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); IFCAnyHandle elemHnd = IFCInstanceExporter.CreateFlowSegment(file, GUIDUtil.CreateGUID(element), exporterIFC.GetOwnerHistoryHandle(), name, description, objectType, localPlacementToUse, prodRep, Tag); if (roomId == ElementId.InvalidElementId) { productWrapper.AddElement(elemHnd, setter.GetLevelInfo(), ecData, true); } else { exporterIFC.RelateSpatialElement(roomId, elemHnd); productWrapper.AddElement(elemHnd, setter.GetLevelInfo(), ecData, false); } OpeningUtil.CreateOpeningsIfNecessary(elemHnd, element, ecData, exporterIFC, localPlacementToUse, setter, productWrapper); } tr.Commit(); } } }
/// <summary> /// Creates IFC room/space/area item, not include boundaries. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="spatialElement">The spatial element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <param name="setter">The PlacementSetter.</param> /// <returns>True if created successfully, false otherwise.</returns> static bool CreateIFCSpace(ExporterIFC exporterIFC, SpatialElement spatialElement, ProductWrapper productWrapper, PlacementSetter setter, out SpatialElementGeometryResults results) { results = null; IList<CurveLoop> curveLoops = null; try { // Avoid throwing for a spatial element with no location. if (spatialElement.Location == null) return false; SpatialElementBoundaryOptions options = GetSpatialElementBoundaryOptions(spatialElement); curveLoops = ExporterIFCUtils.GetRoomBoundaryAsCurveLoopArray(spatialElement, options, true); } catch (Autodesk.Revit.Exceptions.InvalidOperationException) { //Some spatial elements are not placed that have no boundary loops. Don't export them. return false; } Autodesk.Revit.DB.Document document = spatialElement.Document; ElementId levelId = spatialElement.LevelId; ElementId catId = spatialElement.Category != null ? spatialElement.Category.Id : ElementId.InvalidElementId; double dArea = 0.0; if (ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_AREA, out dArea) != null) dArea = UnitUtil.ScaleArea(dArea); IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); string strSpaceNumber = null; string strSpaceName = null; string strSpaceDesc = null; if (ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ROOM_NUMBER, out strSpaceNumber) == null) strSpaceNumber = null; if (ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ROOM_NAME, out strSpaceName) == null) strSpaceName = null; if (ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS, out strSpaceDesc) == null) strSpaceDesc = null; string name = strSpaceNumber; string longName = strSpaceName; string desc = strSpaceDesc; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle localPlacement = setter.LocalPlacement; ElementType elemType = document.GetElement(spatialElement.GetTypeId()) as ElementType; IFCInternalOrExternal internalOrExternal = CategoryUtil.IsElementExternal(spatialElement) ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal; double scaledRoomHeight = GetScaledHeight(spatialElement, levelId, levelInfo); if (scaledRoomHeight <= 0.0) return false; double bottomOffset; ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_LOWER_OFFSET, out bottomOffset); double elevation = (levelInfo != null) ? levelInfo.Elevation : 0.0; XYZ zDir = new XYZ(0, 0, 1); XYZ orig = new XYZ(0, 0, elevation + bottomOffset); Plane plane = new Plane(zDir, orig); // room calculated as level offset. GeometryElement geomElem = null; bool isArea = (spatialElement is Area); Area spatialElementAsArea = isArea ? (spatialElement as Area) : null; if (spatialElement is Autodesk.Revit.DB.Architecture.Room) { Autodesk.Revit.DB.Architecture.Room room = spatialElement as Autodesk.Revit.DB.Architecture.Room; geomElem = room.ClosedShell; } else if (spatialElement is Autodesk.Revit.DB.Mechanical.Space) { Autodesk.Revit.DB.Mechanical.Space space = spatialElement as Autodesk.Revit.DB.Mechanical.Space; geomElem = space.ClosedShell; } else if (isArea) { Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); geomElem = spatialElementAsArea.get_Geometry(geomOptions); } IFCAnyHandle spaceHnd = null; string spatialElementName = null; using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { extraParams.SetLocalPlacement(localPlacement); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; using (IFCTransaction transaction2 = new IFCTransaction(file)) { IFCAnyHandle repHnd = null; if (!ExporterCacheManager.ExportOptionsCache.Use2DRoomBoundaryForRoomVolumeCreation && geomElem != null) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); bodyExporterOptions.TessellationLevel = BodyExporter.GetTessellationLevel(); repHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, spatialElement, catId, geomElem, bodyExporterOptions, null, extraParams, false); if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) extraParams.ClearOpenings(); } else { IFCAnyHandle shapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, plane, zDir, scaledRoomHeight); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return false; IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, shapeRep, ElementId.InvalidElementId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(shapeRep); shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, spatialElement, catId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomElem, Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); repHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); } extraParams.ScaledHeight = scaledRoomHeight; extraParams.ScaledArea = dArea; spatialElementName = NamingUtil.GetNameOverride(spatialElement, name); string spatialElementDescription = NamingUtil.GetDescriptionOverride(spatialElement, desc); string spatialElementObjectType = NamingUtil.GetObjectTypeOverride(spatialElement, null); string spatialElementLongName = NamingUtil.GetLongNameOverride(spatialElement, longName); double? spaceElevationWithFlooring = null; double elevationWithFlooring = 0.0; if (ParameterUtil.GetDoubleValueFromElement(spatialElement, null, "IfcElevationWithFlooring", out elevationWithFlooring) != null) spaceElevationWithFlooring = UnitUtil.ScaleLength(elevationWithFlooring); spaceHnd = IFCInstanceExporter.CreateSpace(file, GUIDUtil.CreateGUID(spatialElement), ExporterCacheManager.OwnerHistoryHandle, spatialElementName, spatialElementDescription, spatialElementObjectType, extraParams.GetLocalPlacement(), repHnd, spatialElementLongName, Toolkit.IFCElementComposition.Element, internalOrExternal, spaceElevationWithFlooring); transaction2.Commit(); } if (spaceHnd != null) { productWrapper.AddSpace(spatialElement, spaceHnd, levelInfo, extraParams, true); if (isArea) { Element areaScheme = spatialElementAsArea.AreaScheme; if (areaScheme != null) { ElementId areaSchemeId = areaScheme.Id; HashSet<IFCAnyHandle> areas = null; if (!ExporterCacheManager.AreaSchemeCache.TryGetValue(areaSchemeId, out areas)) { areas = new HashSet<IFCAnyHandle>(); ExporterCacheManager.AreaSchemeCache[areaSchemeId] = areas; } areas.Add(spaceHnd); } } } } // Save room handle for later use/relationships ExporterCacheManager.SpaceInfoCache.SetSpaceHandle(spatialElement, spaceHnd); // Find Ceiling as a Space boundary and keep the relationship in a cache for use later bool ret = GetCeilingSpaceBoundary(spatialElement, out results); if (!MathUtil.IsAlmostZero(dArea) && !(ExporterCacheManager.ExportOptionsCache.ExportAsCOBIE) && !ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 && !ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { bool isDesignGrossArea = (string.Compare(spatialElementName, "GSA Design Gross Area") > 0); PropertyUtil.CreatePreCOBIEGSAQuantities(exporterIFC, spaceHnd, "GSA Space Areas", (isDesignGrossArea ? "GSA Design Gross Area" : "GSA BIM Area"), dArea); } // Export Classifications for SpatialElement for GSA/COBIE. if (ExporterCacheManager.ExportOptionsCache.ExportAsCOBIE) { ProjectInfo projectInfo = document.ProjectInformation; if (projectInfo != null) CreateCOBIESpaceClassifications(exporterIFC, file, spaceHnd, projectInfo, spatialElement); } return true; }
/// <summary> /// Main implementation to export walls. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="connectedWalls">Information about walls joined to this wall.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="origWrapper">The ProductWrapper.</param> /// <param name="overrideLevelId">The level id.</param> /// <param name="range">The range to be exported for the element.</param> /// <returns>The exported wall handle.</returns> public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, IList<IList<IFCConnectedWallData>> connectedWalls, GeometryElement geometryElement, ProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range) { // Check cases where we choose not to export early. ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; FamilyInstance famInstWallElem = element as FamilyInstance; FaceWall faceWall = element as FaceWall; bool exportingWallElement = (wallElement != null); bool exportingFamilyInstance = (famInstWallElem != null); bool exportingFaceWall = (faceWall != null); if (!exportingWallElement && !exportingFamilyInstance && !exportingFaceWall) return null; if (exportingWallElement && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return null; IFCRange zSpan = null; double depth = 0.0; bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, validRange ? overrideLevelId : element.LevelId, validRange)) return null; IList<Solid> solids = new List<Solid>(); IList<Mesh> meshes = new List<Mesh>(); bool exportingInplaceOpenings = false; if (!exportParts) { if (exportingWallElement || exportingFaceWall) { GetSolidsAndMeshes(geometryElement, range, ref solids, ref meshes); if (solids.Count == 0 && meshes.Count == 0) return null; } else { GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem); if (geomElemToUse != null) { exportingInplaceOpenings = true; } else { exportingInplaceOpenings = false; geomElemToUse = geometryElement; } Transform trf = Transform.Identity; if (geomElemToUse != geometryElement) trf = famInstWallElem.GetTransform(); SolidMeshGeometryInfo solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geomElemToUse, trf); solids = solidMeshCapsule.GetSolids(); meshes = solidMeshCapsule.GetMeshes(); } } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (ProductWrapper localWrapper = ProductWrapper.Create(origWrapper)) { // get bounding box height so that we can subtract out pieces properly. // only for Wall, not FamilyInstance. if (exportingWallElement && geometryElement != null) { // There is a problem in the API where some walls with vertical structures are overreporting their height, // making it appear as if there are clipping problems on export. We will work around this by getting the // height directly from the solid(s). if (solids.Count > 0 && meshes.Count == 0) { zSpan = GetBoundingBoxOfSolids(solids); } else { BoundingBoxXYZ boundingBox = wallElement.get_BoundingBox(null); if (boundingBox != null) zSpan = GetBoundingBoxZRange(boundingBox); } if (zSpan == null) return null; // if we have a top clipping plane, modify depth accordingly. double bottomHeight = validRange ? Math.Max(zSpan.Start, range.Start) : zSpan.Start; double topHeight = validRange ? Math.Min(zSpan.End, range.End) : zSpan.End; depth = topHeight - bottomHeight; if (MathUtil.IsAlmostZero(depth)) return null; depth = UnitUtil.ScaleLength(depth); } else { zSpan = new IFCRange(); } Document doc = element.Document; double baseWallElevation = 0.0; ElementId baseLevelId = PlacementSetter.GetBaseLevelIdForElement(element); if (baseLevelId != ElementId.InvalidElementId) { Element baseLevel = doc.GetElement(baseLevelId); if (baseLevel is Level) baseWallElevation = (baseLevel as Level).Elevation; } IFCAnyHandle axisRep = null; IFCAnyHandle bodyRep = null; bool exportingAxis = false; Curve trimmedCurve = null; bool exportedAsWallWithAxis = false; bool exportedBodyDirectly = false; Curve centerCurve = GetWallAxis(wallElement); XYZ localXDir = new XYZ(1, 0, 0); XYZ localYDir = new XYZ(0, 1, 0); XYZ localZDir = new XYZ(0, 0, 1); XYZ localOrig = new XYZ(0, 0, 0); double eps = MathUtil.Eps(); if (centerCurve != null) { Curve baseCurve = GetWallAxisAtBaseHeight(wallElement); trimmedCurve = GetWallTrimmedCurve(wallElement, baseCurve); IFCRange curveBounds; XYZ oldOrig; GeometryUtil.GetAxisAndRangeFromCurve(trimmedCurve, out curveBounds, out localXDir, out oldOrig); // Move the curve to the bottom of the geometry or the bottom of the range, which is higher. if (baseCurve != null) localOrig = new XYZ(oldOrig.X, oldOrig.Y, validRange ? Math.Max(range.Start, zSpan.Start) : zSpan.Start); else localOrig = oldOrig; double dist = localOrig[2] - oldOrig[2]; if (!MathUtil.IsAlmostZero(dist)) { XYZ moveVec = new XYZ(0, 0, dist); trimmedCurve = GeometryUtil.MoveCurve(trimmedCurve, moveVec); } localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } else { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox != null) { XYZ bBoxMin = boundingBox.Min; XYZ bBoxMax = boundingBox.Max; if (validRange) localOrig = new XYZ(bBoxMin.X, bBoxMin.Y, range.Start); else localOrig = boundingBox.Min; XYZ localXDirMax = null; Transform bTrf = boundingBox.Transform; XYZ localXDirMax1 = new XYZ(bBoxMax.X, localOrig.Y, localOrig.Z); localXDirMax1 = bTrf.OfPoint(localXDirMax1); XYZ localXDirMax2 = new XYZ(localOrig.X, bBoxMax.Y, localOrig.Z); localXDirMax2 = bTrf.OfPoint(localXDirMax2); if (localXDirMax1.DistanceTo(localOrig) >= localXDirMax2.DistanceTo(localOrig)) localXDirMax = localXDirMax1; else localXDirMax = localXDirMax2; localXDir = localXDirMax.Subtract(localOrig); localXDir = localXDir.Normalize(); localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } } IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); Transform orientationTrf = Transform.Identity; orientationTrf.BasisX = localXDir; orientationTrf.BasisY = localYDir; orientationTrf.BasisZ = localZDir; orientationTrf.Origin = localOrig; double scaledFootprintArea = 0; double scaledLength = 0; using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.LocalPlacement; // The local coordinate system of the wall as defined by IFC for IfcWallStandardCase. Plane wallLCS = new Plane(localXDir, localYDir, localOrig); // project curve to XY plane. XYZ projDir = XYZ.BasisZ; // two representations: axis, body. { if (!exportParts && (centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve))) { exportingAxis = true; string identifierOpt = "Axis"; // IFC2x2 convention string representationTypeOpt = "Curve2D"; // IFC2x2 convention IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, wallLCS, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, trimmedCurve, XYZ.Zero, true); IList<IFCAnyHandle> axisItems = info.GetCurves(); if (axisItems.Count == 0) { exportingAxis = false; } else { HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>(); foreach (IFCAnyHandle axisItem in axisItems) axisItemSet.Add(axisItem); IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis"); axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItemsAxis, identifierOpt, representationTypeOpt, axisItemSet); } } } IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>(); if (!exportParts && exportingWallElement && exportingAxis && trimmedCurve != null) { bool isCompletelyClipped; bodyRep = TryToCreateAsExtrusion(exporterIFC, wallElement, connectedWalls, solids, meshes, baseWallElevation, catId, centerCurve, trimmedCurve, wallLCS, depth, zSpan, range, setter, out cutPairOpenings, out isCompletelyClipped, out scaledFootprintArea, out scaledLength); if (isCompletelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) exportedAsWallWithAxis = true; } using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { BodyData bodyData = null; if (!exportedAsWallWithAxis) { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); // Swept solids are not natively exported as part of CV2.0. // We have removed the UI toggle for this, so that it is by default false, but keep for possible future use. if (ExporterCacheManager.ExportOptionsCache.ExportAdvancedSweptSolids) bodyExporterOptions.TryToExportAsSweptSolid = true; ElementId overrideMaterialId = ElementId.InvalidElementId; if (exportingWallElement) overrideMaterialId = HostObjectExporter.GetFirstLayerMaterialId(wallElement); if (!exportParts) { if ((solids.Count > 0) || (meshes.Count > 0)) { bodyRep = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId, solids, meshes, bodyExporterOptions, extraParams).RepresentationHnd; } else { IList<GeometryObject> geomElemList = new List<GeometryObject>(); geomElemList.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId, geomElemList, bodyExporterOptions, extraParams); bodyRep = bodyData.RepresentationHnd; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { extraParams.ClearOpenings(); return null; } } // We will be able to export as a IfcWallStandardCase as long as we have an axis curve. XYZ extrDirUsed = XYZ.Zero; if (extraParams.HasExtrusionDirection) { extrDirUsed = extraParams.ExtrusionDirection; if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0)) { if ((solids.Count == 1) && (meshes.Count == 0)) exportedAsWallWithAxis = exportingAxis; exportedBodyDirectly = true; } } } IFCAnyHandle prodRep = null; if (!exportParts) { IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (exportingAxis) representations.Add(axisRep); representations.Add(bodyRep); IFCAnyHandle boundingBoxRep = null; if ((solids.Count > 0) || (meshes.Count > 0)) boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, solids, meshes, Transform.Identity); else boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) representations.Add(boundingBoxRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); } ElementId matId = ElementId.InvalidElementId; string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = null; string elemGUID = null; int subElementIndex = ExporterStateManager.GetCurrentRangeIndex(); if (subElementIndex == 0) elemGUID = GUIDUtil.CreateGUID(element); else if (subElementIndex <= ExporterStateManager.RangeIndexSetter.GetMaxStableGUIDs()) elemGUID = GUIDUtil.CreateSubElementGUID(element, subElementIndex + (int)IFCGenericSubElements.SplitInstanceStart - 1); else elemGUID = GUIDUtil.CreateGUID(); string elemName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); string ifcType = IFCValidateEntry.GetValidIFCType(element, null); // For Foundation and Retaining walls, allow exporting as IfcFooting instead. bool exportAsFooting = false; if (exportingWallElement) { WallType wallType = wallElement.WallType; if (wallType != null) { int wallFunction; if (ParameterUtil.GetIntValueFromElement(wallType, BuiltInParameter.FUNCTION_PARAM, out wallFunction) != null) { if (wallFunction == (int)WallFunction.Retaining || wallFunction == (int)WallFunction.Foundation) { // In this case, allow potential to export foundation and retaining walls as footing. string enumTypeValue = null; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, wallElement, out enumTypeValue); if (exportType == IFCExportType.IfcFooting) exportAsFooting = true; } } } } if (exportedAsWallWithAxis) { if (exportAsFooting) { wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, ifcType); } else { bool exportAsWall = exportParts; if (!exportAsWall) { // (For Reference View export) If the representation returned earlier is of type Tessellation, create IfcWall instead. foreach (IFCAnyHandle pRep in IFCAnyHandleUtil.GetRepresentations(prodRep)) { if (String.Compare(IFCAnyHandleUtil.GetRepresentationType(pRep), "Tessellation") == 0) { exportAsWall = true; break; } } } if (exportAsWall) { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, null, elemTag, ifcType); } else { wallHnd = IFCInstanceExporter.CreateWallStandardCase(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, prodRep, elemTag, ifcType); } } if (exportParts) PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(element, wallHnd, setter, extraParams, true); if (!exportParts) { OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, null, exporterIFC, localPlacement, setter, localWrapper); if (exportedBodyDirectly) { Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform, exporterIFC, localPlacement, setter, localWrapper); } else { double scaledWidth = UnitUtil.ScaleLength(wallElement.Width); OpeningUtil.AddOpeningsToElement(exporterIFC, wallHnd, wallElement, null, scaledWidth, range, setter, localPlacement, localWrapper); } } // export Base Quantities if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { scaledFootprintArea = MathUtil.AreaIsAlmostZero(scaledFootprintArea) ? extraParams.ScaledArea : scaledFootprintArea; scaledLength = MathUtil.IsAlmostZero(scaledLength) ? extraParams.ScaledLength : scaledLength; PropertyUtil.CreateWallBaseQuantities(exporterIFC, wallElement, solids, meshes, wallHnd, scaledLength, depth, scaledFootprintArea); } } else { if (exportAsFooting) { wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, ifcType); } else { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, ifcType); } if (exportParts) PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(element, wallHnd, setter, extraParams, true); if (!exportParts) { // Only export one material for 2x2; for future versions, export the whole list. if (ExporterCacheManager.ExportOptionsCache.ExportAs2x2 || exportingFamilyInstance) { matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids, meshes, element); if (matId != ElementId.InvalidElementId) CategoryUtil.CreateMaterialAssociation(exporterIFC, wallHnd, matId); } if (exportingInplaceOpenings) { OpeningUtil.AddOpeningsToElement(exporterIFC, wallHnd, famInstWallElem, null, 0.0, range, setter, localPlacement, localWrapper); } if (exportedBodyDirectly) { Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform, exporterIFC, localPlacement, setter, localWrapper); } } } ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; if ((exportingWallElement || exportingFaceWall) && !exportParts) { HostObject hostObject = null; if (exportingWallElement) hostObject = wallElement; else hostObject = faceWall; if (!ExporterCacheManager.ExportOptionsCache.ExportAs2x2 || exportedAsWallWithAxis) HostObjectExporter.ExportHostObjectMaterials(exporterIFC, hostObject, localWrapper.GetAnElement(), geometryElement, localWrapper, wallLevelId, Toolkit.IFCLayerSetDirection.Axis2, !exportedAsWallWithAxis); } ExportWallType(exporterIFC, localWrapper, wallHnd, element, matId, exportedAsWallWithAxis, exportAsFooting); SpaceBoundingElementUtil.RegisterSpaceBoundingElementHandle(exporterIFC, wallHnd, element.Id, wallLevelId); tr.Commit(); return wallHnd; } } } } }
/// <summary> /// Export one IFCGrid in one level. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="levelId">The level ID.</param> /// <param name="sameDirectionAxesU">The U axes of grids.</param> /// <param name="sameDirectionAxesV">The V axes of grids.</param> /// <param name="sameDirectionAxesW">The W axes of grids.</param> public static void ExportGrid(ExporterIFC exporterIFC, ElementId levelId, List<Grid> sameDirectionAxesU, List<Grid> sameDirectionAxesV, List<Grid> sameDirectionAxesW) { List<IFCAnyHandle> axesU = null; List<IFCAnyHandle> axesV = null; List<IFCAnyHandle> axesW = null; List<IFCAnyHandle> representations = new List<IFCAnyHandle>(); using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true)) { IFCFile ifcFile = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(ifcFile)) { GridRepresentationData gridRepresentationData = new GridRepresentationData(); axesU = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesU, representations, gridRepresentationData); axesV = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesV, representations, gridRepresentationData); if (sameDirectionAxesW != null) axesW = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesW, representations, gridRepresentationData); IFCAnyHandle contextOfItemsFootPrint = exporterIFC.Get3DContextHandle("FootPrint"); string identifierOpt = "FootPrint"; string representationTypeOpt = "GeometricCurveSet"; int numGridsToExport = gridRepresentationData.m_Grids.Count; if (numGridsToExport == 0) return; bool useIFCCADLayer = !string.IsNullOrWhiteSpace(gridRepresentationData.m_IFCCADLayer); IFCAnyHandle shapeRepresentation = null; HashSet<IFCAnyHandle> allCurves = new HashSet<IFCAnyHandle>(); for (int ii = 0; ii < numGridsToExport; ii++) allCurves.UnionWith(gridRepresentationData.m_curveSets[ii]); if (useIFCCADLayer) { shapeRepresentation = RepresentationUtil.CreateShapeRepresentation(exporterIFC, contextOfItemsFootPrint, identifierOpt, representationTypeOpt, allCurves, gridRepresentationData.m_IFCCADLayer); } else { ElementId catId = CategoryUtil.GetSafeCategoryId(gridRepresentationData.m_Grids[0]); shapeRepresentation = RepresentationUtil.CreateShapeRepresentation(exporterIFC, gridRepresentationData.m_Grids[0], catId, contextOfItemsFootPrint, identifierOpt, representationTypeOpt, allCurves); } representations.Add(shapeRepresentation); IFCAnyHandle productRep = IFCInstanceExporter.CreateProductDefinitionShape(ifcFile, null, null, representations); IFCLevelInfo levelInfo = ExporterCacheManager.LevelInfoCache.GetLevelInfo(exporterIFC, levelId); string gridGUID = GUIDUtil.CreateGUID(); // Get the first grid's override name, if cannot find it, use null. string gridName = GetGridName(sameDirectionAxesU, sameDirectionAxesV, sameDirectionAxesW); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCAnyHandle gridLevelHandle = levelInfo.GetBuildingStorey(); IFCAnyHandle levelObjectPlacement = IFCAnyHandleUtil.GetInstanceAttribute(gridLevelHandle, "ObjectPlacement"); double elev = levelInfo.Elevation; double scaleFactor = exporterIFC.LinearScale; double elevation = elev * scaleFactor; XYZ orig = new XYZ(0.0, 0.0, elevation); IFCAnyHandle copyLevelPlacement = ExporterUtil.CopyLocalPlacement(ifcFile, levelObjectPlacement); IFCAnyHandle ifcGrid = IFCInstanceExporter.CreateGrid(ifcFile, gridGUID, ownerHistory, gridName, null, null, copyLevelPlacement, productRep, axesU, axesV, axesW); productWrapper.AddElement(null, ifcGrid, levelInfo, null, true); transaction.Commit(); } } }
/// <summary> /// Export one IFCGrid in one level. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="levelId">The level ID.</param> /// <param name="sameDirectionAxesU">The U axes of grids.</param> /// <param name="sameDirectionAxesV">The V axes of grids.</param> /// <param name="sameDirectionAxesW">The W axes of grids.</param> public static void ExportGrid(ExporterIFC exporterIFC, ElementId levelId, List <Grid> sameDirectionAxesU, List <Grid> sameDirectionAxesV, List <Grid> sameDirectionAxesW) { List <IFCAnyHandle> axesU = null; List <IFCAnyHandle> axesV = null; List <IFCAnyHandle> axesW = null; List <IFCAnyHandle> representations = new List <IFCAnyHandle>(); using (ProductWrapper productWrapper = ProductWrapper.Create(exporterIFC, true)) { IFCFile ifcFile = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(ifcFile)) { GridRepresentationData gridRepresentationData = new GridRepresentationData(); axesU = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesU, representations, gridRepresentationData); axesV = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesV, representations, gridRepresentationData); if (sameDirectionAxesW != null) { axesW = CreateIFCGridAxisAndRepresentations(exporterIFC, productWrapper, sameDirectionAxesW, representations, gridRepresentationData); } IFCAnyHandle contextOfItemsFootPrint = exporterIFC.Get3DContextHandle("FootPrint"); string identifierOpt = "FootPrint"; string representationTypeOpt = "GeometricCurveSet"; int numGridsToExport = gridRepresentationData.m_Grids.Count; if (numGridsToExport == 0) { return; } bool useIFCCADLayer = !string.IsNullOrWhiteSpace(gridRepresentationData.m_IFCCADLayer); IFCAnyHandle shapeRepresentation = null; HashSet <IFCAnyHandle> allCurves = new HashSet <IFCAnyHandle>(); for (int ii = 0; ii < numGridsToExport; ii++) { allCurves.UnionWith(gridRepresentationData.m_curveSets[ii]); } if (useIFCCADLayer) { shapeRepresentation = RepresentationUtil.CreateShapeRepresentation(exporterIFC, contextOfItemsFootPrint, identifierOpt, representationTypeOpt, allCurves, gridRepresentationData.m_IFCCADLayer); } else { ElementId catId = CategoryUtil.GetSafeCategoryId(gridRepresentationData.m_Grids[0]); shapeRepresentation = RepresentationUtil.CreateShapeRepresentation(exporterIFC, gridRepresentationData.m_Grids[0], catId, contextOfItemsFootPrint, identifierOpt, representationTypeOpt, allCurves); } representations.Add(shapeRepresentation); IFCAnyHandle productRep = IFCInstanceExporter.CreateProductDefinitionShape(ifcFile, null, null, representations); // We will associate the grid with its level, unless there are no levels in the file, in which case we'll associate it with the building. IFCLevelInfo levelInfo = ExporterCacheManager.LevelInfoCache.GetLevelInfo(exporterIFC, levelId); bool useLevelInfo = (levelInfo != null); string gridGUID = GUIDUtil.CreateGUID(); // Get the first grid's override name, if cannot find it, use null. string gridName = GetGridName(sameDirectionAxesU, sameDirectionAxesV, sameDirectionAxesW); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; IFCAnyHandle gridLevelHandle = useLevelInfo ? levelInfo.GetBuildingStorey() : ExporterCacheManager.BuildingHandle; IFCAnyHandle levelObjectPlacement = IFCAnyHandleUtil.GetObjectPlacement(gridLevelHandle); double elev = useLevelInfo ? levelInfo.Elevation : 0.0; double elevation = UnitUtil.ScaleLength(elev); XYZ orig = new XYZ(0.0, 0.0, elevation); IFCAnyHandle copyLevelPlacement = ExporterUtil.CopyLocalPlacement(ifcFile, levelObjectPlacement); IFCAnyHandle ifcGrid = IFCInstanceExporter.CreateGrid(ifcFile, gridGUID, ownerHistory, gridName, null, null, copyLevelPlacement, productRep, axesU, axesV, axesW); productWrapper.AddElement(null, ifcGrid, levelInfo, null, true); transaction.Commit(); } } }
/// <summary> /// Create the handle corresponding to the "Axis" IfcRepresentation for a beam, if possible. /// </summary> /// <param name="exporterIFC">The ExporterIFC class.</param> /// <param name="element">The beam element.</param> /// <param name="catId">The beam category id.</param> /// <param name="axisInfo">The optional beam axis information.</param> /// <param name="offsetTransform">The optional offset transform applied to the "Body" representation.</param> /// <returns>The handle, or null if not created.</returns> private static IFCAnyHandle CreateBeamAxis(ExporterIFC exporterIFC, Element element, ElementId catId, BeamAxisInfo axisInfo, Transform offsetTransform) { if (axisInfo == null) { return(null); } Curve curve = axisInfo.Axis; XYZ projDir = axisInfo.AxisNormal; Plane plane = axisInfo.LCSAsPlane; XYZ curveOffset = new XYZ(0, 0, 0); if (offsetTransform != null) { curveOffset = -UnitUtil.UnscaleLength(offsetTransform.Origin); } else { // Note that we do not have to have any scaling adjustment here, since the curve origin is in the // same internal coordinate system as the curve. curveOffset = -plane.Origin; } Plane offsetPlane = new Plane(plane.XVec, plane.YVec, XYZ.Zero); IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, offsetPlane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, curveOffset, true); IList <IFCAnyHandle> axis_items = info.GetCurves(); if (axis_items.Count > 0) { string identifierOpt = "Axis"; // This is by IFC2x2+ convention. string representationTypeOpt = "Curve2D"; // This is by IFC2x2+ convention. IFCAnyHandle axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); return(axisRep); } return(null); }
/// <summary> /// Exports a beam to IFC beam. /// </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 ExportBeam(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { if (geometryElement == null) return; IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { LocationCurve locCurve = element.Location as LocationCurve; Transform orientTrf = Transform.Identity; bool canExportAxis = (locCurve != null); IFCAnyHandle axisRep = null; XYZ beamDirection = null; XYZ projDir = null; Curve curve = null; Plane plane = null; if (canExportAxis) { curve = locCurve.Curve; if (curve is Line) { Line line = curve as Line; XYZ planeY, planeOrig; planeOrig = line.GetEndPoint(0); beamDirection = line.Direction; if (Math.Abs(beamDirection.Z) < 0.707) // approx 1.0/sqrt(2.0) { planeY = XYZ.BasisZ.CrossProduct(beamDirection); } else { planeY = XYZ.BasisX.CrossProduct(beamDirection); } planeY = planeY.Normalize(); projDir = beamDirection.CrossProduct(planeY); plane = new Plane(beamDirection, planeY, planeOrig); orientTrf.BasisX = beamDirection; orientTrf.BasisY = planeY; orientTrf.BasisZ = projDir; orientTrf.Origin = planeOrig; } else if (curve is Arc) { XYZ yDir, center; Arc arc = curve as Arc; beamDirection = arc.XDirection; yDir = arc.YDirection; projDir = arc.Normal; center = arc.Center; plane = new Plane(beamDirection, yDir, center); orientTrf.BasisX = beamDirection; orientTrf.BasisY = yDir; orientTrf.BasisZ = projDir; orientTrf.Origin = center; } else canExportAxis = false; } using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, canExportAxis ? orientTrf : null)) { IFCAnyHandle localPlacement = setter.LocalPlacement; SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); 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; IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> meshes = solidMeshInfo.GetMeshes(); ElementId catId = CategoryUtil.GetSafeCategoryId(element); // The representation handle generated from one of the methods below. IFCAnyHandle repHnd = null; // The list of materials in the solids or meshes. ICollection<ElementId> materialIds = new HashSet<ElementId>(); // 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; // If we have a beam with a Linear location line that only has one solid geometry, // we will try to use the ExtrusionAnalyzer to generate an extrusion with 0 or more clippings. // This code is currently limited in that it will not process beams with openings, so we // use other methods below if this one fails. if (solids.Count == 1 && meshes.Count == 0 && (canExportAxis && (curve is Line))) { bool completelyClipped; beamDirection = orientTrf.BasisX; Plane beamExtrusionPlane = new Plane(orientTrf.BasisY, orientTrf.BasisZ, orientTrf.Origin); repHnd = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, element, catId, solids[0], beamExtrusionPlane, beamDirection, null, out completelyClipped); if (completelyClipped) return; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { // This is used by the BeamSlopeCalculator. This should probably be generated automatically by // CreateExtrusionWithClipping. IFCExtrusionBasis bestAxis = (Math.Abs(beamDirection[0]) > Math.Abs(beamDirection[1])) ? IFCExtrusionBasis.BasisX : IFCExtrusionBasis.BasisY; extrusionCreationData.Slope = GeometryUtil.GetSimpleExtrusionSlope(beamDirection, bestAxis); ElementId materialId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids[0], exporterIFC, element); if (materialId != ElementId.InvalidElementId) materialIds.Add(materialId); } } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); if (solids.Count > 0 || meshes.Count > 0) { bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, solids, meshes, bodyExporterOptions, extrusionCreationData); } else { IList<GeometryObject> geomlist = new List<GeometryObject>(); geomlist.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, geomlist, bodyExporterOptions, extrusionCreationData); } repHnd = bodyData.RepresentationHnd; materialIds = bodyData.MaterialIds; offsetTransform = bodyData.OffsetTransform; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { extrusionCreationData.ClearOpenings(); return; } IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (canExportAxis) { XYZ curveOffset = new XYZ(0, 0, 0); if (offsetTransform != null) curveOffset = -UnitUtil.UnscaleLength(offsetTransform.Origin); else { // Note that we do not have to have any scaling adjustment here, since the curve origin is in the // same internal coordinate system as the curve. curveOffset = -plane.Origin; } Plane offsetPlane = new Plane(plane.XVec, plane.YVec, XYZ.Zero); IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, offsetPlane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, curveOffset, true); IList<IFCAnyHandle> axis_items = info.GetCurves(); if (axis_items.Count > 0) { string identifierOpt = "Axis"; // this is by IFC2x2 convention, not temporary string representationTypeOpt = "Curve2D"; // this is by IFC2x2 convention, not temporary axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); representations.Add(axisRep); } } representations.Add(repHnd); Transform boundingBoxTrf = (offsetTransform == null) ? Transform.Identity : offsetTransform.Inverse; 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); string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); string preDefinedType = "BEAM"; // Default predefined type for Beam preDefinedType = IFCValidateEntry.GetValidIFCType (element, preDefinedType); IFCAnyHandle beam = IFCInstanceExporter.CreateBeam(file, instanceGUID, exporterIFC.GetOwnerHistoryHandle(), instanceName, instanceDescription, instanceObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, instanceTag, preDefinedType); productWrapper.AddElement(element, beam, setter, extrusionCreationData, true); OpeningUtil.CreateOpeningsIfNecessary(beam, element, extrusionCreationData, offsetTransform, exporterIFC, extrusionCreationData.GetLocalPlacement(), setter, productWrapper); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); typeInfo.ScaledDepth = extrusionCreationData.ScaledLength; typeInfo.ScaledArea = extrusionCreationData.ScaledArea; typeInfo.ScaledInnerPerimeter = extrusionCreationData.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extrusionCreationData.ScaledOuterPerimeter; PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, beam, element, typeInfo, null); if (materialIds.Count != 0) { CategoryUtil.CreateMaterialAssociations(exporterIFC, beam, materialIds); } // Register the beam's IFC handle for later use by truss and beam system export. ExporterCacheManager.ElementToHandleCache.Register(element.Id, beam); } } transaction.Commit(); } }
/// <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; 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 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 (IFCPlacementSetter placementSetter = IFCPlacementSetter.Create(exporterIFC, sheet, null, null, ExporterUtil.GetBaseLevelIdForElement(sheet))) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { ecData.SetLocalPlacement(placementSetter.GetPlacement()); ElementId categoryId = CategoryUtil.GetSafeCategoryId(sheet); ElementId materialId = ElementId.InvalidElementId; ParameterUtil.GetElementIdValueFromElementOrSymbol(sheet, BuiltInParameter.MATERIAL_ID_PARAM, out materialId); double scale = exporterIFC.LinearScale; string guid = GUIDUtil.CreateGUID(sheet); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); 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 = majorFabricWireType.WireDiameter * scale; 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 = minorFabricWireType.WireDiameter * scale; double localRadius = transverseBarNominalDiameter / 2.0; transverseBarCrossSectionArea = localRadius * localRadius * Math.PI; } longitudinalBarSpacing = fabricSheetType.MajorSpacing * scale; transverseBarSpacing = fabricSheetType.MinorSpacing * scale; } IList<IFCAnyHandle> bodyItems = new List<IFCAnyHandle>(); IList<Curve> wireCenterlines = sheet.GetWireCenterlines(WireDistributionDirection.Major); foreach (Curve wireCenterline in wireCenterlines) { IFCAnyHandle bodyItem = CreateSweptDiskSolid(exporterIFC, file, wireCenterline, longitudinalBarNominalDiameter); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyItem)) bodyItems.Add(bodyItem); } wireCenterlines = sheet.GetWireCenterlines(WireDistributionDirection.Minor); foreach (Curve wireCenterline in wireCenterlines) { IFCAnyHandle bodyItem = CreateSweptDiskSolid(exporterIFC, file, wireCenterline, transverseBarNominalDiameter); 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.GetLevelInfo(), ecData, true); CategoryUtil.CreateMaterialAssociation(exporterIFC, fabricSheet, materialId); } } tr.Commit(); return true; } }
private static HandleAndAnalyzer CreateExtrusionWithClippingBase(ExporterIFC exporterIFC, Element element, ElementId catId, IList<Solid> solids, Plane plane, XYZ projDir, IFCRange range, out bool completelyClipped, out HashSet<ElementId> materialIds) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { completelyClipped = false; materialIds = new HashSet<ElementId>(); HandleAndAnalyzer retVal = new HandleAndAnalyzer(); HashSet<IFCAnyHandle> extrusionBodyItems = new HashSet<IFCAnyHandle>(); HashSet<IFCAnyHandle> extrusionBooleanBodyItems = new HashSet<IFCAnyHandle>(); HashSet<IFCAnyHandle> extrusionClippingBodyItems = new HashSet<IFCAnyHandle>(); foreach (Solid solid in solids) { bool hasClippingResult = false; bool hasBooleanResult = false; ElementId materialId = ElementId.InvalidElementId; retVal = CreateExtrsionWithClippingAndOpening(exporterIFC, element, catId, solid, plane, projDir, range, out completelyClipped, out hasClippingResult, out hasBooleanResult, out materialId); if (retVal != null && retVal.Handle != null) { materialIds.Add(materialId); IFCAnyHandle repHandle = retVal.Handle; if (hasBooleanResult) // if both have boolean and clipping result, use boolean one. extrusionBooleanBodyItems.Add(repHandle); else if (hasClippingResult) extrusionClippingBodyItems.Add(repHandle); else extrusionBodyItems.Add(repHandle); } else { tr.RollBack(); return retVal; } } IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); if (extrusionBodyItems.Count > 0 && (extrusionClippingBodyItems.Count == 0 && extrusionBooleanBodyItems.Count == 0)) { retVal.Handle = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, catId, contextOfItemsBody, extrusionBodyItems, null); } else if (extrusionClippingBodyItems.Count > 0 && (extrusionBodyItems.Count == 0 && extrusionBooleanBodyItems.Count == 0)) { retVal.Handle = RepresentationUtil.CreateClippingRep(exporterIFC, element, catId, contextOfItemsBody, extrusionClippingBodyItems); } else if (extrusionBooleanBodyItems.Count > 0 && (extrusionBodyItems.Count == 0 && extrusionClippingBodyItems.Count == 0)) { retVal.Handle = RepresentationUtil.CreateCSGRep(exporterIFC, element, catId, contextOfItemsBody, extrusionBooleanBodyItems); } else { IFCAnyHandle finalBodyItemHnd = null; ICollection<IFCAnyHandle> booleanBodyItems = extrusionClippingBodyItems.Union<IFCAnyHandle>(extrusionBooleanBodyItems).ToList(); finalBodyItemHnd = booleanBodyItems.ElementAt(0); booleanBodyItems.Remove(finalBodyItemHnd); // union non-boolean result first with a boolean result foreach (IFCAnyHandle bodyRep in extrusionBodyItems) { finalBodyItemHnd = IFCInstanceExporter.CreateBooleanResult(exporterIFC.GetFile(), IFCBooleanOperator.Union, finalBodyItemHnd, bodyRep); } foreach (IFCAnyHandle bodyRep in booleanBodyItems) { finalBodyItemHnd = IFCInstanceExporter.CreateBooleanResult(exporterIFC.GetFile(), IFCBooleanOperator.Union, finalBodyItemHnd, bodyRep); } extrusionBodyItems.Clear(); extrusionBodyItems.Add(finalBodyItemHnd); retVal.Handle = RepresentationUtil.CreateCSGRep(exporterIFC, element, catId, contextOfItemsBody, extrusionBodyItems); } tr.Commit(); return retVal; } }
private static IFCAnyHandle FallbackTryToCreateAsExtrusion(ExporterIFC exporterIFC, Wall wallElement, SolidMeshGeometryInfo smCapsule, ElementId catId, Curve curve, Plane plane, double depth, IFCRange zSpan, IFCRange range, IFCPlacementSetter setter, out IList<IFCExtrusionData> cutPairOpenings, out bool isCompletelyClipped) { cutPairOpenings = new List<IFCExtrusionData>(); IFCAnyHandle bodyRep; isCompletelyClipped = false; XYZ localOrig = plane.Origin; bool hasExtrusion = HasElevationProfile(wallElement); if (hasExtrusion) { IList<CurveLoop> loops = GetElevationProfile(wallElement); if (loops.Count == 0) hasExtrusion = false; else { IList<IList<CurveLoop>> sortedLoops = ExporterIFCUtils.SortCurveLoops(loops); if (sortedLoops.Count == 0) return null; // Current limitation: can't handle wall split into multiple disjointed pieces. int numSortedLoops = sortedLoops.Count; if (numSortedLoops > 1) return null; bool ignoreExtrusion = true; bool cantHandle = false; bool hasGeometry = false; for (int ii = 0; (ii < numSortedLoops) && !cantHandle; ii++) { int sortedLoopSize = sortedLoops[ii].Count; if (sortedLoopSize == 0) continue; if (!ExporterIFCUtils.IsCurveLoopConvexWithOpenings(sortedLoops[ii][0], wallElement, range, out ignoreExtrusion)) { if (ignoreExtrusion) { // we need more information. Is there something to export? If so, we'll // ignore the extrusion. Otherwise, we will fail. if (smCapsule.SolidsCount() == 0 && smCapsule.MeshesCount() == 0) { continue; } } else { cantHandle = true; } hasGeometry = true; } else { hasGeometry = true; } } if (!hasGeometry) { isCompletelyClipped = true; return null; } if (cantHandle) return null; } } if (!CanExportWallGeometryAsExtrusion(wallElement, range)) return null; // extrusion direction. XYZ extrusionDir = GetWallHeightDirection(wallElement); // create extrusion boundary. IList<CurveLoop> boundaryLoops = new List<CurveLoop>(); bool alwaysThickenCurve = IsWallBaseRectangular(wallElement, curve); if (!alwaysThickenCurve) { boundaryLoops = GetLoopsFromTopBottomFace(wallElement, exporterIFC); if (boundaryLoops.Count == 0) return null; } else { CurveLoop newLoop = CurveLoop.CreateViaThicken(curve, wallElement.Width, XYZ.BasisZ); if (newLoop == null) return null; if (!newLoop.IsCounterclockwise(XYZ.BasisZ)) newLoop = GeometryUtil.ReverseOrientation(newLoop); boundaryLoops.Add(newLoop); } // origin gets scaled later. XYZ setterOffset = new XYZ(0, 0, setter.Offset + (localOrig[2] - setter.BaseOffset)); IFCAnyHandle baseBodyItemHnd = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, boundaryLoops, plane, extrusionDir, depth); if (IFCAnyHandleUtil.IsNullOrHasNoValue(baseBodyItemHnd)) return null; IFCAnyHandle bodyItemHnd = AddClippingsToBaseExtrusion(exporterIFC, wallElement, setterOffset, range, zSpan, baseBodyItemHnd, out cutPairOpenings); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyItemHnd)) return null; IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, wallElement.Document, baseBodyItemHnd, ElementId.InvalidElementId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(bodyItemHnd); IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); if (baseBodyItemHnd.Id == bodyItemHnd.Id) { bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems, null); } else { bodyRep = RepresentationUtil.CreateClippingRep(exporterIFC, wallElement, catId, contextOfItemsBody, bodyItems); } return bodyRep; }
/// <summary> /// Exports a beam to IFC beam. /// </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 ExportBeam(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper productWrapper) { if (geometryElement == null) { return; } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { LocationCurve locCurve = element.Location as LocationCurve; Transform orientTrf = Transform.Identity; bool canExportAxis = (locCurve != null); IFCAnyHandle axisRep = null; XYZ beamDirection = null; XYZ projDir = null; Curve curve = null; Plane plane = null; if (canExportAxis) { curve = locCurve.Curve; if (curve is Line) { Line line = curve as Line; XYZ planeY, planeOrig; planeOrig = line.GetEndPoint(0); beamDirection = line.Direction; if (Math.Abs(beamDirection.Z) < 0.707) // approx 1.0/sqrt(2.0) { planeY = XYZ.BasisZ.CrossProduct(beamDirection); } else { planeY = XYZ.BasisX.CrossProduct(beamDirection); } planeY = planeY.Normalize(); projDir = beamDirection.CrossProduct(planeY); plane = new Plane(beamDirection, planeY, planeOrig); orientTrf.BasisX = beamDirection; orientTrf.BasisY = planeY; orientTrf.BasisZ = projDir; orientTrf.Origin = planeOrig; } else if (curve is Arc) { XYZ yDir, center; Arc arc = curve as Arc; beamDirection = arc.XDirection; yDir = arc.YDirection; projDir = arc.Normal; center = arc.Center; plane = new Plane(beamDirection, yDir, center); orientTrf.BasisX = beamDirection; orientTrf.BasisY = yDir; orientTrf.BasisZ = projDir; orientTrf.Origin = center; } else { canExportAxis = false; } } using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, canExportAxis ? orientTrf : null)) { IFCAnyHandle localPlacement = setter.LocalPlacement; SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); 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; } IList <Solid> solids = solidMeshInfo.GetSolids(); IList <Mesh> meshes = solidMeshInfo.GetMeshes(); ElementId catId = CategoryUtil.GetSafeCategoryId(element); // The representation handle generated from one of the methods below. IFCAnyHandle repHnd = null; // The list of materials in the solids or meshes. ICollection <ElementId> materialIds = new HashSet <ElementId>(); // 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; // If we have a beam with a Linear location line that only has one solid geometry, // we will try to use the ExtrusionAnalyzer to generate an extrusion with 0 or more clippings. // This code is currently limited in that it will not process beams with openings, so we // use other methods below if this one fails. if (solids.Count == 1 && meshes.Count == 0 && (canExportAxis && (curve is Line))) { bool completelyClipped; beamDirection = orientTrf.BasisX; Plane beamExtrusionPlane = new Plane(orientTrf.BasisY, orientTrf.BasisZ, orientTrf.Origin); repHnd = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, element, catId, solids[0], beamExtrusionPlane, beamDirection, null, out completelyClipped); if (completelyClipped) { return; } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { // This is used by the BeamSlopeCalculator. This should probably be generated automatically by // CreateExtrusionWithClipping. IFCExtrusionBasis bestAxis = (Math.Abs(beamDirection[0]) > Math.Abs(beamDirection[1])) ? IFCExtrusionBasis.BasisX : IFCExtrusionBasis.BasisY; extrusionCreationData.Slope = GeometryUtil.GetSimpleExtrusionSlope(beamDirection, bestAxis); ElementId materialId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids[0], exporterIFC, element); if (materialId != ElementId.InvalidElementId) { materialIds.Add(materialId); } } } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); if (solids.Count > 0 || meshes.Count > 0) { bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, solids, meshes, bodyExporterOptions, extrusionCreationData); } else { IList <GeometryObject> geomlist = new List <GeometryObject>(); geomlist.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, geomlist, bodyExporterOptions, extrusionCreationData); } repHnd = bodyData.RepresentationHnd; materialIds = bodyData.MaterialIds; offsetTransform = bodyData.OffsetTransform; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { extrusionCreationData.ClearOpenings(); return; } IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); if (canExportAxis) { XYZ curveOffset = new XYZ(0, 0, 0); if (offsetTransform != null) { curveOffset = -UnitUtil.UnscaleLength(offsetTransform.Origin); } else { // Note that we do not have to have any scaling adjustment here, since the curve origin is in the // same internal coordinate system as the curve. curveOffset = -plane.Origin; } Plane offsetPlane = new Plane(plane.XVec, plane.YVec, XYZ.Zero); IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, offsetPlane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, curveOffset, true); IList <IFCAnyHandle> axis_items = info.GetCurves(); if (axis_items.Count > 0) { string identifierOpt = "Axis"; // this is by IFC2x2 convention, not temporary string representationTypeOpt = "Curve2D"; // this is by IFC2x2 convention, not temporary axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); representations.Add(axisRep); } } representations.Add(repHnd); Transform boundingBoxTrf = (offsetTransform == null) ? Transform.Identity : offsetTransform.Inverse; 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); string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); string preDefinedType = "BEAM"; // Default predefined type for Beam preDefinedType = IFCValidateEntry.GetValidIFCType(element, preDefinedType); IFCAnyHandle beam = IFCInstanceExporter.CreateBeam(file, instanceGUID, exporterIFC.GetOwnerHistoryHandle(), instanceName, instanceDescription, instanceObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, instanceTag, preDefinedType); productWrapper.AddElement(element, beam, setter, extrusionCreationData, true); OpeningUtil.CreateOpeningsIfNecessary(beam, element, extrusionCreationData, offsetTransform, exporterIFC, extrusionCreationData.GetLocalPlacement(), setter, productWrapper); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); typeInfo.ScaledDepth = extrusionCreationData.ScaledLength; typeInfo.ScaledArea = extrusionCreationData.ScaledArea; typeInfo.ScaledInnerPerimeter = extrusionCreationData.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extrusionCreationData.ScaledOuterPerimeter; PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, beam, element, typeInfo, null); if (materialIds.Count != 0) { CategoryUtil.CreateMaterialAssociations(exporterIFC, beam, materialIds); } // Register the beam's IFC handle for later use by truss and beam system export. ExporterCacheManager.ElementToHandleCache.Register(element.Id, beam); } } transaction.Commit(); } }
/// <summary> /// Exports a family instance as a mapped item. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="familyInstance"> /// The family instance to be exported. /// </param> /// <param name="exportType"> /// The export type. /// </param> /// <param name="ifcEnumType"> /// The string value represents the IFC type. /// </param> /// <param name="wrapper"> /// The ProductWrapper. /// </param> /// <param name="overrideLevelId"> /// The level id. /// </param> /// <param name="range"> /// The range of this family instance to be exported. /// </param> public static void ExportFamilyInstanceAsMappedItem(ExporterIFC exporterIFC, FamilyInstance familyInstance, IFCExportType exportType, string ifcEnumType, ProductWrapper wrapper, ElementId overrideLevelId, IFCRange range, IFCAnyHandle parentLocalPlacement) { bool exportParts = PartExporter.CanExportParts(familyInstance); bool isSplit = range != null; if (exportParts && !PartExporter.CanExportElementInPartExport(familyInstance, isSplit ? overrideLevelId : familyInstance.Level.Id, isSplit)) return; Document doc = familyInstance.Document; IFCFile file = exporterIFC.GetFile(); FamilySymbol familySymbol = ExporterIFCUtils.GetOriginalSymbol(familyInstance); if (familySymbol == null) return; ProductWrapper familyProductWrapper = ProductWrapper.Create(wrapper); double scale = exporterIFC.LinearScale; Options options = GeometryUtil.GetIFCExportGeometryOptions(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); HostObject hostElement = familyInstance.Host as HostObject; //hostElement could be null ElementId categoryId = CategoryUtil.GetSafeCategoryId(familySymbol); //string emptyString = ""; string familyName = familySymbol.Name; string objectType = familyName; // A Family Instance can have its own copy of geometry, or use the symbol's copy with a transform. // The routine below tells us whether to use the Instance's copy or the Symbol's copy. bool useInstanceGeometry = ExporterIFCUtils.UsesInstanceGeometry(familyInstance); IList<IFCExtrusionData> cutPairOpeningsForColumns = new List<IFCExtrusionData>(); using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { Transform trf = familyInstance.GetTransform(); // Extra information if we are exporting a door or a window. IFCDoorWindowInfo doorWindowInfo = null; if (exportType == IFCExportType.ExportDoorType) doorWindowInfo = IFCDoorWindowInfo.CreateDoorInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf); else if (exportType == IFCExportType.ExportWindowType) doorWindowInfo = IFCDoorWindowInfo.CreateWindowInfo(exporterIFC, familyInstance, familySymbol, hostElement, overrideLevelId, trf); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); XYZ extraOffset = XYZ.Zero; bool flipped = doorWindowInfo != null ? doorWindowInfo.IsSymbolFlipped : false; FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(familySymbol.Id, flipped); bool found = currentTypeInfo.IsValid(); Family family = familySymbol.Family; // TODO: this code to be removed by ExtrusionAnalyzer code. bool trySpecialColumnCreation = ((exportType == IFCExportType.ExportColumnType) && (!family.IsInPlace)); IList<GeometryObject> geomObjects = new List<GeometryObject>(); Transform brepOffsetTransform = null; Transform doorWindowTrf = Transform.Identity; // We will create a new mapped type if: // 1. We are exporting part of a column or in-place wall (range != null), OR // 2. We are using the instance's copy of the geometry (that it, it has unique geometry), OR // 3. We haven't already created the type. bool creatingType = ((range != null) || useInstanceGeometry || !found); if (creatingType) { IFCAnyHandle bodyRepresentation = null; IFCAnyHandle planRepresentation = null; // If we are using the instance geometry, ignore the transformation. if (useInstanceGeometry) trf = Transform.Identity; // TODO: this code to be removed by ExtrusionAnalyzer code. if (trySpecialColumnCreation) { XYZ rangeOffset = trf.Origin; IFCFamilyInstanceExtrusionExportResults results; results = ExporterIFCUtils.ExportFamilyInstanceAsExtrusion(exporterIFC, familyInstance, useInstanceGeometry, range, overrideLevelId, extraParams); bodyRepresentation = results.GetExtrusionHandle(); extraOffset = results.ExtraOffset; cutPairOpeningsForColumns = results.GetCutPairOpenings(); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation)) { typeInfo.MaterialIds.Add(results.MaterialId); // add in level for real columns, not in-place ones. Element actualLevel = (overrideLevelId == ElementId.InvalidElementId) ? familyInstance.Level : doc.GetElement(overrideLevelId); if (actualLevel != null) { IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(actualLevel.Id); double nonStoryLevelOffset = LevelUtil.GetNonStoryLevelOffsetIfAny(exporterIFC, actualLevel as Level); if (range != null) { rangeOffset = new XYZ(rangeOffset.X, rangeOffset.Y, levelInfo.Elevation + nonStoryLevelOffset); } } } rangeOffset += extraOffset; trf.Origin = rangeOffset; } IFCAnyHandle dummyPlacement = null; if (doorWindowInfo != null) { doorWindowTrf = ExporterIFCUtils.GetTransformForDoorOrWindow(familyInstance, familySymbol, doorWindowInfo); } else { dummyPlacement = IFCInstanceExporter.CreateLocalPlacement(file, null, ExporterUtil.CreateAxis2Placement3D(file)); extraParams.SetLocalPlacement(dummyPlacement); } bool needToCreate2d = ExporterCacheManager.ExportOptionsCache.ExportAnnotations; bool needToCreate3d = IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation); if (needToCreate2d || needToCreate3d) { using (IFCTransformSetter trfSetter = IFCTransformSetter.Create()) { if (doorWindowInfo != null) { trfSetter.Initialize(exporterIFC, doorWindowTrf); } GeometryElement exportGeometry = useInstanceGeometry ? familyInstance.get_Geometry(options) : familySymbol.get_Geometry(options); if (exportGeometry == null) return; if (needToCreate3d) { SolidMeshGeometryInfo solidMeshCapsule = null; if (range == null) { solidMeshCapsule = GeometryUtil.GetSolidMeshGeometry(exportGeometry, Transform.Identity); } else { solidMeshCapsule = GeometryUtil.GetClippedSolidMeshGeometry(exportGeometry, range); } IList<Solid> solids = solidMeshCapsule.GetSolids(); IList<Mesh> polyMeshes = solidMeshCapsule.GetMeshes(); if (range != null && (solids.Count == 0 && polyMeshes.Count == 0)) return; // no proper split geometry geomObjects = FamilyExporterUtil.RemoveSolidsAndMeshesSetToDontExport(doc, exporterIFC, solids, polyMeshes); if (geomObjects.Count == 0 && (solids.Count > 0 || polyMeshes.Count > 0)) return; bool tryToExportAsExtrusion = (!exporterIFC.ExportAs2x2 || (exportType == IFCExportType.ExportColumnType)); if (exportType == IFCExportType.ExportColumnType) { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; if (ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 && solids.Count > 0) { LocationPoint point = familyInstance.Location as LocationPoint; XYZ orig = XYZ.Zero; if (point != null) orig = point.Point; Plane plane = new Plane(XYZ.BasisX, XYZ.BasisY, orig); bool completelyClipped = false; HashSet<ElementId> materialIds = null; bodyRepresentation = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, familyInstance, categoryId, solids, plane, XYZ.BasisZ, null, out completelyClipped, out materialIds); typeInfo.MaterialIds = materialIds; } } else { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryXYZ; } BodyData bodyData = null; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation)) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(tryToExportAsExtrusion); if (geomObjects.Count > 0) { bodyData = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, familyInstance, categoryId, ElementId.InvalidElementId, geomObjects, bodyExporterOptions, extraParams); typeInfo.MaterialIds = bodyData.MaterialIds; } else { IList<GeometryObject> exportedGeometries = new List<GeometryObject>(); exportedGeometries.Add(exportGeometry); bodyData = BodyExporter.ExportBody(familyInstance.Document.Application, exporterIFC, familyInstance, categoryId, ElementId.InvalidElementId, exportedGeometries, bodyExporterOptions, extraParams); } bodyRepresentation = bodyData.RepresentationHnd; brepOffsetTransform = bodyData.BrepOffsetTransform; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepresentation)) { extraParams.ClearOpenings(); return; } } // By default: if exporting IFC2x3 or later, export 2D plan rep of family, if it exists, unless we are exporting Coordination View V2. // This default can be overridden in the export options. if (needToCreate2d) { XYZ curveOffset = new XYZ(0, 0, 0); if (brepOffsetTransform != null) curveOffset = -brepOffsetTransform.Origin / scale; HashSet<IFCAnyHandle> curveSet = new HashSet<IFCAnyHandle>(); { Transform planeTrf = doorWindowTrf.Inverse; Plane plane = new Plane(planeTrf.get_Basis(0), planeTrf.get_Basis(1), planeTrf.Origin); XYZ projDir = new XYZ(0, 0, 1); IFCGeometryInfo IFCGeometryInfo = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, true); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, IFCGeometryInfo, exportGeometry, curveOffset, false); IList<IFCAnyHandle> curves = IFCGeometryInfo.GetCurves(); foreach (IFCAnyHandle curve in curves) curveSet.Add(curve); if (curveSet.Count > 0) { IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle(); IFCAnyHandle curveRepresentationItem = IFCInstanceExporter.CreateGeometricSet(file, curveSet); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(curveRepresentationItem); planRepresentation = RepresentationUtil.CreateGeometricSetRep(exporterIFC, familyInstance, categoryId, "Annotation", contextOfItems2d, bodyItems); } } } } } if (doorWindowInfo != null) { typeInfo.StyleTransform = doorWindowTrf.Inverse; } else { if (!MathUtil.IsAlmostZero(extraOffset.DotProduct(extraOffset))) { Transform newTransform = typeInfo.StyleTransform; XYZ newOrig = newTransform.Origin + extraOffset; newTransform.Origin = newOrig; typeInfo.StyleTransform = newTransform; } typeInfo.StyleTransform = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, extraParams.GetLocalPlacement()); } IFCAnyHandle origin = ExporterUtil.CreateAxis2Placement3D(file); IFCAnyHandle repMap2dHnd = null; IFCAnyHandle repMap3dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, bodyRepresentation); IList<IFCAnyHandle> repMapList = new List<IFCAnyHandle>(); repMapList.Add(repMap3dHnd); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(planRepresentation)) { repMap2dHnd = IFCInstanceExporter.CreateRepresentationMap(file, origin, planRepresentation); repMapList.Add(repMap2dHnd); } // for Door, Window bool paramTakesPrecedence = false; // For Revit, this is currently always false. bool sizeable = false; // for many HashSet<IFCAnyHandle> propertySets = new HashSet<IFCAnyHandle>(); string guid = GUIDUtil.CreateGUID(familySymbol); string symId = NamingUtil.CreateIFCElementId(familySymbol); // This covers many generic types. If we can't find it in the list here, do custom exports. IFCAnyHandle typeStyle = FamilyExporterUtil.ExportGenericType(file, exportType, ifcEnumType, guid, ownerHistory, objectType, null, null, propertySets, repMapList, symId, objectType, familyInstance, familySymbol); // Cover special cases not covered above. if (IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle)) { switch (exportType) { case IFCExportType.ExportColumnType: { // If we are using the instance GRep, then we have to create a generic GUID for the // column type, as they share the same ElementId. string colGUID = null; string colElemId = null; if (useInstanceGeometry) colGUID = GUIDUtil.CreateGUID(); else colGUID = guid; colElemId = NamingUtil.CreateIFCElementId(familySymbol); string columnType = "Column"; typeStyle = IFCInstanceExporter.CreateColumnType(file, colGUID, ownerHistory, objectType, null, null, propertySets, repMapList, colElemId, objectType, GetColumnType(familyInstance, columnType)); break; } case IFCExportType.ExportDoorType: { string constructionType = string.Empty; ParameterUtil.GetStringValueFromElementOrSymbol(familyInstance, "Construction", out constructionType); IFCAnyHandle doorLining = DoorWindowUtil.CreateDoorLiningProperties(exporterIFC, familyInstance); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(doorLining)) propertySets.Add(doorLining); IList<IFCAnyHandle> doorPanels = DoorWindowUtil.CreateDoorPanelProperties(exporterIFC, doorWindowInfo, familyInstance); propertySets.UnionWith(doorPanels); string doorStyleGUID = GUIDUtil.CreateGUID(); string doorStyleElemId = NamingUtil.CreateIFCElementId(familySymbol); typeStyle = IFCInstanceExporter.CreateDoorStyle(file, doorStyleGUID, ownerHistory, objectType, null, null, propertySets, repMapList, doorStyleElemId, GetDoorStyleOperation(doorWindowInfo.DoorOperationType), GetDoorStyleConstruction(familyInstance, constructionType), paramTakesPrecedence, sizeable); break; } case IFCExportType.ExportSystemFurnitureElementType: { string furnitureId = NamingUtil.CreateIFCElementId(familySymbol); typeStyle = IFCInstanceExporter.CreateSystemFurnitureElementType(file, guid, ownerHistory, objectType, null, null, propertySets, repMapList, furnitureId, objectType); break; } case IFCExportType.ExportWindowType: { Toolkit.IFCWindowStyleOperation operationType = DoorWindowUtil.GetIFCWindowStyleOperation(familySymbol); IFCWindowStyleConstruction constructionType = DoorWindowUtil.GetIFCWindowStyleConstruction(familyInstance, ""); IFCAnyHandle windowLining = DoorWindowUtil.CreateWindowLiningProperties(exporterIFC, familyInstance, null); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(windowLining)) propertySets.Add(windowLining); IList<IFCAnyHandle> windowPanels = DoorWindowUtil.CreateWindowPanelProperties(exporterIFC, familyInstance, null); propertySets.UnionWith(windowPanels); string windowStyleGUID = GUIDUtil.CreateGUID(); string windowStyleElemId = NamingUtil.CreateIFCElementId(familySymbol); typeStyle = IFCInstanceExporter.CreateWindowStyle(file, windowStyleGUID, ownerHistory, objectType, null, null, propertySets, repMapList, windowStyleElemId, constructionType, operationType, paramTakesPrecedence, sizeable); break; } case IFCExportType.ExportBuildingElementProxy: default: { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd)) typeInfo.Map2DHandle = repMap2dHnd; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd)) typeInfo.Map3DHandle = repMap3dHnd; break; } } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeStyle)) { CategoryUtil.CreateMaterialAssociations(doc, exporterIFC, typeStyle, typeInfo.MaterialIds); typeInfo.Style = typeStyle; if (((exportType == IFCExportType.ExportColumnType) && trySpecialColumnCreation) || (exportType == IFCExportType.ExportMemberType)) { typeInfo.ScaledArea = extraParams.ScaledArea; typeInfo.ScaledDepth = extraParams.ScaledLength; typeInfo.ScaledInnerPerimeter = extraParams.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extraParams.ScaledOuterPerimeter; } ClassificationUtil.CreateUniformatClassification(exporterIFC, file, familySymbol, typeStyle); } } else if (!creatingType && (trySpecialColumnCreation)) { // still need to modify instance trf for columns. trf.Origin += GetLevelOffsetForExtrudedColumns(exporterIFC, familyInstance, overrideLevelId, extraParams); } if (found && !typeInfo.IsValid()) { typeInfo = currentTypeInfo; } // we'll pretend we succeeded, but we'll do nothing. if (!typeInfo.IsValid()) return; // add to the map, as long as we are not using range, not using instance geometry, and don't have extra openings. if ((range == null) && !useInstanceGeometry && (extraParams.GetOpenings().Count == 0)) ExporterCacheManager.TypeObjectsCache.Register(familySymbol.Id, flipped, typeInfo); Transform oldTrf = new Transform(trf); XYZ scaledMapOrigin = XYZ.Zero; trf = trf.Multiply(typeInfo.StyleTransform); // create instance. IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); { IFCAnyHandle contextOfItems2d = exporterIFC.Get2DContextHandle(); IFCAnyHandle contextOfItems3d = exporterIFC.Get3DContextHandle("Body"); // for proxies, we store the IfcRepresentationMap directly since there is no style. IFCAnyHandle style = typeInfo.Style; IList<IFCAnyHandle> repMapList = !IFCAnyHandleUtil.IsNullOrHasNoValue(style) ? GeometryUtil.GetRepresentationMaps(style) : null; int numReps = repMapList != null ? repMapList.Count : 0; IFCAnyHandle repMap2dHnd = typeInfo.Map2DHandle; IFCAnyHandle repMap3dHnd = typeInfo.Map3DHandle; if (IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd) && (numReps > 0)) repMap3dHnd = repMapList[0]; if (IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd) && (numReps > 1)) repMap2dHnd = repMapList[1]; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap3dHnd)) { IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap3dHnd, scaledMapOrigin)); IFCAnyHandle shapeRep = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, familyInstance, categoryId, contextOfItems3d, representations); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return; shapeReps.Add(shapeRep); } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repMap2dHnd)) { HashSet<IFCAnyHandle> representations = new HashSet<IFCAnyHandle>(); representations.Add(ExporterUtil.CreateDefaultMappedItem(file, repMap2dHnd, scaledMapOrigin)); IFCAnyHandle shapeRep = RepresentationUtil.CreatePlanMappedItemRep(exporterIFC, familyInstance, categoryId, contextOfItems2d, representations); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return; shapeReps.Add(shapeRep); } } IFCAnyHandle boundingBoxRep = null; Transform boundingBoxTrf = (brepOffsetTransform != null) ? brepOffsetTransform.Inverse : Transform.Identity; if (geomObjects.Count > 0) boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomObjects, boundingBoxTrf); else { boundingBoxTrf = boundingBoxTrf.Multiply(trf.Inverse); boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, familyInstance.get_Geometry(options), boundingBoxTrf); } if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); IFCAnyHandle rep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle instanceHandle = null; using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, familyInstance, trf, null, overrideLevelId)) { string instanceGUID = GUIDUtil.CreateGUID(familyInstance); string instanceName = NamingUtil.GetIFCName(familyInstance); string instanceDescription = NamingUtil.GetDescriptionOverride(familyInstance, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(familyInstance, objectType); string instanceElemId = NamingUtil.CreateIFCElementId(familyInstance); IFCAnyHandle localPlacement = setter.GetPlacement(); IFCAnyHandle overrideLocalPlacement = null; if (parentLocalPlacement != null) { Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(parentLocalPlacement, localPlacement); Transform inverseTrf = relTrf.Inverse; IFCAnyHandle relativePlacement = ExporterUtil.CreateAxis2Placement3D(file, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX); IFCAnyHandle plateLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, parentLocalPlacement, relativePlacement); overrideLocalPlacement = plateLocalPlacement; } instanceHandle = FamilyExporterUtil.ExportGenericInstance(exportType, exporterIFC, familyInstance, wrapper, setter, extraParams, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, exportParts ? null : rep, instanceElemId, overrideLocalPlacement); if (exportParts) { PartExporter.ExportHostPart(exporterIFC, familyInstance, instanceHandle, familyProductWrapper, setter, setter.GetPlacement(), overrideLevelId); } if (ElementFilteringUtil.IsMEPType(exportType)) ExporterCacheManager.MEPCache.Register(familyInstance, instanceHandle); switch (exportType) { case IFCExportType.ExportColumnType: { IFCAnyHandle placementToUse = localPlacement; if (!useInstanceGeometry) { bool needToCreateOpenings = (cutPairOpeningsForColumns.Count != 0) || OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams); if (needToCreateOpenings) { Transform openingTrf = new Transform(oldTrf); Transform extraRot = new Transform(oldTrf); extraRot.Origin = XYZ.Zero; openingTrf = openingTrf.Multiply(extraRot); openingTrf = openingTrf.Multiply(typeInfo.StyleTransform); IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, openingTrf.Origin * scale, openingTrf.get_Basis(2), openingTrf.get_Basis(0)); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement); GeometryUtil.SetRelativePlacement(openingPlacement, openingRelativePlacement); placementToUse = openingPlacement; } } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, cutPairOpeningsForColumns, exporterIFC, placementToUse, setter, wrapper); OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, placementToUse, setter, wrapper); //export Base Quantities. PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportDoorType: case IFCExportType.ExportWindowType: { double doorHeight = doorWindowInfo.OpeningHeight; if (doorHeight < MathUtil.Eps()) doorHeight = GetMinSymbolHeight(familySymbol); double doorWidth = doorWindowInfo.OpeningWidth; if (doorWidth < MathUtil.Eps()) doorWidth = GetMinSymbolWidth(familySymbol); double height = doorHeight * scale; double width = doorWidth * scale; if (IFCAnyHandleUtil.IsNullOrHasNoValue(doorWindowInfo.GetLocalPlacement())) doorWindowInfo.SetLocalPlacement(localPlacement); IFCAnyHandle doorWindowOrigLocalPlacement = doorWindowInfo.GetLocalPlacement(); Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(localPlacement, doorWindowOrigLocalPlacement); IFCAnyHandle doorWindowRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, relTrf.Origin, relTrf.BasisZ, relTrf.BasisX); IFCAnyHandle doorWindowLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, doorWindowOrigLocalPlacement, doorWindowRelativePlacement); if (exportType == IFCExportType.ExportDoorType) instanceHandle = IFCInstanceExporter.CreateDoor(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, rep, instanceElemId, height, width); else if (exportType == IFCExportType.ExportWindowType) instanceHandle = IFCInstanceExporter.CreateWindow(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, doorWindowLocalPlacement, rep, instanceElemId, height, width); wrapper.AddElement(instanceHandle, setter, extraParams, true); exporterIFC.RegisterSpaceBoundingElementHandle(instanceHandle, familyInstance.Id, setter.LevelId); IFCAnyHandle placementToUse = doorWindowLocalPlacement; if (!useInstanceGeometry) { // correct the placement to the symbol space bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams); if (needToCreateOpenings) { Transform openingTrf = Transform.Identity; openingTrf.Origin = new XYZ(0, 0, setter.Offset); openingTrf = openingTrf.Multiply(doorWindowTrf); XYZ scaledOrigin = openingTrf.Origin * exporterIFC.LinearScale; IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, scaledOrigin, openingTrf.BasisZ, openingTrf.BasisX); IFCAnyHandle openingLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, doorWindowLocalPlacement, openingRelativePlacement); placementToUse = openingLocalPlacement; } } // only necessary when exporting as possible breps. OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, placementToUse, setter, wrapper); if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) ExporterIFCUtils.CreateDoorWindowBaseQuantities(exporterIFC, instanceHandle, (doorHeight * scale), (doorWidth * scale)); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportMemberType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); //export Base Quantities. PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, instanceHandle, familyInstance, typeInfo); // TODO: create PropertySet! //createMemberPropertySet(exporter, pFamInst, pWrapper, extraParams); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportPlateType: { OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, localPlacement, setter, wrapper); // TODO: create PropertySet! //createPlatePropertySet(exporter, pFamInst, pWrapper, extraParams); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportTransportElementType: { IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); instanceHandle = IFCInstanceExporter.CreateTransportElement(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, rep, instanceElemId, null, null, null); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } case IFCExportType.ExportBuildingElementProxy: default: { bool isBuildingElementProxy = (exportType == IFCExportType.ExportBuildingElementProxy); IFCAnyHandle localPlacementToUse; ElementId roomId = setter.UpdateRoomRelativeCoordinates(familyInstance, out localPlacementToUse); if (!isBuildingElementProxy) { if (FamilyExporterUtil.IsDistributionControlElementSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateDistributionControlElement(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, rep, instanceElemId, null); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } } else if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { isBuildingElementProxy = true; } } if (isBuildingElementProxy) { Toolkit.IFCElementComposition proxyType = Toolkit.IFCElementComposition.Element; instanceHandle = IFCInstanceExporter.CreateBuildingElementProxy(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, rep, instanceElemId, proxyType); if (roomId == ElementId.InvalidElementId) { wrapper.AddElement(instanceHandle, setter, extraParams, true); } else { exporterIFC.RelateSpatialElement(roomId, instanceHandle); wrapper.AddElement(instanceHandle, setter, extraParams, false); } } IFCAnyHandle placementToUse = localPlacement; if (!useInstanceGeometry) { bool needToCreateOpenings = OpeningUtil.NeedToCreateOpenings(instanceHandle, extraParams); if (needToCreateOpenings) { Transform openingTrf = new Transform(oldTrf); Transform extraRot = new Transform(oldTrf); extraRot.Origin = XYZ.Zero; openingTrf = openingTrf.Multiply(extraRot); openingTrf = openingTrf.Multiply(typeInfo.StyleTransform); IFCAnyHandle openingRelativePlacement = ExporterUtil.CreateAxis2Placement3D(file, openingTrf.Origin * scale, openingTrf.get_Basis(2), openingTrf.get_Basis(0)); IFCAnyHandle openingPlacement = ExporterUtil.CopyLocalPlacement(file, localPlacement); GeometryUtil.SetRelativePlacement(openingPlacement, openingRelativePlacement); placementToUse = openingPlacement; } } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, familyInstance, extraParams, exporterIFC, placementToUse, setter, wrapper); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, familyInstance, wrapper); break; } } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { if (doorWindowInfo != null) { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(doorWindowInfo.GetOpening())) { string relGUID = GUIDUtil.CreateGUID(); IFCInstanceExporter.CreateRelFillsElement(file, relGUID, ownerHistory, null, null, doorWindowInfo.GetOpening(), instanceHandle); } else if (doorWindowInfo.NeedsOpening) { bool added = doorWindowInfo.SetDelayedFamilyInstance(instanceHandle, localPlacement, doorWindowInfo.AssignedLevelId); if (added) exporterIFC.RegisterDoorWindowForOpeningUpdate(doorWindowInfo); else { // we need to fill a later opening. exporterIFC.RegisterDoorWindowForUncreatedOpening(familyInstance.Id, instanceHandle); } } } if (!exportParts) CategoryUtil.CreateMaterialAssociations(doc, exporterIFC, instanceHandle, typeInfo.MaterialIds); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(typeInfo.Style)) ExporterCacheManager.TypeRelationsCache.Add(typeInfo.Style, instanceHandle); } } } }
/// <summary> /// Exports list of geometries to IFC body representation. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="categoryId">The category id.</param> /// <param name="geometryListIn">The geometry list.</param> /// <param name="options">The settings for how to export the body.</param> /// <param name="exportBodyParams">The extrusion creation data.</param> /// <returns>The BodyData containing the handle, offset and material ids.</returns> public static BodyData ExportBody(ExporterIFC exporterIFC, Element element, ElementId categoryId, ElementId overrideMaterialId, IList<GeometryObject> geometryList, BodyExporterOptions options, IFCExtrusionCreationData exportBodyParams) { BodyData bodyData = new BodyData(); if (geometryList.Count == 0) return bodyData; Document document = element.Document; bool tryToExportAsExtrusion = options.TryToExportAsExtrusion; bool canExportSolidModelRep = tryToExportAsExtrusion && ExporterCacheManager.ExportOptionsCache.CanExportSolidModelRep; bool useCoarseTessellation = (ExporterCacheManager.ExportOptionsCache.LevelOfDetail < 4); bool allowAdvancedBReps = ExporterCacheManager.ExportOptionsCache.ExportAs4 && !ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView; // We will try to export as a swept solid if the option is set, and we are either exporting to a schema that allows it, // or we are using a coarse tessellation, in which case we will export the swept solid as an optimzed BRep. bool tryToExportAsSweptSolid = options.TryToExportAsSweptSolid && (allowAdvancedBReps || useCoarseTessellation); // We will allow exporting swept solids as BReps or TriangulatedFaceSet if we are exporting to a schema before IFC4, or to a Reference View MVD, // and we allow coarse representations. In the future, we may allow more control here. // Note that we disable IFC4 because in IFC4, we will export it as a true swept solid instead, except for the Reference View MVD. bool tryToExportAsSweptSolidAsTessellation = tryToExportAsSweptSolid && useCoarseTessellation && !allowAdvancedBReps; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); double eps = UnitUtil.ScaleLength(element.Document.Application.VertexTolerance); bool allFaces = true; foreach (GeometryObject geomObject in geometryList) { if (!(geomObject is Face)) { allFaces = false; break; } } IList<IFCAnyHandle> bodyItems = new List<IFCAnyHandle>(); IList<ElementId> materialIdsForExtrusions = new List<ElementId>(); // This is a list of geometries that can be exported using the coarse facetation of the SweptSolidExporter. IList<KeyValuePair<int, SimpleSweptSolidAnalyzer>> exportAsBRep = new List<KeyValuePair<int, SimpleSweptSolidAnalyzer>>(); IList<int> exportAsSweptSolid = new List<int>(); IList<int> exportAsExtrusion = new List<int>(); bool hasExtrusions = false; bool hasSweptSolids = false; bool hasSweptSolidsAsBReps = false; ShapeRepresentationType hasRepresentationType = ShapeRepresentationType.Undefined; BoundingBoxXYZ bbox = GeometryUtil.GetBBoxOfGeometries(geometryList); XYZ unscaledTrfOrig = new XYZ(); int numItems = geometryList.Count; bool tryExtrusionAnalyzer = tryToExportAsExtrusion && (options.ExtrusionLocalCoordinateSystem != null) && (numItems == 1) && (geometryList[0] is Solid); bool supportOffsetTransformForExtrusions = !(tryExtrusionAnalyzer || tryToExportAsSweptSolidAsTessellation); bool useOffsetTransformForExtrusions = (options.AllowOffsetTransform && supportOffsetTransformForExtrusions && (exportBodyParams != null)); using (IFCTransaction tr = new IFCTransaction(file)) { // generate "bottom corner" of bbox; create new local placement if passed in. // need to transform, but not scale, this point to make it the new origin. using (TransformSetter transformSetter = TransformSetter.Create()) { if (useOffsetTransformForExtrusions) bodyData.OffsetTransform = transformSetter.InitializeFromBoundingBox(exporterIFC, bbox, exportBodyParams, out unscaledTrfOrig); // If we passed in an ExtrusionLocalCoordinateSystem, and we have 1 Solid, we will try to create an extrusion using the ExtrusionAnalyzer. // If we succeed, we will skip the rest of the routine, otherwise we will try with the backup extrusion method. // This doesn't yet create fallback information for solid models that are hybrid extrusions and BReps. if (tryToExportAsExtrusion) { if (tryExtrusionAnalyzer) { using (IFCTransaction extrusionTransaction = new IFCTransaction(file)) { Plane extrusionPlane = new Plane( options.ExtrusionLocalCoordinateSystem.BasisY, options.ExtrusionLocalCoordinateSystem.BasisZ, options.ExtrusionLocalCoordinateSystem.Origin); XYZ extrusionDirection = options.ExtrusionLocalCoordinateSystem.BasisX; bool completelyClipped; HandleAndData extrusionData = ExtrusionExporter.CreateExtrusionWithClippingAndProperties(exporterIFC, element, CategoryUtil.GetSafeCategoryId(element), geometryList[0] as Solid, extrusionPlane, extrusionDirection, null, out completelyClipped); if (!completelyClipped && !IFCAnyHandleUtil.IsNullOrHasNoValue(extrusionData.Handle) && extrusionData.BaseExtrusions != null && extrusionData.BaseExtrusions.Count == 1) { HashSet<ElementId> materialIds = extrusionData.MaterialIds; // We skip setting and getting the material id from the exporter as unnecessary. ElementId matIdFromGeom = (materialIds != null && materialIds.Count > 0) ? materialIds.First() : ElementId.InvalidElementId; ElementId matId = (overrideMaterialId != ElementId.InvalidElementId) ? overrideMaterialId : matIdFromGeom; bodyItems.Add(extrusionData.BaseExtrusions[0]); materialIdsForExtrusions.Add(matId); if (matId != ElementId.InvalidElementId) bodyData.AddMaterial(matId); bodyData.RepresentationHnd = extrusionData.Handle; bodyData.ShapeRepresentationType = extrusionData.ShapeRepresentationType; if (exportBodyParams != null && extrusionData.Data != null) { exportBodyParams.Slope = extrusionData.Data.Slope; exportBodyParams.ScaledLength = extrusionData.Data.ScaledLength; exportBodyParams.ExtrusionDirection = extrusionData.Data.ExtrusionDirection; exportBodyParams.ScaledHeight = extrusionData.Data.ScaledHeight; exportBodyParams.ScaledWidth = extrusionData.Data.ScaledWidth; exportBodyParams.ScaledArea = extrusionData.Data.ScaledArea; exportBodyParams.ScaledInnerPerimeter = extrusionData.Data.ScaledInnerPerimeter; exportBodyParams.ScaledOuterPerimeter = extrusionData.Data.ScaledOuterPerimeter; } hasExtrusions = true; extrusionTransaction.Commit(); } else { extrusionTransaction.RollBack(); } } } // Only try if ExtrusionAnalyzer wasn't called, or failed. if (!hasExtrusions) { // Check to see if we have Geometries or GFaces. // We will have the specific all GFaces case and then the generic case. IList<Face> faces = null; if (allFaces) { faces = new List<Face>(); foreach (GeometryObject geometryObject in geometryList) { faces.Add(geometryObject as Face); } } // Options used if we try to export extrusions. IFCExtrusionAxes axesToExtrudeIn = exportBodyParams != null ? exportBodyParams.PossibleExtrusionAxes : IFCExtrusionAxes.TryDefault; XYZ directionToExtrudeIn = XYZ.Zero; if (exportBodyParams != null && exportBodyParams.HasCustomAxis) directionToExtrudeIn = exportBodyParams.CustomAxis; double lengthScale = UnitUtil.ScaleLengthForRevitAPI(); IFCExtrusionCalculatorOptions extrusionOptions = new IFCExtrusionCalculatorOptions(exporterIFC, axesToExtrudeIn, directionToExtrudeIn, lengthScale); int numExtrusionsToCreate = allFaces ? 1 : geometryList.Count; IList<IList<IFCExtrusionData>> extrusionLists = new List<IList<IFCExtrusionData>>(); for (int ii = 0; ii < numExtrusionsToCreate; ii++) { IList<IFCExtrusionData> extrusionList = new List<IFCExtrusionData>(); if (tryToExportAsExtrusion) { if (allFaces) extrusionList = IFCExtrusionCalculatorUtils.CalculateExtrusionData(extrusionOptions, faces); else extrusionList = IFCExtrusionCalculatorUtils.CalculateExtrusionData(extrusionOptions, geometryList[ii]); } if (extrusionList.Count == 0) { // If we are trying to create swept solids, we will keep going, but we won't try to create more extrusions unless we are also exporting a solid model. if (tryToExportAsSweptSolid) { if (!canExportSolidModelRep) tryToExportAsExtrusion = false; exportAsSweptSolid.Add(ii); } else if (!canExportSolidModelRep) { tryToExportAsExtrusion = false; break; } else exportAsBRep.Add(new KeyValuePair<int, SimpleSweptSolidAnalyzer>(ii, null)); } else { extrusionLists.Add(extrusionList); exportAsExtrusion.Add(ii); } } int numCreatedExtrusions = extrusionLists.Count; for (int ii = 0; ii < numCreatedExtrusions && tryToExportAsExtrusion; ii++) { int geomIndex = exportAsExtrusion[ii]; ElementId matId = SetBestMaterialIdInExporter(geometryList[geomIndex], element, overrideMaterialId, exporterIFC); if (matId != ElementId.InvalidElementId) bodyData.AddMaterial(matId); if (exportBodyParams != null && exportBodyParams.AreInnerRegionsOpenings) { IList<CurveLoop> curveLoops = extrusionLists[ii][0].GetLoops(); XYZ extrudedDirection = extrusionLists[ii][0].ExtrusionDirection; int numLoops = curveLoops.Count; for (int jj = numLoops - 1; jj > 0; jj--) { ExtrusionExporter.AddOpeningData(exportBodyParams, extrusionLists[ii][0], curveLoops[jj]); extrusionLists[ii][0].RemoveLoopAt(jj); } } bool exportedAsExtrusion = false; IFCExtrusionBasis whichBasis = extrusionLists[ii][0].ExtrusionBasis; if (whichBasis >= 0) { IFCAnyHandle extrusionHandle = ExtrusionExporter.CreateExtrudedSolidFromExtrusionData(exporterIFC, element, extrusionLists[ii][0]); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(extrusionHandle)) { bodyItems.Add(extrusionHandle); materialIdsForExtrusions.Add(exporterIFC.GetMaterialIdForCurrentExportState()); IList<CurveLoop> curveLoops = extrusionLists[ii][0].GetLoops(); XYZ extrusionDirection = extrusionLists[ii][0].ExtrusionDirection; if (exportBodyParams != null) { exportBodyParams.Slope = GeometryUtil.GetSimpleExtrusionSlope(extrusionDirection, whichBasis); exportBodyParams.ScaledLength = extrusionLists[ii][0].ScaledExtrusionLength; exportBodyParams.ExtrusionDirection = extrusionDirection; for (int kk = 1; kk < extrusionLists[ii].Count; kk++) { ExtrusionExporter.AddOpeningData(exportBodyParams, extrusionLists[ii][kk]); } Plane plane = null; double height = 0.0, width = 0.0; if (ExtrusionExporter.ComputeHeightWidthOfCurveLoop(curveLoops[0], plane, out height, out width)) { exportBodyParams.ScaledHeight = UnitUtil.ScaleLength(height); exportBodyParams.ScaledWidth = UnitUtil.ScaleLength(width); } double area = ExporterIFCUtils.ComputeAreaOfCurveLoops(curveLoops); if (area > 0.0) { exportBodyParams.ScaledArea = UnitUtil.ScaleArea(area); } double innerPerimeter = ExtrusionExporter.ComputeInnerPerimeterOfCurveLoops(curveLoops); double outerPerimeter = ExtrusionExporter.ComputeOuterPerimeterOfCurveLoops(curveLoops); if (innerPerimeter > 0.0) exportBodyParams.ScaledInnerPerimeter = UnitUtil.ScaleLength(innerPerimeter); if (outerPerimeter > 0.0) exportBodyParams.ScaledOuterPerimeter = UnitUtil.ScaleLength(outerPerimeter); } exportedAsExtrusion = true; hasExtrusions = true; } } if (!exportedAsExtrusion) { if (tryToExportAsSweptSolid) exportAsSweptSolid.Add(ii); else if (!canExportSolidModelRep) { tryToExportAsExtrusion = false; break; } else exportAsBRep.Add(new KeyValuePair<int, SimpleSweptSolidAnalyzer>(ii, null)); } } } } if (tryToExportAsSweptSolid) { int numCreatedSweptSolids = exportAsSweptSolid.Count; for (int ii = 0; (ii < numCreatedSweptSolids) && tryToExportAsSweptSolid; ii++) { bool exported = false; int geomIndex = exportAsSweptSolid[ii]; Solid solid = geometryList[geomIndex] as Solid; SimpleSweptSolidAnalyzer simpleSweptSolidAnalyzer = null; // TODO: allFaces to SweptSolid if (solid != null) { // TODO: give normal hint below if we have an idea. simpleSweptSolidAnalyzer = SweptSolidExporter.CanExportAsSweptSolid(exporterIFC, solid, null); // If we are exporting as a BRep, we will keep the analyzer for later, if it isn't null. if (simpleSweptSolidAnalyzer != null) { if (!tryToExportAsSweptSolidAsTessellation) { SweptSolidExporter sweptSolidExporter = SweptSolidExporter.Create(exporterIFC, element, simpleSweptSolidAnalyzer, solid); IFCAnyHandle sweptHandle = (sweptSolidExporter != null) ? sweptSolidExporter.RepresentationItem : null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(sweptHandle)) { bodyItems.Add(sweptHandle); materialIdsForExtrusions.Add(exporterIFC.GetMaterialIdForCurrentExportState()); exported = true; hasRepresentationType = sweptSolidExporter.RepresentationType; // These are the only two valid cases for true sweep export: either an extrusion or a sweep. // We don't expect regular BReps or triangulated face sets here. if (sweptSolidExporter.isSpecificRepresentationType(ShapeRepresentationType.SweptSolid)) hasExtrusions = true; else if (sweptSolidExporter.isSpecificRepresentationType(ShapeRepresentationType.AdvancedSweptSolid)) hasSweptSolids = true; } else simpleSweptSolidAnalyzer = null; // Didn't work for some reason. } } } if (!exported) { exportAsBRep.Add(new KeyValuePair<int, SimpleSweptSolidAnalyzer>(geomIndex, simpleSweptSolidAnalyzer)); hasSweptSolidsAsBReps |= (simpleSweptSolidAnalyzer != null); } } } bool exportSucceeded = (exportAsBRep.Count == 0) && (tryToExportAsExtrusion || tryToExportAsSweptSolid) && (hasExtrusions || hasSweptSolids || hasRepresentationType != ShapeRepresentationType.Undefined); if (exportSucceeded || canExportSolidModelRep) { int sz = bodyItems.Count(); for (int ii = 0; ii < sz; ii++) BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, bodyItems[ii], materialIdsForExtrusions[ii]); if (exportSucceeded) { if (bodyData.RepresentationHnd == null) { HashSet<IFCAnyHandle> bodyItemSet = new HashSet<IFCAnyHandle>(); bodyItemSet.UnionWith(bodyItems); if (hasExtrusions && !hasSweptSolids) { bodyData.RepresentationHnd = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, categoryId, contextOfItems, bodyItemSet, bodyData.RepresentationHnd); bodyData.ShapeRepresentationType = ShapeRepresentationType.SweptSolid; } else if (hasSweptSolids && !hasExtrusions) { bodyData.RepresentationHnd = RepresentationUtil.CreateAdvancedSweptSolidRep(exporterIFC, element, categoryId, contextOfItems, bodyItemSet, bodyData.RepresentationHnd); bodyData.ShapeRepresentationType = ShapeRepresentationType.AdvancedSweptSolid; } else if (hasRepresentationType == ShapeRepresentationType.Tessellation) { bodyData.RepresentationHnd = RepresentationUtil.CreateTessellatedRep(exporterIFC, element, categoryId, contextOfItems, bodyItemSet, bodyData.RepresentationHnd); bodyData.ShapeRepresentationType = ShapeRepresentationType.Tessellation; } else { bodyData.RepresentationHnd = RepresentationUtil.CreateSolidModelRep(exporterIFC, element, categoryId, contextOfItems, bodyItemSet); bodyData.ShapeRepresentationType = ShapeRepresentationType.SolidModel; } } // TODO: include BRep, CSG, Clipping XYZ lpOrig = ((bodyData != null) && (bodyData.OffsetTransform != null)) ? bodyData.OffsetTransform.Origin : new XYZ(); transformSetter.CreateLocalPlacementFromOffset(exporterIFC, bbox, exportBodyParams, lpOrig, unscaledTrfOrig); tr.Commit(); return bodyData; } } // If we are going to export a solid model, keep the created items. if (!canExportSolidModelRep) tr.RollBack(); else tr.Commit(); } // We couldn't export it as an extrusion; export as a solid, brep, or a surface model. if (!canExportSolidModelRep) { exportAsExtrusion.Clear(); bodyItems.Clear(); if (exportBodyParams != null) exportBodyParams.ClearOpenings(); } if (exportAsExtrusion.Count == 0) { // We used to clear exportAsBRep, but we need the SimpleSweptSolidAnalyzer information, so we will fill out the rest. int numGeoms = geometryList.Count; IList<KeyValuePair<int, SimpleSweptSolidAnalyzer>> newExportAsBRep = new List<KeyValuePair<int, SimpleSweptSolidAnalyzer>>(numGeoms); int exportAsBRepCount = exportAsBRep.Count; int currIndex = 0; for (int ii = 0; ii < numGeoms; ii++) { if ((currIndex < exportAsBRepCount) && (ii == exportAsBRep[currIndex].Key)) { newExportAsBRep.Add(exportAsBRep[currIndex]); currIndex++; } else newExportAsBRep.Add(new KeyValuePair<int, SimpleSweptSolidAnalyzer>(ii, null)); } exportAsBRep = newExportAsBRep; } } // If we created some extrusions that we are using (e.g., creating a solid model), and we didn't use an offset transform for the extrusions, don't do it here either. bool supportOffsetTransformForBreps = !hasSweptSolidsAsBReps; bool disallowOffsetTransformForBreps = (exportAsExtrusion.Count > 0) && !useOffsetTransformForExtrusions; bool useOffsetTransformForBReps = options.AllowOffsetTransform && supportOffsetTransformForBreps && !disallowOffsetTransformForBreps; using (IFCTransaction tr = new IFCTransaction(file)) { using (TransformSetter transformSetter = TransformSetter.Create()) { // Need to do extra work to support offset transforms if we are using the sweep analyzer. if (useOffsetTransformForBReps) bodyData.OffsetTransform = transformSetter.InitializeFromBoundingBox(exporterIFC, bbox, exportBodyParams, out unscaledTrfOrig); BodyData brepBodyData = ExportBodyAsBRep(exporterIFC, geometryList, exportAsBRep, bodyItems, element, categoryId, overrideMaterialId, contextOfItems, eps, options, bodyData); if (brepBodyData == null) tr.RollBack(); else { XYZ lpOrig = ((bodyData != null) && (bodyData.OffsetTransform != null)) ? bodyData.OffsetTransform.Origin : new XYZ(); transformSetter.CreateLocalPlacementFromOffset(exporterIFC, bbox, exportBodyParams, lpOrig, unscaledTrfOrig); tr.Commit(); } return brepBodyData; } } }
/// <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 subSlabType = null; IFCExportInfoPair roofExportType = ExporterUtil.GetProductExportType(exporterIFC, element, out _); if (roofExportType.IsUnKnown) { IFCEntityType elementClassTypeEnum = elementIsFloor ? IFCEntityType.IfcSlab: IFCEntityType.IfcRoof; roofExportType = new IFCExportInfoPair(elementClassTypeEnum, ""); } else { if (elementIsFloor) { subSlabType = "FLOOR"; } else if (elementIsRoof) { subSlabType = "ROOF"; } } // 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)) { using (IFCTransaction transaction = new IFCTransaction(file)) { MaterialLayerSetInfo layersetInfo = new MaterialLayerSetInfo(exporterIFC, element, productWrapper); bool hasLayers = false; if (layersetInfo.MaterialIds.Count > 1) { hasLayers = true; } bool exportByComponents = ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView && hasLayers; // 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; 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 prodDefShape = 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, false, itemShapeRep, matId); bodyItems.Add(itemShapeRep); } else { double scaleProj = extrusionDir.DotProduct(plane.Normal); foreach (MaterialLayerSetInfo.MaterialInfo matLayerInfo in layersetInfo.MaterialIds) { double itemExtrDepth = matLayerInfo.m_matWidth; IFCAnyHandle itemShapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, lcs, extrusionDir, itemExtrDepth, false); if (IFCAnyHandleUtil.IsNullOrHasNoValue(itemShapeRep)) { productWrapper.ClearInternalHandleWrapperData(element); return(null); } BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, element.Document, false, itemShapeRep, matLayerInfo.m_baseMatId); bodyItems.Add(itemShapeRep); RepresentationUtil.CreateRepForShapeAspect(exporterIFC, element, prodDefShape, representationType, matLayerInfo.m_layerName, itemShapeRep); 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(prodDefShape, "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, prodDefShape, 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, subSlabType); productWrapper.AddElement(null, slabHnd, setter, slabExtrusionCreationData, false, slabRoofExportType); // Create type IFCAnyHandle slabRoofTypeHnd = ExporterUtil.CreateGenericTypeFromElement(element, slabRoofExportType, exporterIFC.GetFile(), ownerHistory, subSlabType, 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(); } } } } }
private static HandleAndAnalyzer CreateExtrusionWithClippingBase(ExporterIFC exporterIFC, Element element, ElementId catId, IList<Solid> solids, Plane plane, XYZ projDir, IFCRange range, out bool completelyClipped, out HashSet<ElementId> materialIds) { IFCFile file = exporterIFC.GetFile(); bool mustUseTessellation = false; using (IFCTransaction tr = new IFCTransaction(file)) { completelyClipped = false; materialIds = new HashSet<ElementId>(); HandleAndAnalyzer retVal = new HandleAndAnalyzer(); HashSet<IFCAnyHandle> extrusionBodyItems = new HashSet<IFCAnyHandle>(); HashSet<IFCAnyHandle> extrusionBooleanBodyItems = new HashSet<IFCAnyHandle>(); HashSet<IFCAnyHandle> extrusionClippingBodyItems = new HashSet<IFCAnyHandle>(); foreach (Solid solid in solids) { bool hasClippingResult = false; bool hasBooleanResult = false; ElementId materialId = ElementId.InvalidElementId; HandleAndAnalyzer currRetVal = CreateExtrusionWithClippingAndOpening(exporterIFC, element, catId, solid, plane, projDir, range, out completelyClipped, out hasClippingResult, out hasBooleanResult, out materialId); if (currRetVal != null && currRetVal.Handle != null) { // If any of the solid is of the type of Clipping or Boolean and export is for Reference View, exit the loop and collect the geometries entirely // for TriangulatedFaceSet if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView && (hasClippingResult || hasBooleanResult)) { mustUseTessellation = true; break; } materialIds.Add(materialId); IFCAnyHandle repHandle = currRetVal.Handle; if (hasBooleanResult) // if both have boolean and clipping result, use boolean one. extrusionBooleanBodyItems.Add(repHandle); else if (hasClippingResult) extrusionClippingBodyItems.Add(repHandle); else extrusionBodyItems.Add(repHandle); } else { tr.RollBack(); // TODO: include this cleanup in RollBack(), to avoid issues. ExporterCacheManager.MaterialIdToStyleHandleCache.RemoveInvalidHandles(materialIds, IFCEntityType.IfcSurfaceStyle); ExporterCacheManager.PresentationStyleAssignmentCache.RemoveInvalidHandles(materialIds); return retVal; } // currRetVal will only have one extrusion. Use the analyzer from the "last" extrusion. Should only really be used for one extrusion. retVal.Analyzer = currRetVal.Analyzer; retVal.BaseExtrusions.Add(currRetVal.BaseExtrusions[0]); } IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); // Handle Tessellation here for Reference View export. If all are extrusions, it should not get in here if (mustUseTessellation) { BodyExporterOptions options = new BodyExporterOptions(true); Document document = element.Document; ElementId materialId = ElementId.InvalidElementId; materialIds.Clear(); extrusionBodyItems.Clear(); foreach (Solid solid in solids) { IFCAnyHandle triangulatedBodyItem = BodyExporter.ExportBodyAsTriangulatedFaceSet(exporterIFC, element, options, solid); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(triangulatedBodyItem)) extrusionBodyItems.Add(triangulatedBodyItem); materialId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solid, exporterIFC, element); materialIds.Add(materialId); BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, triangulatedBodyItem, materialId); } retVal.Handle = RepresentationUtil.CreateTessellatedRep(exporterIFC, element, catId, contextOfItemsBody, extrusionBodyItems, null); retVal.ShapeRepresentationType = ShapeRepresentationType.Tessellation; } else { if (extrusionBodyItems.Count > 0 && (extrusionClippingBodyItems.Count == 0 && extrusionBooleanBodyItems.Count == 0)) { retVal.Handle = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, catId, contextOfItemsBody, extrusionBodyItems, null); retVal.ShapeRepresentationType = ShapeRepresentationType.SweptSolid; } else if (extrusionClippingBodyItems.Count > 0 && (extrusionBodyItems.Count == 0 && extrusionBooleanBodyItems.Count == 0)) { retVal.Handle = RepresentationUtil.CreateClippingRep(exporterIFC, element, catId, contextOfItemsBody, extrusionClippingBodyItems); retVal.ShapeRepresentationType = ShapeRepresentationType.Clipping; } else if (extrusionBooleanBodyItems.Count > 0 && (extrusionBodyItems.Count == 0 && extrusionClippingBodyItems.Count == 0)) { retVal.Handle = RepresentationUtil.CreateCSGRep(exporterIFC, element, catId, contextOfItemsBody, extrusionBooleanBodyItems); retVal.ShapeRepresentationType = ShapeRepresentationType.CSG; } else { IFCAnyHandle finalBodyItemHnd = null; ICollection<IFCAnyHandle> booleanBodyItems = extrusionClippingBodyItems.Union<IFCAnyHandle>(extrusionBooleanBodyItems).ToList(); finalBodyItemHnd = booleanBodyItems.ElementAt(0); booleanBodyItems.Remove(finalBodyItemHnd); // union non-boolean result first with a boolean result foreach (IFCAnyHandle bodyRep in extrusionBodyItems) { finalBodyItemHnd = IFCInstanceExporter.CreateBooleanResult(exporterIFC.GetFile(), IFCBooleanOperator.Union, finalBodyItemHnd, bodyRep); } foreach (IFCAnyHandle bodyRep in booleanBodyItems) { finalBodyItemHnd = IFCInstanceExporter.CreateBooleanResult(exporterIFC.GetFile(), IFCBooleanOperator.Union, finalBodyItemHnd, bodyRep); } extrusionBodyItems.Clear(); extrusionBodyItems.Add(finalBodyItemHnd); retVal.Handle = RepresentationUtil.CreateCSGRep(exporterIFC, element, catId, contextOfItemsBody, extrusionBodyItems); retVal.ShapeRepresentationType = ShapeRepresentationType.CSG; } } tr.Commit(); return retVal; } }
/// <summary> /// Exports a Rebar to IFC ReinforcingMesh. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element to be exported. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportRebar(ExporterIFC exporterIFC, Element element, Autodesk.Revit.DB.View filterView, ProductWrapper productWrapper) { try { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element)) { if (element is Rebar) { GeometryElement rebarGeometry = ExporterIFCUtils.GetRebarGeometry(element as Rebar, filterView); // only options are: Not Export, BuildingElementProxy, or ReinforcingBar/Mesh, depending on layout. // Not Export is handled previously, and ReinforcingBar vs Mesh will be determined below. string ifcEnumType; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, element, out ifcEnumType); if (exportType == IFCExportType.ExportBuildingElementProxy) { if (rebarGeometry != null) { ProxyElementExporter.ExportBuildingElementProxy(exporterIFC, element, rebarGeometry, productWrapper); transaction.Commit(); } return; } } IFCAnyHandle prodRep = null; double scale = exporterIFC.LinearScale; double totalBarLengthUnscale = GetRebarTotalLength(element); double volumeUnscale = GetRebarVolume(element); double totalBarLength = totalBarLengthUnscale * scale; if (MathUtil.IsAlmostZero(totalBarLength)) return; ElementId typeId = element.GetTypeId(); RebarBarType elementType = element.Document.GetElement(element.GetTypeId()) as RebarBarType; double diameter = (elementType == null ? 1.0 / 12.0 : elementType.BarDiameter) * scale; double radius = diameter / 2.0; double longitudinalBarNominalDiameter = diameter; double longitudinalBarCrossSectionArea = (volumeUnscale / totalBarLengthUnscale) * scale * scale; double barLength = totalBarLength / GetRebarQuantity(element); IList<Curve> baseCurves = GetRebarCenterlineCurves(element, true, false, false); int numberOfBarPositions = GetNumberOfBarPositions(element); for (int i = 0; i < numberOfBarPositions; i++) { if (!DoesBarExistAtPosition(element, i)) continue; Transform barTrf = GetBarPositionTransform(element, i); IList<Curve> curves = new List<Curve>(); foreach (Curve baseCurve in baseCurves) { curves.Add(baseCurve.get_Transformed(barTrf)); } IFCAnyHandle compositeCurve = GeometryUtil.CreateCompositeCurve(exporterIFC, curves); IFCAnyHandle sweptDiskSolid = IFCInstanceExporter.CreateSweptDiskSolid(file, compositeCurve, radius, null, 0, 1); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(sweptDiskSolid); ElementId categoryId = CategoryUtil.GetSafeCategoryId(element); IFCAnyHandle shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, categoryId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); string steelGradeOpt = null; IFCAnyHandle elemHnd = null; string rebarGUID = GUIDUtil.CreateGUID(element); string rebarName = NamingUtil.GetIFCName(element); string rebarDescription = NamingUtil.GetDescriptionOverride(element, null); string rebarObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string rebarElemId = NamingUtil.CreateIFCElementId(element); IFCReinforcingBarRole role = IFCReinforcingBarRole.NotDefined; elemHnd = IFCInstanceExporter.CreateReinforcingBar(file, rebarGUID, exporterIFC.GetOwnerHistoryHandle(), rebarName, rebarDescription, rebarObjectType, setter.GetPlacement(), prodRep, rebarElemId, steelGradeOpt, longitudinalBarNominalDiameter, longitudinalBarCrossSectionArea, barLength, role, null); productWrapper.AddElement(elemHnd, setter.GetLevelInfo(), null, true); PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, productWrapper); } } transaction.Commit(); } } catch (Exception) { // It will throw exception at GetBarPositionTransform when exporting rebars with Revit 2013 UR1 and before versions, so we skip the export. // It should not come here and will export the rebars properly at Revit later versions. } }
/// <summary> /// Exports a roof as a container of multiple roof slabs. Returns the handle, if successful. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="ifcEnumType">The roof type.</param> /// <param name="element">The roof element.</param> /// <param name="geometry">The geometry of the element.</param> /// <param name="productWrapper">The product wrapper.</param> /// <returns>The roof handle.</returns> public static IFCAnyHandle ExportRoofAsContainer(ExporterIFC exporterIFC, string ifcEnumType, Element element, GeometryElement geometry, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); if (!(element is ExtrusionRoof) && !(element is FootPrintRoof)) { return(null); } using (IFCTransaction transaction = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element)) { IFCAnyHandle localPlacement = setter.LocalPlacement; RoofComponents roofComponents = null; try { roofComponents = ExporterIFCUtils.GetRoofComponents(exporterIFC, element as RoofBase); } catch { return(null); } if (roofComponents == null) { return(null); } try { using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); 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); string elementName = NamingUtil.GetIFCName(element); string elementDescription = NamingUtil.GetDescriptionOverride(element, null); string elementObjectType = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName()); string elementId = NamingUtil.CreateIFCElementId(element); string roofType = IFCValidateEntry.GetValidIFCType(element, ifcEnumType); IFCAnyHandle roofHandle = IFCInstanceExporter.CreateRoof(file, elementGUID, ownerHistory, elementName, elementDescription, elementObjectType, localPlacement, prodRepHnd, elementId, roofType); IList <IFCAnyHandle> elementHandles = new List <IFCAnyHandle>(); elementHandles.Add(roofHandle); //only thing supported right now. XYZ extrusionDir = new XYZ(0, 0, 1); ElementId catId = CategoryUtil.GetSafeCategoryId(element); IList <CurveLoop> roofCurveloops = roofComponents.GetCurveLoops(); IList <XYZ> planeDirs = roofComponents.GetPlaneDirections(); IList <XYZ> planeOrigins = roofComponents.GetPlaneOrigins(); IList <Face> loopFaces = roofComponents.GetLoopFaces(); double scaledDepth = roofComponents.ScaledDepth; IList <double> areas = roofComponents.GetAreasOfCurveLoops(); IList <IFCAnyHandle> slabHandles = new List <IFCAnyHandle>(); using (IFCExtrusionCreationData slabExtrusionCreationData = new IFCExtrusionCreationData()) { slabExtrusionCreationData.SetLocalPlacement(extrusionCreationData.GetLocalPlacement()); slabExtrusionCreationData.ReuseLocalPlacement = false; slabExtrusionCreationData.ForceOffset = true; for (int numLoop = 0; numLoop < roofCurveloops.Count; numLoop++) { trfSetter.InitializeFromBoundingBox(exporterIFC, geometryList, slabExtrusionCreationData); Plane plane = new Plane(planeDirs[numLoop], planeOrigins[numLoop]); IList <CurveLoop> curveLoops = new List <CurveLoop>(); curveLoops.Add(roofCurveloops[numLoop]); double slope = Math.Abs(planeDirs[numLoop].Z); double scaledExtrusionDepth = scaledDepth * slope; IFCAnyHandle shapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, plane, extrusionDir, scaledExtrusionDepth); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) { return(null); } ElementId matId = HostObjectExporter.GetFirstLayerMaterialId(element as HostObject); BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, element.Document, shapeRep, matId); HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); bodyItems.Add(shapeRep); shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle repHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); // Allow support for up to 256 named IfcSlab components, as defined in IFCSubElementEnums.cs. string slabGUID = (numLoop < 256) ? GUIDUtil.CreateSubElementGUID(element, (int)IFCRoofSubElements.RoofSlabStart + numLoop) : GUIDUtil.CreateGUID(); IFCAnyHandle slabPlacement = ExporterUtil.CreateLocalPlacement(file, slabExtrusionCreationData.GetLocalPlacement(), null); IFCAnyHandle slabHnd = IFCInstanceExporter.CreateSlab(file, slabGUID, ownerHistory, elementName, elementDescription, elementObjectType, slabPlacement, repHnd, elementId, "ROOF"); //slab quantities slabExtrusionCreationData.ScaledLength = scaledExtrusionDepth; slabExtrusionCreationData.ScaledArea = UnitUtil.ScaleArea(areas[numLoop]); slabExtrusionCreationData.ScaledOuterPerimeter = UnitUtil.ScaleLength(curveLoops[0].GetExactLength()); slabExtrusionCreationData.Slope = UnitUtil.ScaleAngle(Math.Acos(Math.Abs(planeDirs[numLoop].Z))); productWrapper.AddElement(null, slabHnd, setter, slabExtrusionCreationData, false); elementHandles.Add(slabHnd); slabHandles.Add(slabHnd); } } productWrapper.AddElement(element, roofHandle, setter, extrusionCreationData, true); ExporterUtil.RelateObjects(exporterIFC, null, roofHandle, slabHandles); OpeningUtil.AddOpeningsToElement(exporterIFC, elementHandles, roofCurveloops, element, null, roofComponents.ScaledDepth, null, setter, localPlacement, productWrapper); transaction.Commit(); return(roofHandle); } } } finally { exporterIFC.ClearFaceWithElementHandleMap(); } } } }