Python_Zip Function_1

Un recurso muy útil a la hora de organizar listas en pithon es utilizar la función zip()

En este ejemplo utilizamos la función zip para ordenar los ids y las habitaciones en una lista que nos podría servir por ejemplo para exportar a un excel.

import clr

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

elementos = UnwrapElement(IN[0])

rooms =[]
roomsIDs=[]

for elemento in elementos:
	rooms.append(elemento.ToString())
	roomsIDs.append(elemento.Id)
	
OUT = zip(rooms,roomsIDs)

Este post está numerado a propósito, con el objetivo de ir escalando el código empleado para reutilizar y aumentar la funcionalidad del mismo.

El siguiente objetivo será conseguir los parámetros “útiles” de la habitaciones y desarrollar alguna función que podamos reutilizar más adelante…..

Filtros Utilizando API con C#

Algunas referencias y apuntes:

https://dynamopythonprimer.gitbook.io/dynamo-python-primer/4-revit-specific-topics/fetching-revit-elements

https://thebuildingcoder.typepad.com/blog/2010/10/filtered-element-collectors.html

https://knowledge.autodesk.com/support/revit-products/learn-explore/caas/CloudHelp/cloudhelp/2014/ENU/Revit/files/GUID-A2686090-69D5-48D3-8DF9-0AC4CC4067A5-htm.html

Practicando en la cuarenta la aplicación de filtros en el API de revit.

Filtered Element Collector Class_Constructor

https://www.revitapidocs.com/2019/0635f1e4-652a-7e42-15af-94f24c4d8e8d.htm

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;

