BIM 42

Insulation Tag

I am not very fond of duct and pipe insulations in Revit. If the concept is very useful, I find difficult to add and edit them. Furthermore, seeing the insulation on every duct and pipe can quickly clutters the view. We want to know how much insulation we have, but we don’t want to see it everywhere.

In a technical drawing, we generally represent insulation only on small parts of the duct, with an annotation, and then infer that the duck is covered everywhere else.

To adapt this method on Revit, I create two detail components, representing the insulation on a round and on a rectangular duct.

Annotations

This components have a “Width” instance parameter for setting their width regarding the thickness of the insulation.

Width

I also create a small piece of code to instantiate these components on selected ducts and pipes.

The idea is to pick a series of duct and pipe, read their insulation thickness, and add a detail component with the corresponding thickness. Like this, we can control where we want to see an insulation, and improve the overall legibility of the drawing.

Animation

This solution allow me to create quickly some annotations to represent the insulation without having to display it everywhere. However, this is more a workaround than a real solution. Nothing here is adaptive, and you have to restart the tool each time you edit or even move your duct.

public void InsulationTag()
{
    UIDocument uidoc = this.ActiveUIDocument;
    Document doc = uidoc.Document;

    Reference r = null;

    //Retrive the two symbols
    FamilySymbol rectangularSymbol = null;
    FamilySymbol roundSymbol = null;
    ICollection<Element> collection = new FilteredElementCollector(doc)
        .OfClass(typeof(FamilySymbol))
        .OfCategory(BuiltInCategory.OST_DetailComponents)
        .ToElements();

    foreach (Element element in collection)
    {
        FamilySymbol current = element as FamilySymbol;
        // This NewFamilyInstance overload requires a curve based family
        if (current.Family.Name == "DuctInsulationAnnotationRectangular")
        {
            rectangularSymbol = current;
        }
        else if (current.Family.Name == "DuctInsulationAnnotationRound")
        {
            roundSymbol = current;
        }
    }


    try
    {
        while (true)
        {

            using (Transaction t = new Transaction(doc))
            {
                t.Start("Annotate Insulations");

                r = uidoc.Selection.PickObject(ObjectType.Element, new SelectionFilter(), "Pick a duct");

                if (r != null)
                {
                    MEPCurve mepCurve = doc.GetElement(r.ElementId) as MEPCurve;
                    //doc.ActiveView.GetElementOverrides
                    //Get the middle of the duct
                    LocationCurve locCurve = mepCurve.Location as LocationCurve;
                    XYZ insertionPoint = locCurve.Curve.Evaluate(0.5, true);
                    //Get the angle
                    XYZ vector = locCurve.Curve.GetEndPoint(1) - locCurve.Curve.GetEndPoint(0);
                    double angle = new XYZ(1, 0, 0).AngleTo(vector);

                    //Get the insulation
                    ICollection<ElementId> insulationIds =
                        InsulationLiningBase.GetInsulationIds(doc, r.ElementId);

                    if (insulationIds.Count != 0)
                    {
                        InsulationLiningBase insulation = 
                            doc.GetElement(insulationIds.First()) as InsulationLiningBase;

                        if (insulation != null)
                        {
                            FamilySymbol symbol = null;
                            double widht;
                            try
                            {
                                widht = insulation.Width;
                                //Select the detail familly
                                symbol = rectangularSymbol;
                            }
                            catch (Autodesk.Revit.Exceptions.InvalidOperationException)
                            {
                                Parameter outerDiameter = 
                                    mepCurve.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER);
                                if (outerDiameter != null)
                                {
                                    widht = insulation.Thickness * 2 + outerDiameter.AsDouble();
                                }
                                else
                                {
                                    widht = insulation.Diameter;
                                }

                                //Select the detail familly
                                symbol = roundSymbol;
                            }

                            //Create the annotation
                            FamilyInstance annotation = 
                                doc.Create.NewFamilyInstance(insertionPoint, symbol, doc.ActiveView);

                            //Change the witdh
                            annotation.GetParameters("Width").First().Set(widht);

                            //rotate the component
                            annotation.Location.Rotate(Line.CreateUnbound(insertionPoint, new XYZ(0, 0, 1)), -angle);
                        }
                    }
                }

                t.Commit();
            }
        }

    }
    catch (Autodesk.Revit.Exceptions.OperationCanceledException)
    {
    }
}

public class SelectionFilter : ISelectionFilter
{
    #region ISelectionFilter Members

    public bool AllowElement(Element elem)
    {

        if (elem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_DuctCurves) return true;
        if (elem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves) return true;

        return false;
    }

    public bool AllowReference(Reference refer, XYZ pos)
    {
        if (refer.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_NONE) return false;

        if (refer.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_SURFACE) return true;
        if (refer.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_LINEAR) return true;

        return false;
    }

    #endregion
}

This blog is maintained by Simon Moreau