; boundpt.lsp - to test the method of checking for a point within a bounding ; polygon by counting the intersections of a ray drawn from the; point to be checked with the boundary.; A point within the boundary will always have an odd number; of intersections of the ray with the boundary. A point ; outside will always have an even number of intersections of; the ray with the boundary. This is true regardless of the; complexity of the boundary topology.; There are, of course, potential problems that can occur.; For example, what is to be done when the ray intersects a; point just at the corner where a pair of segments meets?; Or if the ray aligns precisely with a segment? This program; handles these glancing cases by using multiple rays with a; majority vote determination of the total number of; intersections.; This program is limited to polygons of line segments only,; no polylines and no arcs. This demo program assumes the; drawing consists of one closed boundary with any number of; point entities distributed inside and outside the boundary.; All entities must be visible for proper operation. At the; end of processing, the set of all points within the; boundary is selected and highlighted.;; On a 1.6 MHz processor with 2 Gb RAM, and a boundary of 60; segments, this program checks about 26 points per second. ; random number generator to randomize the ray angles(defun rnd (/ modulus multiplier increment random) (if (not seed) (setq seed (getvar "DATE")) ) (setq modulus 65536 multiplier 25173 increment 13849 seed (rem (+ (* multiplier seed) increment) modulus) random (/ seed modulus) )); main(defun c:bpt (/ sscl cl_ln n cl_ed cl_en points_1 points_2 raylen rayang pt ppt1 ppt2 copy_cl ipt ef ic vlist sumc xmx xmn pt ptset pt_ln pt_en pt_ed loc_points oldcolor boundset) (setq sscl (ssget "X" '((0 . "LINE")))) ; get set of all lines(if sscl (setq cl_ln (sslength sscl)))(setq n 0)(if sscl ; not nil, store start and end points in list(progn (repeat cl_ln (setq cl_en (ssname sscl n)) (setq cl_ed (entget cl_en)) (setq points_1 (cons (cdr (assoc 10 cl_ed)) points_1)) ; save start point (setq points_2 (cons (cdr (assoc 11 cl_ed)) points_2)) ; save end point (setq n (+ n 1)) )))(setq xmx (getvar "EXTMAX"))(setq xmn (getvar "EXTMIN"))(setq raylen (distance xmx xmn))(setq boundset (ssadd)) ; initialize in-bounds point set(setq ptset (ssget "X" '((0 . "POINT"))))(if ptset (setq pt_ln (sslength ptset)))(setq n 0)(if ptset ; not nil, store X Y location of points in list(progn (repeat pt_ln (setq pt_en (ssname ptset n)) (setq pt_ed (entget pt_en)) (setq loc_points (cons (cdr (assoc 10 pt_ed)) loc_points)) ; save point location (setq n (+ n 1)) )))(setq np (- pt_ln 1))(repeat pt_ln(setq pt (car loc_points))(setq loc_points (cdr loc_points))(setq vlist nil)(setq ic 0)(setq n 0)(setq rayang (* (/ pi 1.5) (rnd))) ; for 3 rays(repeat 3 ; simulate 3 lines at random angles (while (< n cl_ln) ; check every segment of boundary for intersection (setq ppt1 (nth n points_1)) (setq ppt2 (nth n points_2)) (setq ipt (inters pt (polar pt rayang raylen) ppt1 ppt2)) (if ipt (setq ic (+ ic 1)) ) (setq n (+ n 1)) ) ; end inner loop (if (= (- (/ ic 2.0) (fix (/ ic 2.0))) 0) (setq ef 1) (setq ef 0) ) (setq ic 0) (setq n 0) (setq vlist (cons ef vlist)) (setq rayang (+ rayang (/ pi 1.5) (* (/ pi 1.5) (rnd)))) ; get new angle) ; end outer loop(setq sumc (apply '+ vlist))(if (not (or (= sumc 0) (= sumc 3))) (progn (princ "\n **** vote taken ****") (if (> sumc 1) (setq ef 1) ; for 3 lines (setq ef 0) ) ))(if (= ef 0) (ssadd (ssname ptset np) boundset))(setq np (- np 1)))(sssetfirst boundset boundset)(setq sscl nil)(setq ptset nil)(setq boundset nil)(princ))
One strange thing I encountered while writing this program : My first version used nested REPEAT loops. Once it was working, I noticed that the execution time increased in a regular way with every trial within the same drawing session. With a new drawing, the clock was, as it were, reset. After playing around a bit, I concluded that changing either the inner or outer loop to a WHILE eliminated the lengthening execution time. So at least for Intellicad's Lisp implementation, the advice is don't use nested REPEAT loops if the program will be used repeatedly in the same drawing, or performance will gradually degrade. I wonder if this is true with Autolisp or Visual lisp.