namespace FiltroDeCategorías
{
	// La clase que va a contener el comando externo de Revit, ha de implementar la interface 'IExternalCommand'.
	[Transaction(TransactionMode.Manual)]
	public class Class1 : IExternalCommand
	{
		// Método público el cual buscará Revit para ejecutar el comando externo.
		public Result Execute(
			ExternalCommandData DatosDelComandoExterno,
			ref string mensaje,
			ElementSet elementos)
		{
			// Declaración de una variable local con el documento actual.
			Document doc = DatosDelComandoExterno.Application.ActiveUIDocument.Document;

			//Filtered Element Collector
			FilteredElementCollector colectorPuertas = new FilteredElementCollector(doc);
			FilteredElementCollector colectorMuros = new FilteredElementCollector(doc);
			FilteredElementCollector colectorVentanas = new FilteredElementCollector(doc);

			//------------------------------
			//Filtro a colector Puertas
			ElementCategoryFilter filtroPuertas = new ElementCategoryFilter(BuiltInCategory.OST_Doors);

			//Aplicar el filtro al colector Puertas
			IList<Element> listaPuertas = colectorPuertas.WherePasses(filtroPuertas)
				.WhereElementIsNotElementType()
				.ToElements();

			//-----------------------
			//Filtro a colector Muros
			ElementCategoryFilter filtroMuros = new ElementCategoryFilter(BuiltInCategory.OST_Walls);

			//Aplicar el filtro al colector Muros
			IList<Element> listaMuros = colectorMuros.WherePasses(filtroMuros)
				.WhereElementIsNotElementType()
				.ToElements();

			//-----------------------
			//Filtro a colector Ventanas
			ElementCategoryFilter filtroVentanas = new ElementCategoryFilter(BuiltInCategory.OST_Windows);

			//Aplicar el filtro al colector Ventanas
			IList<Element> listaVentanas = colectorVentanas.WherePasses(filtroVentanas)
				.WhereElementIsNotElementType()
				.ToElements();

			//TaskDialog
			TaskDialog.Show("Puertas"
				, "El numero de puertas es " + listaPuertas.Count());
			TaskDialog.Show("Muros"
				, "El numero de muros es " + listaMuros.Count());
			TaskDialog.Show("Puertas"
				, "El numero de ventanas es " + listaVentanas.Count());


		}
	}


Se puede resumir la aplicación del filtro sobre el colector combinando métodos de la siguiente manera en una única línea:

public void ColectorNombresPuertas()
		{
			//Utilizamos uidoc y doc:
			Document doc = this.ActiveUIDocument.Document;

			//Filtered Element Collector
			FilteredElementCollector colectorPuertas= new FilteredElementCollector(doc)
				.OfCategory(BuiltInCategory.OST_Doors)
				.WhereElementIsNotElementType();
			
			
			//string  vacía para almacenar los nombres de las puertas
			string nombresPuertas = "";
			//bucle iterando sobreo el colector con el método name.
			foreach (Element elem in colectorPuertas)
			{
				nombresPuertas += elem.Name + "\n";
			}
			
			//TaskDialog
			TaskDialog.Show("Puertas","El nombre de los tipos de las puertas es "+"\n" + nombresPuertas);
		}

Creación de un plano utilizando la revit API.

Un ejemplo básico para comprender el uso de una transacción para crear un nuevo plano con el método ViewSheet.Create

ref: ViewSheet.Create RevitApiDocs

https://www.revitapidocs.com/2019/bc9e8be3-f3fd-97c2-2709-1d6eea3db775.htm

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;

namespace DCA_NuevoPlano
{
    // La clase que va a contener el comando externo de Revit, 
    //ha de implementar la interface 'IExternalCommand'.
    [Transaction(TransactionMode.Manual)]
    public class Class1 : IExternalCommand
    {
        // Método público el cual buscará Revit para ejecutar el comando externo.
        public Result Execute(
            ExternalCommandData DatosDelComandoExterno,
            ref string mensaje,
            ElementSet elementos)
        {
            // Declaración de una variable local con el documento actual.
            Document documento = DatosDelComandoExterno.Application.ActiveUIDocument.Document;

            // Declaración de una variable local con una selección.
            Selection seleccion = DatosDelComandoExterno.Application.ActiveUIDocument.Selection;

            // Recuperación de la selección actual en el documento activo.
            ICollection<ElementId> idsDeElementosSelecionados = seleccion.GetElementIds();


                   
           #region Búsqueda del cajetín a utilizar.
           // Declaración de una variable local con el ID del tipo de cajetín a utilizar.
           // Se declara con valor nulo.
              ElementId idDelCajetinAUtilizar = null;

           // Declaración de una variable local con el nombre del tipo de cajetín a utilizar.
                string nombreDeCajetin = "A2 derecha abajo";

           // Creación de un filtro para buscar los tipo de familia de cajetín.
                FilteredElementCollector filtroDeTiposDeCajetin = new FilteredElementCollector(documento).
                    OfCategory(BuiltInCategory.OST_TitleBlocks).
                    WhereElementIsElementType();

           // Iteración por todos los tipos de cajetín filtrados para buscar el id del que corresponde
           // al nombre seleccionado.
                foreach (Element cualquierTipoDeCajetin in filtroDeTiposDeCajetin)
                {
                    // Código a ejecutar si el nombre del tipo del cajetín de la iteración actual corresponde con el
                    // indicado.
                    if (cualquierTipoDeCajetin.Name.Equals(nombreDeCajetin))
                    {
                        // Asignación del valor a la variable 'idDelCajetinAUtilizar'.
                        idDelCajetinAUtilizar = cualquierTipoDeCajetin.Id;

                        // interrupción del bucle actual.
                        break;
                    }
                }
            #endregion


            // Creación de un recurso con una transacción.
            using (Transaction transaccion = new Transaction(documento))
            {
                // Apertura de la transacción.
                transaccion.Start("Creación automática de planos");

                #region Creación del plano.
                // creación de un plano con el nombre de la vista.
                ViewSheet NuevoPlano = ViewSheet.Create(
                    documento,
                    idDelCajetinAUtilizar);

                // Asignación al nombre del nuevo plano del nombre de la vista seleccionada.
                NuevoPlano.Name = "NuevoPlano";
                
                // Asignación al nombre del nuevo plano del nombre de la vista seleccionada.
                NuevoPlano.SheetNumber = "100-";
                #endregion
                
                // Cierre de la transacción.
                transaccion.Commit();
            }
          
            // Retorno del método.
            return Result.Succeeded;
        }
    }
}

+++Sumando longitudes +++

Un script muy simple pero potente para realizar mediciones rápidas sobre cualquier objeto/s con el parámetro length que seleccionemos.

Original de https://boostyourbim.wordpress.com/2016/06/21/total-length-of-multiple-lines/ de Harry Mattison.

 
public void CurveTotalLenght()
{
       //obtenemos el documento en curso (*variación sobre el original)
       UIDocument uidoc = this.Application.ActiveUIDocument;
       Document doc = uidoc.Document;
        //Selección y obtención de ids
        ICollection<ElementId> ids = uidoc.Selection.GetElementIds();
        //variable vacía para almacenar el valor
        double length = 0;
        //loop sobre la selección           
        foreach (ElementId id in ids)
        {
            //obtenemos el id
            Element e = doc.GetElement(id);
            //obtenemos el parámetro curve_elem_lenght
            Parameter lengthParam = e.get_Parameter(BuiltInParameter.CURVE_ELEM_LENGTH);
            //si no ... pasamos
            if (lengthParam == null)
                continue;
            //si si ... lo cogemos
            length += lengthParam.AsDouble();
        }
        //UnitUtils sobre las unidades del document         
        string lengthWithUnits = UnitFormatUtils.Format(doc.GetUnits(), UnitType.UT_Length, length, false, false);
        //Mostramos la información por pantalla
        TaskDialog.Show("Length", ids.Count + " elements = " + lengthWithUnits);
    }

Place Legends on Sheets

Script para colocar leyendas en planos de manera automatizada en función del nombre del plano y el nombre de la leyenda.

2018-11-24_10-41-Place legend

VERSIÓN MACRO C# (USANDO EL MACRO MANAGER)

/*
* Created by SharpDevelop.
* User: david
* Date: 10/23/2018
* Time: 10:58 AM
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;

namespace MAC_DCA
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.DB.Macros.AddInId(“75915E9A-4149-47F2-93D9-DED3102ECC0E”)]
public partial class ThisDocument
{
public void legendOnSheets()
{
Document doc = this.ActiveUIDocument.Document;

// create list of element ids for the sheets that will get the legends
List<ElementId> sheetIds = new List<ElementId>();

// use SheetNumber to find the desired sheets add each sheet to the list of sheet ids //

sheetIds.Add(new FilteredElementCollector(doc)
.OfClass(typeof(ViewSheet))
.Cast<ViewSheet>()
.FirstOrDefault(q => q.SheetNumber == “A101”).Id);

sheetIds.Add(new FilteredElementCollector(doc)
.OfClass(typeof(ViewSheet))
.Cast<ViewSheet>()
.FirstOrDefault(q => q.SheetNumber == “A102”).Id);

sheetIds.Add(new FilteredElementCollector(doc)
.OfClass(typeof(ViewSheet))
.Cast<ViewSheet>()
.FirstOrDefault(q => q.SheetNumber == “A103”).Id);

// find the legend to put on the sheets
// use ViewType.Legend and the view name to find the legend view

Element legend = new FilteredElementCollector(doc)
.OfClass(typeof(View))
.Cast<View>()
.FirstOrDefault(q => q.ViewType == ViewType.Legend && q.Name == “Legend 1”);

// create a transaction so that the document can be modified

using (Transaction t = new Transaction(doc, “Legends on Sheets”))
{
// start the transaction
t.Start();

// foreach loop through the list of sheet ids
foreach (ElementId sheetid in sheetIds)
{
// create a new viewport for the legend on each sheet
// place the legend view at the 0,0,0 location on each sheet
// user will need to move the legend to the desired location
Viewport.Create(doc, sheetid, legend.Id, new XYZ(0,0,0));
}

// commit the changes
t.Commit();
}
}

VERSIÓN ADDIN USANDO VISUAL STUDIO 2017

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;

namespace LegendsOnSheets
{
[TransactionAttribute(TransactionMode.Manual)]
public class PlaceLegends : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
//Get UIDocument
UIDocument uidoc = commandData.Application.ActiveUIDocument;

//Get Document
Document doc = uidoc.Document;

//Find Sheet
ViewSheet vSheet = new FilteredElementCollector(doc)
.OfCategory(BuiltInCategory.OST_Sheets)
.Cast<ViewSheet>()
.First(x => x.Name == “Plano Ejemplo”);

//Find ViewLegend
Element vLegend = new FilteredElementCollector(doc)
.OfCategory(BuiltInCategory.OST_Views)
.First(x => x.Name == “Legend_01”);

//Get Midpoint
BoundingBoxUV outline = vSheet.Outline;
double xu = (outline.Max.U + outline.Min.U) / 2;
double yu = (outline.Max.V + outline.Min.V) / 2;
XYZ midPoint = new XYZ(xu, yu, 0);

try
{
using (Transaction trans = new Transaction(doc, “Place View”))
{
trans.Start();

//Place View
Viewport vPort = Viewport.Create(doc, vSheet.Id, vLegend.Id, midPoint);

trans.Commit();
}

return Result.Succeeded;
}
catch (Exception e)
{
message = e.Message;
return Result.Failed;
}

}
}
}