Duplicar Armaduras

Revit API Macro

Descripción

A raíz de uno de los proyectos de consultoría que tenemos en marcha hemos llevado Revit al extremo en lo que se refiere al diseño y detallado de armaduras. Revit no es, ni de lejos, la mejor aplicación para hacer despieces o estudiar conexiones complejas, pero si que es una aplicación robusta y que cada día integra a más profesionales, y muchas de las cosas que no pueden hacerse "out-of-the-box" son posibles con un mínimo conocimiento de la API. Resulta que en algunas ocasiones, cuando duplicamos una barra de armadura que se encuentra interactuando con otras y sobre todo si éstas últimas son estribos, la copia acaba en una posición imprevisible y, lo peor de todo, con unas restricciones que poco tienen que ver con las de la barra original. Fíjate en la imagen, la barra azul está interactuando con el estribo en U: DupRebar00 Y ahora, tras copiar la barra al portapapeles y pegarla en el mismo sitio, obtenemos esto. DupRebar01 La barra se recoloca y se pega al otro estribo. De hecho, las restricciones han cambiado, sólo en uno de los Handles, pero lo suficiente para que tengamos que reposicionarla. Pues bien, para remediar este comportamiento es necesario conocer bien cómo funcionan las interacciones entre barras en Revit (Inglés) para poder sacarle partido a la API. El siguiente código crea un comando que permite copiar una armadura manteniendo las mismas restricciones.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;

namespace CopyReinforcementKeepConstraints
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    public class ReinforcementCopier:IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIDocument uidoc=commandData.Application.ActiveUIDocument;
            Document doc= uidoc.Document;
            RebarPickFilter selFilter = new RebarPickFilter(); //use the selection filter
            Reference reference = uidoc.Selection.PickObject(ObjectType.Element, selFilter, "Please select a rebar to be copied");
            Element el = doc.GetElement(reference); //get the Rebar reference
            ICollection<ElementId> elID = new List<ElementId>();
            elID.Add(el.Id); //create a list to pass it to the copy method below
            Rebar myRebar = el as Rebar; //get the Rebar 
            ICollection<ElementId> newID = new List<ElementId>(); //create a list to host the duplicate rebar
            RebarConstraintsManager myRCM = myRebar.GetRebarConstraintsManager();
            IList<RebarConstrainedHandle> handleClander=myRCM.GetAllConstrainedHandles(); //A list to hold constrained handles
            IList<RebarConstraint> constraints = new List<RebarConstraint>(); //A list to host constraints applied to each handle
            foreach (RebarConstrainedHandle cHandle in handleClander)
            {
                constraints.Add(myRCM.GetCurrentConstraintOnHandle(cHandle)); //collect all constraints
            }
            Transaction trans1 = new Transaction(doc, "DUPLICATE REBAR");
            trans1.Start();
                try
                {
                    newID = ElementTransformUtils.CopyElements(doc, elID, new XYZ(0, 0, 0)); //duplicate rebar, in same place

                    Rebar myNewRebar = doc.GetElement(newID.ElementAt(0)) as Rebar; //retrieve the rebar from the newly created ID

                    RebarConstraintsManager myNewRCM = myNewRebar.GetRebarConstraintsManager(); //access the new rebar constraints
                    IList<RebarConstrainedHandle> handleClanderDuodenal = myNewRCM.GetAllConstrainedHandles(); //access the new rebar handles
                    for (int i = 0; i < handleClanderDuodenal.Count; i++)
                    {
                        myNewRCM.SetPreferredConstraintForHandle(handleClanderDuodenal[i],constraints[i]); //assign the new rebar handles the same constrains as the original one
                    }
                }
                catch (Exception ex)
                {
                   message = ex.Message;
                   return Result.Failed;
                }
            trans1.Commit(); //close your transaction
            return Result.Succeeded;
        }
        //create a filter to select only rebars.
        public class RebarPickFilter : ISelectionFilter
        { 
            public bool AllowElement(Element e)
            {
                return (e.Category.Id.IntegerValue.Equals(
                  (int)BuiltInCategory.OST_Rebar));
            }
            public bool AllowReference(Reference r, XYZ p)
            {
                return false;
            }
        }
    }
}
Utiliza este Addin Manifest para registrar tu Comando.
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
  <AddIn Type="Command">
    <Name>CopyReinforcementKeepConstraints</Name>
    <Assembly>C:ProgramDataAutodeskRevitAddins2014CopyReinforcementKeepConstraints.dll</Assembly>
    <AddInId>8c22e788-192d-4388-82b6-bff244938829</AddInId>
    <FullClassName>CopyReinforcementKeepConstraints.ReinforcementCopier</FullClassName>
    <Text>Duplicate Rebar</Text>
    <VendorId>Modelical</VendorId>
    <VendorDescription>Modelical FTW</VendorDescription>
  </AddIn>
</RevitAddIns>
Quiero dar las gracias a Javier Giménez y Juan Ma Pérez por ayudarme con este primer comando para Revit.

Plataforma

Revit.

Tipo

Revit API Macro.