I created a script to place structural column face–to–nearest grid dimensions. It works fine for rectangular columns in the X and Y directions, but it’s not working for rotated columns or grids. Please help me.
-- coding: utf-8 --
import clr
clr.AddReference(‘RevitAPI’)
clr.AddReference(‘RevitAPIUI’)
clr.AddReference(‘System.Windows.Forms’)
clr.AddReference(‘System.Drawing’)
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI import *
from System.Collections.Generic import List
from System.Windows.Forms import Form, Label, TextBox, Button, DialogResult, FormStartPosition
from System.Drawing import Point, Size
Show offset popup
class OffsetInputForm(Form):
def init(self):
self.Text = “Column to Grid Offset”
self.Size = Size(250, 130)
self.StartPosition = FormStartPosition.CenterScreen
self.label = Label()
self.label.Text = "Offset in mm:"
self.label.Location = Point(10, 20)
self.label.Size = Size(100, 20)
self.Controls.Add(self.label)
self.textbox = TextBox()
self.textbox.Text = "500"
self.textbox.Location = Point(110, 18)
self.textbox.Size = Size(100, 20)
self.Controls.Add(self.textbox)
self.ok_button = Button()
self.ok_button.Text = "OK"
self.ok_button.Location = Point(40, 60)
self.ok_button.Click += self.on_ok
self.Controls.Add(self.ok_button)
self.cancel_button = Button()
self.cancel_button.Text = "Cancel"
self.cancel_button.Location = Point(120, 60)
self.cancel_button.Click += self.on_cancel
self.Controls.Add(self.cancel_button)
self.Result = None
def on_ok(self, sender, args):
self.Result = self.textbox.Text
self.DialogResult = DialogResult.OK
self.Close()
def on_cancel(self, sender, args):
self.DialogResult = DialogResult.Cancel
self.Close()
Show dialog and get offset
form = OffsetInputForm()
if form.ShowDialog() != DialogResult.OK:
raise Exception(“User cancelled offset input.”)
try:
offset_mm = float(form.Result)
except:
TaskDialog.Show(“Invalid Input”, “Please enter a numeric offset.”)
raise
offset_ft = offset_mm / 304.8
short_tol = 0.01
doc = revit.ActiveUIDocument.Document
view = doc.ActiveView
def get_visible_columns():
return FilteredElementCollector(doc, view.Id)
.OfCategory(BuiltInCategory.OST_StructuralColumns)
.WhereElementIsNotElementType().ToElements()
def get_visible_grids():
return FilteredElementCollector(doc, view.Id)
.OfCategory(BuiltInCategory.OST_Grids)
.WhereElementIsNotElementType().ToElements()
def is_inclined_column_geometry(column):
try:
options = Options()
options.IncludeNonVisibleObjects = True
options.ComputeReferences = False
geometry = column.get_Geometry(options)
for geo in geometry:
if isinstance(geo, Solid):
for edge in geo.Edges:
p1 = edge.AsCurve().GetEndPoint(0)
p2 = edge.AsCurve().GetEndPoint(1)
direction = (p2 - p1).Normalize()
if abs(direction.Z) > 0.1 and abs(direction.Z) < 0.9:
return True
except:
pass
return False
def create_dimension_with_cut_paste(view, dim_line, ref_array):
dim = doc.Create.NewDimension(view, dim_line, ref_array)
dim_ids = ListElementId
ElementTransformUtils.CopyElements(doc, dim_ids, XYZ(0, 0, 0))
doc.Delete(dim.Id)
def create_perpendicular_dimension(view, face_ref, face_normal, grid_ref, base_point, offset_ft):
try:
face_normal = face_normal.Normalize()
up = XYZ.BasisZ
dim_dir = face_normal.CrossProduct(up).Normalize()
offset_point = base_point + face_normal.Multiply(offset_ft)
p1 = offset_point - dim_dir.Multiply(5)
p2 = offset_point + dim_dir.Multiply(5)
if p1.DistanceTo(p2) > short_tol:
dim_line = Line.CreateBound(p1, p2)
ref_array = ReferenceArray()
ref_array.Append(grid_ref)
ref_array.Append(face_ref)
create_dimension_with_cut_paste(view, dim_line, ref_array)
except Exception as e:
print("⛔ Inclined dimension error: {}".format(e))
Start transaction
t = Transaction(doc, “Column to Grid Dimensions”)
t.Start()
try:
columns = get_visible_columns()
grids = get_visible_grids()
for column in columns:
location = column.Location
if not isinstance(location, LocationPoint):
continue
col_point = location.Point
bbox = column.get_BoundingBox(view)
if not bbox:
continue
is_inclined = is_inclined_column_geometry(column)
options = Options()
options.ComputeReferences = True
options.IncludeNonVisibleObjects = True
geo_elem = column.get_Geometry(options)
face_refs_x = []
face_refs_y = []
solid = None
for g in geo_elem:
if isinstance(g, Solid) and g.Faces.Size > 0:
solid = g
break
elif isinstance(g, GeometryInstance):
for sg in g.GetInstanceGeometry():
if isinstance(sg, Solid) and sg.Faces.Size > 0:
solid = sg
break
if not solid:
continue
for face in solid.Faces:
if isinstance(face, PlanarFace):
normal = face.FaceNormal
if abs(normal.X) > 0.9:
face_refs_x.append((face.Reference, normal))
elif abs(normal.Y) > 0.9:
face_refs_y.append((face.Reference, normal))
closest_grid_x, min_dx = None, float('inf')
closest_grid_y, min_dy = None, float('inf')
for grid in grids:
curve = grid.Curve
if not curve:
continue
vec = curve.GetEndPoint(1) - curve.GetEndPoint(0)
proj = curve.Project(col_point)
if not proj:
continue
if abs(vec.X) > abs(vec.Y): # horizontal grid
dist = abs(proj.XYZPoint.Y - col_point.Y)
if dist < min_dy:
min_dy = dist
closest_grid_y = (grid, proj.XYZPoint)
else: # vertical grid
dist = abs(proj.XYZPoint.X - col_point.X)
if dist < min_dx:
min_dx = dist
closest_grid_x = (grid, proj.XYZPoint)
if face_refs_x and closest_grid_x:
if is_inclined:
create_perpendicular_dimension(view, face_refs_x[0][0], face_refs_x[0][1],
Reference(closest_grid_x[0]), closest_grid_x[1], offset_ft)
else:
try:
ref_array = ReferenceArray()
ref_array.Append(Reference(closest_grid_x[0]))
ref_array.Append(face_refs_x[0][0])
y = bbox.Min.Y - offset_ft
dim_line = Line.CreateBound(XYZ(bbox.Min.X, y, 0), XYZ(bbox.Max.X, y, 0))
if dim_line.Length > short_tol:
create_dimension_with_cut_paste(view, dim_line, ref_array)
except Exception as e:
print("⛔ X-dim error: {}".format(e))
if face_refs_y and closest_grid_y:
if is_inclined:
create_perpendicular_dimension(view, face_refs_y[0][0], face_refs_y[0][1],
Reference(closest_grid_y[0]), closest_grid_y[1], offset_ft)
else:
try:
ref_array = ReferenceArray()
ref_array.Append(Reference(closest_grid_y[0]))
ref_array.Append(face_refs_y[0][0])
x = bbox.Min.X - offset_ft
dim_line = Line.CreateBound(XYZ(x, bbox.Min.Y, 0), XYZ(x, bbox.Max.Y, 0))
if dim_line.Length > short_tol:
create_dimension_with_cut_paste(view, dim_line, ref_array)
except Exception as e:
print("⛔ Y-dim error: {}".format(e))
t.Commit()
except Exception as e:
t.RollBack()
TaskDialog.Show(“Error”, “Failed to create column-grid dimensions:\n{}”.format(str(e)))