BIM World
A Professional BIM Learning Platform


Revit API Tutorial: Fast and Easy Grid Annotation

Implement rapid annotation of parallel grids through secondary development using Revit. The interactive process involves selecting the grid, clicking on the desired dimension location, and then generating two dimensions automatically.

Revit secondary development _ Quick grid annotation

To achieve this functionality, several special considerations are required:

  • The box selection method may accidentally include incorrect grids. At minimum, grids that are not parallel to the initially selected grid should be filtered out. The closest axis grid chosen in the second step serves as the reference for determining parallelism. By traversing all selected grids, any grid whose vector direction matches or is opposite to the reference grid’s vector is considered parallel.
  • For outer dimension annotations, the two outermost grids must be identified. This can be done by checking whether all other grids lie entirely on one side (left or right) of a given grid, thereby determining the two extremities.
  • The dimension text height varies depending on the view scale. Therefore, it is necessary to read the font height and calculate the correct position for the inner dimension annotation based on the current view scale.

The following code demonstrates this approach:

class QGridDimension : IExternalCommand
{
    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
        UIDocument uidoc = commandData.Application.ActiveUIDocument;
        Document doc = uidoc.Document;

        // Retrieve the grid dimension type
        DimensionType dimType = null;
        FilteredElementCollector elems = new FilteredElementCollector(doc);
        foreach (DimensionType dt in elems.OfClass(typeof(DimensionType)))
        {
            if (dt.Name == "轴网尺寸标注")
            {
                dimType = dt;
                break;
            }
        }

        if (dimType != null)
        {
            IList<Element> grids = uidoc.Selection.PickElementsByRectangle(new GridFilter(), "Select grids by box");
            if (grids.Count > 1)
            {
                XYZ selPoint = uidoc.Selection.PickPoint(ObjectSnapTypes.None, "Select dimension placement point");
                View activeView = uidoc.ActiveView;

                ReferenceArray referenceArrayInner = new ReferenceArray();
                ReferenceArray referenceArrayOuter = new ReferenceArray();

                // Determine the closest grid line to the selected point for reference
                List<Grid> lineGrids = new List<Grid>();
                Line referenceLine = null;
                double minDistance = double.MaxValue;
                foreach (Grid g in grids)
                {
                    double distance = g.Curve.Distance(selPoint);
                    Line line = g.Curve as Line;
                    if (line != null)
                    {
                        lineGrids.Add(g);
                        if (distance < minDistance)
                        {
                            referenceLine = line;
                            minDistance = distance;
                        }
                    }
                }

                // Collect references for inner dimension annotation (parallel grids)
                foreach (Grid grid in lineGrids)
                {
                    Line line = grid.Curve as Line;
                    if (line.Direction.IsAlmostEqualTo(referenceLine.Direction) || 
                        line.Direction.IsAlmostEqualTo(referenceLine.Direction.Multiply(-1)))
                    {
                        referenceArrayInner.Append(new Reference(grid));
                    }
                }

                // Identify outermost grids for outer dimension annotation
                foreach (Reference refGrid in referenceArrayInner)
                {
                    Grid g = doc.GetElement(refGrid) as Grid;
                    Line line = g.Curve as Line;
                    XYZ startPoint = line.GetEndPoint(0);
                    XYZ endPoint = line.GetEndPoint(1);
                    int leftCount = 0;

                    foreach (Reference otherRef in referenceArrayInner)
                    {
                        Grid otherGrid = doc.GetElement(otherRef) as Grid;
                        Line otherLine = otherGrid.Curve as Line;
                        XYZ point = otherLine.GetEndPoint(0);
                        if (PointOnTheLeft(startPoint, endPoint, point))
                        {
                            leftCount++;
                        }
                    }

                    if (leftCount == 0 || leftCount == referenceArrayInner.Size - 1)
                    {
                        referenceArrayOuter.Append(new Reference(g));
                    }
                }

                // Calculate dimension placement positions
                XYZ perpDirection = referenceLine.Direction.CrossProduct(new XYZ(0, 0, 1));
                XYZ pointStart = referenceLine.GetEndPoint(0);
                XYZ pointEnd = referenceLine.GetEndPoint(1);

                if (pointStart.DistanceTo(selPoint) > pointEnd.DistanceTo(selPoint))
                {
                    XYZ temp = pointStart;
                    pointStart = pointEnd;
                    pointEnd = temp;
                }

                XYZ offsetDirection = pointEnd - pointStart;
                double textSize = dimType.get_Parameter(BuiltInParameter.TEXT_SIZE).AsDouble();

                Line outerLine = Line.CreateUnbound(selPoint, perpDirection);
                Line innerLine = Line.CreateUnbound(selPoint + offsetDirection.Normalize() * textSize * activeView.Scale * 1.9, perpDirection);

                // Create dimensions within a transaction
                using (Transaction trans = new Transaction(doc, "Grid Dimension Annotation"))
                {
                    trans.Start();
                    document.Create.NewDimension(activeView, outerLine, referenceArrayOuter, dimType);
                    document.Create.NewDimension(activeView, innerLine, referenceArrayInner, dimType);
                    trans.Commit();
                }
            }
        }
        else
        {
            TaskDialog.Show("Error", "Grid dimension type not found");
        }
        return Result.Succeeded;
    }

    bool PointOnTheLeft(XYZ point1, XYZ point2, XYZ point)
    {
        double r = (point1.X - point2.X) / (point1.Y - point2.Y) * (point.Y - point2.Y) + point2.X;
        return r > point.X;
    }
}

internal class GridFilter : ISelectionFilter
{
    public bool AllowElement(Element elem)
    {
        return elem is Grid;
    }
    public bool AllowReference(Reference reference, XYZ position)
    {
        return true;
    }
}
xuebim
Follow the latest BIM developments in the architecture industry, explore innovative building technologies, and discover cutting-edge industry insights.
← Scan with WeChat
Like(0) 打赏
BIM WORLD » Revit API Tutorial: Fast and Easy Grid Annotation

Comment Get first!

Must log in before commenting!

 

BIM World, A Professional BIM Learning Platform

Stay updated on the latest architecture trends and share new building technologies.

Contact UsAbout Us

觉得文章有用就打赏一下小编吧

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

Account Login

By signing in, you agree toUser Agreement

Sign Up