This question intrigued me and I have been thinking about a stragey for a program on and off for awhile. My thoughts have evolved around casting imaginary lines from the light source to the vertices of a polyline and then checking which vertices would be visible to the light and which would be hidden. In addition, this approach requires finding the points on exposed walsl where the edges of shadows appear. The coding for this became cumbersom for me.
The recent post by @john.uhden inspired a different, and much simpler to implement, approach. Why not just cast a set of radial rays and see what "walls" they hit. Connect the intersection points and you have the shape of the strobe coverage. The program sends out a ray every 1°. There are a couple of shortcomings to this approach including an excessive number of vertices and room corners may not be sharp. A routine to delete excessive collinear points could address the first problem.
Here's a example solution. The red lines defines the shape of the room, the point is the location of the light and the green polyline the strobe coverage.
(defun c:shadow (/ obj1 p1 shadowlist ang angrad delta p2 p x )
; Determines where shadows will fall given a polyline that defines the plan view
; of a room and the location of a point light source. The program casts rays every
; 1° to dtermine where light will hit.
; L. Minardi 11/17/2024
(setq obj1 (vlax-ename->vla-object (car (entsel "Select Polyline"))))
(setq p1 (getpoint "\n Specify light location"))
(setq shadowList nil)
(setq ang 0
delta 1
)
(while (< ang 360)
(setq angrad (/ (* ang pi) 180.))
(setq p2 (polar p1 angrad 100000))
(setq p (GetNearIntersetion obj1 P1 p2))
(if p
(progn
(setq shadowList (append shadowList (list p)))
)
)
(setq ang (+ ang delta))
) ; end while
(setvar "cmdecho" 0)
(command "_pline") ;start pline command
(while (= (getvar "cmdactive") 1) ;while a command is running loop
(repeat (setq x (length shadowlist))
(command "_non" (nth (setq x (- x 1)) shadowList))
) ;end repeat
(command "") ;end pline
)
(setvar "cmdecho" 1)
(princ)
)
(defun GetNearIntersetion (obj1 p1 p2 / e obj2 x n Q qlist i p dmin d )
(setq e (entmakex
(list '(0 . "line") (cons 10 p1) (cons 11 p2) (cons 60 1))
)
)
(setq obj2 (vlax-ename->vla-object e))
(setq x (vlax-invoke OBJ1 'intersectwith OBJ2 acextendnone))
(setq n (/ (length x) 3))
(setq i 0
qList nil
)
(repeat n
(setq Q (list (nth i x) (nth (+ i 1) x)))
(setq qList (append qlist (list q)))
(setq i (+ i 3))
)
(setq i 0)
(cond
((= qList nil) (setq p nil))
((= (length qList) 1) (setq p (car qList)))
((> (length qList) 1)
(progn
(setq n (length qList)
p (nth i qList)
dmin (distance p1 p)
i (+ 1)
)
(repeat (- n 1)
(setq d (distance p1 (nth i qList)))
(if (< d dmin)
(setq dmin d
p (nth i qList)
)
)
(setq i (+ i 1))
)
)
)
) ; end cond
(setq p p)
)
lee.minardi