/// <summary> /// Copies a BodyData object. /// </summary> /// <param name="representationHnd"> /// The representation handle. /// </param> /// <param name="offsetTransform"> /// The offset transform. /// </param> /// <param name="materialIds"> /// The material ids. /// </param> public BodyData(BodyData bodyData) { this.m_RepresentationHnd = bodyData.RepresentationHnd; this.m_ShapeRepresentationType = bodyData.m_ShapeRepresentationType; this.m_OffsetTransform = bodyData.OffsetTransform; this.m_MaterialIds = bodyData.MaterialIds; }
/// <summary> /// Creates a SweptSolid, Brep, SolidModel or SurfaceModel product definition shape representation, based on the geometry and IFC version. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="categoryId">The category id.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="bodyExporterOptions">The body exporter options.</param> /// <param name="extraReps">Extra representations (e.g. Axis, Boundary). May be null.</param> /// <param name="extrusionCreationData">The extrusion creation data.</param> /// <param name="bodyData">The body data.</param> /// <returns>The handle.</returns> public static IFCAnyHandle CreateAppropriateProductDefinitionShape(ExporterIFC exporterIFC, Element element, ElementId categoryId, GeometryElement geometryElement, BodyExporterOptions bodyExporterOptions, IList<IFCAnyHandle> extraReps, IFCExtrusionCreationData extrusionCreationData, out BodyData bodyData) { bodyData = null; SolidMeshGeometryInfo info = null; IList<GeometryObject> geometryList = new List<GeometryObject>(); if (!exporterIFC.ExportAs2x2) { info = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement, Transform.Identity); IList<Mesh> meshes = info.GetMeshes(); if (meshes.Count == 0) { IList<Solid> solidList = info.GetSolids(); foreach (Solid solid in solidList) { geometryList.Add(solid); } } } if (geometryList.Count == 0) geometryList.Add(geometryElement); else bodyExporterOptions.TryToExportAsExtrusion = true; bodyData = BodyExporter.ExportBody(exporterIFC, element, categoryId, ElementId.InvalidElementId, geometryList, bodyExporterOptions, extrusionCreationData); IFCAnyHandle bodyRep = bodyData.RepresentationHnd; List<IFCAnyHandle> bodyReps = new List<IFCAnyHandle>(); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { if (extrusionCreationData != null) extrusionCreationData.ClearOpenings(); } else bodyReps.Add(bodyRep); if (extraReps != null) { foreach (IFCAnyHandle hnd in extraReps) bodyReps.Add(hnd); } IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) bodyReps.Add(boundingBoxRep); if (bodyReps.Count == 0) return null; return IFCInstanceExporter.CreateProductDefinitionShape(exporterIFC.GetFile(), null, null, bodyReps); }
/// <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(); double scale = exporterIFC.LinearScale; 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.get_EndPoint(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 (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, canExportAxis ? orientTrf : null, ExporterUtil.GetBaseLevelIdForElement(element))) { IFCAnyHandle localPlacement = setter.GetPlacement(); 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 = -offsetTransform.Origin / scale; } 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)); IFCAnyHandle beam = IFCInstanceExporter.CreateBeam(file, instanceGUID, exporterIFC.GetOwnerHistoryHandle(), instanceName, instanceDescription, instanceObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, instanceTag); 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); 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 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); } }
private static bool ProcessGroupMembership(ExporterIFC exporterIFC, IFCFile file, Element element, ElementId categoryId, IFCAnyHandle contextOfItems, IList<GeometryObject> geomList, BodyData bodyDataIn, out BodyGroupKey groupKey, out BodyGroupData groupData, out BodyData bodyData) { // Set back to true if all checks are passed. bool useGroupsIfPossible = false; groupKey = null; groupData = null; bodyData = null; Group group = element.Group; if (group != null) { ElementId elementId = element.Id; bool pristineGeometry = true; foreach (GeometryObject geomObject in geomList) { try { ICollection<ElementId> generatingElementIds = element.GetGeneratingElementIds(geomObject); int numGeneratingElements = generatingElementIds.Count; if ((numGeneratingElements > 1) || (numGeneratingElements == 1 && (generatingElementIds.First() != elementId))) { pristineGeometry = false; break; } } catch { pristineGeometry = false; break; } } if (pristineGeometry) { groupKey = new BodyGroupKey(); IList<ElementId> groupMemberIds = group.GetMemberIds(); int numMembers = groupMemberIds.Count; for (int idx = 0; idx < numMembers; idx++) { if (groupMemberIds[idx] == elementId) { groupKey.GroupMemberIndex = idx; break; } } if (groupKey.GroupMemberIndex >= 0) { groupKey.GroupTypeId = group.GetTypeId(); groupData = ExporterCacheManager.GroupElementGeometryCache.Find(groupKey); if (groupData == null) { groupData = new BodyGroupData(); useGroupsIfPossible = true; } else { IList<IFCAnyHandle> groupBodyItems = new List<IFCAnyHandle>(); foreach (IFCAnyHandle mappedRepHnd in groupData.Handles) { IFCAnyHandle mappedItemHnd = ExporterUtil.CreateDefaultMappedItem(file, mappedRepHnd); groupBodyItems.Add(mappedItemHnd); } bodyData = new BodyData(bodyDataIn); bodyData.RepresentationHnd = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, element, categoryId, contextOfItems, groupBodyItems); return true; } } } } return useGroupsIfPossible; }
/// <summary> /// Creates a Brep product definition shape representation. /// </summary> /// <param name="application">The Revit application object.</param> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="categoryId">The category id.</param> /// <param name="geometryObject">The geometry object.</param> /// <param name="extraReps">Extra representations (e.g. Axis, Footprint). May be null.</param> /// <param name="options">The settings for how to export the body.</param> /// <param name="extrusionCreationData">The extrusion creation data.</param> /// <param name="bodyData">The body data.</param> /// <returns>The handle.</returns> public static IFCAnyHandle CreateBRepProductDefinitionShape(Autodesk.Revit.ApplicationServices.Application application, ExporterIFC exporterIFC, Element element, ElementId categoryId, IList<GeometryObject> geometryObjectIn, IList<IFCAnyHandle> extraReps, BodyExporterOptions bodyExporterOptions, IFCExtrusionCreationData extrusionCreationData, out BodyData bodyData) { bodyData = BodyExporter.ExportBody(application, exporterIFC, element, categoryId, geometryObjectIn, bodyExporterOptions, extrusionCreationData); IFCAnyHandle bodyRep = bodyData.RepresentationHnd; List<IFCAnyHandle> bodyReps = new List<IFCAnyHandle>(); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { if (extrusionCreationData != null) extrusionCreationData.ClearOpenings(); } else bodyReps.Add(bodyRep); if (extraReps != null) { foreach (IFCAnyHandle hnd in extraReps) bodyReps.Add(hnd); } if (bodyReps.Count == 0) return null; return IFCInstanceExporter.CreateProductDefinitionShape(exporterIFC.GetFile(), null, null, bodyReps); }
// NOTE: the useMappedGeometriesIfPossible and useGroupsIfPossible options are experimental and do not yet work well. // In shipped code, these are always false, and should be kept false until API support routines are proved to be reliable. private static BodyData ExportBodyAsBRep(ExporterIFC exporterIFC, IList<GeometryObject> splitGeometryList, IList<int> exportAsBRep, IList<IFCAnyHandle> bodyItems, Element element, ElementId categoryId, IFCAnyHandle contextOfItems, double eps, BodyExporterOptions options, BodyData bodyDataIn) { bool exportAsBReps = true; IFCFile file = exporterIFC.GetFile(); Document document = element.Document; // Can't use the optimization functions below if we already have partially populated our body items with extrusions. int numExtrusions = bodyItems.Count; bool useMappedGeometriesIfPossible = options.UseMappedGeometriesIfPossible && (numExtrusions != 0); bool useGroupsIfPossible = options.UseGroupsIfPossible && (numExtrusions != 0); IList<HashSet<IFCAnyHandle>> currentFaceHashSetList = new List<HashSet<IFCAnyHandle>>(); IList<int> startIndexForObject = new List<int>(); BodyData bodyData = new BodyData(bodyDataIn); IDictionary<SolidMetrics, HashSet<Solid>> solidMappingGroups = null; IList<KeyValuePair<int, Transform>> solidMappings = null; IList<ElementId> materialIds = new List<ElementId>(); if (useMappedGeometriesIfPossible) { IList<GeometryObject> newGeometryList = null; useMappedGeometriesIfPossible = GatherMappedGeometryGroupings(splitGeometryList, out newGeometryList, out solidMappingGroups, out solidMappings); if (useMappedGeometriesIfPossible && (newGeometryList != null)) splitGeometryList = newGeometryList; } BodyGroupKey groupKey = null; BodyGroupData groupData = null; if (useGroupsIfPossible) { BodyData bodyDataOut = null; useGroupsIfPossible = ProcessGroupMembership(exporterIFC, file, element, categoryId, contextOfItems, splitGeometryList, bodyData, out groupKey, out groupData, out bodyDataOut); if (bodyDataOut != null) return bodyDataOut; if (useGroupsIfPossible) useMappedGeometriesIfPossible = true; } bool isCoarse = (options.TessellationLevel == BodyExporterOptions.BodyTessellationLevel.Coarse); int numBRepsToExport = exportAsBRep.Count; bool selectiveBRepExport = (numBRepsToExport > 0); int numGeoms = selectiveBRepExport ? numBRepsToExport : splitGeometryList.Count; for (int index = 0; index < numGeoms; index++) { GeometryObject geomObject = selectiveBRepExport ? splitGeometryList[exportAsBRep[index]] : splitGeometryList[index]; startIndexForObject.Add(currentFaceHashSetList.Count); ElementId materialId = SetBestMaterialIdInExporter(geomObject, exporterIFC); materialIds.Add(materialId); bodyData.AddMaterial(materialId); bool exportedAsSolid = false; if (exportAsBReps || isCoarse) { exportedAsSolid = ExportBodyAsSolid(exporterIFC, element, options, currentFaceHashSetList, geomObject); } if (!exportedAsSolid) { IFCGeometryInfo faceListInfo = IFCGeometryInfo.CreateFaceGeometryInfo(eps, isCoarse); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, faceListInfo, geomObject, 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)) { exportAsBReps = false; // We'll need to invalidate the extrusions we created and replace them with BReps. if (selectiveBRepExport && (numGeoms != splitGeometryList.Count)) { for (int fixIndex = 0; fixIndex < numExtrusions; fixIndex++) { bodyItems[0].Delete(); bodyItems.RemoveAt(0); } numExtrusions = 0; numGeoms = splitGeometryList.Count; int brepIndex = 0; for (int fixIndex = 0; fixIndex < numGeoms; fixIndex++) { if ((brepIndex < numBRepsToExport) && (exportAsBRep[brepIndex] == fixIndex)) { brepIndex++; continue; } exportAsBRep.Add(fixIndex); } numBRepsToExport = exportAsBRep.Count; } } } currentFaceHashSetList.Add(new HashSet<IFCAnyHandle>(currentFaceSet)); } } } startIndexForObject.Add(currentFaceHashSetList.Count); // end index for last object. IList<IFCAnyHandle> repMapItems = new List<IFCAnyHandle>(); int size = currentFaceHashSetList.Count; if (exportAsBReps) { int matToUse = -1; for (int ii = 0; ii < size; ii++) { if (startIndexForObject[matToUse + 1] == ii) matToUse++; HashSet<IFCAnyHandle> currentFaceHashSet = currentFaceHashSetList[ii]; IFCAnyHandle faceOuter = IFCInstanceExporter.CreateClosedShell(file, currentFaceHashSet); IFCAnyHandle brepHnd = RepresentationUtil.CreateFacetedBRep(exporterIFC, document, faceOuter, materialIds[matToUse]); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(brepHnd)) { if (useMappedGeometriesIfPossible) { IFCAnyHandle currMappedRepHnd = CreateBRepRepresentationMap(exporterIFC, file, element, categoryId, contextOfItems, brepHnd); repMapItems.Add(currMappedRepHnd); IFCAnyHandle mappedItemHnd = ExporterUtil.CreateDefaultMappedItem(file, currMappedRepHnd); bodyItems.Add(mappedItemHnd); } else bodyItems.Add(brepHnd); } } } else { IDictionary<ElementId, HashSet<IFCAnyHandle>> faceSets = new Dictionary<ElementId, HashSet<IFCAnyHandle>>(); int matToUse = -1; for (int ii = 0; ii < size; ii++) { HashSet<IFCAnyHandle> currentFaceHashSet = currentFaceHashSetList[ii]; if (startIndexForObject[matToUse+1] == ii) matToUse++; IFCAnyHandle faceSetHnd = IFCInstanceExporter.CreateConnectedFaceSet(file, currentFaceHashSet); if (useMappedGeometriesIfPossible) { IFCAnyHandle currMappedRepHnd = CreateSurfaceRepresentationMap(exporterIFC, file, element, categoryId, contextOfItems, faceSetHnd); repMapItems.Add(currMappedRepHnd); IFCAnyHandle mappedItemHnd = ExporterUtil.CreateDefaultMappedItem(file, currMappedRepHnd); bodyItems.Add(mappedItemHnd); } else { HashSet<IFCAnyHandle> surfaceSet = null; if (faceSets.TryGetValue(materialIds[matToUse], out surfaceSet)) { surfaceSet.Add(faceSetHnd); } else { surfaceSet = new HashSet<IFCAnyHandle>(); surfaceSet.Add(faceSetHnd); faceSets[materialIds[matToUse]] = surfaceSet; } } } if (faceSets.Count > 0) { foreach (KeyValuePair<ElementId, HashSet<IFCAnyHandle>> faceSet in faceSets) { IFCAnyHandle surfaceModel = IFCInstanceExporter.CreateFaceBasedSurfaceModel(file, faceSet.Value); BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, surfaceModel, faceSet.Key); bodyItems.Add(surfaceModel); } } } if (bodyItems.Count == 0) return bodyData; // Add in mapped items. if (useMappedGeometriesIfPossible && (solidMappings != null)) { foreach (KeyValuePair<int, Transform> mappedItem in solidMappings) { for (int idx = startIndexForObject[mappedItem.Key]; idx < startIndexForObject[mappedItem.Key + 1]; idx++) { IFCAnyHandle mappedItemHnd = ExporterUtil.CreateMappedItemFromTransform(file, repMapItems[idx], mappedItem.Value); bodyItems.Add(mappedItemHnd); } } } if (useMappedGeometriesIfPossible) { bodyData.RepresentationHnd = RepresentationUtil.CreateBodyMappedItemRep(exporterIFC, element, categoryId, contextOfItems, bodyItems); } else if (exportAsBReps) { if (numExtrusions > 0) bodyData.RepresentationHnd = RepresentationUtil.CreateSolidModelRep(exporterIFC, element, categoryId, contextOfItems, bodyItems); else bodyData.RepresentationHnd = RepresentationUtil.CreateBRepRep(exporterIFC, element, categoryId, contextOfItems, bodyItems); } else bodyData.RepresentationHnd = RepresentationUtil.CreateSurfaceRep(exporterIFC, element, categoryId, contextOfItems, bodyItems, false, null); if (useGroupsIfPossible && (groupKey != null) && (groupData != null)) { groupData.Handles = repMapItems; ExporterCacheManager.GroupElementGeometryCache.Register(groupKey, groupData); } return bodyData; }
/// <summary> /// Copies a BodyData object. /// </summary> /// <param name="representationHnd"> /// The representation handle. /// </param> /// <param name="brepOffsetTransform"> /// The offset transform. /// </param> /// <param name="materialIds"> /// The material ids. /// </param> public BodyData(BodyData bodyData) { this.m_RepresentationHnd = bodyData.RepresentationHnd; this.m_BrepOffsetTransform = bodyData.BrepOffsetTransform; this.m_MaterialIds = bodyData.MaterialIds; }
/// <summary> /// Creates a Brep product definition shape representation. /// </summary> /// <remarks> /// It will try to export the geometry as an extrusion if it is not exported as IFC 2x2 version. /// </remarks> /// <param name="application"> /// The Revit application object. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="categoryId"> /// The category id. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="bodyExporterOptions"> /// The body exporter options. /// </param> /// <param name="extraReps"> /// Extra representations (e.g. Axis, Boundary). May be null. /// </param> /// <param name="extrusionCreationData"> /// The extrusion creation data. /// </param> /// <param name="bodyData"> /// The body data. /// </param> /// <returns> /// The handle. /// </returns> public static IFCAnyHandle CreateBRepProductDefinitionShape(Autodesk.Revit.ApplicationServices.Application application, ExporterIFC exporterIFC, Element element, ElementId categoryId, GeometryElement geometryElement, BodyExporterOptions bodyExporterOptions, IList<IFCAnyHandle> extraReps, IFCExtrusionCreationData extrusionCreationData, out BodyData bodyData) { SolidMeshGeometryInfo info = null; IList<GeometryObject> solids = new List<GeometryObject>(); if (!exporterIFC.ExportAs2x2) { info = GeometryUtil.GetSolidMeshGeometry(geometryElement, Transform.Identity); IList<Mesh> meshes = info.GetMeshes(); if (meshes.Count == 0) { IList<Solid> solidList = info.GetSolids(); foreach (Solid solid in solidList) { solids.Add(solid); } } } IFCAnyHandle ret = null; if (solids.Count == 0) { IList<GeometryObject> geometryList = new List<GeometryObject>(); geometryList.Add(geometryElement); ret = CreateBRepProductDefinitionShape(application, exporterIFC, element, categoryId, geometryList, extraReps, bodyExporterOptions, extrusionCreationData, out bodyData); } else { bodyExporterOptions.TryToExportAsExtrusion = true; ret = CreateBRepProductDefinitionShape(application, exporterIFC, element, categoryId, solids, extraReps, bodyExporterOptions, extrusionCreationData, out bodyData); } return ret; }
/// <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; } } }
/// <summary> /// Exports an element as IFC railing. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element to be exported. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportRailing(ExporterIFC exporterIFC, Element element, GeometryElement geomElem, string ifcEnumType, ProductWrapper productWrapper) { ElementType elemType = element.Document.GetElement(element.GetTypeId()) as ElementType; IFCFile file = exporterIFC.GetFile(); Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); using (IFCTransaction transaction = new IFCTransaction(file)) { using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, null, ExporterUtil.GetBaseLevelIdForElement(element))) { using (IFCExtrusionCreationData ecData = new IFCExtrusionCreationData()) { IFCAnyHandle localPlacement = setter.GetPlacement(); StairRampContainerInfo stairRampInfo = null; ElementId hostId = GetStairOrRampHostId(exporterIFC, element as Railing); if (hostId != ElementId.InvalidElementId) { stairRampInfo = ExporterCacheManager.StairRampContainerInfoCache.GetStairRampContainerInfo(hostId); IFCAnyHandle stairRampLocalPlacement = stairRampInfo.LocalPlacements[0]; Transform relTrf = ExporterIFCUtils.GetRelativeLocalPlacementOffsetTransform(stairRampLocalPlacement, localPlacement); Transform inverseTrf = relTrf.Inverse; IFCAnyHandle relativePlacement = ExporterUtil.CreateAxis2Placement3D(file, inverseTrf.Origin, inverseTrf.BasisZ, inverseTrf.BasisX); IFCAnyHandle railingLocalPlacement = ExporterUtil.CreateLocalPlacement(file, stairRampLocalPlacement, relativePlacement); localPlacement = railingLocalPlacement; } ecData.SetLocalPlacement(localPlacement); SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geomElem); IList <Solid> solids = solidMeshInfo.GetSolids(); IList <Mesh> meshes = solidMeshInfo.GetMeshes(); Railing railingElem = element as Railing; IList <ElementId> subElementIds = CollectSubElements(railingElem); foreach (ElementId subElementId in subElementIds) { Element subElement = railingElem.Document.GetElement(subElementId); if (subElement != null) { GeometryElement subElementGeom = GeometryUtil.GetOneLevelGeometryElement(subElement.get_Geometry(geomOptions)); SolidMeshGeometryInfo subElementSolidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(subElementGeom); IList <Solid> subElementSolids = subElementSolidMeshInfo.GetSolids(); IList <Mesh> subElementMeshes = subElementSolidMeshInfo.GetMeshes(); foreach (Solid subElementSolid in subElementSolids) { solids.Add(subElementSolid); } foreach (Mesh subElementMesh in subElementMeshes) { meshes.Add(subElementMesh); } } } ElementId catId = CategoryUtil.GetSafeCategoryId(element); BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); bodyExporterOptions.TessellationLevel = BodyExporter.GetTessellationLevel(); //bodyExporterOptions.UseGroupsIfPossible = true; //bodyExporterOptions.UseMappedGeometriesIfPossible = true; if (solids.Count > 0 || meshes.Count > 0) { bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, solids, meshes, bodyExporterOptions, ecData); } else { IList <GeometryObject> geomlist = new List <GeometryObject>(); geomlist.Add(geomElem); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, ElementId.InvalidElementId, geomlist, bodyExporterOptions, ecData); } IFCAnyHandle bodyRep = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { if (ecData != null) { ecData.ClearOpenings(); } return; } IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); representations.Add(bodyRep); IList <GeometryObject> geomObjects = new List <GeometryObject>(); foreach (Solid solid in solids) { geomObjects.Add(solid); } foreach (Mesh mesh in meshes) { geomObjects.Add(mesh); } Transform boundingBoxTrf = (bodyData.OffsetTransform != null) ? bodyData.OffsetTransform.Inverse : Transform.Identity; IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomObjects, boundingBoxTrf); if (boundingBoxRep != null) { representations.Add(boundingBoxRep); } IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string instanceGUID = GUIDUtil.CreateGUID(element); string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, exporterIFC.GetFamilyName()); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); Toolkit.IFCRailingType railingType = GetIFCRailingType(element, ifcEnumType); IFCAnyHandle railing = IFCInstanceExporter.CreateRailing(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, ecData.GetLocalPlacement(), prodRep, instanceTag, railingType); bool associateToLevel = (hostId == ElementId.InvalidElementId); productWrapper.AddElement(element, railing, setter, ecData, associateToLevel); OpeningUtil.CreateOpeningsIfNecessary(railing, element, ecData, bodyData.OffsetTransform, exporterIFC, ecData.GetLocalPlacement(), setter, productWrapper); CategoryUtil.CreateMaterialAssociations(exporterIFC, railing, bodyData.MaterialIds); // Create multi-story duplicates of this railing. if (stairRampInfo != null) { stairRampInfo.AddComponent(0, railing); List <IFCAnyHandle> stairHandles = stairRampInfo.StairOrRampHandles; for (int ii = 1; ii < stairHandles.Count; ii++) { IFCAnyHandle railingLocalPlacement = stairRampInfo.LocalPlacements[ii]; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(railingLocalPlacement)) { IFCAnyHandle railingHndCopy = CopyRailingHandle(exporterIFC, element, catId, railingLocalPlacement, railing); stairRampInfo.AddComponent(ii, railingHndCopy); productWrapper.AddElement(element, railingHndCopy, (IFCLevelInfo)null, ecData, false); CategoryUtil.CreateMaterialAssociations(exporterIFC, railingHndCopy, bodyData.MaterialIds); } } ExporterCacheManager.StairRampContainerInfoCache.AddStairRampContainerInfo(hostId, stairRampInfo); } } transaction.Commit(); } } }
/// <summary> /// Exports a MEP family instance. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="exportType">The export type of the element. /// <param name="ifcEnumType">The sub-type of the element.</param></param> /// <param name="productWrapper">The ProductWrapper.</param> /// <returns>True if an entity was created, false otherwise.</returns> public static bool Export(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCExportType exportType, string ifcEnumType, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, null, ExporterUtil.GetBaseLevelIdForElement(element))) { IFCAnyHandle localPlacementToUse = setter.GetPlacement(); using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { extraParams.SetLocalPlacement(localPlacementToUse); ElementId catId = CategoryUtil.GetSafeCategoryId(element); BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); BodyData bodyData = null; IFCAnyHandle productRepresentation = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, element, catId, geometryElement, bodyExporterOptions, null, extraParams, out bodyData); if (IFCAnyHandleUtil.IsNullOrHasNoValue(productRepresentation)) { extraParams.ClearOpenings(); return(false); } IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); ElementId typeId = element.GetTypeId(); ElementType type = element.Document.GetElement(typeId) as ElementType; FamilyTypeInfo currentTypeInfo = ExporterCacheManager.TypeObjectsCache.Find(typeId, false); bool found = currentTypeInfo.IsValid(); if (!found) { string typeGUID = GUIDUtil.CreateGUID(type); string typeName = NamingUtil.GetNameOverride(type, NamingUtil.GetIFCName(type)); string typeObjectType = NamingUtil.GetObjectTypeOverride(type, NamingUtil.CreateIFCObjectName(exporterIFC, type)); string applicableOccurence = NamingUtil.GetOverrideStringValue(type, "IfcApplicableOccurrence", typeObjectType); string typeDescription = NamingUtil.GetDescriptionOverride(type, null); string typeTag = NamingUtil.GetTagOverride(type, NamingUtil.CreateIFCElementId(type)); string typeElementType = NamingUtil.GetOverrideStringValue(type, "IfcElementType", typeName); IList <IFCAnyHandle> repMapListOpt = new List <IFCAnyHandle>(); IFCAnyHandle styleHandle = FamilyExporterUtil.ExportGenericType(exporterIFC, exportType, ifcEnumType, typeGUID, typeName, typeDescription, applicableOccurence, null, repMapListOpt, typeTag, typeElementType, element, type); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(styleHandle)) { productWrapper.RegisterHandleWithElementType(type, styleHandle, null); currentTypeInfo.Style = styleHandle; ExporterCacheManager.TypeObjectsCache.Register(typeId, false, currentTypeInfo); } } string instanceGUID = GUIDUtil.CreateGUID(element); string instanceName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); bool roomRelated = !FamilyExporterUtil.IsDistributionFlowElementSubType(exportType); ElementId roomId = ElementId.InvalidElementId; if (roomRelated) { roomId = setter.UpdateRoomRelativeCoordinates(element, out localPlacementToUse); } IFCAnyHandle instanceHandle = null; if (FamilyExporterUtil.IsFurnishingElementSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateFurnishingElement(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } else if (FamilyExporterUtil.IsDistributionFlowElementSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateDistributionFlowElement(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } else if (FamilyExporterUtil.IsEnergyConversionDeviceSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateEnergyConversionDevice(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } else if (FamilyExporterUtil.IsFlowFittingSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateFlowFitting(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } else if (FamilyExporterUtil.IsFlowMovingDeviceSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateFlowMovingDevice(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } else if (FamilyExporterUtil.IsFlowSegmentSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateFlowSegment(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } else if (FamilyExporterUtil.IsFlowStorageDeviceSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateFlowStorageDevice(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } else if (FamilyExporterUtil.IsFlowTerminalSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateFlowTerminal(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } else if (FamilyExporterUtil.IsFlowTreatmentDeviceSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateFlowTreatmentDevice(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } else if (FamilyExporterUtil.IsFlowControllerSubType(exportType)) { instanceHandle = IFCInstanceExporter.CreateFlowController(file, instanceGUID, ownerHistory, instanceName, instanceDescription, instanceObjectType, localPlacementToUse, productRepresentation, instanceTag); } if (IFCAnyHandleUtil.IsNullOrHasNoValue(instanceHandle)) { return(false); } bool relatedToSpace = (roomId != ElementId.InvalidElementId); productWrapper.AddElement(element, instanceHandle, setter, extraParams, !relatedToSpace); if (relatedToSpace) { exporterIFC.RelateSpatialElement(roomId, instanceHandle); } OpeningUtil.CreateOpeningsIfNecessary(instanceHandle, element, extraParams, null, exporterIFC, localPlacementToUse, setter, productWrapper); if (currentTypeInfo.IsValid()) { ExporterCacheManager.TypeRelationsCache.Add(currentTypeInfo.Style, instanceHandle); } if (bodyData != null && bodyData.MaterialIds.Count != 0) { CategoryUtil.CreateMaterialAssociations(exporterIFC, instanceHandle, bodyData.MaterialIds); } ExporterCacheManager.MEPCache.Register(element, instanceHandle); tr.Commit(); } } } return(true); }
/// <summary> /// Export the individual part (IfcBuildingElementPart). /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="partElement">The part element to export.</param> /// <param name="geometryElement">The geometry of part.</param> /// <param name="productWrapper">The ProductWrapper object.</param> public static void ExportPart(ExporterIFC exporterIFC, Element partElement, ProductWrapper productWrapper, IFCPlacementSetter placementSetter, IFCAnyHandle originalPlacement, IFCRange range, IFCExtrusionAxes ifcExtrusionAxes, Element hostElement, ElementId overrideLevelId, bool asBuildingElement) { if (!ElementFilteringUtil.IsElementVisible(partElement)) { return; } Part part = partElement as Part; if (part == null) { return; } IFCPlacementSetter standalonePlacementSetter = null; bool standaloneExport = hostElement == null && !asBuildingElement; ElementId partExportLevel = null; if (overrideLevelId != null) { partExportLevel = overrideLevelId; } else if (standaloneExport || asBuildingElement) { if (partElement.Level != null) { partExportLevel = partElement.Level.Id; } } else { if (part.OriginalCategoryId != hostElement.Category.Id) { return; } partExportLevel = hostElement.Level.Id; } if (ExporterCacheManager.PartExportedCache.HasExported(partElement.Id, partExportLevel)) { return; } Options options = GeometryUtil.GetIFCExportGeometryOptions(); View ownerView = partElement.Document.GetElement(partElement.OwnerViewId) as View; if (ownerView != null) { options.View = ownerView; } GeometryElement geometryElement = partElement.get_Geometry(options); if (geometryElement == null) { return; } try { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { IFCAnyHandle partPlacement = null; if (standaloneExport || asBuildingElement) { Transform orientationTrf = Transform.Identity; standalonePlacementSetter = IFCPlacementSetter.Create(exporterIFC, partElement, null, orientationTrf, partExportLevel); partPlacement = standalonePlacementSetter.GetPlacement(); } else { partPlacement = ExporterUtil.CreateLocalPlacement(file, originalPlacement, null); } bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); SolidMeshGeometryInfo solidMeshInfo; if (validRange) { solidMeshInfo = GeometryUtil.GetSplitClippedSolidMeshGeometry(geometryElement, range); if (solidMeshInfo.GetSolids().Count == 0 && solidMeshInfo.GetMeshes().Count == 0) { return; } } else { solidMeshInfo = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); } using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { extrusionCreationData.SetLocalPlacement(partPlacement); extrusionCreationData.ReuseLocalPlacement = false; extrusionCreationData.PossibleExtrusionAxes = ifcExtrusionAxes; IList <Solid> solids = solidMeshInfo.GetSolids(); IList <Mesh> meshes = solidMeshInfo.GetMeshes(); ElementId catId = CategoryUtil.GetSafeCategoryId(partElement); BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); if (solids.Count > 0 || meshes.Count > 0) { bodyData = BodyExporter.ExportBody(exporterIFC, partElement, catId, ElementId.InvalidElementId, solids, meshes, bodyExporterOptions, extrusionCreationData); } else { IList <GeometryObject> geomlist = new List <GeometryObject>(); geomlist.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, partElement, catId, ElementId.InvalidElementId, geomlist, bodyExporterOptions, extrusionCreationData); } IFCAnyHandle bodyRep = bodyData.RepresentationHnd; if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { extrusionCreationData.ClearOpenings(); return; } IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); representations.Add(bodyRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) { representations.Add(boundingBoxRep); } IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); string partGUID = GUIDUtil.CreateGUID(partElement); string partName = NamingUtil.GetNameOverride(partElement, NamingUtil.GetIFCName(partElement)); string partDescription = NamingUtil.GetDescriptionOverride(partElement, null); string partObjectType = NamingUtil.GetObjectTypeOverride(partElement, NamingUtil.CreateIFCObjectName(exporterIFC, partElement)); string partTag = NamingUtil.GetTagOverride(partElement, NamingUtil.CreateIFCElementId(partElement)); IFCAnyHandle ifcPart = null; if (!asBuildingElement) { ifcPart = IFCInstanceExporter.CreateBuildingElementPart(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag); } else { string ifcEnumType; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, hostElement, out ifcEnumType); switch (exportType) { case IFCExportType.ExportColumnType: ifcPart = IFCInstanceExporter.CreateColumn(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag); break; case IFCExportType.ExportCovering: IFCCoveringType coveringType = CeilingExporter.GetIFCCoveringType(hostElement, ifcEnumType); ifcPart = IFCInstanceExporter.CreateCovering(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, coveringType); break; case IFCExportType.ExportFooting: IFCFootingType footingType = FootingExporter.GetIFCFootingType(hostElement, ifcEnumType); ifcPart = IFCInstanceExporter.CreateFooting(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, footingType); break; case IFCExportType.ExportRoof: IFCRoofType roofType = RoofExporter.GetIFCRoofType(ifcEnumType); ifcPart = IFCInstanceExporter.CreateRoof(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, roofType); break; case IFCExportType.ExportSlab: IFCSlabType slabType = FloorExporter.GetIFCSlabType(ifcEnumType); ifcPart = IFCInstanceExporter.CreateSlab(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, slabType); break; case IFCExportType.ExportWall: ifcPart = IFCInstanceExporter.CreateWall(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag); break; default: ifcPart = IFCInstanceExporter.CreateBuildingElementProxy(file, partGUID, ownerHistory, partName, partDescription, partObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, partTag, null); break; } } bool containedInLevel = (standaloneExport || asBuildingElement); IFCPlacementSetter whichPlacementSetter = containedInLevel ? standalonePlacementSetter : placementSetter; productWrapper.AddElement(partElement, ifcPart, whichPlacementSetter, extrusionCreationData, containedInLevel); //Add the exported part to exported cache. TraceExportedParts(partElement, partExportLevel, standaloneExport || asBuildingElement ? ElementId.InvalidElementId : hostElement.Id); CategoryUtil.CreateMaterialAssociations(exporterIFC, ifcPart, bodyData.MaterialIds); transaction.Commit(); } } } finally { if (standalonePlacementSetter != null) { standalonePlacementSetter.Dispose(); } } }