I just tried something, I think it works pretty well.
What the script did: it picks a point within a rectangle/box. If that point is not inside the polyline (which can have a weird shape) that point is skipped. and the while-loop tries again. Eventually a point will be found.
I added a "not_too_close" condition to the if (in the while). The difference is: there is no guarantee that it's possible to find points that are not too close, you could get into an infinite loop. So maximum 3000 rejected points; after that any point will be marked as okay. You can adapt that 3000 to whatever integer you wish.
;; example: block_name "b", 20 points, 1.5 max_scale, 0.01 min_scale, minimum distance = 1000.0
(defun c:scatter ( / )
(while
(populate "b" 20 1.5 0.01 1000.0) ;;
)
)
You can adapt at line 76, inside function populate: (setq max_tries 3000)
---
(defun rnd (/ modulus multiplier increment rand)
(if (not seed)
(setq seed (getvar "DATE"))
)
(setq modulus 65536
multiplier 25173
increment 13849
seed (rem (+ (* multiplier seed) increment) modulus)
rand (/ seed modulus)
)
)
(defun GroupByNum ( lst n / r)
(if lst
(cons
(reverse (repeat n (setq r (cons (car lst) r) lst (cdr lst)) r))
(GroupByNum lst n)
)
)
)
(defun ptonline ( pt pt1 pt2 / vec12 vec1p d result )
(setq vec12 (mapcar '- pt2 pt1))
(setq vec12 (reverse (cdr (reverse vec12))))
(setq vec1p (mapcar '- pt pt1))
(setq vec1p (reverse (cdr (reverse vec1p))))
(setq vec2p (mapcar '- pt2 pt))
(setq vec2p (reverse (cdr (reverse vec2p))))
(setq d (distance '(0.0 0.0) vec12) d1 (distance '(0.0 0.0) vec1p) d2 (distance '(0.0 0.0) vec2p))
(if (equal d (+ d1 d2) 1e-8) (setq result T) (setq result nil))
result
)
(defun ptinsideent ( pt ent / msp ptt xlin int k kk tst result )
(vl-load-com)
(setq msp (vla-get-modelspace (vla-get-activedocument (vlax-get-acad-object))))
(setq ptt (vlax-curve-getclosestpointto ent pt))
(setq xlin (vla-addxline msp (vlax-3d-point pt) (vlax-3d-point ptt)))
(setq int (GroupByNum (vlax-invoke (if (eq (type ent) 'ENAME) (vlax-ename->vla-object ent)) 'intersectwith xlin acExtendBoth) 3))
(setq int (vl-sort int '(lambda (a b) (< (vlax-curve-getparamatpoint xlin a) (vlax-curve-getparamatpoint xlin b)))))
(setq k 0)
(while (< (setq k (1+ k)) (length int))
(if (and (eq (rem k 2) 1) (ptonline pt (nth (- k 1) int) (nth k int))) (setq tst (cons T tst)) (setq tst (cons nil tst)))
)
(setq tst (reverse tst))
(setq k 0)
(mapcar '(lambda (x) (setq k (1+ k)) (if (eq x T) (setq kk k))) tst)
(vla-delete xlin)
(if kk
(if (eq (rem kk 2) 1) (setq result T) (setq result nil))
(setq result nil)
)
result
)
(setq max_tries 3000)
(defun not_too_close (pt allpoints min_dist / okay i)
(setq okay T)
(setq i 0)
(if (> max_tries 0)
(repeat (length allpoints)
(if (< (distance pt (nth i allpoints) ) min_dist )
(setq okay nil)
)
(setq max_tries (- max_tries 1))
(setq i (+ i 1))
)
)
okay
)
(defun populate ( bname no scf scfmin min_dist / DX DXX DY DYY ENT ENTA MAXPOINT MAXPT MINPOINT MINPT MSP PT SCFF result) (vl-load-com)
(setq result nil)
(setq allpoints (list))
(setq max_tries 3000) ;; 3000 attemps to reject a block that is too close to other blocks
(setq ent (car (entsel "\nPick 2D closed entity")))
(while (eq (cdr (assoc 70 (entget ent))) 0)
(prompt "\nPicked entity is open, please pick closed one")
(setq ent (car (entsel "\nPick 2D closed entity")))
)
(setq entA (vlax-ename->vla-object ent))
(setq msp (vla-get-modelspace (vla-get-activedocument (vlax-get-acad-object))))
(vla-getboundingbox entA 'minpoint 'maxpoint)
(setq
minpt (vlax-safearray->list minpoint)
maxpt (vlax-safearray->list maxpoint)
)
(setq dx (- (car maxpt) (car minpt)))
(setq dy (- (cadr maxpt) (cadr minpt)))
(if (null scfmin) (setq scfmin 1.0))
(while (> no 0)
(setq dxx (* dx (rnd)))
(setq dyy (* dy (rnd)))
(setq pt (list (+ (car minpt) dxx) (+ (cadr minpt) dyy) 0.0))
(if (and (eq scfmin 1.0) (eq scf 1.0)) (setq scff 1.0) (setq scff (+ scfmin (* (- scf scfmin) (rnd)))))
(if (and (not_too_close pt allpoints min_dist) (ptinsideent pt ent))
(progn
(setq no (1- no))
(setq result (vla-insertblock msp (vlax-3d-point pt) bname scff scff scff (* 2 pi (rnd))))
(setq allpoints (append allpoints (list pt)))
)
)
)
result
)
(defun c:populate ( / bname no min_dist)
(setq bname "")
(while (not (tblsearch "BLOCK" bname))
(setq bname (getstring T "\nInput name of block to populate (CASE UNSENSITIVE) : "))
)
(initget 6)
(setq no (getint "\nInput number of blocks to populate : "))
(initget 6)
(setq scf (getreal "\nInput max. scale factor for block insertion <1.0> : "))
(if (null scf) (setq scf 1.0))
(initget 6)
(setq scfmin (getreal "\nInput min. scale factor for block insertion <1.0> : "))
(setq min_dist (getreal "\nMinimum distance: ") )
(while
(populate bname no scf scfmin min_dist)
)
(princ)
)
(defun c:scatter ( / )
(while
(populate "b" 20 1.5 0.01 1000.0)
)
)