/// <summary> /// Collects all solids and meshes within a GeometryElement; the solids which consist of multiple closed volumes /// will be split into single closed volume Solids. /// </summary> /// <remarks> /// Added in 2013 to replace the temporary API method ExporterIFCUtils.GetSplitClippedSolidMeshGeometry. /// </remarks> /// <param name="range"> /// The upper and lower levels which act as the clipping boundaries. /// </param> /// <param name="geomElemToUse">The GeometryElement.</param> /// <returns>The collection of solids and meshes.</returns> public static SolidMeshGeometryInfo GetSplitClippedSolidMeshGeometry(GeometryElement geomElemToUse, IFCRange range) { SolidMeshGeometryInfo geometryInfo = GetClippedSolidMeshGeometry(geomElemToUse, range); geometryInfo.SplitSolidsList(); return(geometryInfo); }
/// <summary> /// Collects all solids and meshes within a GeometryElement; the solids which consist of multiple closed volumes /// will be split into single closed volume Solids. /// </summary> /// <remarks> /// Added in 2013 to replace the temporary API method ExporterIFCUtils.GetSplitSolidMeshGeometry. /// </remarks> /// <param name="geomElemToUse">The GeometryElement.</param> /// <returns>The collection of solids and meshes.</returns> public static SolidMeshGeometryInfo GetSplitSolidMeshGeometry(GeometryElement geomElemToUse) { SolidMeshGeometryInfo geometryInfo = GetSolidMeshGeometry(geomElemToUse, Transform.Identity); geometryInfo.SplitSolidsList(); return(geometryInfo); }
/// <summary> /// Collects all meshes within a GeometryElement and all solids clipped between a given IFCRange. /// </summary> /// <remarks> /// Added in 2013 to replace the temporary API method ExporterIFCUtils.GetClippedSolidMeshGeometry. /// </remarks> /// <param name="elem"> /// The Element from which we can obtain a bounding box. Not handled directly in this method, it is used in an internal helper method. /// </param> /// <param name="geomElemToUse"> /// The GeometryElement. /// </param> /// <param name="range"> /// The upper and lower levels which act as the clipping boundaries. /// </param> /// <returns>The collection of solids and meshes.</returns> public static SolidMeshGeometryInfo GetClippedSolidMeshGeometry(GeometryElement geomElemToUse, IFCRange range) { SolidMeshGeometryInfo geometryInfo = GetSolidMeshGeometry(geomElemToUse, Transform.Identity); geometryInfo.ClipSolidsList(geomElemToUse, range); return(geometryInfo); }
/// <summary> /// Collects all solids and meshes within a GeometryElement. /// </summary> /// <remarks> /// Added in 2013 to replace the temporary API method ExporterIFCUtils.GetSolidMeshGeometry. /// </remarks> /// <param name="geomElemToUse"> /// The GeometryElement. /// </param> /// <param name="trf"> /// The initial Transform applied on the GeometryElement. /// </param> /// <returns>The collection of solids and meshes.</returns> public static SolidMeshGeometryInfo GetSolidMeshGeometry(GeometryElement geomElemToUse, Transform trf) { if (geomElemToUse == null) { throw new ArgumentNullException("geomElemToUse"); } SolidMeshGeometryInfo geometryInfo = new SolidMeshGeometryInfo(); // call to recursive helper method to obtain all solid and mesh geometry within geomElemToUse CollectSolidMeshGeometry(geomElemToUse, trf, geometryInfo); return(geometryInfo); }
/// <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); }
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> /// Collects all solids and meshes within all nested levels of a given GeometryElement. /// </summary> /// <remarks> /// This is a private helper method for the GetSolidMeshGeometry type collection methods. /// </remarks> /// <param name="geomElem">The GeometryElement we are collecting solids and meshes from.</param> /// <param name="trf">The initial Transform applied on the GeometryElement.</param> /// <param name="solidMeshCapsule">The SolidMeshGeometryInfo object that contains the lists of collected solids and meshes.</param> private static void CollectSolidMeshGeometry(GeometryElement geomElem, Transform trf, SolidMeshGeometryInfo solidMeshCapsule) { if (geomElem == null) return; GeometryElement currGeomElem = geomElem; Transform localTrf = trf; if (localTrf == null) localTrf = Transform.Identity; else if (!localTrf.IsIdentity) currGeomElem = GetTransformedGeometry(geomElem, localTrf); // iterate through the GeometryObjects contained in the GeometryElement foreach (GeometryObject geomObj in currGeomElem) { Solid solid = geomObj as Solid; if (solid != null && solid.Faces.Size > 0 && solid.Volume > 0.0) { solidMeshCapsule.AddSolid(solid); } else { Mesh mesh = geomObj as Mesh; if (mesh != null) { solidMeshCapsule.AddMesh(mesh); } else { // if the current geomObj is castable as a GeometryInstance, then we perform the same collection on its symbol geometry GeometryInstance inst = geomObj as GeometryInstance; if (inst != null) { GeometryElement instanceSymbol = inst.GetSymbolGeometry(); if (instanceSymbol != null) { Transform instanceTransform = localTrf.Multiply(inst.Transform); CollectSolidMeshGeometry(instanceSymbol, instanceTransform, solidMeshCapsule); } } } } } }
/// <summary> /// Collects all solids and meshes within a GeometryElement. /// </summary> /// <remarks> /// Added in 2013 to replace the temporary API method ExporterIFCUtils.GetSolidMeshGeometry. /// </remarks> /// <param name="geomElemToUse">The GeometryElement.</param> /// <param name="trf">The initial Transform applied on the GeometryElement.</param> /// <returns>The collection of solids and meshes.</returns> public static SolidMeshGeometryInfo GetSolidMeshGeometry(GeometryElement geomElemToUse, Transform trf) { if (geomElemToUse == null) { throw new ArgumentNullException("geomElemToUse"); } SolidMeshGeometryInfo geometryInfo = new SolidMeshGeometryInfo(); // call to recursive helper method to obtain all solid and mesh geometry within geomElemToUse CollectSolidMeshGeometry(geomElemToUse, trf, geometryInfo); return geometryInfo; }
/// <summary> /// Collects all solids and meshes within all nested levels of a given GeometryElement. /// </summary> /// <remarks> /// This is a private helper method for the GetSolidMeshGeometry type collection methods. /// </remarks> /// <param name="geomElem"> /// The GeometryElement we are collecting solids and meshes from. /// </param> /// <param name="trf"> /// The initial Transform applied on the GeometryElement. /// </param> /// <param name="solidMeshCapsule"> /// The SolidMeshGeometryInfo object that contains the lists of collected solids and meshes. /// </param> private static void CollectSolidMeshGeometry(GeometryElement geomElem, Transform trf, SolidMeshGeometryInfo solidMeshCapsule) { if (geomElem == null) { return; } GeometryElement currGeomElem = geomElem; Transform localTrf = trf; if (localTrf == null) { localTrf = Transform.Identity; } else if (!localTrf.IsIdentity) { currGeomElem = geomElem.GetTransformed(localTrf); // The geometry element created by "GetTransformed" is a copy which will have its own allocated // membership - this needs to be stored and disposed of (see AllocatedGeometryObjectCache // for details) ExporterCacheManager.AllocatedGeometryObjectCache.AddGeometryObject(currGeomElem); } // iterate through the GeometryObjects contained in the GeometryElement foreach (GeometryObject geomObj in currGeomElem){ Solid solid = geomObj as Solid; if (solid != null && solid.Faces.Size > 0 && solid.Volume > 0.0) { solidMeshCapsule.AddSolid(solid); } else { Mesh mesh = geomObj as Mesh; if (mesh != null) { solidMeshCapsule.AddMesh(mesh); } else { // if the current geomObj is castable as a GeometryInstance, then we perform the same collection on its symbol geometry GeometryInstance inst = geomObj as GeometryInstance; if (inst != null) { GeometryElement instanceSymbol = inst.GetSymbolGeometry(); if (instanceSymbol != null) { Transform instanceTransform = localTrf.Multiply(inst.Transform); CollectSolidMeshGeometry(instanceSymbol, instanceTransform, solidMeshCapsule); } } } } } }
/// <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> /// Collects all solids and meshes within all nested levels of a given GeometryElement. /// </summary> /// <remarks> /// This is a private helper method for the GetSolidMeshGeometry type collection methods. /// </remarks> /// <param name="geomElem"> /// The GeometryElement we are collecting solids and meshes from. /// </param> /// <param name="trf"> /// The initial Transform applied on the GeometryElement. /// </param> /// <param name="solidMeshCapsule"> /// The SolidMeshGeometryInfo object that contains the lists of collected solids and meshes. /// </param> private static void CollectSolidMeshGeometry(GeometryElement geomElem, Transform trf, SolidMeshGeometryInfo solidMeshCapsule) { if (geomElem == null) { return; } GeometryElement currGeomElem = geomElem; Transform localTrf = trf; if (localTrf == null) { localTrf = Transform.Identity; } else if (!localTrf.IsIdentity) { currGeomElem = geomElem.GetTransformed(localTrf); // The geometry element created by "GetTransformed" is a copy which will have its own allocated // membership - this needs to be stored and disposed of (see AllocatedGeometryObjectCache // for details) ExporterCacheManager.AllocatedGeometryObjectCache.AddGeometryObject(currGeomElem); } // iterate through the GeometryObjects contained in the GeometryElement foreach (GeometryObject geomObj in currGeomElem) { Solid solid = geomObj as Solid; if (solid != null && solid.Faces.Size > 0 && solid.Volume > 0.0) { solidMeshCapsule.AddSolid(solid); } else { Mesh mesh = geomObj as Mesh; if (mesh != null) { solidMeshCapsule.AddMesh(mesh); } else { // if the current geomObj is castable as a GeometryInstance, then we perform the same collection on its symbol geometry GeometryInstance inst = geomObj as GeometryInstance; if (inst != null) { GeometryElement instanceSymbol = inst.GetSymbolGeometry(); if (instanceSymbol != null) { Transform instanceTransform = localTrf.Multiply(inst.Transform); CollectSolidMeshGeometry(instanceSymbol, instanceTransform, solidMeshCapsule); } } } } } }