public static List <List <RoomEdge> > GetRoomEdges(Document doc, SpatialElement room) { //Extract the boundary curves for a room based on the center of the enclosing element SpatialElementBoundaryOptions opt = new SpatialElementBoundaryOptions(); opt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Center; IList <IList <BoundarySegment> > boundarySegments = room.GetBoundarySegments(opt); List <List <RoomEdge> > allRoomEdges = new List <List <RoomEdge> >(); foreach (List <BoundarySegment> l1 in boundarySegments) { List <RoomEdge> roomEdges = new List <RoomEdge>(); foreach (BoundarySegment l2 in l1) { RoomEdge roomEdge = new RoomEdge() { _Edge = l2.GetCurve(), _StartPoint = l2.GetCurve().GetEndPoint(0), }; roomEdges.Add(roomEdge); } allRoomEdges.Add(roomEdges); } return(allRoomEdges); }
private static void GetstructuralWallArea(Document doc, SpatialElement spElem, out double wallArea) { SpatialElementBoundaryOptions boundaryOptions = new SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Center }; IList <IList <BoundarySegment> > bndSegmentsList = spElem.GetBoundarySegments(boundaryOptions); wallArea = 0; for (int i = 0; i < bndSegmentsList.Count; ++i) { for (int j = 0; j < bndSegmentsList[i].Count; ++j) { Element boundaryElem = doc.GetElement(bndSegmentsList[i][j].ElementId); if (boundaryElem is Wall && ((Wall)boundaryElem).get_Parameter(BuiltInParameter.WALL_STRUCTURAL_SIGNIFICANT).AsInteger() == 1) { Wall strWall = (Wall)boundaryElem; wallArea += (strWall.WallType.Width / 2) * (bndSegmentsList[i][j].GetCurve().Length); } } } }
/// <summary> /// Gets intersect element list. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="room"></param> /// <param name="doc"></param> /// <returns></returns> public static List <T> GetIntersectElements <T>(this SpatialElement room, Document doc) where T : Element { if (room == null) { throw new ArgumentNullException(nameof(room)); } if (doc == null) { throw new ArgumentNullException(nameof(doc)); } var results = new List <T>(); var elms = room.GetIntersectElements(doc); foreach (var elm in elms) { if (elm is T t) { results.Add(t); } } return(results); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static oM.Architecture.Elements.Room RoomFromRevit(this SpatialElement spatialElement, RevitSettings settings = null, Dictionary <string, List <IBHoMObject> > refObjects = null) { settings = settings.DefaultIfNull(); oM.Architecture.Elements.Room room = refObjects.GetValue <oM.Architecture.Elements.Room>(spatialElement.Id); if (room != null) { return(room); } room = new oM.Architecture.Elements.Room() { Perimeter = spatialElement.Perimeter(settings).First() }; room.Name = spatialElement.Name; //Set location if (spatialElement.Location != null && spatialElement.Location is LocationPoint) { room.Location = ((LocationPoint)spatialElement.Location).FromRevit(); } //Set identifiers, parameters & custom data room.SetIdentifiers(spatialElement); room.CopyParameters(spatialElement, settings.ParameterSettings); room.SetProperties(spatialElement, settings.ParameterSettings); refObjects.AddOrReplace(spatialElement.Id, room); return(room); }
public override float Evaluate(Representation representation) { RepresentationMesh repre = representation as RepresentationMesh; if (repre == null) { return(0); } if (repre.structure == null) { return(0); } asymetryList.Clear(); symmetryNode = null; symmetryNode = _getSymNode(repre.structure as LSystemGraph, level); _fillNodeValues(symmetryNode); float returnValue = 0; for (int i = 0; i < asymetryList.Count; i++) { returnValue += asymetryList[i].delta * asymetryList[i].weight; } return(returnValue); }
//Energy Analysis public void EnergyAnalysis() { // Collect space and surface data from the building's analytical thermal model EnergyAnalysisDetailModelOptions options = new EnergyAnalysisDetailModelOptions(); options.Tier = EnergyAnalysisDetailModelTier.Final; // include constructions, schedules, and non-graphical data in the computation of the energy analysis model options.EnergyModelType = EnergyModelType.SpatialElement; // Energy model based on rooms or spaces options.EnergyModelType = EnergyModelType.BuildingElement; EnergyAnalysisDetailModel eadm = EnergyAnalysisDetailModel.Create(doc, options); // Create a new energy analysis detailed model from the physical model IList <EnergyAnalysisSpace> spaces = eadm.GetAnalyticalSpaces(); StringBuilder builder = new StringBuilder(); builder.AppendLine("Spaces: " + spaces.Count); foreach (EnergyAnalysisSpace space in spaces) { SpatialElement spatialElement = doc.GetElement(space.CADObjectUniqueId) as SpatialElement; ElementId spatialElementId = spatialElement == null ? ElementId.InvalidElementId : spatialElement.Id; builder.AppendLine(" >>> " + space.SpaceName + " related to " + spatialElementId); IList <EnergyAnalysisSurface> surfaces = space.GetAnalyticalSurfaces(); builder.AppendLine(" has " + surfaces.Count + " surfaces."); foreach (EnergyAnalysisSurface surface in surfaces) { builder.AppendLine(" +++ Surface from " + surface.OriginatingElementDescription); } } TaskDialog.Show("EAM", builder.ToString()); }
public List <SpatialElement> getVeriticality(SpatialElement el) { List <SpatialElement> spatialElements = new List <SpatialElement>(); int nbPerVerticality = 0; int caughttemp1 = 0; int caughttemp2 = Convert.ToInt16(el.Name[2].ToString() + el.Name[3].ToString()); foreach (var item in localsTech) { if (item.Name.ToUpper().Contains("GT")) { try { caughttemp1 = Convert.ToInt16(item.Name[2].ToString() + item.Name[3].ToString()); if (caughttemp1 == caughttemp2) { nbPerVerticality += 1; spatialElements.Add(item); } } catch { TaskDialog.Show("Erreur de codification.", "Codification invalide de la gaine: " + item.Name); System.Environment.Exit(-1); } } spatialElements.Sort(delegate(SpatialElement c1, SpatialElement c2) { return(c1.Level.Elevation.CompareTo(c2.Level.Elevation)); }); } return(spatialElements); }
/// <summary> /// Gets the room's edge list. /// </summary> /// <param name="room"></param> /// <param name="boundary"></param> /// <returns></returns> public static List <Line> GetEdgeList(this SpatialElement room, SpatialElementBoundaryLocation boundary) { if (room == null) { throw new ArgumentNullException(nameof(room)); } var result = new List <Line>(); var opt = new SpatialElementBoundaryOptions { StoreFreeBoundaryFaces = true, SpatialElementBoundaryLocation = boundary }; var segments = room.GetBoundarySegments(opt).SelectMany(s => s); foreach (var seg in segments) { var sp = seg.GetCurve().GetEndPoint(0); var ep = seg.GetCurve().GetEndPoint(1); result.Add(Line.CreateBound(sp, ep)); } return(result); }
/// <summary> /// Gets intersect element list. /// </summary> /// <param name="room"></param> /// <param name="doc"></param> /// <returns></returns> public static List <Element> GetIntersectElements(this SpatialElement room, Document doc) { if (room is null) { throw new ArgumentNullException(nameof(room)); } if (doc is null) { throw new ArgumentNullException(nameof(doc)); } var opt = new SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = Center }; var calc = new SpatialElementGeometryCalculator(doc, opt); var solid = calc.CalculateSpatialElementGeometry(room).GetGeometry(); var instFilter = new FilteredElementCollector(doc).WhereElementIsNotElementType(); var itstFilter = new ElementIntersectsSolidFilter(solid); return(instFilter.WherePasses(itstFilter).ToList()); }
void _fillNodeValues(SpatialElement node) { SumElement se = new SumElement(); se.level = node.level; float leftSum = 0; for (int i = 0; i < node.leftBranches.Count; i++) { leftSum += node.leftBranches[i].allSize; } float rightSum = 0; for (int i = 0; i < node.rightBranches.Count; i++) { rightSum += node.rightBranches[i].allSize; } se.delta = (leftSum + rightSum) == 0 ? 0 : (float)Mathf.Abs(leftSum - rightSum) / (float)(node.allCount); se.weight = (float)node.allSize / (float)symmetryNode.allSize; asymetryList.Add(se); for (int i = 0; i < node.leftBranches.Count; i++) { _fillNodeValues(node.leftBranches[i]); } for (int i = 0; i < node.rightBranches.Count; i++) { _fillNodeValues(node.rightBranches[i]); } }
/***************************************************/ public static IBHoMObject FromRevit(this SpatialElement spatialElement, Discipline discipline, Transform transform = null, RevitSettings settings = null, Dictionary <string, List <IBHoMObject> > refObjects = null) { IElement2D result = null; switch (discipline) { case Discipline.Environmental: result = spatialElement.SpaceFromRevit(settings, refObjects); break; case Discipline.Facade: case Discipline.Architecture: case Discipline.Physical: result = spatialElement.RoomFromRevit(settings, refObjects); break; } if (result != null && transform?.IsIdentity == false) { TransformMatrix bHoMTransform = transform.FromRevit(); result = result.ITransform(bHoMTransform); } return(result as IBHoMObject); }
private bool CreateRoomMass(SpatialElement room) { if (!SpatialElementGeometryCalculator.CanCalculateGeometry(room)) { return(false); } try { SpatialElementGeometryResults results; using (var calculator = new SpatialElementGeometryCalculator(doc)) { results = calculator.CalculateSpatialElementGeometry(room); } using (Solid roomSolid = results.GetGeometry()) { var eid = new ElementId(BuiltInCategory.OST_Mass); DirectShape roomShape = DirectShape.CreateElement(doc, eid); if (roomShape != null && roomSolid.Volume > 0 && roomSolid.Faces.Size > 0) { var geomObj = new GeometryObject[] { roomSolid }; if (geomObj.Length > 0) { roomShape.SetShape(geomObj); CopyAllRoomParametersToMasses(room, roomShape); return(true); } } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } return(false); }
/***************************************************/ /**** Public methods ****/ /***************************************************/ public static List <PolyCurve> Perimeter(this SpatialElement spatialElement, RevitSettings settings = null) { if (spatialElement == null) { return(null); } IList <IList <BoundarySegment> > boundarySegments = spatialElement.GetBoundarySegments(new SpatialElementBoundaryOptions()); if (boundarySegments == null) { return(null); } List <PolyCurve> results = new List <PolyCurve>(); foreach (IList <BoundarySegment> boundarySegmentList in boundarySegments) { if (boundarySegmentList == null) { continue; } List <BH.oM.Geometry.ICurve> curves = new List <ICurve>(); foreach (BoundarySegment boundarySegment in boundarySegmentList) { curves.Add(boundarySegment.GetCurve().IFromRevit()); } results.Add(BH.Engine.Geometry.Create.PolyCurve(curves)); } return(results); }
/// <summary> /// Gets boundary curve list of the room. /// </summary> /// <param name="room"></param> /// <param name="opt"></param> /// <returns></returns> public static CurveLoop GetRoomProfile(this SpatialElement room, Option opt = null) { if (room is null) { throw new ArgumentNullException(nameof(room)); } if (opt == null) { opt = new Option { SpatialElementBoundaryLocation = Finish } } ; var segs = room.GetBoundarySegments(opt).SelectMany(s => s); var result = segs.Select(s => s.GetCurve()).ToCurveLoop(); if (result.IsOpen()) { throw new InvalidDataException("The profile isn't closed!"); } return(result); }
/// <summary> /// Curtain system parameter for ceiling, floor, etc. /// </summary> /// <param name="room"></param> /// <param name="typeName"></param> /// <param name="tplName"></param> public CurtainSystemParameter(SpatialElement room, string typeName, string tplName) { Room = room ?? throw new ArgumentNullException(nameof(room)); TypeName = typeName ?? throw new ArgumentNullException(nameof(typeName)); TemplateFileName = tplName ?? throw new ArgumentNullException(nameof(tplName)); }
/// <summary> /// Gets the nearest planar face by ray that room cener point to element center point. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="elm"></param> /// <param name="room"></param> /// <param name="doc"></param> /// <param name="view"></param> /// <returns></returns> public static PlanarFace GetNearestPlanarFace <T>(this T elm, SpatialElement room, Document doc, View3D view) where T : Element { if (elm is null) { throw new ArgumentNullException(nameof(elm)); } if (room is null) { throw new ArgumentNullException(nameof(room)); } if (doc is null) { throw new ArgumentNullException(nameof(doc)); } if (view is null) { throw new ArgumentNullException(nameof(view)); } var elmCenter = elm.GetBoundingBox(doc).GetBoxCenter(); var roomCenter = room.GetBoundingBox(doc).GetBoxCenter(); var direction = (elmCenter - roomCenter).Normalize(); var elmFilter = new ElementClassFilter(elm.GetType()); var intersector = new ReferenceIntersector(elmFilter, FindReferenceTarget.Face, view); var context = intersector.FindNearest(roomCenter, direction); doc.AutoTransaction(() => { doc.CreateModelCurve(Line.CreateBound(roomCenter, elmCenter), out _); }); if (context == null) { return(null); } var reference = context.GetReference(); var refElm = doc.GetElement(reference.ElementId); var face = refElm.GetGeometryObjectFromReference(reference) as Face; if (face is PlanarFace planarFace) { return(planarFace); } return(null); }
public static List <Panel> Panels(this SpatialElement spatialElement, SpatialElementBoundaryOptions spatialElementBoundaryOptions, Core.Revit.ConvertSettings convertSettings) { if (spatialElement == null || spatialElementBoundaryOptions == null) { return(null); } SpatialElementGeometryCalculator spatialElementGeometryCalculator = new SpatialElementGeometryCalculator(spatialElement.Document, spatialElementBoundaryOptions); return(Panels(spatialElement, spatialElementGeometryCalculator, convertSettings)); }
public SpatialElementStream(ArrayList data, object elem) { this.data = data; spatialElement = elem as SpatialElement; boundaryOptions = new SpatialElementBoundaryOptions { StoreFreeBoundaryFaces = true, SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Center }; }
/***************************************************/ public static Space SpaceFromRevit(this SpatialElement spatialElement, SpatialElementBoundaryOptions spatialElementBoundaryOptions, RevitSettings settings = null, Dictionary <string, List <IBHoMObject> > refObjects = null) { if (spatialElement == null || spatialElementBoundaryOptions == null) { return(new Space()); } SpatialElementGeometryCalculator spatialElementGeometryCalculator = new SpatialElementGeometryCalculator(spatialElement.Document, spatialElementBoundaryOptions); return(SpaceFromRevit(spatialElement, spatialElementGeometryCalculator, settings, refObjects)); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static Space SpaceFromRevit(this SpatialElement spatialElement, RevitSettings settings = null, Dictionary <string, List <IBHoMObject> > refObjects = null) { settings = settings.DefaultIfNull(); SpatialElementBoundaryOptions spatialElementBoundaryOptions = new SpatialElementBoundaryOptions(); spatialElementBoundaryOptions.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Center; spatialElementBoundaryOptions.StoreFreeBoundaryFaces = false; return(spatialElement.SpaceFromRevit(spatialElementBoundaryOptions, settings, refObjects)); }
/// <summary> /// Gets planar face list by ray that room cener point to element center point. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="elm"></param> /// <param name="room"></param> /// <param name="doc"></param> /// <param name="view"></param> /// <returns></returns> public static List <PlanarFace> GetPlanarFaceList <T>(this T elm, SpatialElement room, Document doc, View3D view) where T : Element { if (elm is null) { throw new ArgumentNullException(nameof(elm)); } if (room is null) { throw new ArgumentNullException(nameof(room)); } if (doc is null) { throw new ArgumentNullException(nameof(doc)); } if (view is null) { throw new ArgumentNullException(nameof(view)); } var elmCenter = elm.GetBoundingBox(doc).GetBoxCenter(); var roomCenter = room.GetBoundingBox(doc).GetBoxCenter(); var direction = (elmCenter - roomCenter).Normalize(); var elmFilter = new ElementClassFilter(elm.GetType()); var intersector = new ReferenceIntersector(elmFilter, FindReferenceTarget.Face, view); var contexts = intersector.Find(roomCenter, direction); var results = new List <PlanarFace>(); foreach (var context in contexts) { var reference = context.GetReference(); var refElm = doc.GetElement(reference.ElementId); var face = refElm.GetGeometryObjectFromReference(reference) as Face; if (face is PlanarFace planarFace) { results.Add(planarFace); } } return(results); }
/// <summary> /// Gets intersect element list. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="room"></param> /// <param name="doc"></param> /// <returns></returns> public static List <T> GetIntersectElements <T>(this SpatialElement room, Document doc) where T : Element { if (room is null) { throw new ArgumentNullException(nameof(room)); } if (doc is null) { throw new ArgumentNullException(nameof(doc)); } return(room.GetIntersectElements(doc).Where(w => w is T).Cast <T>().ToList()); }
public static List <Panel> Panels(this SpatialElement spatialElement, Core.Revit.ConvertSettings convertSettings) { if (spatialElement == null) { return(null); } SpatialElementBoundaryOptions spatialElementBoundaryOptions = new SpatialElementBoundaryOptions(); spatialElementBoundaryOptions.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Center; spatialElementBoundaryOptions.StoreFreeBoundaryFaces = true; return(Panels(spatialElement, spatialElementBoundaryOptions, convertSettings)); }
/***************************************************/ public static IBHoMObject FromRevit(this SpatialElement spatialElement, Discipline discipline, RevitSettings settings = null, Dictionary <string, List <IBHoMObject> > refObjects = null) { switch (discipline) { case Discipline.Environmental: return(spatialElement.SpaceFromRevit(settings, refObjects)); case Discipline.Architecture: case Discipline.Physical: return(spatialElement.RoomFromRevit(settings, refObjects)); default: return(null); } }
bool ContainsRoom(Element scopeBox, SpatialElement room) { BoundingBoxXYZ boundingBox = scopeBox.get_BoundingBox(room.Document.ActiveView); XYZ min = boundingBox.Min; XYZ max = boundingBox.Max; XYZ rmPnt = ((LocationPoint)room.Location).Point; if (rmPnt.X >= min.X && rmPnt.X <= max.X && rmPnt.Y >= min.Y && rmPnt.Y <= max.Y && rmPnt.Z >= min.Z && rmPnt.Z <= max.Z) { return(true); } return(false); }
public static InternalCondition ToSAM_InternalCondition(this SpatialElement spatialElement, ConvertSettings convertSettings) { if (spatialElement == null) { return(null); } InternalCondition result = convertSettings?.GetObject <InternalCondition>(spatialElement.Id); if (result != null) { return(result); } string name = null; Core.TypeMap typeMap = ActiveSetting.Setting.GetValue <Core.TypeMap>(Core.Revit.ActiveSetting.Name.ParameterMap); if (typeMap != null) { string parameterName = typeMap.GetName(typeof(InternalCondition), typeof(Autodesk.Revit.DB.Mechanical.Space), "Name", 2); if (!string.IsNullOrWhiteSpace(parameterName)) { Parameter parameter = spatialElement.GetParameters(parameterName)?.ToList().Find(x => x.StorageType == StorageType.String); if (parameter != null) { name = parameter.AsString(); } } if (string.IsNullOrWhiteSpace(name)) { name = Core.Revit.Query.Name(spatialElement); } if (string.IsNullOrWhiteSpace(name)) { name = spatialElement.Name; } } result = new InternalCondition(name); result.UpdateParameterSets(spatialElement, typeMap, null, null, false); convertSettings?.Add(spatialElement.Id, result); return(result); }
/// <summary> /// Finds the spatial element to its associated level. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element. /// </param> /// <returns> /// The handle. /// </returns> public override IFCAnyHandle RedirectDescription(ExporterIFC exporterIFC, Element element) { SpatialElement spatialElem = element as SpatialElement; if (spatialElem != null) { ElementId levelId = spatialElem.LevelId; IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); if (levelInfo != null) { return(levelInfo.GetBuildingStorey()); } } return(null); }
private object CreateListItem(FamilyInstance familyInstance, Phase phase) { SpatialElement spatialElement = this.GetSpatialElement(familyInstance, phase); if (spatialElement != null) { return(new object[] { familyInstance.Id.IntegerValue, phase.Id.IntegerValue, spatialElement.Id.IntegerValue, APIObjectList.GetElementId(familyInstance.DesignOption) }); } return(null); }
static public List <List <Curve> > GetCurvesListFromSpatialElement(SpatialElement spatial) { List <List <Curve> > profiles = new List <List <Curve> >(); SpatialElementBoundaryOptions opt = new SpatialElementBoundaryOptions(); IList <IList <BoundarySegment> > boundaries = spatial.GetBoundarySegments(opt); for (int i = 0; i < boundaries.Count; i++) { profiles.Add(new List <Curve>()); foreach (BoundarySegment s in boundaries[i]) { profiles[i].Add(s.GetCurve()); } } return(profiles); }
/// <summary> /// Gets boundary wall list of the room. /// </summary> /// <param name="room"></param> /// <param name="doc"></param> /// <param name="opt"></param> /// <returns></returns> public static List <Wall> GetBoundaryWallList(this SpatialElement room, Document doc, Option opt = null) { if (room is null) { throw new ArgumentNullException(nameof(room)); } if (doc is null) { throw new ArgumentNullException(nameof(doc)); } var results = new List <Wall>(); if (opt == null) { opt = new Option { SpatialElementBoundaryLocation = Finish } } ; var segments = room.GetBoundarySegments(opt).SelectMany(s => s); foreach (var segment in segments) { // It's invalid! if (segment.ElementId.IntegerValue == -1) { continue; } // Because base room boundary to do, so one wall maybe be picked up some times. if (results.FirstOrDefault(f => f.Id == segment.ElementId) != null) { continue; } if (doc.GetElement(segment.ElementId) is Wall wall) { results.Add(wall); } } return(results); } }
/// <summary> /// Exports spatial elements, including rooms, areas and spaces. 1st level space boundaries. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void ExportSpatialElement(ExporterIFC exporterIFC, SpatialElement spatialElement, ProductWrapper productWrapper) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, spatialElement, null, null)) { SpatialElementGeometryResults spatialElemGeomResult = null; if (!CreateIFCSpace(exporterIFC, spatialElement, productWrapper, setter, out spatialElemGeomResult)) return; bool isArea = (spatialElement is Area); // Do not create boundary information for areas. if (!isArea && (ExporterCacheManager.ExportOptionsCache.SpaceBoundaryLevel == 1)) { Document document = spatialElement.Document; ElementId levelId = spatialElement.LevelId; IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); double baseHeightNonScaled = (levelInfo != null) ? levelInfo.Elevation : 0.0; try { // This can throw an exception. If it does, continue to export element without boundary information. // We will re-use the previously generated value, if we have it. // TODO: warn user. if (spatialElemGeomResult == null) spatialElemGeomResult = s_SpatialElementGeometryCalculator.CalculateSpatialElementGeometry(spatialElement); Solid spatialElemGeomSolid = spatialElemGeomResult.GetGeometry(); FaceArray faces = spatialElemGeomSolid.Faces; foreach (Face face in faces) { IList<SpatialElementBoundarySubface> spatialElemBoundarySubfaces = spatialElemGeomResult.GetBoundaryFaceInfo(face); foreach (SpatialElementBoundarySubface spatialElemBSubface in spatialElemBoundarySubfaces) { if (spatialElemBSubface.SubfaceType == SubfaceType.Side) continue; if (spatialElemBSubface.GetSubface() == null) continue; ElementId elemId = spatialElemBSubface.SpatialBoundaryElement.LinkInstanceId; if (elemId == ElementId.InvalidElementId) { elemId = spatialElemBSubface.SpatialBoundaryElement.HostElementId; } Element boundingElement = document.GetElement(elemId); if (boundingElement == null) continue; bool isObjectExt = CategoryUtil.IsElementExternal(boundingElement); IFCGeometryInfo info = IFCGeometryInfo.CreateSurfaceGeometryInfo(spatialElement.Document.Application.VertexTolerance); Face subFace = spatialElemBSubface.GetSubface(); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, subFace, XYZ.Zero, false); foreach (IFCAnyHandle surfaceHnd in info.GetSurfaces()) { IFCAnyHandle connectionGeometry = IFCInstanceExporter.CreateConnectionSurfaceGeometry(file, surfaceHnd, null); SpaceBoundary spaceBoundary = new SpaceBoundary(spatialElement.Id, boundingElement.Id, setter.LevelId, connectionGeometry, IFCPhysicalOrVirtual.Physical, isObjectExt ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal); if (!ProcessIFCSpaceBoundary(exporterIFC, spaceBoundary, file)) ExporterCacheManager.SpaceBoundaryCache.Add(spaceBoundary); } } } } catch { } IList<IList<BoundarySegment>> roomBoundaries = spatialElement.GetBoundarySegments(GetSpatialElementBoundaryOptions(spatialElement)); double scaledRoomHeight = GetScaledHeight(spatialElement, levelId, levelInfo); double unscaledHeight = UnitUtil.UnscaleLength(scaledRoomHeight); Plane xyPlane = new Plane(XYZ.BasisZ, XYZ.Zero); foreach (IList<BoundarySegment> roomBoundaryList in roomBoundaries) { foreach (BoundarySegment roomBoundary in roomBoundaryList) { Element boundingElement = roomBoundary.Element; if (boundingElement == null) continue; ElementId buildingElemId = boundingElement.Id; Curve trimmedCurve = roomBoundary.Curve; if (trimmedCurve == null) continue; //trimmedCurve.Visibility = Visibility.Visible; readonly IFCAnyHandle connectionGeometry = ExtrusionExporter.CreateConnectionSurfaceGeometry( exporterIFC, trimmedCurve, xyPlane, scaledRoomHeight, baseHeightNonScaled); IFCPhysicalOrVirtual physOrVirt = IFCPhysicalOrVirtual.Physical; if (boundingElement is CurveElement) physOrVirt = IFCPhysicalOrVirtual.Virtual; else if (boundingElement is Autodesk.Revit.DB.Architecture.Room) physOrVirt = IFCPhysicalOrVirtual.NotDefined; bool isObjectExt = CategoryUtil.IsElementExternal(boundingElement); bool isObjectPhys = (physOrVirt == IFCPhysicalOrVirtual.Physical); ElementId actualBuildingElemId = isObjectPhys ? buildingElemId : ElementId.InvalidElementId; SpaceBoundary spaceBoundary = new SpaceBoundary(spatialElement.Id, actualBuildingElemId, setter.LevelId, !IFCAnyHandleUtil.IsNullOrHasNoValue(connectionGeometry) ? connectionGeometry : null, physOrVirt, isObjectExt ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal); if (!ProcessIFCSpaceBoundary(exporterIFC, spaceBoundary, file)) ExporterCacheManager.SpaceBoundaryCache.Add(spaceBoundary); // try to add doors and windows for host objects if appropriate. if (isObjectPhys && boundingElement is HostObject) { HostObject hostObj = boundingElement as HostObject; HashSet<ElementId> elemIds = new HashSet<ElementId>(); elemIds.UnionWith(hostObj.FindInserts(false, false, false, false)); if (elemIds.Count == 0) { CurtainGridSet curtainGridSet = CurtainSystemExporter.GetCurtainGridSet(hostObj); if (curtainGridSet != null) { foreach (CurtainGrid curtainGrid in curtainGridSet) elemIds.UnionWith(CurtainSystemExporter.GetVisiblePanelsForGrid(curtainGrid)); } } foreach (ElementId elemId in elemIds) { // we are going to do a simple bbox export, not complicated geometry. Element instElem = document.GetElement(elemId); if (instElem == null) continue; BoundingBoxXYZ instBBox = instElem.get_BoundingBox(null); if (instBBox == null) continue; // make copy of original trimmed curve. Curve instCurve = trimmedCurve.Clone(); XYZ instOrig = instCurve.GetEndPoint(0); // make sure that the insert is on this level. if (instBBox.Max.Z < instOrig.Z) continue; if (instBBox.Min.Z > instOrig.Z + unscaledHeight) continue; double insHeight = Math.Min(instBBox.Max.Z, instOrig.Z + unscaledHeight) - Math.Max(instOrig.Z, instBBox.Min.Z); if (insHeight < (1.0 / (12.0 * 16.0))) continue; // move base curve to bottom of bbox. XYZ moveDir = new XYZ(0.0, 0.0, instBBox.Min.Z - instOrig.Z); Transform moveTrf = Transform.CreateTranslation(moveDir); instCurve = instCurve.CreateTransformed(moveTrf); bool isHorizOrVert = false; if (instCurve is Line) { Line instLine = instCurve as Line; XYZ lineDir = instLine.Direction; if (MathUtil.IsAlmostEqual(Math.Abs(lineDir.X), 1.0) || (MathUtil.IsAlmostEqual(Math.Abs(lineDir.Y), 1.0))) isHorizOrVert = true; } double[] parameters = new double[2]; double[] origEndParams = new double[2]; bool paramsSet = false; if (!isHorizOrVert) { FamilyInstance famInst = instElem as FamilyInstance; if (famInst == null) continue; ElementType elementType = document.GetElement(famInst.GetTypeId()) as ElementType; if (elementType == null) continue; BoundingBoxXYZ symBBox = elementType.get_BoundingBox(null); if (symBBox != null) { Curve symCurve = trimmedCurve.Clone(); Transform trf = famInst.GetTransform(); Transform invTrf = trf.Inverse; Curve trfCurve = symCurve.CreateTransformed(invTrf); parameters[0] = trfCurve.Project(symBBox.Min).Parameter; parameters[1] = trfCurve.Project(symBBox.Max).Parameter; paramsSet = true; } } if (!paramsSet) { parameters[0] = instCurve.Project(instBBox.Min).Parameter; parameters[1] = instCurve.Project(instBBox.Max).Parameter; } // ignore if less than 1/16". if (Math.Abs(parameters[1] - parameters[0]) < 1.0 / (12.0 * 16.0)) continue; if (parameters[0] > parameters[1]) { //swap double tempParam = parameters[0]; parameters[0] = parameters[1]; parameters[1] = tempParam; } origEndParams[0] = instCurve.GetEndParameter(0); origEndParams[1] = instCurve.GetEndParameter(1); if (origEndParams[0] > parameters[1] - (1.0 / (12.0 * 16.0))) continue; if (origEndParams[1] < parameters[0] + (1.0 / (12.0 * 16.0))) continue; instCurve.MakeBound(parameters[0] > origEndParams[0] ? parameters[0] : origEndParams[0], parameters[1] < origEndParams[1] ? parameters[1] : origEndParams[1]); double insHeightScaled = UnitUtil.ScaleLength(insHeight); IFCAnyHandle insConnectionGeom = ExtrusionExporter.CreateConnectionSurfaceGeometry(exporterIFC, instCurve, xyPlane, insHeightScaled, baseHeightNonScaled); SpaceBoundary instBoundary = new SpaceBoundary(spatialElement.Id, elemId, setter.LevelId, !IFCAnyHandleUtil.IsNullOrHasNoValue(insConnectionGeom) ? insConnectionGeom : null, physOrVirt, isObjectExt ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal); if (!ProcessIFCSpaceBoundary(exporterIFC, instBoundary, file)) ExporterCacheManager.SpaceBoundaryCache.Add(instBoundary); } } } } } CreateZoneInfos(exporterIFC, file, spatialElement, productWrapper); CreateSpaceOccupantInfo(exporterIFC, file, spatialElement, productWrapper); } transaction.Commit(); } }
/// <summary> /// Creates IFC room/space/area item, not include boundaries. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="spatialElement">The spatial element.</param> /// <param name="productWrapper">The ProductWrapper.</param> /// <param name="setter">The PlacementSetter.</param> /// <returns>True if created successfully, false otherwise.</returns> static bool CreateIFCSpace(ExporterIFC exporterIFC, SpatialElement spatialElement, ProductWrapper productWrapper, PlacementSetter setter, out SpatialElementGeometryResults results) { results = null; IList<CurveLoop> curveLoops = null; try { // Avoid throwing for a spatial element with no location. if (spatialElement.Location == null) return false; SpatialElementBoundaryOptions options = GetSpatialElementBoundaryOptions(spatialElement); curveLoops = ExporterIFCUtils.GetRoomBoundaryAsCurveLoopArray(spatialElement, options, true); } catch (Autodesk.Revit.Exceptions.InvalidOperationException) { //Some spatial elements are not placed that have no boundary loops. Don't export them. return false; } Autodesk.Revit.DB.Document document = spatialElement.Document; ElementId levelId = spatialElement.LevelId; ElementId catId = spatialElement.Category != null ? spatialElement.Category.Id : ElementId.InvalidElementId; double dArea = 0.0; if (ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_AREA, out dArea) != null) dArea = UnitUtil.ScaleArea(dArea); IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); string strSpaceNumber = null; string strSpaceName = null; string strSpaceDesc = null; if (ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ROOM_NUMBER, out strSpaceNumber) == null) strSpaceNumber = null; if (ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ROOM_NAME, out strSpaceName) == null) strSpaceName = null; if (ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS, out strSpaceDesc) == null) strSpaceDesc = null; string name = strSpaceNumber; string longName = strSpaceName; string desc = strSpaceDesc; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle localPlacement = setter.LocalPlacement; ElementType elemType = document.GetElement(spatialElement.GetTypeId()) as ElementType; IFCInternalOrExternal internalOrExternal = CategoryUtil.IsElementExternal(spatialElement) ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal; double scaledRoomHeight = GetScaledHeight(spatialElement, levelId, levelInfo); if (scaledRoomHeight <= 0.0) return false; double bottomOffset; ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_LOWER_OFFSET, out bottomOffset); double elevation = (levelInfo != null) ? levelInfo.Elevation : 0.0; XYZ zDir = new XYZ(0, 0, 1); XYZ orig = new XYZ(0, 0, elevation + bottomOffset); Plane plane = new Plane(zDir, orig); // room calculated as level offset. GeometryElement geomElem = null; bool isArea = (spatialElement is Area); Area spatialElementAsArea = isArea ? (spatialElement as Area) : null; if (spatialElement is Autodesk.Revit.DB.Architecture.Room) { Autodesk.Revit.DB.Architecture.Room room = spatialElement as Autodesk.Revit.DB.Architecture.Room; geomElem = room.ClosedShell; } else if (spatialElement is Autodesk.Revit.DB.Mechanical.Space) { Autodesk.Revit.DB.Mechanical.Space space = spatialElement as Autodesk.Revit.DB.Mechanical.Space; geomElem = space.ClosedShell; } else if (isArea) { Options geomOptions = GeometryUtil.GetIFCExportGeometryOptions(); geomElem = spatialElementAsArea.get_Geometry(geomOptions); } IFCAnyHandle spaceHnd = null; string spatialElementName = null; using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { extraParams.SetLocalPlacement(localPlacement); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; using (IFCTransaction transaction2 = new IFCTransaction(file)) { IFCAnyHandle repHnd = null; if (!ExporterCacheManager.ExportOptionsCache.Use2DRoomBoundaryForRoomVolumeCreation && geomElem != null) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); bodyExporterOptions.TessellationLevel = BodyExporter.GetTessellationLevel(); repHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, spatialElement, catId, geomElem, bodyExporterOptions, null, extraParams, false); if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) extraParams.ClearOpenings(); } else { IFCAnyHandle shapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, plane, zDir, scaledRoomHeight); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return false; IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, shapeRep, ElementId.InvalidElementId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(shapeRep); shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, spatialElement, catId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomElem, Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); repHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); } extraParams.ScaledHeight = scaledRoomHeight; extraParams.ScaledArea = dArea; spatialElementName = NamingUtil.GetNameOverride(spatialElement, name); string spatialElementDescription = NamingUtil.GetDescriptionOverride(spatialElement, desc); string spatialElementObjectType = NamingUtil.GetObjectTypeOverride(spatialElement, null); string spatialElementLongName = NamingUtil.GetLongNameOverride(spatialElement, longName); double? spaceElevationWithFlooring = null; double elevationWithFlooring = 0.0; if (ParameterUtil.GetDoubleValueFromElement(spatialElement, null, "IfcElevationWithFlooring", out elevationWithFlooring) != null) spaceElevationWithFlooring = UnitUtil.ScaleLength(elevationWithFlooring); spaceHnd = IFCInstanceExporter.CreateSpace(file, GUIDUtil.CreateGUID(spatialElement), ExporterCacheManager.OwnerHistoryHandle, spatialElementName, spatialElementDescription, spatialElementObjectType, extraParams.GetLocalPlacement(), repHnd, spatialElementLongName, Toolkit.IFCElementComposition.Element, internalOrExternal, spaceElevationWithFlooring); transaction2.Commit(); } if (spaceHnd != null) { productWrapper.AddSpace(spatialElement, spaceHnd, levelInfo, extraParams, true); if (isArea) { Element areaScheme = spatialElementAsArea.AreaScheme; if (areaScheme != null) { ElementId areaSchemeId = areaScheme.Id; HashSet<IFCAnyHandle> areas = null; if (!ExporterCacheManager.AreaSchemeCache.TryGetValue(areaSchemeId, out areas)) { areas = new HashSet<IFCAnyHandle>(); ExporterCacheManager.AreaSchemeCache[areaSchemeId] = areas; } areas.Add(spaceHnd); } } } } // Save room handle for later use/relationships ExporterCacheManager.SpaceInfoCache.SetSpaceHandle(spatialElement, spaceHnd); // Find Ceiling as a Space boundary and keep the relationship in a cache for use later bool ret = GetCeilingSpaceBoundary(spatialElement, out results); if (!MathUtil.IsAlmostZero(dArea) && !(ExporterCacheManager.ExportOptionsCache.ExportAsCOBIE) && !ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 && !ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { bool isDesignGrossArea = (string.Compare(spatialElementName, "GSA Design Gross Area") > 0); PropertyUtil.CreatePreCOBIEGSAQuantities(exporterIFC, spaceHnd, "GSA Space Areas", (isDesignGrossArea ? "GSA Design Gross Area" : "GSA BIM Area"), dArea); } // Export Classifications for SpatialElement for GSA/COBIE. if (ExporterCacheManager.ExportOptionsCache.ExportAsCOBIE) { ProjectInfo projectInfo = document.ProjectInformation; if (projectInfo != null) CreateCOBIESpaceClassifications(exporterIFC, file, spaceHnd, projectInfo, spatialElement); } return true; }
/// <summary> /// Creates COBIESpaceClassifications. /// </summary> /// <param name="exporterIFC">The ExporterIFC.</param> /// <param name="file">The file.</param> /// <param name="spaceHnd">The space handle.</param> /// <param name="projectInfo">The project info.</param> /// <param name="spatialElement">The spatial element.</param> private static void CreateCOBIESpaceClassifications(ExporterIFC exporterIFC, IFCFile file, IFCAnyHandle spaceHnd, ProjectInfo projectInfo, SpatialElement spatialElement) { HashSet<IFCAnyHandle> spaceHnds = new HashSet<IFCAnyHandle>(); spaceHnds.Add(spaceHnd); string bimStandardsLocation = null; if (projectInfo != null) ParameterUtil.GetStringValueFromElement(projectInfo.Id, "BIM Standards URL", out bimStandardsLocation); // OCCS - Space by Function. string itemReference = ""; if (ParameterUtil.GetStringValueFromElement(spatialElement.Id, "OmniClass Number", out itemReference) != null) { string itemName; ParameterUtil.GetStringValueFromElement(spatialElement.Id, "OmniClass Title", out itemName); IFCAnyHandle classification; if (!ExporterCacheManager.ClassificationCache.ClassificationHandles.TryGetValue("OmniClass", out classification)) { classification = IFCInstanceExporter.CreateClassification(file, "http://www.omniclass.org", "v 1.0", null, "OmniClass"); ExporterCacheManager.ClassificationCache.ClassificationHandles.Add("OmniClass", classification); } IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, "http://www.omniclass.org/tables/OmniClass_13_2006-03-28.pdf", itemReference, itemName, classification); IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, GUIDUtil.CreateGUID(), ExporterCacheManager.OwnerHistoryHandle, "OmniClass", null, spaceHnds, classificationReference); } // Space Type (Owner) itemReference = ""; if (ParameterUtil.GetStringValueFromElement(spatialElement.Id, "Space Type (Owner) Reference", out itemReference) != null) { string itemName; ParameterUtil.GetStringValueFromElement(spatialElement.Id, "Space Type (Owner) Name", out itemName); IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, bimStandardsLocation, itemReference, itemName, null); IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, GUIDUtil.CreateGUID(), ExporterCacheManager.OwnerHistoryHandle, "Space Type (Owner)", null, spaceHnds, classificationReference); } // Space Category (Owner) itemReference = ""; if (ParameterUtil.GetStringValueFromElement(spatialElement.Id, "Space Category (Owner) Reference", out itemReference) != null) { string itemName; ParameterUtil.GetStringValueFromElement(spatialElement.Id, "Space Category (Owner) Name", out itemName); IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, bimStandardsLocation, itemReference, itemName, null); IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, GUIDUtil.CreateGUID(), ExporterCacheManager.OwnerHistoryHandle, "Space Category (Owner)", null, spaceHnds, classificationReference); } // Space Category (BOMA) itemReference = ""; if (ParameterUtil.GetStringValueFromElement(spatialElement.Id, "Space Category (BOMA) Reference", out itemReference) != null) { string itemName; ParameterUtil.GetStringValueFromElement(spatialElement.Id, "Space Category (BOMA) Name", out itemName); IFCAnyHandle classificationReference = IFCInstanceExporter.CreateClassificationReference(file, "http://www.BOMA.org", itemReference, itemName, null); IFCAnyHandle relAssociates = IFCInstanceExporter.CreateRelAssociatesClassification(file, GUIDUtil.CreateGUID(), ExporterCacheManager.OwnerHistoryHandle, "Space Category (BOMA)", "", spaceHnds, classificationReference); } }
/// <summary> /// Gets the height of a spatial element. /// </summary> /// <param name="spatialElement">The spatial element.</param> /// <param name="levelId">The level id.</param> /// <param name="levelInfo">The level info.</param> /// <returns> /// The height, scaled in IFC units. /// </returns> static double GetScaledHeight(SpatialElement spatialElement, ElementId levelId, IFCLevelInfo levelInfo) { Document document = spatialElement.Document; bool isArea = spatialElement is Area; ElementId topLevelId = ElementId.InvalidElementId; double topOffset = 0.0; // These values are internally set for areas, but are invalid. Ignore them and just use the level height. if (!isArea) { ParameterUtil.GetElementIdValueFromElement(spatialElement, BuiltInParameter.ROOM_UPPER_LEVEL, out topLevelId); ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_UPPER_OFFSET, out topOffset); } double bottomOffset; ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_LOWER_OFFSET, out bottomOffset); Level bottomLevel = document.GetElement(levelId) as Level; Level topLevel = (levelId == topLevelId) ? bottomLevel : document.GetElement(topLevelId) as Level; double roomHeight = 0.0; if (bottomLevel != null && topLevel != null) { roomHeight = (topLevel.Elevation - bottomLevel.Elevation) + (topOffset - bottomOffset); roomHeight = UnitUtil.ScaleLength(roomHeight); } if (MathUtil.IsAlmostZero(roomHeight)) { double levelHeight = ExporterCacheManager.LevelInfoCache.FindHeight(levelId); if (levelHeight < 0.0) levelHeight = LevelUtil.CalculateDistanceToNextLevel(document, levelId, levelInfo); roomHeight = UnitUtil.ScaleLength(levelHeight); } // For area spaces, we assign a dummy height (1 unit), as we are not allowed to export IfcSpaces without a volumetric representation. if (MathUtil.IsAlmostZero(roomHeight) && spatialElement is Area) { roomHeight = 1.0; } return roomHeight; }
/// <summary> /// Gets the boundary options of a spatial element. /// </summary> /// <param name="spatialElement">The spatial element. null to get the default options.</param> /// <returns>The SpatialElementBoundaryOptions.</returns> static SpatialElementBoundaryOptions GetSpatialElementBoundaryOptions(SpatialElement spatialElement) { SpatialElementBoundaryOptions spatialElementBoundaryOptions = new SpatialElementBoundaryOptions(); spatialElementBoundaryOptions.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish; if (spatialElement == null) return spatialElementBoundaryOptions; SpatialElementType spatialElementType = SpatialElementType.Room; if (spatialElement is Autodesk.Revit.DB.Architecture.Room) { spatialElementType = SpatialElementType.Room; } else if (spatialElement is Area) { spatialElementType = SpatialElementType.Area; } else if (spatialElement is Autodesk.Revit.DB.Mechanical.Space) { spatialElementType = SpatialElementType.Space; } else return spatialElementBoundaryOptions; AreaVolumeSettings areaSettings = AreaVolumeSettings.GetAreaVolumeSettings(spatialElement.Document); if (areaSettings != null) { spatialElementBoundaryOptions.SpatialElementBoundaryLocation = areaSettings.GetSpatialElementBoundaryLocation(spatialElementType); } return spatialElementBoundaryOptions; }
/// <summary> /// Creates IFC room/space/area item, not include boundaries. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> /// <param name="setter"> /// The IFCPlacementSetter. /// </param> /// <returns> /// True if created successfully, false otherwise. /// </returns> static bool CreateIFCSpace(ExporterIFC exporterIFC, SpatialElement spatialElement, ProductWrapper productWrapper, IFCPlacementSetter setter) { IList<CurveLoop> curveLoops = null; try { SpatialElementBoundaryOptions options = ExporterIFCUtils.GetSpatialElementBoundaryOptions(exporterIFC, spatialElement); curveLoops = ExporterIFCUtils.GetRoomBoundaryAsCurveLoopArray(spatialElement, options, true); } catch (Autodesk.Revit.Exceptions.InvalidOperationException) { //Some spatial elements are not placed that have no boundary loops. Don't export them. return false; } Autodesk.Revit.DB.Document document = spatialElement.Document; ElementId levelId = spatialElement.Level != null ? spatialElement.Level.Id : ElementId.InvalidElementId; double scale = exporterIFC.LinearScale; ElementId catId = spatialElement.Category != null ? spatialElement.Category.Id : ElementId.InvalidElementId; double dArea = 0.0; if (ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_AREA, out dArea)) dArea *= (scale * scale); IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); string strSpaceNumber = null; string strSpaceName = null; string strSpaceDesc = null; bool isArea = spatialElement is Area; if (!isArea) { if (!ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ROOM_NUMBER, out strSpaceNumber)) strSpaceNumber = null; if (!ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ROOM_NAME, out strSpaceName)) strSpaceName = null; if (!ParameterUtil.GetStringValueFromElement(spatialElement, BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS, out strSpaceDesc)) strSpaceDesc = null; } else { // Default to true to preserve previous behavior. bool? exportGSADesignGrossArea = ExporterCacheManager.ExportOptionsCache.ExportGSAGrossDesignArea; if (!exportGSADesignGrossArea.HasValue || exportGSADesignGrossArea.Value) { Element level = document.GetElement(levelId); if (level != null) { strSpaceNumber = level.Name + " GSA Design Gross Area"; } } } string name = strSpaceNumber; string longName = strSpaceName; string desc = strSpaceDesc; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle localPlacement = setter.GetPlacement(); ElementType elemType = document.GetElement(spatialElement.GetTypeId()) as ElementType; IFCInternalOrExternal internalOrExternal = CategoryUtil.IsElementExternal(spatialElement, true) ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal; double roomHeight = 0.0; roomHeight = GetHeight(spatialElement, scale, levelId, levelInfo); if (roomHeight <= 0.0) return false; double bottomOffset; ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_LOWER_OFFSET, out bottomOffset); XYZ zDir = new XYZ(0, 0, 1); XYZ orig = new XYZ(0, 0, levelInfo.Elevation + bottomOffset); Plane plane = new Plane(zDir, orig); // room calculated as level offset. GeometryElement geomElem = null; if (spatialElement is Autodesk.Revit.DB.Architecture.Room) { Autodesk.Revit.DB.Architecture.Room room = spatialElement as Autodesk.Revit.DB.Architecture.Room; geomElem = room.ClosedShell; } else if (spatialElement is Autodesk.Revit.DB.Mechanical.Space) { Autodesk.Revit.DB.Mechanical.Space space = spatialElement as Autodesk.Revit.DB.Mechanical.Space; geomElem = space.ClosedShell; } IFCAnyHandle spaceHnd = null; using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { extraParams.SetLocalPlacement(localPlacement); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; using (IFCTransaction transaction2 = new IFCTransaction(file)) { IFCAnyHandle repHnd = null; if (!ExporterCacheManager.ExportOptionsCache.Use2DRoomBoundaryForRoomVolumeCreation && geomElem != null) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); bodyExporterOptions.TessellationLevel = BodyExporterOptions.BodyTessellationLevel.Coarse; repHnd = RepresentationUtil.CreateAppropriateProductDefinitionShape(exporterIFC, spatialElement, catId, geomElem, bodyExporterOptions, null, extraParams); if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) extraParams.ClearOpenings(); } else { IFCAnyHandle shapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, plane, zDir, roomHeight); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return false; IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, shapeRep, ElementId.InvalidElementId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(shapeRep); shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, spatialElement, catId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); IFCAnyHandle boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geomElem, Transform.Identity); if (boundingBoxRep != null) shapeReps.Add(boundingBoxRep); repHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); } extraParams.ScaledHeight = roomHeight; extraParams.ScaledArea = dArea; string spatialElementName = NamingUtil.GetNameOverride(spatialElement, name); string spatialElementDescription = NamingUtil.GetDescriptionOverride(spatialElement, desc); string spatialElementObjectType = NamingUtil.GetObjectTypeOverride(spatialElement, null); double? spaceElevationWithFlooring = null; double elevationWithFlooring = 0.0; if (ParameterUtil.GetDoubleValueFromElement(spatialElement, "IfcElevationWithFlooring", out elevationWithFlooring) == true) spaceElevationWithFlooring = elevationWithFlooring; spaceHnd = IFCInstanceExporter.CreateSpace(file, GUIDUtil.CreateGUID(spatialElement), exporterIFC.GetOwnerHistoryHandle(), spatialElementName,spatialElementDescription, spatialElementObjectType, extraParams.GetLocalPlacement(), repHnd, longName, Toolkit.IFCElementComposition.Element, internalOrExternal, spaceElevationWithFlooring); transaction2.Commit(); } productWrapper.AddSpace(spaceHnd, levelInfo, extraParams, true); } // Save room handle for later use/relationships ExporterCacheManager.SpatialElementHandleCache.Register(spatialElement.Id, spaceHnd); exporterIFC.RegisterSpatialElementHandle(spatialElement.Id, spaceHnd); // Find Ceiling as a Space boundary and keep the relationship in a cache for use later Boolean ret = getCeilingSpaceBoundary(spatialElement); if (!MathUtil.IsAlmostZero(dArea) && !(ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE) && !ExporterCacheManager.ExportOptionsCache.ExportAs2x3CoordinationView2 && !ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { ExporterIFCUtils.CreatePreCOBIEGSAQuantities(exporterIFC, spaceHnd, "GSA Space Areas", (isArea ? "GSA Design Gross Area" : "GSA BIM Area"), dArea); } // Export BaseQuantities for SpatialElement if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities && !(ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE)) { // Skip this step. The "standard" quantities will be exported at the end of export element process in exportElement (Exporter.cs) // ExporterIFCUtils.CreateNonCOBIERoomQuantities(exporterIFC, spaceHnd, spatialElement, dArea, roomHeight); } // Create general classification for Spatial element from ClassificationCode(s). This is not done here but rather at the end of exportElement process // ClassificationUtil.CreateClassification(exporterIFC, file, spatialElement, spaceHnd, ""); // Export Classifications for SpatialElement for GSA/COBIE. if (ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE) { CreateCOBIESpaceClassifications(exporterIFC, file, spaceHnd, document.ProjectInformation, spatialElement); } return true; }
/// <summary> /// Collect relationship information from Ceiling to Room to be used later to determine whether a Ceiling can be contained in a Room /// </summary> /// <param name="spatialElement">The revit spatial object to process</param> /// <param name="results">The results of the CalculateSpatialElementGeometry call, for caching for later use.</param> /// <returns>True if it found a ceiling, false otherwise.</returns> static private bool GetCeilingSpaceBoundary(SpatialElement spatialElement, out SpatialElementGeometryResults results) { results = null; // Areas don't have a 3D rep, so no ceiling space boundaries. if (spatialElement is Area) return false; // Represents the criteria for boundary elements to be considered bounding Ceiling LogicalOrFilter categoryFilter = new LogicalOrFilter(new ElementCategoryFilter(BuiltInCategory.OST_Ceilings), new ElementCategoryFilter(BuiltInCategory.OST_Ceilings)); try { results = s_SpatialElementGeometryCalculator.CalculateSpatialElementGeometry(spatialElement); } catch { return false; } Solid geometry = results.GetGeometry(); // Go through the boundary faces to identify whether it is bounded by a Ceiling. If it is Ceiling, add into the Cache foreach (Face face in geometry.Faces) { IList<SpatialElementBoundarySubface> boundaryFaces = results.GetBoundaryFaceInfo(face); foreach (SpatialElementBoundarySubface boundaryFace in boundaryFaces) { // Get boundary element LinkElementId boundaryElementId = boundaryFace.SpatialBoundaryElement; // Only considering local file room bounding elements ElementId localElementId = boundaryElementId.HostElementId; // Evaluate if element meets criteria using PassesFilter() if (localElementId != ElementId.InvalidElementId && categoryFilter.PassesFilter(spatialElement.Document, localElementId)) { if (ExporterCacheManager.CeilingSpaceRelCache.ContainsKey(localElementId)) { // The ceiling already exists in the Dictionary, add the Space into list IList<ElementId> roomlist = ExporterCacheManager.CeilingSpaceRelCache[localElementId]; roomlist.Add(spatialElement.Id); } else { // The first time this Ceiling Id appears IList<ElementId> roomlist = new List<ElementId>(); roomlist.Add(spatialElement.Id); ExporterCacheManager.CeilingSpaceRelCache.Add(localElementId, roomlist); } } } } return true; }
/// <summary> /// Export spatial elements, including rooms, areas and spaces. 1st level space boundaries. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> public static void ExportSpatialElement(ExporterIFC exporterIFC, SpatialElement spatialElement, IFCProductWrapper productWrapper) { //quick reject bool isArea = spatialElement is Area; if (isArea) { if (!IsAreaGrossInterior(exporterIFC, spatialElement)) return; } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { ElementId levelId = spatialElement.Level != null ? spatialElement.Level.Id : ElementId.InvalidElementId; using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, spatialElement, null, null, levelId)) { CreateIFCSpace(exporterIFC, spatialElement, productWrapper, setter); // Do not create boundary information, or extra property sets. if (spatialElement is Area) { tr.Commit(); return; } if (exporterIFC.SpaceBoundaryLevel == 1) { Document document = spatialElement.Document; IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); double baseHeightNonScaled = levelInfo.Elevation; SpatialElementGeometryResults spatialElemGeomResult = s_SpatialElemGeometryCalculator.CalculateSpatialElementGeometry(spatialElement); Solid spatialElemGeomSolid = spatialElemGeomResult.GetGeometry(); FaceArray faces = spatialElemGeomSolid.Faces; foreach (Face face in faces) { IList<SpatialElementBoundarySubface> spatialElemBoundarySubfaces = spatialElemGeomResult.GetBoundaryFaceInfo(face); foreach (SpatialElementBoundarySubface spatialElemBSubface in spatialElemBoundarySubfaces) { if (spatialElemBSubface.SubfaceType == SubfaceType.Side) continue; if (spatialElemBSubface.GetSubface() == null) continue; ElementId elemId = spatialElemBSubface.SpatialBoundaryElement.LinkInstanceId; if (elemId == ElementId.InvalidElementId) { elemId = spatialElemBSubface.SpatialBoundaryElement.HostElementId; } Element boundingElement = document.get_Element(elemId); if (boundingElement == null) continue; bool isObjectExt = CategoryUtil.IsElementExternal(boundingElement); IFCGeometryInfo info = IFCGeometryInfo.CreateSurfaceGeometryInfo(spatialElement.Document.Application.VertexTolerance); Face subFace = spatialElemBSubface.GetSubface(); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, subFace, XYZ.Zero, false); IFCAnyHandle ifcOptionalHnd = IFCAnyHandle.Create(); foreach (IFCAnyHandle surfaceHnd in info.GetSurfaces()) { IFCAnyHandle connectionGeometry = file.CreateConnectionSurfaceGeometry(surfaceHnd, ifcOptionalHnd); IFCSpaceBoundary spaceBoundary = IFCSpaceBoundary.Create(spatialElement.Id, boundingElement.Id, connectionGeometry, IFCSpaceBoundaryType.Physical, isObjectExt); if (!ProcessIFCSpaceBoundary(exporterIFC, spaceBoundary, file)) exporterIFC.RegisterIFCSpaceBoundary(spaceBoundary); } } } IList<IList<BoundarySegment>> roomBoundaries = spatialElement.GetBoundarySegments(ExporterIFCUtils.GetSpatialElementBoundaryOptions(exporterIFC, spatialElement)); double roomHeight = GetHeight(spatialElement, exporterIFC.LinearScale, levelInfo); XYZ zDir = new XYZ(0, 0, 1); foreach (IList<BoundarySegment> roomBoundaryList in roomBoundaries) { foreach (BoundarySegment roomBoundary in roomBoundaryList) { Element boundingElement = roomBoundary.Element; if (boundingElement == null) continue; ElementId buildingElemId = boundingElement.Id; Curve trimmedCurve = roomBoundary.Curve; if (trimmedCurve == null) continue; //trimmedCurve.Visibility = Visibility.Visible; readonly IFCAnyHandle connectionGeometry = ExporterIFCUtils.CreateExtrudedSurfaceFromCurve( exporterIFC, trimmedCurve, zDir, roomHeight, baseHeightNonScaled); IFCSpaceBoundaryType physOrVirt = IFCSpaceBoundaryType.Physical; if (boundingElement is CurveElement) physOrVirt = IFCSpaceBoundaryType.Virtual; else if (boundingElement is Autodesk.Revit.DB.Architecture.Room) physOrVirt = IFCSpaceBoundaryType.Undefined; bool isObjectExt = CategoryUtil.IsElementExternal(boundingElement); bool isObjectPhys = (physOrVirt == IFCSpaceBoundaryType.Physical); ElementId actualBuildingElemId = isObjectPhys ? buildingElemId : ElementId.InvalidElementId; IFCSpaceBoundary boundary = IFCSpaceBoundary.Create(spatialElement.Id, actualBuildingElemId, connectionGeometry, physOrVirt, isObjectExt); if (!ProcessIFCSpaceBoundary(exporterIFC, boundary, file)) exporterIFC.RegisterIFCSpaceBoundary(boundary); // try to add doors and windows for host objects if appropriate. if (isObjectPhys && boundingElement is HostObject) { HostObject hostObj = boundingElement as HostObject; IList<ElementId> elemIds = hostObj.FindInserts(false, false, false, false); foreach (ElementId elemId in elemIds) { // we are going to do a simple bbox export, not complicated geometry. Element instElem = document.get_Element(elemId); if (instElem == null) continue; BoundingBoxXYZ instBBox = instElem.get_BoundingBox(null); // make copy of original trimmed curve. Curve instCurve = trimmedCurve.Clone(); XYZ instOrig = instCurve.get_EndPoint(0); // make sure that the insert is on this level. if (instBBox.Max.Z < instOrig.Z) continue; if (instBBox.Min.Z > instOrig.Z + roomHeight) continue; double insHeight = Math.Min(instBBox.Max.Z, instOrig.Z + roomHeight) - Math.Max(instOrig.Z, instBBox.Min.Z); if (insHeight < (1.0 / (12.0 * 16.0))) continue; // move base curve to bottom of bbox. XYZ moveDir = new XYZ(0.0, 0.0, instBBox.Min.Z - instOrig.Z); Transform moveTrf = Transform.get_Translation(moveDir); instCurve = instCurve.get_Transformed(moveTrf); bool isHorizOrVert = false; if (instCurve is Line) { Line instLine = instCurve as Line; XYZ lineDir = instLine.Direction; if (MathUtil.IsAlmostEqual(Math.Abs(lineDir.X), 1.0) || (MathUtil.IsAlmostEqual(Math.Abs(lineDir.Y), 1.0))) isHorizOrVert = true; } double[] parameters = new double[2]; double[] origEndParams = new double[2]; if (isHorizOrVert) { parameters[0] = instCurve.Project(instBBox.Min).Parameter; parameters[1] = instCurve.Project(instBBox.Max).Parameter; } else { FamilyInstance famInst = instElem as FamilyInstance; if (famInst == null) continue; ElementType elementType = document.get_Element(famInst.GetTypeId()) as ElementType; if (elementType == null) continue; BoundingBoxXYZ symBBox = elementType.get_BoundingBox(null); Curve symCurve = trimmedCurve.Clone(); Transform trf = famInst.GetTransform(); Transform invTrf = trf.Inverse; Curve trfCurve = symCurve.get_Transformed(invTrf); parameters[0] = trfCurve.Project(symBBox.Min).Parameter; parameters[1] = trfCurve.Project(symBBox.Max).Parameter; } // ignore if less than 1/16". if (Math.Abs(parameters[1] - parameters[0]) < 1.0 / (12.0 * 16.0)) continue; if (parameters[0] > parameters[1]) { //swap double tempParam = parameters[0]; parameters[0] = parameters[1]; parameters[1] = tempParam; } origEndParams[0] = instCurve.get_EndParameter(0); origEndParams[1] = instCurve.get_EndParameter(1); if (origEndParams[0] > parameters[1] - (1.0 / (12.0 * 16.0))) continue; if (origEndParams[1] < parameters[0] + (1.0 / (12.0 * 16.0))) continue; if (parameters[0] > origEndParams[0]) instCurve.set_EndParameter(0, parameters[0]); if (parameters[1] < origEndParams[1]) instCurve.set_EndParameter(1, parameters[1]); IFCAnyHandle insConnectionGeom = ExporterIFCUtils.CreateExtrudedSurfaceFromCurve(exporterIFC, instCurve, zDir, insHeight, baseHeightNonScaled); IFCSpaceBoundary instBoundary = IFCSpaceBoundary.Create(spatialElement.Id, elemId, insConnectionGeom, physOrVirt, isObjectExt); if (!ProcessIFCSpaceBoundary(exporterIFC, instBoundary, file)) exporterIFC.RegisterIFCSpaceBoundary(instBoundary); } } } } } ExporterIFCUtils.CreateSpatialElementPropertySet(exporterIFC, spatialElement, productWrapper); } tr.Commit(); } }
/// <summary> /// Creates SpaceBoundary from a bounding element. /// </summary> /// <param name="file"> /// The IFC file. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="boundingElement"> /// The bounding element. /// </param> /// <param name="connectionGeometry"> /// The connection geometry handle. /// </param> static void CreateIFCSpaceBoundary(IFCFile file, ExporterIFC exporterIFC, SpatialElement spatialElement, Element boundingElement, IFCAnyHandle connectionGeometry) { IFCSpaceBoundaryType physOrVirt = IFCSpaceBoundaryType.Physical; if (boundingElement is CurveElement) physOrVirt = IFCSpaceBoundaryType.Virtual; else if (boundingElement is Autodesk.Revit.DB.Architecture.Room) physOrVirt = IFCSpaceBoundaryType.Undefined; bool isObjectExt = CategoryUtil.IsElementExternal(boundingElement); IFCSpaceBoundary spaceBoundary = IFCSpaceBoundary.Create(spatialElement.Id, boundingElement.Id, connectionGeometry, physOrVirt, isObjectExt); if (!ProcessIFCSpaceBoundary(exporterIFC, spaceBoundary, file)) exporterIFC.RegisterIFCSpaceBoundary(spaceBoundary); }
/// <summary> /// Get the height of a spatial element. /// </summary> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="scale"> /// The scale value. /// </param> /// <param name="levelInfo"> /// The level info. /// </param> /// <returns> /// The height. /// </returns> static double GetHeight(SpatialElement spatialElement, double scale, IFCLevelInfo levelInfo) { Document document = spatialElement.Document; double roomHeight = 0.0; double bottomOffset = 0.0; ElementId bottomLevelId = spatialElement.Level.Id; Parameter paramTopLevelId = spatialElement.get_Parameter(BuiltInParameter.ROOM_UPPER_LEVEL); ElementId topLevelId = paramTopLevelId != null ? paramTopLevelId.AsElementId() : ElementId.InvalidElementId; Parameter paramTopOffset = spatialElement.get_Parameter(BuiltInParameter.ROOM_UPPER_OFFSET); double topOffset = paramTopOffset != null ? paramTopOffset.AsDouble() : 0.0; Parameter paramBottomOffset = spatialElement.get_Parameter(BuiltInParameter.ROOM_LOWER_OFFSET); bottomOffset = paramBottomOffset != null ? paramBottomOffset.AsDouble() : 0.0; Level bottomLevel = document.get_Element(bottomLevelId) as Level; Level topLevel = (bottomLevelId == topLevelId) ? bottomLevel : document.get_Element(topLevelId) as Level; if (bottomLevel != null && topLevel != null) { roomHeight = (topLevel.Elevation - bottomLevel.Elevation) + (topOffset - bottomOffset); roomHeight *= scale; } if (MathUtil.IsAlmostZero(roomHeight)) { roomHeight = levelInfo.DistanceToNextLevel * scale; } // For area spaces, we assign a dummy height (1'), as we are not allowed to export IfcSpaces without a volumetric representation. if (MathUtil.IsAlmostZero(roomHeight) && spatialElement is Area) { roomHeight = 1.0; } return roomHeight; }
/// <summary> /// Create IFC room/space/area item, not include boundaries. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> /// <param name="setter"> /// The IFCPlacementSetter. /// </param> /// <returns> /// True if created successfully, false otherwise. /// </returns> static void CreateIFCSpace(ExporterIFC exporterIFC, SpatialElement spatialElement, IFCProductWrapper productWrapper, IFCPlacementSetter setter) { Autodesk.Revit.DB.Document document = spatialElement.Document; ElementId levelId = spatialElement.Level != null ? spatialElement.Level.Id : ElementId.InvalidElementId; double scale = exporterIFC.LinearScale; ElementId catId = spatialElement.Category != null ? spatialElement.Category.Id : ElementId.InvalidElementId; double dArea = 0.0; Parameter param = spatialElement.get_Parameter(BuiltInParameter.ROOM_AREA); if (param != null) { dArea = param.AsDouble(); dArea *= (scale * scale); } SpatialElementBoundaryOptions options = ExporterIFCUtils.GetSpatialElementBoundaryOptions(exporterIFC, spatialElement); IList<CurveLoop> curveLoops = ExporterIFCUtils.GetRoomBoundaryAsCurveLoopArray(spatialElement, options, true); IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); string strSpaceNumber = null; string strSpaceName = null; string strSpaceDesc = null; bool isArea = spatialElement is Area; if (!isArea) { Parameter paramRoomNum = spatialElement.get_Parameter(BuiltInParameter.ROOM_NUMBER); if (paramRoomNum != null) { strSpaceNumber = paramRoomNum.AsString(); } Parameter paramRoomName = spatialElement.get_Parameter(BuiltInParameter.ROOM_NAME); if (paramRoomName != null) { strSpaceName = paramRoomName.AsString(); } Parameter paramRoomComm = spatialElement.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS); if (paramRoomComm != null) { strSpaceDesc = paramRoomComm.AsString(); } } else { Element level = document.get_Element(levelId); if (level != null) { strSpaceNumber = level.Name + " GSA Design Gross Area"; } } //assign empty string if it is null if (strSpaceNumber == null) strSpaceNumber = ""; if (strSpaceName == null) strSpaceName = ""; if (strSpaceDesc == null) strSpaceDesc = ""; IFCLabel name = IFCLabel.Create(strSpaceNumber); IFCLabel longName = IFCLabel.Create(strSpaceName); IFCLabel desc = IFCLabel.Create(strSpaceDesc); IFCFile file = exporterIFC.GetFile(); IFCAnyHandle localPlacement = setter.GetPlacement(); ElementType elemType = document.get_Element(spatialElement.GetTypeId()) as ElementType; bool isObjectExternal = CategoryUtil.IsElementExternal(spatialElement); IFCMeasureValue elevationWithFlooring = IFCMeasureValue.Create(); double roomHeight = 0.0; roomHeight = GetHeight(spatialElement, scale, levelInfo); double bottomOffset = 0.0; Parameter paramBottomOffset = spatialElement.get_Parameter(BuiltInParameter.ROOM_LOWER_OFFSET); bottomOffset = paramBottomOffset != null ? paramBottomOffset.AsDouble() : 0.0; XYZ zDir = new XYZ(0, 0, 1); XYZ orig = new XYZ(0, 0, levelInfo.Elevation + bottomOffset); Plane plane = new Plane(zDir, orig); // room calculated as level offset. GeometryElement geomElem = null; if (spatialElement is Autodesk.Revit.DB.Architecture.Room) { Autodesk.Revit.DB.Architecture.Room room = spatialElement as Autodesk.Revit.DB.Architecture.Room; geomElem = room.ClosedShell; } else if (spatialElement is Autodesk.Revit.DB.Mechanical.Space) { Autodesk.Revit.DB.Mechanical.Space space = spatialElement as Autodesk.Revit.DB.Mechanical.Space; geomElem = space.ClosedShell; } IFCAnyHandle spaceHnd = null; IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData(); extraParams.SetLocalPlacement(localPlacement); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; using (IFCTransaction tr2 = new IFCTransaction(file)) { IFCAnyHandle repHnd = null; if (!(exporterIFC.ExportAs2x2 || Use2DRoomBoundaryForRoomVolumeCalculation()) && geomElem != null) { IFCSolidMeshGeometryInfo solidMeshInfo = ExporterIFCUtils.GetSolidMeshGeometry(exporterIFC, geomElem, Transform.Identity); IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> polyMeshes = solidMeshInfo.GetMeshes(); bool tryToExportAsExtrusion = true; if (solids.Count != 1 || polyMeshes.Count != 0) tryToExportAsExtrusion = false; IList<GeometryObject> geomObjects = new List<GeometryObject>(); foreach (Solid solid in solids) geomObjects.Add(solid); IFCAnyHandle shapeRep = BodyExporter.ExportBody(spatialElement.Document.Application, exporterIFC, catId, geomObjects, tryToExportAsExtrusion, extraParams); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); repHnd = file.CreateProductDefinitionShape(IFCLabel.Create(), IFCLabel.Create(), shapeReps); } else { IFCAnyHandle shapeRep = file.CreateExtrudedSolidFromCurveLoop(exporterIFC, catId, curveLoops, plane, zDir, roomHeight); //pScaledOrig? HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(shapeRep); shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, catId, exporterIFC.Get3DContextHandle(), bodyItems, IFCAnyHandle.Create()); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); repHnd = file.CreateProductDefinitionShape(IFCLabel.Create(), IFCLabel.Create(), shapeReps); } extraParams.ScaledHeight = roomHeight; extraParams.ScaledArea = dArea; spaceHnd = file.CreateSpace(IFCLabel.CreateGUID(spatialElement), exporterIFC.GetOwnerHistoryHandle(), NamingUtil.GetNameOverride(spatialElement, name), NamingUtil.GetDescriptionOverride(spatialElement, desc), NamingUtil.GetObjectTypeOverride(spatialElement, IFCLabel.Create()), extraParams.GetLocalPlacement(), repHnd, longName, IFCElementComposition.Element , isObjectExternal, elevationWithFlooring); tr2.Commit(); } productWrapper.AddSpace(spaceHnd, levelInfo, extraParams, true); // Save room handle for later use/relationships exporterIFC.RegisterSpatialElementHandle(spatialElement.Id, spaceHnd); if (!MathUtil.IsAlmostZero(dArea) && !(exporterIFC.FileVersion == IFCVersion.IFCCOBIE)) { ExporterIFCUtils.CreatePreCOBIEGSAQuantities(exporterIFC, spaceHnd, "GSA Space Areas", (isArea ? "GSA Design Gross Area" : "GSA BIM Area"), dArea); } // Export BaseQuantities for RoomElem if (exporterIFC.ExportBaseQuantities && !(exporterIFC.FileVersion == IFCVersion.IFCCOBIE)) { ExporterIFCUtils.CreateNonCOBIERoomQuantities(exporterIFC, spaceHnd, spatialElement, dArea, roomHeight); } }
/// <summary> /// Checks if the spatial element is gross interior. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <returns> /// True if the area is gross interior. /// </returns> static bool IsAreaGrossInterior(ExporterIFC exporterIFC, SpatialElement spatialElement) { Area area = spatialElement as Area; if (area != null) { if (!area.IsGrossInterior) return false; double dArea; if (!ParameterUtil.GetDoubleValueFromElement(area, BuiltInParameter.ROOM_AREA, out dArea)) return false; return !MathUtil.IsAlmostZero(dArea); } return false; }
/// <summary> /// Creates IFC room/space/area item, not include boundaries. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> /// <param name="setter"> /// The IFCPlacementSetter. /// </param> /// <returns> /// True if created successfully, false otherwise. /// </returns> static bool CreateIFCSpace(ExporterIFC exporterIFC, SpatialElement spatialElement, IFCProductWrapper productWrapper, IFCPlacementSetter setter) { IList<CurveLoop> curveLoops = null; try { SpatialElementBoundaryOptions options = ExporterIFCUtils.GetSpatialElementBoundaryOptions(exporterIFC, spatialElement); curveLoops = ExporterIFCUtils.GetRoomBoundaryAsCurveLoopArray(spatialElement, options, true); } catch (Autodesk.Revit.Exceptions.InvalidOperationException) { //Some spatial elements are not placed that have no boundary loops. Don't export them. return false; } Autodesk.Revit.DB.Document document = spatialElement.Document; ElementId levelId = spatialElement.Level != null ? spatialElement.Level.Id : ElementId.InvalidElementId; double scale = exporterIFC.LinearScale; ElementId catId = spatialElement.Category != null ? spatialElement.Category.Id : ElementId.InvalidElementId; double dArea = 0.0; Parameter param = spatialElement.get_Parameter(BuiltInParameter.ROOM_AREA); if (param != null) { dArea = param.AsDouble(); dArea *= (scale * scale); } IFCLevelInfo levelInfo = exporterIFC.GetLevelInfo(levelId); string strSpaceNumber = null; string strSpaceName = null; string strSpaceDesc = null; bool isArea = spatialElement is Area; if (!isArea) { Parameter paramRoomNum = spatialElement.get_Parameter(BuiltInParameter.ROOM_NUMBER); if (paramRoomNum != null) { strSpaceNumber = paramRoomNum.AsString(); } Parameter paramRoomName = spatialElement.get_Parameter(BuiltInParameter.ROOM_NAME); if (paramRoomName != null) { strSpaceName = paramRoomName.AsString(); } Parameter paramRoomComm = spatialElement.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS); if (paramRoomComm != null) { strSpaceDesc = paramRoomComm.AsString(); } } else { Element level = document.GetElement(levelId); if (level != null) { strSpaceNumber = level.Name + " GSA Design Gross Area"; } } string name = strSpaceNumber; string longName = strSpaceName; string desc = strSpaceDesc; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle localPlacement = setter.GetPlacement(); ElementType elemType = document.GetElement(spatialElement.GetTypeId()) as ElementType; IFCInternalOrExternal internalOrExternal = CategoryUtil.IsElementExternal(spatialElement) ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal; double roomHeight = 0.0; roomHeight = GetHeight(spatialElement, scale, levelId, levelInfo); double bottomOffset = 0.0; Parameter paramBottomOffset = spatialElement.get_Parameter(BuiltInParameter.ROOM_LOWER_OFFSET); bottomOffset = paramBottomOffset != null ? paramBottomOffset.AsDouble() : 0.0; XYZ zDir = new XYZ(0, 0, 1); XYZ orig = new XYZ(0, 0, levelInfo.Elevation + bottomOffset); Plane plane = new Plane(zDir, orig); // room calculated as level offset. GeometryElement geomElem = null; if (spatialElement is Autodesk.Revit.DB.Architecture.Room) { Autodesk.Revit.DB.Architecture.Room room = spatialElement as Autodesk.Revit.DB.Architecture.Room; geomElem = room.ClosedShell; } else if (spatialElement is Autodesk.Revit.DB.Mechanical.Space) { Autodesk.Revit.DB.Mechanical.Space space = spatialElement as Autodesk.Revit.DB.Mechanical.Space; geomElem = space.ClosedShell; } IFCAnyHandle spaceHnd = null; using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { extraParams.SetLocalPlacement(localPlacement); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; using (IFCTransaction transaction2 = new IFCTransaction(file)) { IFCAnyHandle repHnd = null; if (!ExporterCacheManager.ExportOptionsCache.Use2DRoomBoundaryForRoomVolumeCreation && geomElem != null) { BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); bodyExporterOptions.TessellationLevel = BodyExporterOptions.BodyTessellationLevel.Coarse; repHnd = RepresentationUtil.CreateBRepProductDefinitionShape(spatialElement.Document.Application, exporterIFC, spatialElement, catId, geomElem, bodyExporterOptions, null, extraParams); if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) extraParams.ClearOpenings(); } else { IFCAnyHandle shapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, plane, zDir, roomHeight); if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep)) return false; IFCAnyHandle styledItemHnd = BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, document, shapeRep, ElementId.InvalidElementId); HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(shapeRep); shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, spatialElement, catId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null); IList<IFCAnyHandle> shapeReps = new List<IFCAnyHandle>(); shapeReps.Add(shapeRep); repHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); } extraParams.ScaledHeight = roomHeight; extraParams.ScaledArea = dArea; spaceHnd = IFCInstanceExporter.CreateSpace(file, ExporterIFCUtils.CreateGUID(spatialElement), exporterIFC.GetOwnerHistoryHandle(), NamingUtil.GetNameOverride(spatialElement, name), NamingUtil.GetDescriptionOverride(spatialElement, desc), NamingUtil.GetObjectTypeOverride(spatialElement, null), extraParams.GetLocalPlacement(), repHnd, longName, Toolkit.IFCElementComposition.Element , internalOrExternal, null); transaction2.Commit(); } productWrapper.AddSpace(spaceHnd, levelInfo, extraParams, true); } // Save room handle for later use/relationships ExporterCacheManager.SpatialElementHandleCache.Register(spatialElement.Id, spaceHnd); exporterIFC.RegisterSpatialElementHandle(spatialElement.Id, spaceHnd); if (!MathUtil.IsAlmostZero(dArea) && !(ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE)) { ExporterIFCUtils.CreatePreCOBIEGSAQuantities(exporterIFC, spaceHnd, "GSA Space Areas", (isArea ? "GSA Design Gross Area" : "GSA BIM Area"), dArea); } // Export BaseQuantities for SpatialElement if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities && !(ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE)) { ExporterIFCUtils.CreateNonCOBIERoomQuantities(exporterIFC, spaceHnd, spatialElement, dArea, roomHeight); } // Export Classifications for SpatialElement for GSA/COBIE. if (ExporterCacheManager.ExportOptionsCache.FileVersion == IFCVersion.IFCCOBIE) { CreateCOBIESpaceClassifications(exporterIFC, file, spaceHnd, document.ProjectInformation, spatialElement); } return true; }
/// <summary> /// Creates SpaceBoundary from a bounding element. /// </summary> /// <param name="file"> /// The IFC file. /// </param> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="boundingElement"> /// The bounding element. /// </param> /// <param name="levelId"> /// The level id. /// </param> /// <param name="connectionGeometry"> /// The connection geometry handle. /// </param> static void CreateIFCSpaceBoundary(IFCFile file, ExporterIFC exporterIFC, SpatialElement spatialElement, Element boundingElement, ElementId levelId, IFCAnyHandle connectionGeometry) { IFCPhysicalOrVirtual physOrVirt = IFCPhysicalOrVirtual.Physical; if (boundingElement == null || boundingElement is CurveElement) physOrVirt = IFCPhysicalOrVirtual.Virtual; else if (boundingElement is Autodesk.Revit.DB.Architecture.Room) physOrVirt = IFCPhysicalOrVirtual.NotDefined; bool isObjectExt = CategoryUtil.IsElementExternal(boundingElement); SpaceBoundary spaceBoundary = new SpaceBoundary(spatialElement.Id, boundingElement != null ? boundingElement.Id : ElementId.InvalidElementId, levelId, connectionGeometry, physOrVirt, isObjectExt ? IFCInternalOrExternal.External : IFCInternalOrExternal.Internal); if (!ProcessIFCSpaceBoundary(exporterIFC, spaceBoundary, file)) ExporterCacheManager.SpaceBoundaryCache.Add(spaceBoundary); }
/// <summary> /// Check if the spatial element is gross interior. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <returns> /// True if the area is gross interior. /// </returns> static bool IsAreaGrossInterior(ExporterIFC exporterIFC, SpatialElement spatialElement) { Area area = spatialElement as Area; if (area != null) { double scale = exporterIFC.LinearScale; double dArea = 0.0; Parameter paramRoomArea = area.get_Parameter(BuiltInParameter.ROOM_AREA); if (paramRoomArea != null && paramRoomArea.StorageType == StorageType.Double) { dArea = paramRoomArea.AsDouble(); dArea *= (scale * scale); } // convert scale to export scale; area is scale squared. if (!MathUtil.IsAlmostZero(dArea) && area.IsGrossInterior) return true; } return false; }
/// <summary> /// Gets the height of a spatial element. /// </summary> /// <param name="spatialElement"> /// The spatial element. /// </param> /// <param name="scale"> /// The scale value. /// </param> /// <param name="levelInfo"> /// The level info. /// </param> /// <returns> /// The height. /// </returns> static double GetHeight(SpatialElement spatialElement, double scale, ElementId levelId, IFCLevelInfo levelInfo) { Document document = spatialElement.Document; ElementId topLevelId; ParameterUtil.GetElementIdValueFromElement(spatialElement, BuiltInParameter.ROOM_UPPER_LEVEL, out topLevelId); double topOffset; ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_UPPER_OFFSET, out topOffset); double bottomOffset; ParameterUtil.GetDoubleValueFromElement(spatialElement, BuiltInParameter.ROOM_LOWER_OFFSET, out bottomOffset); Level bottomLevel = document.GetElement(levelId) as Level; Level topLevel = (levelId == topLevelId) ? bottomLevel : document.GetElement(topLevelId) as Level; double roomHeight = 0.0; if (bottomLevel != null && topLevel != null) { roomHeight = (topLevel.Elevation - bottomLevel.Elevation) + (topOffset - bottomOffset); roomHeight *= scale; } if (MathUtil.IsAlmostZero(roomHeight)) { double levelHeight = ExporterCacheManager.LevelInfoCache.FindHeight(levelId); if (levelHeight < 0.0) levelHeight = LevelUtil.calculateDistanceToNextLevel(document, levelId, levelInfo); roomHeight = levelHeight * scale; } // For area spaces, we assign a dummy height (1'), as we are not allowed to export IfcSpaces without a volumetric representation. if (MathUtil.IsAlmostZero(roomHeight) && spatialElement is Area) { roomHeight = 1.0; } return roomHeight; }