// // (C) Copyright 2003-2019 by Autodesk, Inc. // // Permission to use, copy, modify, and distribute this software in // object code form for any purpose and without fee is hereby granted // provided that the above copyright notice appears in all copies and // that both that copyright notice and the limited warranty and // restricted rights notice below appear in all supporting // documentation. // // AUTODESK PROVIDES THIS PROGRAM 'AS IS' AND WITH ALL ITS FAULTS. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE // UNINTERRUPTED OR ERROR FREE. // // Use, duplication, or disclosure by the U.S. Government is subject to // restrictions set forth in FAR 52.227-19 (Commercial Computer // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. // using System; using System.Collections.Generic; using System.Text; using System.Collections.ObjectModel; using Autodesk.Revit; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.DB.Structure; namespace Revit.SDK.Samples.FoundationSlab.CS { /// /// A class collecting all useful datas from revit API for UI. /// public class SlabData { const double PlanarPrecision = 0.00033; // For finding elements and creating foundations slabs. public static Autodesk.Revit.UI.UIApplication m_revit; public static Autodesk.Revit.Creation.Application CreApp; // Foundation slab type for creating foundation slabs. FloorType m_foundationSlabType; // A set of levels to find out the lowest level of the building. SortedList m_levelList = new SortedList(); // A set of views to find out the regular slab's bounding box. List m_viewList = new List(); // A set of floors to find out all the regular slabs at the base of the building. List m_floorList = new List(); // A set of regular slabs at the base of the building. // This set supplies all the regular slabs' datas for UI. List m_allBaseSlabList = new List(); // A set of the types of foundation slab. // This set supplies all the types of foundation slab for UI. List m_slabTypeList = new List(); /// /// BaseSlabList property. /// This property is for UI. It can be edited by user. /// public Collection BaseSlabList { get { return new Collection(m_allBaseSlabList); } } /// /// FoundationSlabTypeList property. /// This property is for UI. It can not be edited by user. /// public ReadOnlyCollection FoundationSlabTypeList { get { return new ReadOnlyCollection(m_slabTypeList); } } /// /// FoundationSlabType property. /// This property gets value from UI to create foundation slabs. /// public object FoundationSlabType { set { m_foundationSlabType = value as FloorType; } } /// /// Constructor. /// /// An application object that contains data related to revit command. public SlabData(UIApplication revit) { m_revit = revit; CreApp = m_revit.Application.Create; // Find out all useful elements. FindElements(); // Get all base slabs. If no slab be found, throw an exception and return cancel. if (!GetAllBaseSlabs()) throw new NullReferenceException("No planar slabs at the base of the building."); } /// /// Check whether a regular slab is selected. /// /// The bool value suggest being selected or not. public bool CheckHaveSelected() { foreach (RegularSlab slab in m_allBaseSlabList) { if (slab.Selected) return true; } return false; } /// /// Change the Selected property for all regular slabs. /// /// The value for Selected property public void ChangeAllSelected(bool value) { foreach (RegularSlab slab in m_allBaseSlabList) { slab.Selected = value; } } /// /// Create foundation slabs. /// /// The bool value suggest successful or not. public bool CreateFoundationSlabs() { // Create a foundation slab for each selected regular slab. foreach (RegularSlab slab in m_allBaseSlabList) { if (!slab.Selected) { continue; } // Create a new slab. Autodesk.Revit.DB.XYZ normal = new Autodesk.Revit.DB.XYZ(0, 0, 1); Transaction t = new Transaction(m_revit.ActiveUIDocument.Document, Guid.NewGuid().GetHashCode().ToString()); t.Start(); Floor foundationSlab = m_revit.ActiveUIDocument.Document.Create.NewFoundationSlab( slab.OctagonalProfile, m_foundationSlabType, m_levelList.Values[0], true, normal); t.Commit(); if (null == foundationSlab) { return false; } // Delete the regular slab. Transaction t2 = new Transaction(m_revit.ActiveUIDocument.Document, Guid.NewGuid().GetHashCode().ToString()); t2.Start(); Autodesk.Revit.DB.ElementId deleteSlabId = slab.Id; m_revit.ActiveUIDocument.Document.Delete(deleteSlabId); t2.Commit(); } return true; } /// /// Find out all useful elements. /// private void FindElements() { IList filters = new List(4); filters.Add(new ElementClassFilter(typeof(Level))); filters.Add(new ElementClassFilter(typeof(View))); filters.Add(new ElementClassFilter(typeof(Floor))); filters.Add(new ElementClassFilter(typeof(FloorType))); LogicalOrFilter orFilter = new LogicalOrFilter(filters); FilteredElementCollector collector = new FilteredElementCollector(m_revit.ActiveUIDocument.Document); FilteredElementIterator iterator = collector.WherePasses(orFilter).GetElementIterator(); while (iterator.MoveNext()) { // Find out all levels. Level level = (iterator.Current) as Level; if (null != level) { m_levelList.Add(level.Elevation, level); continue; } // Find out all views. View view = (iterator.Current) as View; if (null != view && !view.IsTemplate) { m_viewList.Add(view); continue; } // Find out all floors. Floor floor = (iterator.Current) as Floor; if (null != floor) { m_floorList.Add(floor); continue; } // Find out all foundation slab types. FloorType floorType = (iterator.Current) as FloorType; if (null == floorType) { continue; } if ("Structural Foundations" == floorType.Category.Name) { m_slabTypeList.Add(floorType); } } } /// /// Get all base slabs. /// /// A bool value suggests successful or not. private bool GetAllBaseSlabs() { // No level, no slabs. if (0 == m_levelList.Count) return false; // Find out the lowest level's view for finding the bounding box of slab. View baseView = null; foreach (View view in m_viewList) { if (view.Name == m_levelList.Values[0].Name) { baseView = view; } } if (null == baseView) return false; // Get all slabs at the base of the building. foreach (Floor floor in m_floorList) { if (floor.LevelId.IntegerValue == m_levelList.Values[0].Id.IntegerValue) { BoundingBoxXYZ bbXYZ = floor.get_BoundingBox(baseView); // Get the slab's bounding box. // Check the floor. If the floor is planar, deal with it, otherwise, leap it. if (!IsPlanarFloor(bbXYZ, floor)) continue; CurveArray floorProfile = GetFloorProfile(floor); // Get the slab's profile. RegularSlab regularSlab = new RegularSlab(floor, floorProfile, bbXYZ); // Get a regular slab. m_allBaseSlabList.Add(regularSlab); // Add regular slab to the set. } } // Getting regular slabs. if (0 != m_allBaseSlabList.Count) return true; else return false; } /// /// Check whether the floor is planar. /// /// The floor's bounding box. /// The floor object. /// A bool value suggests the floor is planar or not. private static bool IsPlanarFloor(BoundingBoxXYZ bbXYZ, Floor floor) { // Get floor thickness. double floorThickness = 0.0; ElementType floorType = m_revit.ActiveUIDocument.Document.GetElement(floor.GetTypeId()) as ElementType; Parameter attribute = floorType.get_Parameter(BuiltInParameter.FLOOR_ATTR_DEFAULT_THICKNESS_PARAM); if (null != attribute) { floorThickness = attribute.AsDouble(); } // Get bounding box thickness. double boundThickness = Math.Abs(bbXYZ.Max.Z - bbXYZ.Min.Z); // Planar or not. if (Math.Abs(boundThickness - floorThickness) < PlanarPrecision) return true; else return false; } /// /// Get a floor's profile. /// /// The floor whose profile you want to get. /// The profile of the floor. private CurveArray GetFloorProfile(Floor floor) { CurveArray floorProfile = new CurveArray(); // Structural slab's profile can be found in it's AnalyticalModel. if (null != floor.GetAnalyticalModel()) { AnalyticalModel analyticalModel = floor.GetAnalyticalModel(); IList curveList = analyticalModel.GetCurves(AnalyticalCurveType.ActiveCurves); for (int i = 0; i < curveList.Count; i++) { floorProfile.Append(curveList[i]); } return floorProfile; } // Nonstructural floor's profile can be formed through it's Geometry. Options aOptions = m_revit.Application.Create.NewGeometryOptions(); Autodesk.Revit.DB.GeometryElement aElementOfGeometry = floor.get_Geometry(aOptions); //GeometryObjectArray geometryObjects = aElementOfGeometry.Objects; IEnumerator Objects = aElementOfGeometry.GetEnumerator(); //foreach (GeometryObject o in geometryObjects) while (Objects.MoveNext()) { GeometryObject o = Objects.Current; Solid solid = o as Solid; if (null == solid) continue; // Form the floor's profile through solid's edges. EdgeArray edges = solid.Edges; for (int i = 0; i < (edges.Size) / 3; i++) { Edge edge = edges.get_Item(i); List xyzArray = edge.Tessellate() as List; // A set of points. for (int j = 0; j < (xyzArray.Count - 1); j++) { Autodesk.Revit.DB.XYZ startPoint = xyzArray[j]; Autodesk.Revit.DB.XYZ endPoint = xyzArray[j + 1]; Line line = Line.CreateBound(startPoint, endPoint); floorProfile.Append(line); } } } return floorProfile; } } }