Separar suelos y cubiertas multicuerpo

Revit Macro

Descripción

Esta macro te servirá para seleccionar y limpiar categorías de sistema de Revit con más de una región o cuerpo, lo que resulta muy útil para corregir errores de modelado.

  • SelectMultibodyFloors: selecciona suelos visibles en la vista con más de un cuerpo. Ten en cuenta que aquellos suelos divididos en dos o más cuerpos por una abertura también serán seleccionados.
  • SelectMultibodyCeilings: selecciona falsos techos visibles en la vista con más de un cuerpo. Ten en cuenta que aquellos techos divididos en dos o más cuerpos por una abertura también serán seleccionados. Ten en cuenta que la API de Revit no permite (2019) crear techos automáticamente, así que solo podemos aspiarar a seleccionar los que estén erróneos.
  • SplitMultibodyFloors: selecciona y divide los suelos visibles en la vista con más de un cuerpo o región. Por favor ten en cuenta que los suelos cortados o divididos por aberturas se recrearán con la geometría visible.
Para usarlo, crea un nuevo módulo de macros en C# y llámalo "GeometryCleaner", luego reemplaza todo el texto con el siguiente código. Pulsa F8 para compilar y asegúrate de que Build Successfully Completed aparece en la barra inferior de tu pantalla.
/*
 * Created by SharpDevelop.
 * User: Roberto Molinos [Modelical]
 * Date: 3/20/2015
 * Time: 1:42 AM
 */
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB.Macros;

