Drafting reflective ceiling plans (RCP) or MEP layouts often requires placing light fixtures, smoke detectors, or ceiling diffusers in perfectly balanced grids. Standard drafting rules specify a 1:2:1 spacing ratio—meaning the distance from the perimeter wall to the first fixture is half the distance between adjacent fixtures ($1/2 \times D$ from walls, $D$ between fixtures). Calculating these offset distances for every unique room dimension and moving blocks individually consumes a lot of setup time.
The FAR.lsp (Fixture Adaptive Grid) routine automates grid layout calculations into a two-point boundary pick. It automatically calculates row and column counts, detects room orientation, and snaps selected lighting blocks into a mathematically balanced 1:2:1 grid.
How FAR.lsp Handles Ceiling Layouts
1:2:1 Proportional Spacing: Automatically calculates half-spacing at wall boundaries and full spacing between interior fixtures to comply with standard ceiling layout rules.
Aspect Ratio Detection: Compares boundary width versus height to group fixtures logically into rows or columns, adapting automatically to narrow corridors or wide open offices.
Bounding Center Alignment: Calculates placement using the geometric bounding box center of each block rather than arbitrary insertion points, ensuring clean alignment across irregular block shapes.
Visual Reference Line: Draws a subtle diagonal reference line across the boundary corners, giving you instant visual verification that the grid layout command executed properly.
Quick Setup & Command Steps
Load
FAR.lspinto AutoCAD using theAPPLOADcommand.Type
FARin the command prompt and press Enter.Select all the lighting blocks or fixture symbols you want to arrange, then press Enter.
Click the first corner point of your ceiling boundary (e.g., top-left corner of the room).
Click the opposite diagonal corner (e.g., bottom-right corner).
The script immediately aligns and centers your selected fixtures in a clean, uniform grid layout.
AutoLISP Code (FAR.lsp)
Copy the code below and save it as FAR.lsp inside your AutoCAD support folder:
(defun c:FAR ( / *error* acadObj doc space ss p1_ucs p2_ucs p1 p2 minX maxX minY maxY totalW totalH cX cY cnt i ent vla-obj minpt maxpt cenX cenY items tol rows current_row numR r unitY row numC unitX targetY c item targetX cols current_col startPt endPt lineObj oldOsnap )
(vl-load-com)
(setq acadObj (vlax-get-acad-object)
doc (vla-get-activedocument acadObj)
space (vla-get-modelspace doc))
(defun *error* (msg)
(if oldOsnap (setvar "OSMODE" oldOsnap))
(if doc (vla-EndUndoMark doc))
(princ "\nCAD Lisp [www.daolpro.com]")
(princ)
)
(setq oldOsnap (getvar "OSMODE"))
(vla-StartUndoMark doc)
(princ "\nSelect objects to arrange: ")
(if (and (setq ss (ssget))
(setq p1_ucs (getpoint "\nSpecify first corner of boundary: "))
(setq p2_ucs (getcorner p1_ucs "\nSpecify opposite corner of boundary: ")))
(progn
(setq p1 (trans p1_ucs 1 0)
p2 (trans p2_ucs 1 0)
minX (min (car p1) (car p2))
maxX (max (car p1) (car p2))
minY (min (cadr p1) (cadr p2))
maxY (max (cadr p1) (cadr p2))
totalW (- maxX minX)
totalH (- maxY minY)
cX (/ (+ minX maxX) 2.0)
cY (/ (+ minY maxY) 2.0)
cnt (sslength ss)
i 0
items nil)
(repeat cnt
(setq ent (ssname ss i)
vla-obj (vlax-ename->vla-object ent))
(vla-getboundingbox vla-obj 'minpt 'maxpt)
(setq minpt (vlax-safearray->list minpt)
maxpt (vlax-safearray->list maxpt)
cenX (/ (+ (car minpt) (car maxpt)) 2.0)
cenY (/ (+ (cadr minpt) (cadr maxpt)) 2.0)
items (cons (list cenX cenY vla-obj) items)
i (1+ i))
)
(if (>= totalW totalH)
(progn
(setq tol (* totalH 0.1)
items (vl-sort items '(lambda (a b) (> (cadr a) (cadr b))))
rows nil
current_row nil)
(foreach item items
(if (null current_row)
(setq current_row (list item))
(if (< (abs (- (cadr item) (cadr (car current_row)))) tol)
(setq current_row (cons item current_row))
(progn
(setq rows (cons (vl-sort current_row '(lambda (a b) (< (car a) (car b)))) rows)
current_row (list item))
)
)
)
)
(if current_row
(setq rows (cons (vl-sort current_row '(lambda (a b) (< (car a) (car b)))) rows))
)
(setq rows (reverse rows)
numR (length rows)
r 1
unitY (/ totalH (* 2.0 numR)))
(foreach row rows
(setq numC (length row)
unitX (/ totalW (* 2.0 numC))
targetY (- maxY (* (- (* 2.0 r) 1.0) unitY))
c 1)
(foreach item row
(setq vla-obj (caddr item)
targetX (+ minX (* (- (* 2.0 c) 1.0) unitX)))
(vla-move vla-obj (vlax-3d-point (list (car item) (cadr item) 0.0)) (vlax-3d-point (list targetX targetY 0.0)))
(setq c (1+ c))
)
(setq r (1+ r))
)
)
(progn
(setq tol (* totalW 0.1)
items (vl-sort items '(lambda (a b) (< (car a) (car b))))
cols nil
current_col nil)
(foreach item items
(if (null current_col)
(setq current_col (list item))
(if (< (abs (- (car item) (car (car current_col)))) tol)
(setq current_col (cons item current_col))
(progn
(setq cols (cons (vl-sort current_col '(lambda (a b) (> (cadr a) (cadr b)))) cols)
current_col (list item))
)
)
)
)
(if current_col
(setq cols (cons (vl-sort current_col '(lambda (a b) (> (cadr a) (cadr b)))) cols))
)
(setq cols (reverse cols)
numC (length cols)
c 1
unitX (/ totalW (* 2.0 numC)))
(foreach col cols
(setq numR (length col)
unitY (/ totalH (* 2.0 numR))
targetX (+ minX (* (- (* 2.0 c) 1.0) unitX))
r 1)
(foreach item col
(setq vla-obj (caddr item)
targetY (- maxY (* (- (* 2.0 r) 1.0) unitY)))
(vla-move vla-obj (vlax-3d-point (list (car item) (cadr item) 0.0)) (vlax-3d-point (list targetX targetY 0.0)))
(setq r (1+ r))
)
(setq c (1+ c))
)
)
)
(setq startPt (vlax-3d-point p1)
endPt (vlax-3d-point p2)
lineObj (vla-addline space startPt endPt))
(vla-put-color lineObj 252)
(vla-EndUndoMark doc)
(setvar "OSMODE" oldOsnap)
(princ "\nObjects arranged successfully in adaptive grid layout (1:2:1 ratio).")
(princ "\nCAD Lisp [www.daolpro.com]")
)
(progn
(vla-EndUndoMark doc)
(setvar "OSMODE" oldOsnap)
(princ "\nCAD Lisp [www.daolpro.com]")
)
)
(princ)
)
Reflective Ceiling Plan (RCP) Tip
When coordinating ceiling plans with HVAC diffusers or sprinkler heads, run FAR on your primary downlights first to establish the main grid anchor, then align secondary sensors to the generated diagonal reference line.

Post a Comment