{"id":1416,"date":"2018-10-30T11:24:25","date_gmt":"2018-10-30T10:24:25","guid":{"rendered":"https:\/\/www.modelical.com\/?p=1416"},"modified":"2022-05-09T11:40:50","modified_gmt":"2022-05-09T09:40:50","slug":"system-categories-multiple-body-fix-and-clean","status":"publish","type":"node","link":"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/","title":{"rendered":"Split Multibody floors and roofs"},"content":{"rendered":"<p>This macro will help you clean Revit models where the user has created multibody floors and ceilings as these can pose challenges for proper quantity takeoff. The macro has three methods:<\/p>\n<ul>\n<li>SelectMultibodyFloors: selects floors visible in the view with more than one body. Please note that floors completely split by an opening will be selected also.<\/li>\n<li>SelectMultibodyCeilings:\u00a0 selects ceilings\u00a0visible in the view with more than one body. Please note that ceilings\u00a0completely split by an opening will be selected also. Please note that the Revit API (2019) does not expose methods for creating ceilings so we are limited to selecting them.<\/li>\n<li>SplitMultibodyFloors: selects and splits floors visible in the view with more than one body. Please note that floors cut or split by openings will be recreated with the visible shape.<\/li>\n<\/ul>\n<p>To use it, create a new module and name it &#8220;GeometryCleaner&#8221;, then replace all the text with the following content. Press F8 and make sure Build Completed Successfully is shown in the lower left corner of your screen.<\/p>\n<pre class=\"lang:c# decode:true\">\/*\r\n * Created by SharpDevelop.\r\n * User: Roberto Molinos [Modelical]\r\n * Date: 3\/20\/2015\r\n * Time: 1:42 AM\r\n *\/\r\nusing System;\r\nusing Autodesk.Revit.UI;\r\nusing Autodesk.Revit.DB;\r\nusing Autodesk.Revit.UI.Selection;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing Autodesk.Revit.DB.Macros;\r\n\r\nnamespace GeometryCleaner\r\n{\r\n\t[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]\r\n\t[Autodesk.Revit.DB.Macros.AddInId(\"6ACE9B39-339F-4D56-BC11-9D6973B54D94\")]\r\n\tpublic partial class ThisApplication\r\n\t{\r\n\t\tprivate void Module_Startup(object sender, EventArgs e)\r\n\t\t{\r\n\r\n\t\t}\r\n\r\n\t\tprivate void Module_Shutdown(object sender, EventArgs e)\r\n\t\t{\r\n\r\n\t\t}\r\n\r\n\t\t#region Revit Macros generated code\r\n\t\tprivate void InternalStartup()\r\n\t\t{\r\n\t\t\tthis.Startup += new System.EventHandler(Module_Startup);\r\n\t\t\tthis.Shutdown += new System.EventHandler(Module_Shutdown);\r\n\t\t}\r\n\t\t#endregion\r\n\t\tconst double _eps = 1.0e-9;\r\n\t\t\r\n\t\tpublic void SelectMultibodyFloors()\r\n\t\t{\r\n\t\t\t\r\n\t\t\tDocument document = this.ActiveUIDocument.Document;\r\n\t\t\tUIDocument uidoc = new UIDocument (document);\r\n\t\t\t\r\n\t\t\tList&lt;ElementId&gt; ids = new List&lt;ElementId&gt;();\r\n\t\t\tList&lt;ElementId&gt; badIds = new List&lt;ElementId&gt;();\r\n\t\t\t\r\n\t\t\tList&lt;int&gt; cs = new List&lt;int&gt;();\r\n\t\t\t\r\n\t\t\tFilteredElementCollector collector = new FilteredElementCollector(document,this.ActiveUIDocument.ActiveView.Id);\r\n\t\t\tICollection&lt;Element&gt; elems = collector.WherePasses(new ElementCategoryFilter(BuiltInCategory.OST_Floors)).WhereElementIsNotElementType().ToElements();\r\n\t\t\t\r\n\t\t\tAutodesk.Revit.DB.Options geomOption = document.Application.Create.NewGeometryOptions();\r\n\t\t\t\r\n\t\t\tTransaction tempTransaction = new Transaction(document, \"Temp geometry extraction\");\r\n\t\t\ttempTransaction.Start();\r\n\t\t\t\r\n\t\t\tforeach (Element e in elems)\r\n\t\t\t{\r\n\t\t\t\tif (e is Floor)\r\n\t\t\t\t{\r\n\t\t\t\t\tFloor f = e as Floor;\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (!PartUtils.HasAssociatedParts(document, f.Id))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tFloorType fType = f.FloorType;\r\n\t\t\t\t\t\tCompoundStructure comStruct = fType.GetCompoundStructure();\r\n\t\t\t\t\t\tint c = 0;\r\n\t\t\t\t\t\tfor (int j = 0; j &lt; comStruct.LayerCount; j++)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tIList&lt;CompoundStructureLayer&gt; cslList = comStruct.GetLayers();\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tbool countLayer = true;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tif(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.Membrane)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tcountLayer = false;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.StructuralDeck)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif(comStruct.GetDeckEmbeddingType(j) != StructDeckEmbeddingType.Standalone)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tcountLayer = false;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (countLayer)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tc++;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcs.Add(c);\r\n\t\t\t\t\t\tids.Add(f.Id);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tPartUtils.CreateParts(document,ids);\r\n\t\t\tdocument.Regenerate();\r\n\t\t\tint i = 0;\r\n\t\t\tforeach (ElementId fid in ids)\r\n\t\t\t{\r\n\t\t\t\tICollection&lt;ElementId&gt; partIds = PartUtils.GetAssociatedParts(document,fid,false,false);\r\n\t\t\t\tif (cs[i] != partIds.Count)\r\n\t\t\t\t{\r\n\t\t\t\t\tbadIds.Add(fid);\r\n\t\t\t\t\t\/\/TaskDialog.Show(\"Warning\", \"Multibody Object Found\");\r\n\t\t\t\t}\r\n\t\t\t\ti++;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\ttempTransaction.RollBack();\r\n\r\n\t\t\tusing (Transaction transaction = new Transaction(document, \"Select Multibody Floors\"))\r\n\t\t\t{\r\n\t\t\t\tif(transaction.Start() == TransactionStatus.Started)\r\n\t\t\t\t{\r\n\r\n\t\t\t\t\tuidoc.Selection.SetElementIds(badIds);\r\n\t\t\t\t\t\r\n\t\t\t\t\tif(transaction.Commit() == TransactionStatus.Committed)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tTaskDialog.Show(\"Selected \" , badIds.Count.ToString() + \" floor(s) with multiple bodies.\");\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttransaction.RollBack();\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tpublic void SelectMultibodyCeilings()\r\n\t\t{\r\n\t\t\t\r\n\t\t\tDocument document = this.ActiveUIDocument.Document;\r\n\t\t\tUIDocument uidoc = new UIDocument (document);\r\n\t\t\t\r\n\t\t\tList&lt;ElementId&gt; ids = new List&lt;ElementId&gt;();\r\n\t\t\tList&lt;ElementId&gt; badIds = new List&lt;ElementId&gt;();\r\n\t\t\t\r\n\t\t\tList&lt;int&gt; cs = new List&lt;int&gt;();\r\n\t\t\t\r\n\t\t\tElementFilter ff = new ElementCategoryFilter(BuiltInCategory.OST_Ceilings);\r\n\t\t\tFilteredElementCollector collector = new FilteredElementCollector(document,this.ActiveUIDocument.ActiveView.Id);\r\n\t\t\tICollection&lt;Element&gt; elems = collector.WherePasses(ff).WhereElementIsNotElementType().ToElements();\r\n\t\t\t\r\n\t\t\tAutodesk.Revit.DB.Options geomOption = document.Application.Create.NewGeometryOptions();\r\n\t\t\t\r\n\t\t\tTransaction tempTransaction = new Transaction(document, \"Temp geometry extraction\");\r\n\t\t\ttempTransaction.Start();\r\n\t\t\t\r\n\t\t\tforeach (Element e in elems)\r\n\t\t\t{\r\n\t\t\t\tif (e is Ceiling)\r\n\t\t\t\t\t\r\n\t\t\t\t{\r\n\t\t\t\t\tCeiling f = e as Ceiling;\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (!PartUtils.HasAssociatedParts(document, f.Id))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tElementId fTypeId = f.GetTypeId();\r\n\t\t\t\t\t\tCeilingType fType = document.GetElement(fTypeId) as CeilingType;\r\n\t\t\t\t\t\tCompoundStructure comStruct = fType.GetCompoundStructure();\r\n\t\t\t\t\t\tint c = 0;\r\n\t\t\t\t\t\tfor (int j = 0; j &lt; comStruct.LayerCount; j++)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tIList&lt;CompoundStructureLayer&gt; cslList = comStruct.GetLayers();\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tbool countLayer = true;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tif(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.Membrane)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tcountLayer = false;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.StructuralDeck)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif(comStruct.GetDeckEmbeddingType(j) != StructDeckEmbeddingType.Standalone)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tcountLayer = false;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (countLayer)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\tc++;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcs.Add(c);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tids.Add(f.Id);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tPartUtils.CreateParts(document,ids);\r\n\t\t\tdocument.Regenerate();\r\n\t\t\tint i = 0;\r\n\t\t\tforeach (ElementId fid in ids)\r\n\t\t\t{\r\n\t\t\t\tICollection&lt;ElementId&gt; partIds = PartUtils.GetAssociatedParts(document,fid,false,false);\r\n\t\t\t\tif (cs[i] != partIds.Count)\r\n\t\t\t\t{\r\n\t\t\t\t\tbadIds.Add(fid);\r\n\t\t\t\t\t\/\/TaskDialog.Show(\"Warning\", \"Multibody Object Found\");\r\n\t\t\t\t}\r\n\t\t\t\ti++;\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\ttempTransaction.RollBack();\r\n\t\t\t\r\n\t\t\tusing (Transaction transaction = new Transaction(document, \"Select Multibody Ceilings\"))\r\n\t\t\t{\r\n\t\t\t\tif(transaction.Start() == TransactionStatus.Started)\r\n\t\t\t\t{\r\n\r\n\t\t\t\t\tuidoc.Selection.SetElementIds(badIds);\r\n\t\t\t\t\t\r\n\t\t\t\t\tif(transaction.Commit() == TransactionStatus.Committed)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tTaskDialog.Show(\"Selected \" , badIds.Count.ToString() + \" ceiling(s) with multiple bodies.\");\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttransaction.RollBack();\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\tpublic void SplitDisjointFloors()\r\n\t\t{\r\n\t\t\t\r\n\t\t\tDocument document = this.ActiveUIDocument.Document;\r\n\t\t\tUIDocument uidoc = new UIDocument (document);\r\n\t\t\t\r\n\t\t\tList&lt;ElementId&gt; ids = new List&lt;ElementId&gt;();\r\n\t\t\tList&lt;ElementId&gt; badIds = new List&lt;ElementId&gt;();\r\n\t\t\t\r\n\t\t\tList&lt;int&gt; cs = new List&lt;int&gt;();\r\n\t\t\t\r\n\t\t\tElementFilter ff = new ElementCategoryFilter(BuiltInCategory.OST_Floors);\r\n\t\t\tFilteredElementCollector collector = new FilteredElementCollector(document,this.ActiveUIDocument.ActiveView.Id);\r\n\t\t\tICollection&lt;Element&gt; elems = collector.WherePasses(ff).WhereElementIsNotElementType().ToElements();\r\n\t\t\t\r\n\t\t\tAutodesk.Revit.DB.Options geomOption = document.Application.Create.NewGeometryOptions();\r\n\t\t\t\r\n\t\t\tTransaction tempTransaction = new Transaction(document, \"Temp geometry extraction\");\r\n\t\t\ttempTransaction.Start();\r\n\t\t\t\r\n\t\t\tforeach (Element e in elems)\r\n\t\t\t{\r\n\t\t\t\tFloor f = e as Floor;\r\n\t\t\t\t\r\n\t\t\t\tif (f != null)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (!PartUtils.HasAssociatedParts(document, f.Id))\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tFloorType fType = f.FloorType;\r\n\t\t\t\t\t\tCompoundStructure comStruct = fType.GetCompoundStructure();\r\n\t\t\t\t\t\tint c = 0;\r\n\t\t\t\t\t\tfor (int j = 0; j &lt; comStruct.LayerCount; j++)\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tIList&lt;CompoundStructureLayer&gt; cslList = comStruct.GetLayers();\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tbool countLayer = true;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tif(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.Membrane)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tcountLayer = false;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.StructuralDeck)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif(comStruct.GetDeckEmbeddingType(j) != StructDeckEmbeddingType.Standalone)\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tcountLayer = false;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (countLayer)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tc++;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcs.Add(c);\r\n\t\t\t\t\t\tids.Add(f.Id);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tPartUtils.CreateParts(document,ids);\r\n\t\t\tdocument.Regenerate();\r\n\t\t\tint i = 0;\r\n\t\t\tforeach (ElementId fid in ids)\r\n\t\t\t{\r\n\t\t\t\tICollection&lt;ElementId&gt; partIds = PartUtils.GetAssociatedParts(document,fid,false,false);\r\n\t\t\t\tif (cs[i] != partIds.Count)\r\n\t\t\t\t{\r\n\t\t\t\t\tbadIds.Add(fid);\r\n\t\t\t\t\t\/\/TaskDialog.Show(\"Warning\", \"Multibody Object Found\");\r\n\t\t\t\t}\r\n\t\t\t\ti++;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\r\n\t\t\ttempTransaction.RollBack();\r\n\t\t\t\r\n\t\t\tusing (Transaction transaction = new Transaction(document, \"Split Multibody Floors\"))\r\n\t\t\t{\r\n\t\t\t\tif(transaction.Start() == TransactionStatus.Started)\r\n\t\t\t\t{\r\n\r\n\t\t\t\t\t\/\/uidoc.Selection.SetElementIds(badIds);\r\n\t\t\t\t\tList&lt;Floor&gt; badFloors = new List&lt;Floor&gt;();\r\n\t\t\t\t\t\r\n\t\t\t\t\tforeach (ElementId badId in badIds)\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tFloor sourceFloor = document.GetElement(badId) as Floor;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tif (sourceFloor == null) continue;\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\/\/int c = 0;\r\n\t\t\t\t\t\tAutodesk.Revit.DB.GeometryElement floorGeometryElement = sourceFloor.get_Geometry( geomOption );\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tforeach( Autodesk.Revit.DB.GeometryObject geometryObject in floorGeometryElement )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tvar floorSolid = geometryObject as Solid;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tif( floorSolid == null )\r\n\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tvar topFace = GetTopFace( floorSolid );\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tif( topFace == null )\r\n\t\t\t\t\t\t\t\tthrow new NotSupportedException(\r\n\t\t\t\t\t\t\t\t\t\"Floor does not have top face\" );\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tif( topFace.EdgeLoops.IsEmpty )\r\n\t\t\t\t\t\t\t\tthrow new NotSupportedException(\r\n\t\t\t\t\t\t\t\t\t\"Floor top face does not have edges\" );\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tEdgeArrayArray eaa = topFace.EdgeLoops;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tforeach (EdgeArray ea in eaa)\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tCurveArray floorCurveArray = GetCurveArrayFromEdgeArary( ea );\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\tdocument.Create.NewFloor(floorCurveArray,sourceFloor.FloorType,document.GetElement(sourceFloor.LevelId) as Level,false);\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\/\/ Create new floor using source\r\n\t\t\t\t\t\t\t\/\/ floor outer boundaries\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tdocument.Delete(badId);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tif(transaction.Commit() == TransactionStatus.Committed)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tTaskDialog.Show(\"Split \" , badIds.Count.ToString() + \" floors with several bodies.\");\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttransaction.RollBack();\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t\t\r\n\t\tprivate CurveArray GetCurveArrayFromEdgeArary(EdgeArray edgeArray )\r\n\t\t{\r\n\t\t\tCurveArray curveArray =\r\n\t\t\t\tnew CurveArray();\r\n\t\t\t\r\n\t\t\tforeach( Edge edge in edgeArray )\r\n\t\t\t{\r\n\t\t\t\tvar edgeCurve =\r\n\t\t\t\t\tedge.AsCurve();\r\n\t\t\t\t\r\n\t\t\t\tcurveArray.Append( edgeCurve );\r\n\t\t\t}\r\n\t\t\treturn curveArray;\r\n\t\t}\r\n\t\t\r\n\t\tprivate PlanarFace GetTopFace( Solid solid )\r\n\t\t{\r\n\t\t\tPlanarFace topFace = null;\r\n\t\t\tFaceArray faces = solid.Faces;\r\n\t\t\tforeach( Face f in faces )\r\n\t\t\t{\r\n\t\t\t\tPlanarFace pf = f as PlanarFace;\r\n\t\t\t\tif( null != pf\r\n\t\t\t\t   &amp;&amp; ( Math.Abs( pf.Normal.X - 0 ) &lt; _eps &amp;&amp; Math.Abs( pf.Normal.Y - 0 ) &lt; _eps ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( ( null == topFace )\r\n\t\t\t\t\t   || ( topFace.Origin.Z &lt; pf.Origin.Z ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttopFace = pf;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn topFace;\r\n\t\t}\r\n\t\t\r\n\t}\r\n}\r\n<\/pre>\n<p>Here you can <a href=\"https:\/\/www.modelical.com\/wp-content\/uploads\/2015\/04\/MultiBodyGeometryCleaner.zip\">download the .cs file<\/a><\/p>\n<p>Thanks to <a title=\"The Building Coder\" href=\"http:\/\/thebuildingcoder.typepad.com\/\">Jeremy Tammik<\/a> and <a title=\"Spiderinnet\" href=\"http:\/\/spiderinnet.typepad.com\/\">Spiderinnet<\/a> for their valuable examples.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This macro will help you clean Revit models where the user has created multibody floors and ceilings as these can pose challenges for proper quantity takeoff.<\/p>\n","protected":false},"featured_media":9262,"template":"","categories":[708],"tags":[410],"class_list":["post-1416","node","type-node","status-publish","has-post-thumbnail","hentry","category-nodes","tag-technology-revit-api"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Split Multibody floors and roofs - Modelical<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Split Multibody floors and roofs - Modelical\" \/>\n<meta property=\"og:description\" content=\"This macro will help you clean Revit models where the user has created multibody floors and ceilings as these can pose challenges for proper quantity takeoff.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/\" \/>\n<meta property=\"og:site_name\" content=\"Modelical\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Modelical\/\" \/>\n<meta property=\"article:modified_time\" content=\"2022-05-09T09:40:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.modelical.com\/wp-content\/uploads\/M-Alys.png\" \/>\n\t<meta property=\"og:image:width\" content=\"480\" \/>\n\t<meta property=\"og:image:height\" content=\"480\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@modelical\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/node\\\/system-categories-multiple-body-fix-and-clean\\\/\",\"url\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/node\\\/system-categories-multiple-body-fix-and-clean\\\/\",\"name\":\"Split Multibody floors and roofs - Modelical\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/node\\\/system-categories-multiple-body-fix-and-clean\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/node\\\/system-categories-multiple-body-fix-and-clean\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.modelical.com\\\/wp-content\\\/uploads\\\/M-Alys.png\",\"datePublished\":\"2018-10-30T10:24:25+00:00\",\"dateModified\":\"2022-05-09T09:40:50+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/node\\\/system-categories-multiple-body-fix-and-clean\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.modelical.com\\\/en\\\/node\\\/system-categories-multiple-body-fix-and-clean\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/node\\\/system-categories-multiple-body-fix-and-clean\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.modelical.com\\\/wp-content\\\/uploads\\\/M-Alys.png\",\"contentUrl\":\"https:\\\/\\\/www.modelical.com\\\/wp-content\\\/uploads\\\/M-Alys.png\",\"width\":480,\"height\":480},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/node\\\/system-categories-multiple-body-fix-and-clean\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Nodes & Macros\",\"item\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/node\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Split Multibody floors and roofs\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/\",\"name\":\"Modelical\",\"description\":\"We build information\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.modelical.com\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Split Multibody floors and roofs - Modelical","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/","og_locale":"en_US","og_type":"article","og_title":"Split Multibody floors and roofs - Modelical","og_description":"This macro will help you clean Revit models where the user has created multibody floors and ceilings as these can pose challenges for proper quantity takeoff.","og_url":"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/","og_site_name":"Modelical","article_publisher":"https:\/\/www.facebook.com\/Modelical\/","article_modified_time":"2022-05-09T09:40:50+00:00","og_image":[{"width":480,"height":480,"url":"https:\/\/www.modelical.com\/wp-content\/uploads\/M-Alys.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_site":"@modelical","twitter_misc":{"Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/","url":"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/","name":"Split Multibody floors and roofs - Modelical","isPartOf":{"@id":"https:\/\/www.modelical.com\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/#primaryimage"},"image":{"@id":"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/#primaryimage"},"thumbnailUrl":"https:\/\/www.modelical.com\/wp-content\/uploads\/M-Alys.png","datePublished":"2018-10-30T10:24:25+00:00","dateModified":"2022-05-09T09:40:50+00:00","breadcrumb":{"@id":"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/#primaryimage","url":"https:\/\/www.modelical.com\/wp-content\/uploads\/M-Alys.png","contentUrl":"https:\/\/www.modelical.com\/wp-content\/uploads\/M-Alys.png","width":480,"height":480},{"@type":"BreadcrumbList","@id":"https:\/\/www.modelical.com\/en\/node\/system-categories-multiple-body-fix-and-clean\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Nodes & Macros","item":"https:\/\/www.modelical.com\/en\/node\/"},{"@type":"ListItem","position":2,"name":"Split Multibody floors and roofs"}]},{"@type":"WebSite","@id":"https:\/\/www.modelical.com\/en\/#website","url":"https:\/\/www.modelical.com\/en\/","name":"Modelical","description":"We build information","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.modelical.com\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/www.modelical.com\/en\/wp-json\/wp\/v2\/node\/1416","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modelical.com\/en\/wp-json\/wp\/v2\/node"}],"about":[{"href":"https:\/\/www.modelical.com\/en\/wp-json\/wp\/v2\/types\/node"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modelical.com\/en\/wp-json\/wp\/v2\/media\/9262"}],"wp:attachment":[{"href":"https:\/\/www.modelical.com\/en\/wp-json\/wp\/v2\/media?parent=1416"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modelical.com\/en\/wp-json\/wp\/v2\/categories?post=1416"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modelical.com\/en\/wp-json\/wp\/v2\/tags?post=1416"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}