public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; Document doc = uiapp.ActiveUIDocument.Document; Result rc; try { SpatialElementBoundaryOptions sebOptions = new SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish }; IEnumerable <Element> rooms = new FilteredElementCollector(doc) .OfClass(typeof(SpatialElement)) .Where <Element>(e => (e is Room)); List <string> compareWallAndRoom = new List <string>(); OpeningHandler openingHandler = new OpeningHandler(); List <SpatialBoundaryCache> lstSpatialBoundaryCache = new List <SpatialBoundaryCache>(); foreach (Room room in rooms) { if (room == null) { continue; } if (room.Location == null) { continue; } if (room.Area.Equals(0)) { continue; } Autodesk.Revit.DB.SpatialElementGeometryCalculator calc = new Autodesk.Revit.DB.SpatialElementGeometryCalculator( doc, sebOptions); SpatialElementGeometryResults results = calc.CalculateSpatialElementGeometry( room); Solid roomSolid = results.GetGeometry(); foreach (Face face in results.GetGeometry().Faces) { IList <SpatialElementBoundarySubface> boundaryFaceInfo = results.GetBoundaryFaceInfo(face); foreach (var spatialSubFace in boundaryFaceInfo) { if (spatialSubFace.SubfaceType != SubfaceType.Side) { continue; } SpatialBoundaryCache spatialData = new SpatialBoundaryCache(); Wall wall = doc.GetElement(spatialSubFace .SpatialBoundaryElement.HostElementId) as Wall; if (wall == null) { continue; } WallType wallType = doc.GetElement( wall.GetTypeId()) as WallType; if (wallType.Kind == WallKind.Curtain) { // Leave out, as curtain walls are not painted. LogCreator.LogEntry("WallType is CurtainWall"); continue; } HostObject hostObject = wall as HostObject; IList <ElementId> insertsThisHost = hostObject.FindInserts( true, false, true, true); double openingArea = 0; foreach (ElementId idInsert in insertsThisHost) { string countOnce = room.Id.ToString() + wall.Id.ToString() + idInsert.ToString(); if (!compareWallAndRoom.Contains(countOnce)) { Element elemOpening = doc.GetElement( idInsert) as Element; openingArea = openingArea + openingHandler.GetOpeningArea( wall, elemOpening, room, roomSolid); compareWallAndRoom.Add(countOnce); } } // Cache SpatialElementBoundarySubface info. spatialData.roomName = room.Name; spatialData.idElement = wall.Id; spatialData.idMaterial = spatialSubFace .GetBoundingElementFace().MaterialElementId; spatialData.dblNetArea = Util.sqFootToSquareM( spatialSubFace.GetSubface().Area - openingArea); spatialData.dblOpeningArea = Util.sqFootToSquareM( openingArea); lstSpatialBoundaryCache.Add(spatialData); } // end foreach subface from which room bounding elements are derived } // end foreach Face } // end foreach Room List <string> t = new List <string>(); List <SpatialBoundaryCache> groupedData = SortByRoom(lstSpatialBoundaryCache); foreach (SpatialBoundaryCache sbc in groupedData) { t.Add(sbc.roomName + "; all wall types and materials: " + sbc.AreaReport); } Util.InfoMsg2("Total Net Area in m2 by Room", string.Join(System.Environment.NewLine, t)); t.Clear(); groupedData = SortByRoomAndWallType( lstSpatialBoundaryCache); foreach (SpatialBoundaryCache sbc in groupedData) { Element elemWall = doc.GetElement( sbc.idElement) as Element; t.Add(sbc.roomName + "; " + elemWall.Name + "(" + sbc.idElement.ToString() + "): " + sbc.AreaReport); } Util.InfoMsg2("Net Area in m2 by Wall Type", string.Join(System.Environment.NewLine, t)); t.Clear(); groupedData = SortByRoomAndMaterial( lstSpatialBoundaryCache); foreach (SpatialBoundaryCache sbc in groupedData) { string materialName = (sbc.idMaterial == ElementId.InvalidElementId) ? string.Empty : doc.GetElement(sbc.idMaterial).Name; t.Add(sbc.roomName + "; " + materialName + ": " + sbc.AreaReport); } Util.InfoMsg2( "Net Area in m2 by Outer Layer Material", string.Join(System.Environment.NewLine, t)); rc = Result.Succeeded; } catch (Exception ex) { TaskDialog.Show("Room Boundaries", ex.Message + "\r\n" + ex.StackTrace); rc = Result.Failed; } return(rc); }
/// <summary> /// Test whether each room has a roof to bound it. /// </summary> /// <param name="message">Error message to be dumped.</param> /// <param name="elements">Some elements to return.</param> /// <returns></returns> private bool FindRoomBoundingRoofs(ref string message, Autodesk.Revit.DB.ElementSet elements) { // Get all rooms List <Element> rooms = GetRoomsElements(); if (rooms.Count == 0) { message = "Unable to identify any rooms, please create room first!"; return(false); } // Represents the criteria for boundary elements to be considered bounding roofs LogicalOrFilter categoryFilter = new LogicalOrFilter(new ElementCategoryFilter(BuiltInCategory.OST_Roofs), new ElementCategoryFilter(BuiltInCategory.OST_RoofSoffit)); // Calculator for room/space geometry. SpatialElementGeometryCalculator calculator = new SpatialElementGeometryCalculator(m_document); // Stores the resulting room->roof relationships Dictionary <Element, List <ElementId> > roomsAndRoofs = new Dictionary <Element, List <ElementId> >(); foreach (Element room in rooms) { // Get room geometry & boundaries SpatialElementGeometryResults results = calculator.CalculateSpatialElementGeometry((SpatialElement)room); // Get solid geometry so we can examine each face Solid geometry = results.GetGeometry(); foreach (Face face in geometry.Faces) { // Get list of roof boundary subfaces for a given face 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(m_document, localElementId)) { // Room already has roofs, add more if (roomsAndRoofs.ContainsKey(room)) { List <ElementId> roofs = roomsAndRoofs[room]; if (!roofs.Contains(localElementId)) { roofs.Add(localElementId); } } // Room found first roof else { List <ElementId> roofs = new List <ElementId>(); roofs.Add(localElementId); roomsAndRoofs.Add(room, roofs); } break; } } } } // Format results if (roomsAndRoofs.Count > 0) { String logs = String.Format("Rooms that have a bounding roof:"); message += logs + "\t\r\n"; Trace.WriteLine(logs); foreach (KeyValuePair <Element, List <ElementId> > kvp in roomsAndRoofs) { // remove this room from all rooms list rooms.Remove(kvp.Key); List <ElementId> roofs = kvp.Value; String roofsString; // Single roof boundary if (roofs.Count == 1) { Element roof = m_document.GetElement(roofs[0]); roofsString = String.Format("Roof: Id = {0}, Name = {1}", roof.Id.IntegerValue, roof.Name); } // Multiple roofs else { roofsString = "Roofs ids = " + string.Join(", ", Array.ConvertAll <ElementId, string>(roofs.ToArray(), i => i.ToString())); } // Save results logs = String.Format( " Room: Id = {0}, Name = {1} --> {2}", kvp.Key.Id.IntegerValue, kvp.Key.Name, roofsString); message += logs + "\t\r\n"; Trace.WriteLine(logs); } } // Format the rooms that have no bounding roof Trace.WriteLine("Geometry relationship checking finished..."); if (rooms.Count != 0) { String logs = String.Format("Below rooms don't have bounding roofs:"); message += logs + "\t\r\n"; Trace.WriteLine(logs); foreach (Element room in rooms) { elements.Insert(room); logs = String.Format(" Room Id: {0}, Room Name: {1}", room.Id.IntegerValue, room.Name); message += logs + "\t\r\n"; Trace.WriteLine(logs); } } 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; }
public static Dictionary <ElementId, double> MaterialsAreas(this SpatialElement spatialElement, double minArea = 0, SpatialElementGeometryCalculator spatialElementGeometryCalculator = null) { if (spatialElement == null) { return(null); } if (double.IsNaN(spatialElement.Area) || spatialElement.Area < minArea) { return(null); } if (spatialElementGeometryCalculator == null) { SpatialElementBoundaryOptions spatialElementBoundaryOptions = new SpatialElementBoundaryOptions() { SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish, StoreFreeBoundaryFaces = false }; spatialElementGeometryCalculator = new SpatialElementGeometryCalculator(spatialElement.Document, spatialElementBoundaryOptions); } SpatialElementGeometryResults spatialElementGeometryResults = spatialElementGeometryCalculator.CalculateSpatialElementGeometry(spatialElement); if (spatialElementGeometryResults == null) { return(null); } Solid solid = spatialElementGeometryResults.GetGeometry(); if (solid == null) { return(null); } Dictionary <ElementId, double> result = new Dictionary <ElementId, double>(); foreach (Face face in solid.Faces) { if (face.Area < minArea) { continue; } foreach (SpatialElementBoundarySubface spatialElementBoundarySubface in spatialElementGeometryResults.GetBoundaryFaceInfo(face)) { Face face_SpatialElement = spatialElementBoundarySubface.GetSpatialElementFace(); if (face_SpatialElement == null) { continue; } if (face_SpatialElement.Area < minArea) { continue; } Face face_BoundingElement = spatialElementBoundarySubface.GetBoundingElementFace(); if (face_BoundingElement == null) { continue; } ElementId elementId = face_BoundingElement.MaterialElementId; if (elementId != null && elementId != Autodesk.Revit.DB.ElementId.InvalidElementId) { if (result.ContainsKey(elementId)) { result[elementId] += face_SpatialElement.Area; } else { result[elementId] = face_SpatialElement.Area; } } } } return(result); }
public static List <Panel> Panels(this SpatialElement spatialElement, SpatialElementGeometryCalculator spatialElementGeometryCalculator, Core.Revit.ConvertSettings convertSettings) { if (spatialElement == null || spatialElementGeometryCalculator == null) { return(null); } SpatialElementGeometryResults spatialElementGeometryResults = spatialElementGeometryCalculator.CalculateSpatialElementGeometry(spatialElement); if (spatialElementGeometryResults == null) { return(null); } Solid solid = spatialElementGeometryResults.GetGeometry(); if (solid == null) { return(null); } List <Tuple <Face, LinkElementId, SubfaceType> > tuples = new List <Tuple <Face, LinkElementId, SubfaceType> >(); foreach (Face face in solid.Faces) { IList <SpatialElementBoundarySubface> spatialElementBoundarySubfaces = spatialElementGeometryResults.GetBoundaryFaceInfo(face); if (spatialElementBoundarySubfaces == null || spatialElementBoundarySubfaces.Count == 0) { tuples.Add(new Tuple <Face, LinkElementId, SubfaceType>(face, null, SubfaceType.Side)); continue; } foreach (SpatialElementBoundarySubface spatialElementBoundarySubface in spatialElementBoundarySubfaces) { if (spatialElementBoundarySubface == null) { continue; } Face face_Subface = spatialElementBoundarySubface.GetSubface(); //Face face_Subface = spatialElementBoundarySubface.GetSpatialElementFace(); LinkElementId linkElementId = spatialElementBoundarySubface.SpatialBoundaryElement; tuples.Add(new Tuple <Face, LinkElementId, SubfaceType>(face_Subface, linkElementId, spatialElementBoundarySubface.SubfaceType)); } } List <Panel> result = new List <Panel>(); foreach (Tuple <Face, LinkElementId, SubfaceType> tuple in tuples) { List <Geometry.Spatial.Face3D> face3Ds = Geometry.Revit.Convert.ToSAM(tuple.Item1); if (face3Ds == null || face3Ds.Count == 0) { continue; } foreach (Geometry.Spatial.Face3D face3D in face3Ds) { PanelType panelType = PanelType.Undefined; Construction construction = null; Panel panel = null; if (tuple.Item2 != null) { Element element = Core.Revit.Query.Element(spatialElement.Document, tuple.Item2); if (element != null) { HostObject hostObject = element as HostObject; if (hostObject != null) { List <Panel> panels = hostObject.ToSAM(convertSettings); if (panels != null && panels.Count > 0) { panel = panels[0]; } if (panel != null) { construction = panel.Construction; panelType = Analytical.Query.PanelType(construction?.Name); if (panelType == PanelType.Undefined) { panelType = panel.PanelType; } } if (panelType == PanelType.Undefined) { panelType = Query.PanelType(hostObject); } if (construction == null) { ElementId elementId_Type = hostObject.GetTypeId(); if (elementId_Type != null && elementId_Type != ElementId.InvalidElementId) { construction = ((HostObjAttributes)hostObject.Document.GetElement(elementId_Type)).ToSAM(convertSettings); } } } } } if (panelType == PanelType.Undefined) { panelType = Analytical.Query.PanelType(face3D.GetPlane()?.Normal); } if (panelType == PanelType.Undefined) { switch (tuple.Item3) { case SubfaceType.Bottom: panelType = PanelType.Floor; break; case SubfaceType.Top: panelType = PanelType.Roof; break; case SubfaceType.Side: panelType = PanelType.Wall; break; } } if (construction == null) { construction = Analytical.Query.DefaultConstruction(panelType); //Default Construction } if (panel == null) { panel = Analytical.Create.Panel(construction, panelType, face3D); } else { panel = Analytical.Create.Panel(panel.Guid, panel, face3D); } result.Add(panel); } } return(result); }
// defines the Main Method with 1 argument: ActiveUIDoc public void SetRoomFinishingParameters(UIDocument ActiveUIDoc) { //Active document in Revit application Document doc = ActiveUIDoc.Document; //Get collection of Rooms in indicated level IEnumerable <Element> collector = FindRooms(ActiveUIDoc); //List of RoomData List <RoomData> roomDataList = new List <RoomData>(); foreach (Room r in collector) { #region Retrieving of Room Data //List of RoomBoudingElements List <Element> roomBoundingElems = new List <Element>(); // Calculate a room's geometry and find its boundary faces SpatialElementGeometryCalculator calculator = new SpatialElementGeometryCalculator(doc); SpatialElementGeometryResults results = calculator.CalculateSpatialElementGeometry(r); // compute the room geometry Solid roomSolid = results.GetGeometry(); // get the solid representing the room's geometry // Go through the boundary faces to add this element to the list of roomBoundingElems foreach (Face face in roomSolid.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; Element elem = doc.GetElement(localElementId); //Add Room Bounding Element to list roomBoundingElems.Add(elem); } } //List of all Element Types of the Room Bounding Elements List <Element> elemsType = new List <Element>(); foreach (Element elem in roomBoundingElems) { ElementId id = elem.GetTypeId(); Element elemType = doc.GetElement(id); elemsType.Add(elemType); } //List of all unique Element Types of the Room Bounding Elements List <Element> elemsTypeDist = elemsType.Distinct(new ElemTypeIdEqualityComparer()).ToList(); //List of all unique Element Types of the Room Bounding Elements with the Floors Assembly Code indicated IEnumerable <Element> finishingFloorsElemsTypes = GetFinishingElemsTypes(elemsTypeDist, finishingFloorsAssemblyCode); //Dictionary with Key values and Keynote Texts Dictionary <string, string> finishingFloorsKeynote = GetKeynote(finishingFloorsElemsTypes, ActiveUIDoc); //Dictionary<string, string> //List of all unique Element Types of the Room Bounding Elements with the Floors Assembly Code indicated IEnumerable <Element> finishingWallsElemsTypes = GetFinishingElemsTypes(elemsTypeDist, finishingWallsAssemblyCode); //Dictionary with Key values and Keynote Texts Dictionary <string, string> finishingWallsKeynote = GetKeynote(finishingWallsElemsTypes, ActiveUIDoc); //List of all unique Element Types of the Room Bounding Elements with the Floors Assembly Code indicated IEnumerable <Element> ceilingsElemsTypes = GetFinishingElemsTypes(elemsTypeDist, ceilingsAssemblyCode); //Dictionary with Key values and Keynote Texts Dictionary <string, string> ceilingsKeynote = GetKeynote(ceilingsElemsTypes, ActiveUIDoc); #endregion // Retrieving of Room Data //new RoomData class per room var RD = new RoomData { room = r, elems = roomBoundingElems, finishingFloors = finishingFloorsKeynote, finishingWalls = finishingWallsKeynote, ceilings = ceilingsKeynote, }; //Adds Room Data to Room Data List roomDataList.Add(RD); } //Fills Parameters FillParameters(roomDataList, doc); }