/// <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; // This will default to false for now in all cases, as swept solids are not included in CV2.0. bool tryToExportAsSweptSolid = options.TryToExportAsSweptSolid; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Body"); double scale = exporterIFC.LinearScale; double eps = element.Document.Application.VertexTolerance * scale; bool allFaces = true; foreach (GeometryObject geomObject in geometryList) { if (allFaces && !(geomObject is Face)) allFaces = false; break; } IList<IFCAnyHandle> bodyItems = new List<IFCAnyHandle>(); IList<ElementId> materialIdsForExtrusions = new List<ElementId>(); IList<int> exportAsBRep = new List<int>(); IList<int> exportAsSweptSolid = new List<int>(); IList<int> exportAsExtrusion = new List<int>(); bool hasExtrusions = false; bool hasSweptSolids = false; XYZ unscaledTrfOrig = new XYZ(); 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 (IFCTransformSetter transformSetter = IFCTransformSetter.Create()) { // We may need to get the original values back, in case the export rolls back. IFCLocalPlacementBackup localPlacementBackup = null; if (options.AllowOffsetTransform && exportBodyParams!= null) { localPlacementBackup = new IFCLocalPlacementBackup(exportBodyParams.GetLocalPlacement()); bodyData.OffsetTransform = transformSetter.InitializeFromBoundingBox(exporterIFC, geometryList, exportBodyParams); } 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 geometryList) { faces.Add(geometryObject as Face); } } int numExtrusionsToCreate = allFaces ? 1 : geometryList.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, geometryList[ii]); if (extrusionList.Count == 0) { if (tryToExportAsSweptSolid) exportAsSweptSolid.Add(ii); else if (!canExportSolidModelRep) { tryToExportAsExtrusion = false; break; } else 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]; 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 = 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; hasExtrusions = true; } } if (!exportedAsExtrusion) { if (tryToExportAsSweptSolid) exportAsSweptSolid.Add(ii); else if (!canExportSolidModelRep) { tryToExportAsExtrusion = false; break; } else exportAsBRep.Add(ii); } } } 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; // TODO: allFaces to SweptSolid if (solid != null) { // TODO: other types of Axes XYZ normal = new XYZ(0, 0, 1); SweptSolidExporter sweptSolidExporter = SweptSolidExporter.Create(exporterIFC, element, solid, normal); if (sweptSolidExporter != null) { IFCAnyHandle sweptHandle = sweptSolidExporter.RepresentationItem; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(sweptHandle)) { bodyItems.Add(sweptHandle); materialIdsForExtrusions.Add(exporterIFC.GetMaterialIdForCurrentExportState()); exported = true; if (sweptSolidExporter.IsExtrusion) hasExtrusions = true; else hasSweptSolids = true; } } } if (!exported) exportAsBRep.Add(ii); } } bool exportSucceeded = (exportAsBRep.Count == 0) && (tryToExportAsExtrusion || tryToExportAsSweptSolid) && (hasExtrusions || hasSweptSolids); 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 (hasExtrusions && !hasSweptSolids) { bodyData.RepresentationHnd = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, categoryId, contextOfItems, bodyItems, bodyData.RepresentationHnd); bodyData.ShapeRepresentationType = ShapeRepresentationType.SweptSolid; } else if (hasSweptSolids && !hasExtrusions) { bodyData.RepresentationHnd = RepresentationUtil.CreateAdvancedSweptSolidRep(exporterIFC, element, categoryId, contextOfItems, bodyItems, bodyData.RepresentationHnd); bodyData.ShapeRepresentationType = ShapeRepresentationType.AdvancedSweptSolid; } else { bodyData.RepresentationHnd = RepresentationUtil.CreateSolidModelRep(exporterIFC, element, categoryId, contextOfItems, bodyItems); bodyData.ShapeRepresentationType = ShapeRepresentationType.SolidModel; } // TODO: include BRep, CSG, Clipping tr.Commit(); return bodyData; } } // If we are going to export a solid model, keep the created items. if (!canExportSolidModelRep) { tr.RollBack(); // Revert to the original local placement, and re-set the relative placement, as the rollback may delete either. if (localPlacementBackup != null) { IFCAnyHandle origLocalPlacement = localPlacementBackup.Restore(); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(origLocalPlacement)) exportBodyParams.SetLocalPlacement(origLocalPlacement); } } 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) exportAsBRep.Clear(); } using (IFCTransaction tr = new IFCTransaction(file)) { using (IFCTransformSetter transformSetter = IFCTransformSetter.Create()) { if (exportBodyParams != null && (exportAsBRep.Count == 0)) bodyData.OffsetTransform = transformSetter.InitializeFromBoundingBox(exporterIFC, geometryList, exportBodyParams); BodyData retBodyData = ExportBodyAsBRep(exporterIFC, geometryList, exportAsBRep, bodyItems, element, categoryId, overrideMaterialId, contextOfItems, eps, options, bodyData); if (retBodyData != null) tr.Commit(); else tr.RollBack(); return retBodyData; } } }
public IFCLocalPlacementBackup(IFCAnyHandle localPlacement) { if (!IFCAnyHandleUtil.IsNullOrHasNoValue(localPlacement)) { m_LocalPlacement = localPlacement; IFCAnyHandle placementRelTo = IFCAnyHandleUtil.GetInstanceAttribute(m_LocalPlacement, "PlacementRelTo"); if (IFCAnyHandleUtil.IsSubTypeOf(placementRelTo, IFCEntityType.IfcLocalPlacement)) m_PlacementRelTo = new IFCLocalPlacementBackup(placementRelTo); IFCAnyHandle relativePlacement = IFCAnyHandleUtil.GetInstanceAttribute(m_LocalPlacement, "RelativePlacement"); if (IFCAnyHandleUtil.IsSubTypeOf(relativePlacement, IFCEntityType.IfcAxis2Placement3D)) m_RelativePlacement = new IFCAxis2Placement3DBackup(relativePlacement); } }