namespace GeometryCleaner
{
	[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
	[Autodesk.Revit.DB.Macros.AddInId("6ACE9B39-339F-4D56-BC11-9D6973B54D94")]
	public partial class ThisApplication
	{
		private void Module_Startup(object sender, EventArgs e)
		{

		}

		private void Module_Shutdown(object sender, EventArgs e)
		{

		}

		#region Revit Macros generated code
		private void InternalStartup()
		{
			this.Startup += new System.EventHandler(Module_Startup);
			this.Shutdown += new System.EventHandler(Module_Shutdown);
		}
		#endregion
		const double _eps = 1.0e-9;
		
		public void SelectMultibodyFloors()
		{
			
			Document document = this.ActiveUIDocument.Document;
			UIDocument uidoc = new UIDocument (document);
			
			List<ElementId> ids = new List<ElementId>();
			List<ElementId> badIds = new List<ElementId>();
			
			List<int> cs = new List<int>();
			
			FilteredElementCollector collector = new FilteredElementCollector(document,this.ActiveUIDocument.ActiveView.Id);
			ICollection<Element> elems = collector.WherePasses(new ElementCategoryFilter(BuiltInCategory.OST_Floors)).WhereElementIsNotElementType().ToElements();
			
			Autodesk.Revit.DB.Options geomOption = document.Application.Create.NewGeometryOptions();
			
			Transaction tempTransaction = new Transaction(document, "Temp geometry extraction");
			tempTransaction.Start();
			
			foreach (Element e in elems)
			{
				if (e is Floor)
				{
					Floor f = e as Floor;
					
					if (!PartUtils.HasAssociatedParts(document, f.Id))
					{
						FloorType fType = f.FloorType;
						CompoundStructure comStruct = fType.GetCompoundStructure();
						int c = 0;
						for (int j = 0; j < comStruct.LayerCount; j++)
						{
							IList<CompoundStructureLayer> cslList = comStruct.GetLayers();
							
							bool countLayer = true;
							
							if(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.Membrane)
							{
								countLayer = false;
							}
							if(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.StructuralDeck)
							{
								if(comStruct.GetDeckEmbeddingType(j) != StructDeckEmbeddingType.Standalone)
								{
									countLayer = false;
								}
							}
							if (countLayer)
							{
								
									c++;
							}
						}
						cs.Add(c);
						ids.Add(f.Id);
					}
				}
			}
			
			PartUtils.CreateParts(document,ids);
			document.Regenerate();
			int i = 0;
			foreach (ElementId fid in ids)
			{
				ICollection<ElementId> partIds = PartUtils.GetAssociatedParts(document,fid,false,false);
				if (cs[i] != partIds.Count)
				{
					badIds.Add(fid);
					//TaskDialog.Show("Warning", "Multibody Object Found");
				}
				i++;
			}
			
			tempTransaction.RollBack();

			using (Transaction transaction = new Transaction(document, "Select Multibody Floors"))
			{
				if(transaction.Start() == TransactionStatus.Started)
				{

					uidoc.Selection.SetElementIds(badIds);
					
					if(transaction.Commit() == TransactionStatus.Committed)
					{
						
						TaskDialog.Show("Selected " , badIds.Count.ToString() + " floor(s) with multiple bodies.");
						
					}
					else
					{
						transaction.RollBack();
					}
					
				}
				
			}
		}
		
		public void SelectMultibodyCeilings()
		{
			
			Document document = this.ActiveUIDocument.Document;
			UIDocument uidoc = new UIDocument (document);
			
			List<ElementId> ids = new List<ElementId>();
			List<ElementId> badIds = new List<ElementId>();
			
			List<int> cs = new List<int>();
			
			ElementFilter ff = new ElementCategoryFilter(BuiltInCategory.OST_Ceilings);
			FilteredElementCollector collector = new FilteredElementCollector(document,this.ActiveUIDocument.ActiveView.Id);
			ICollection<Element> elems = collector.WherePasses(ff).WhereElementIsNotElementType().ToElements();
			
			Autodesk.Revit.DB.Options geomOption = document.Application.Create.NewGeometryOptions();
			
			Transaction tempTransaction = new Transaction(document, "Temp geometry extraction");
			tempTransaction.Start();
			
			foreach (Element e in elems)
			{
				if (e is Ceiling)
					
				{
					Ceiling f = e as Ceiling;
					
					if (!PartUtils.HasAssociatedParts(document, f.Id))
					{
						ElementId fTypeId = f.GetTypeId();
						CeilingType fType = document.GetElement(fTypeId) as CeilingType;
						CompoundStructure comStruct = fType.GetCompoundStructure();
						int c = 0;
						for (int j = 0; j < comStruct.LayerCount; j++)
						{
							IList<CompoundStructureLayer> cslList = comStruct.GetLayers();
							
							bool countLayer = true;
							
							if(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.Membrane)
							{
								countLayer = false;
							}
							if(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.StructuralDeck)
							{
								if(comStruct.GetDeckEmbeddingType(j) != StructDeckEmbeddingType.Standalone)
								{
									countLayer = false;
								}
							}
							if (countLayer)
							{
								
									c++;
							}
						}
						cs.Add(c);
						
						ids.Add(f.Id);
						
						
						
					}
				}
				
			}
			
			PartUtils.CreateParts(document,ids);
			document.Regenerate();
			int i = 0;
			foreach (ElementId fid in ids)
			{
				ICollection<ElementId> partIds = PartUtils.GetAssociatedParts(document,fid,false,false);
				if (cs[i] != partIds.Count)
				{
					badIds.Add(fid);
					//TaskDialog.Show("Warning", "Multibody Object Found");
				}
				i++;
				
			}
			
			tempTransaction.RollBack();
			
			using (Transaction transaction = new Transaction(document, "Select Multibody Ceilings"))
			{
				if(transaction.Start() == TransactionStatus.Started)
				{

					uidoc.Selection.SetElementIds(badIds);
					
					if(transaction.Commit() == TransactionStatus.Committed)
					{
						
						TaskDialog.Show("Selected " , badIds.Count.ToString() + " ceiling(s) with multiple bodies.");
						
					}
					else
					{
						transaction.RollBack();
					}
					
				}
				
			}
		}
		
		public void SplitDisjointFloors()
		{
			
			Document document = this.ActiveUIDocument.Document;
			UIDocument uidoc = new UIDocument (document);
			
			List<ElementId> ids = new List<ElementId>();
			List<ElementId> badIds = new List<ElementId>();
			
			List<int> cs = new List<int>();
			
			ElementFilter ff = new ElementCategoryFilter(BuiltInCategory.OST_Floors);
			FilteredElementCollector collector = new FilteredElementCollector(document,this.ActiveUIDocument.ActiveView.Id);
			ICollection<Element> elems = collector.WherePasses(ff).WhereElementIsNotElementType().ToElements();
			
			Autodesk.Revit.DB.Options geomOption = document.Application.Create.NewGeometryOptions();
			
			Transaction tempTransaction = new Transaction(document, "Temp geometry extraction");
			tempTransaction.Start();
			
			foreach (Element e in elems)
			{
				Floor f = e as Floor;
				
				if (f != null)
				{
					if (!PartUtils.HasAssociatedParts(document, f.Id))
					{
						FloorType fType = f.FloorType;
						CompoundStructure comStruct = fType.GetCompoundStructure();
						int c = 0;
						for (int j = 0; j < comStruct.LayerCount; j++)
						{
							IList<CompoundStructureLayer> cslList = comStruct.GetLayers();
							
							bool countLayer = true;
							
							if(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.Membrane)
							{
								countLayer = false;
							}
							if(comStruct.GetLayerFunction(j) == MaterialFunctionAssignment.StructuralDeck)
							{
								if(comStruct.GetDeckEmbeddingType(j) != StructDeckEmbeddingType.Standalone)
								{
									countLayer = false;
								}
							}
							if (countLayer)
							{
									c++;
							}
						}
						cs.Add(c);
						ids.Add(f.Id);
					}
				}
			}
			
			PartUtils.CreateParts(document,ids);
			document.Regenerate();
			int i = 0;
			foreach (ElementId fid in ids)
			{
				ICollection<ElementId> partIds = PartUtils.GetAssociatedParts(document,fid,false,false);
				if (cs[i] != partIds.Count)
				{
					badIds.Add(fid);
					//TaskDialog.Show("Warning", "Multibody Object Found");
				}
				i++;
			}
			
			
			tempTransaction.RollBack();
			
			using (Transaction transaction = new Transaction(document, "Split Multibody Floors"))
			{
				if(transaction.Start() == TransactionStatus.Started)
				{

					//uidoc.Selection.SetElementIds(badIds);
					List<Floor> badFloors = new List<Floor>();
					
					foreach (ElementId badId in badIds)
						
					{
						Floor sourceFloor = document.GetElement(badId) as Floor;
						
						if (sourceFloor == null) continue;
						
						//int c = 0;
						Autodesk.Revit.DB.GeometryElement floorGeometryElement = sourceFloor.get_Geometry( geomOption );
						
						foreach( Autodesk.Revit.DB.GeometryObject geometryObject in floorGeometryElement )
						{
							var floorSolid = geometryObject as Solid;
							
							if( floorSolid == null )
								continue;
							
							var topFace = GetTopFace( floorSolid );
							
							if( topFace == null )
								throw new NotSupportedException(
									"Floor does not have top face" );
							
							if( topFace.EdgeLoops.IsEmpty )
								throw new NotSupportedException(
									"Floor top face does not have edges" );
							
							EdgeArrayArray eaa = topFace.EdgeLoops;
							
							foreach (EdgeArray ea in eaa)
							{
								CurveArray floorCurveArray = GetCurveArrayFromEdgeArary( ea );
								
								document.Create.NewFloor(floorCurveArray,sourceFloor.FloorType,document.GetElement(sourceFloor.LevelId) as Level,false);
								
							}
							
							break;
							
							
							
							// Create new floor using source
							// floor outer boundaries
							
						}
						
						document.Delete(badId);
						
					}
					
					if(transaction.Commit() == TransactionStatus.Committed)
					{
						
						TaskDialog.Show("Split " , badIds.Count.ToString() + " floors with several bodies.");
						
					}
					else
					{
						transaction.RollBack();
					}
					
				}
				
			}
			
		}
		
		private CurveArray GetCurveArrayFromEdgeArary(EdgeArray edgeArray )
		{
			CurveArray curveArray =
				new CurveArray();
			
			foreach( Edge edge in edgeArray )
			{
				var edgeCurve =
					edge.AsCurve();
				
				curveArray.Append( edgeCurve );
			}
			return curveArray;
		}
		
		private PlanarFace GetTopFace( Solid solid )
		{
			PlanarFace topFace = null;
			FaceArray faces = solid.Faces;
			foreach( Face f in faces )
			{
				PlanarFace pf = f as PlanarFace;
				if( null != pf
				   && ( Math.Abs( pf.Normal.X - 0 ) < _eps && Math.Abs( pf.Normal.Y - 0 ) < _eps ) )
				{
					if( ( null == topFace )
					   || ( topFace.Origin.Z < pf.Origin.Z ) )
					{
						topFace = pf;
					}
				}
			}
			return topFace;
		}
		
	}
}
Aquí puedes descargar el archivo cs. Gracias a Jeremy Tammik y Spiderinnet por sus valiosos ejemplos.

Plataforma

Revit.

Tipo

Revit API Macro.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Time limit exceeded. Please complete the captcha once again.

  • Antes de enviar tu consulta, échale un vistazo a la información básica sobre protección de datos aquí.

    Modelical.com le informa que los datos personales que usted proporcione serán tratados por MODELICAL CONSULTORIA S.L. como responsable de este sitio web.

    Finalidad de la recogida y tratamiento de los datos personales: Enviar la información que el usuario requiera a través del sitio web. - Legitimación: Consentimiento del interesado. - Destinatarios: Hosting: Gigas, hosting 100% español y 100% seguro. - Derechos: Podrá ejercer sus derechos de acceso, rectificación, limitación y supresión de los datos de unsubscribe@modelical.com así como el derecho a presentar una reclamación ante una autoridad de control.