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.

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













Must log in before commenting!
Sign Up