Arraypath with various step values

Arraypath with various step values

Anonymous
Not applicable
6,067 Views
41 Replies
Message 1 of 42

Arraypath with various step values

Anonymous
Not applicable

Hi,

I would create a LISP that draw a circle at the starting or ending point (depends where I click) of a existing line.

Then with this circle I would do an ARRAYPATH but with different value of distance between the circles. The value of the distance should be taken from a fixed pool of values.

 

Example

1. I click on the line in the side where I want the circle (with fixed radius)

2. LISP command draws the circle

3. LIPS command draws a second circle "VAR1" unit far from the first circle, LIPS command draws a third circle "VAR2" unit far from the second circle, and so on until the end of the line/path.

 

"VAR1" "VAR2" "VAR3"... are fixed values that the command should take randomly.

It could be plus if I could edit manually some values of distance (maybe with something like a input text box between the circles).

 

Is it possible to do this? Maybe at the least without the random distance value?

Where I could find guide of the ARRAYPATH parameters?

 

Thank you

 

PS: I would change the default distance of the arraypath command. There isn't any system variable to change? I see only solutions with "actions recording" or "lisp" for this...and it can't be!!!😅

 

 

0 Likes
Accepted solutions (2)
6,068 Views
41 Replies
Replies (41)
Message 2 of 42

Kent1Cooper
Consultant
Consultant

I don't think there's anything out-of-the-box that can do that.  It may be possible with a custom routine, for which you would be better off posting in the Customization Forum.

 

But I have a question [you could say something about it if you post there]:  Does "random" selection of distance values from a fixed list mean really random, or "controlled" random in some way?  For example, should it not use any value more than once?  A truly random selection, let's say 5 times, of values from a list could result in repeats of some value(s), or even [however unlikely] the same  value being drawn for all 5 selections.  Should a value that has been used be removed from the list before the next selection?

 

Of course, if the length of the path and the typical distances mean there will need to be more Circles than there are distances, it would be unavoidable to have repeats.  But should there be some attempt to have all the different values used, and spread the repeats around?

Kent Cooper, AIA
0 Likes
Message 3 of 42

Anonymous
Not applicable

Thank you for your reply, I will follow your suggest.

 

About your question on the "random mode", yes, I should have 5 times the same value.

About the attempts to fill the path completly using all the allowed distance value, it could be a nice feature but I think too much advanced for my case.

Can you help me about the default arraypath distance? There is a system variable to set?

Where a I could find a guide to make a custom LISP for the arraypath?

Thank you

0 Likes
Message 4 of 42

ВeekeeCZ
Consultant
Consultant

Not sure if I follow you... but give it a try.

 

(vl-load-com)

(defun c:ArrayOfCircles ( / r d u p1 p2 d1 d2)

  (setq r 2.  				; radius
	d '(10. 8. 5. 3.5 3.5)		; distances
	i -1)

  (if (and (setq p1 (getpoint "\nPlace initial circle: "))
	   (setq p2 (getpoint p1 "\nPlace last circle: "))
	   (or (setq pl (car (nentselp p1)))
	       (setq pl (car (nentselp p2))))
	   (setq p1 (vlax-curve-getClosestPointTo pl p1))
	   (setq d1 (vlax-curve-getDistAtPoint pl p1))
	   (setq p2 (vlax-curve-getClosestPointTo pl p2))
	   (setq d2 (vlax-curve-getDistAtPoint pl p2))
	   (or (< d1 d2)
	       (prompt "\nError: Wrong direction."))
	   (entmake (list (cons 0 "CIRCLE") (cons 10 p2) (cons 40 r)))
	   )
    (while (< d1 d2)
      (entmake (list (cons 0 "CIRCLE") (cons 10 (vlax-curve-getPointAtDist pl d1)) (cons 40 r)))
      (setq d1 (+ d1 (cond ((nth (setq i (1+ i)) d))
			   ((nth (setq i 0) d)))))))
  (princ)
  )

 

And to answer your question - the is no such variable. It's calculated somehow according to the actual length of the path. 

Message 5 of 42

Moshe-A
Mentor
Mentor

@Anonymous  hi,

 

Check this one. it call ARPTH (Array Path)

this program is base on Lee's Mac (LM:randrange) function to get a random value so thank you very much Lee Mac

it works in a loop letting you pick a line path (actually it's a curve which lets you also select a polylines and splines) each one in a row.

 

the next code line defined the fix distances. you can changes these numbers as you like to meet your requirements.

(setq FIXVAL '(5.35 6.68 4.59 7.51 8.23 9.15 5.35 6.75 7.45))

 

also there is a constant defines the circle radius you can set it with your radius

(setq RADIUS 2)

 

another constant refers to the randomize value. there must be a limit for trying to get a random value otherwise the program might enter an infinite loop 😀  if 96 is a low value, you can increase (or decrease) it to speed the program.

(setq RANDTRY 96)

 

the program make sure there will not be an overlapping circles if you did not mind this i can remove this check.

 

and last:

the circles in each line path (curve) is collected and put in a group, giving the feel of array path (it's totally static you can not edit it, only select to move\copy\rotate or delete)

 

enjoy

Moshe

 

 

 

 

 

;; Rand  -  Lee Mac
;; PRNG implementing a linear congruential generator with
;; parameters derived from the book 'Numerical Recipes'

(defun LM:rand ( / a c m )
    (setq m   4294967296.0
          a   1664525.0
          c   1013904223.0
          $xn (rem (+ c (* a (cond ($xn) ((getvar 'date))))) m)
    )
    (/ $xn m)
)

;; Random in Range  -  Lee Mac
;; Returns a pseudo-random integral number in a given range (inclusive)

(defun LM:randrange ( a b )
    (+ (min a b) (fix (* (LM:rand) (1+ (abs (- a b))))))
)

(defun c:arpth (/ wcs->ucs randomize ; local functions
                  RADIUS FIXVAL ss0 ss1 pick ename p0 p1 d0 d1 d2 seg len rnd dirMode bool)

 (defun wcs->ucs (pt)
  (trans pt 0 1)
 )
  
 (defun randomize (/ n r)
  (setq n 0)
  (while (and
           (< n RANDTRY) ; make sure not enter infinite loop
           (< (setq r (nth (LM:randrange 0 (length FIXVAL)) FIXVAL)) (* RADIUS 2))
         )
   (setq n (1+ n)) 
  )

  (if (= n RANDTRY)
   (alert "radomize fail to generate a reasonable number.")  
   r)
 ); radomize


 ; here start c:arpth 
 (setvar "cmdecho" 0)
 (command "._undo" "_begin")

 ; constant declaration
 (setq RANDTRY 96)   ; max radomize tries
 (setq RADIUS 2)     ; fix circle radius
 ; fix dist values 
 (setq FIXVAL '(5.35 6.68 4.59 7.51 8.23 9.15 5.35 6.75 7.45))
  
 (while (setq ss0 (ssget ":s:e+." '((0 . "*line")))) ; line,polyline,lwpolyline,spline can be picked here
  (setq pick (ssnamex ss0))
  (setq ename (cadar pick))
  (setq p0 (cadr (last (car pick))))

  (setq d0 0.0)
  (setq d1 (vlax-curve-getDistAtParam ename (vlax-curve-getParamAtPoint ename (vlax-curve-getClosestPointTo ename p0))))
  (setq d2 (vlax-curve-getDistAtParam ename (vlax-curve-getEndParam ename)))

  (if (setq dirMode (< d1 (- d2 d1)))
   (setq bool '< seg 0.0 upto d2)
   (setq bool '> seg d2 upto 0.0)
  )
   
  (setq rnd t len d2)
  (setq ss1 (ssadd)) ; for group

  (while (and rnd (eval (list bool seg upto)))
   (setq p1 (wcs->ucs (vlax-curve-getPointAtDist ename seg)))
   (command "._circle" p1 RADIUS)
   (ssadd (entlast) ss1) 

   (if (setq rnd (randomize))
    (if dirMode 
     (setq seg (+ seg rnd))
     (setq seg (- len (setq d0 (+ d0 rnd))))
    ); if
   ); if
  ); while

  (command "._group" "" "*" "" "_si" ss1)
  (setq ss1 nil) 
 ); while

 (command "._undo" "_end") 
 (setvar "cmdecho" 1) 
 (princ)  
); c:arpth

 

 

 

 

 

 

 

Message 6 of 42

ВeekeeCZ
Consultant
Consultant

Also, I remember THIS  video referring to SCATTER  routine. See if you find it helpful.

0 Likes
Message 7 of 42

Anonymous
Not applicable

Thank you!

 

of course I gave it a chance. The idea is correct but I need to select arcs too.

Do you think it can works with some edit?

0 Likes
Message 8 of 42

Anonymous
Not applicable

Thank you for your time.

 

I've tried with this

 ; constant declaration
 (setq RANDTRY 20)   ; max radomize tries
 (setq RADIUS 3)     ; fix circle radius
 ; fix dist values 
 (setq FIXVAL '(20 30 40))

but i got this (see picture below)
There is maybe something I've not understood.

What I meant is that the command must randomly choose between the values ​​"20" "30" "40" and draw the circle.
Does your LISP works with arcs too? It seems not on my tries.

Sorry, maybe I has not been enought clear on my question.
Do you think your command are "fixable" in this way?

Thank you in advance again

0 Likes
Message 9 of 42

Moshe-A
Mentor
Mentor

@Anonymous 

 


@Anonymous wrote:

Thank you!

 

of course I gave it a chance. The idea is correct but I need to select arcs too.

Do you think it can works with some edit?


change this line

 (while (setq ss0 (ssget ":s:e+." '((0 . "*line")))) ; line,polyline,lwpolyline,spline can be picked here

 

to this line

(while (setq ss0 (ssget ":s:e+." '((0 . "*line,arc")))) ; line,polyline,lwpolyline,spline + ARCs can be picked here

 

 

0 Likes
Message 10 of 42

pbejse
Mentor
Mentor

@Anonymous wrote:

Sorry, maybe I has not been enought clear on my question.


 

Indeed, the surprise is killing me, how is it supposed to look anyway?

 

0 Likes
Message 11 of 42

Moshe-A
Mentor
Mentor

What I meant is that the command must randomly choose between the values ​​"20" "30" "40" and draw the circle.

of course it picks distance randomly, you did not specifies enough values to look it selects varies value

 

0 Likes
Message 12 of 42

ВeekeeCZ
Consultant
Consultant
Accepted solution

Here you go. Also added a second version for even more fun!

 

(vl-load-com)

(defun c:ArrayOfCircles ( / r d i p1 p2 d1 d2 o1 o2)
  
  (setq r 2.  				; radius
	d '(10. 8. 5. 3.5 3.5)		; distances
	i -1)
  
  (if (and (setq p1 (getpoint "\nPlace initial circle: "))
	   (setq p2 (getpoint p1 "\nPlace last circle: "))
	   (or (setq pl (car (nentselp p1)))
	       (setq pl (car (nentselp p2))))
	   (setq p1 (vlax-curve-getClosestPointTo pl p1))
	   (setq d1 (vlax-curve-getDistAtPoint pl p1))
	   (setq p2 (vlax-curve-getClosestPointTo pl p2))
	   (setq d2 (vlax-curve-getDistAtPoint pl p2))
	   (if (< d1 d2)
	     (setq o1 < o2 +)
	     (setq d (reverse d) o1 > o2 -))
	   (entmake (list (cons 0 "CIRCLE") (cons 10 p2) (cons 40 r)))
	   )
    (while (o1 d1 d2)
      (entmake (list (cons 0 "CIRCLE") (cons 10 (vlax-curve-getPointAtDist pl d1)) (cons 40 r)))
      (setq d1 (o2 d1 (cond ((nth (setq i (1+ i)) d))
			    ((nth (setq i 0) d)))))))
  (princ)
  )



(vl-load-com)

(defun c:ArrayOfCirclesRandom ( / r d i p1 p2 d1 d2 o1 o2)
  
  ;; Rand  -  Lee Mac
  ;; PRNG implementing a linear congruential generator with
  ;; parameters derived from the book 'Numerical Recipes'
  
  (defun LM:rand ( / a c m )
    (setq m   4294967296.0
	  a   1664525.0
	  c   1013904223.0
	  $xn (rem (+ c (* a (cond ($xn) ((getvar 'date))))) m))
    (/ $xn m))
  
  (defun LM:randrange ( a b )
    (+ (min a b) (fix (* (LM:rand) (1+ (abs (- a b)))))))
  
  ; ----------------------------------------------------------------------
  
  (setq r 2.  				; radius
	d '(10. 8. 5. 3.5 3.5)		; distances
	i -1)
  
  (if (and (setq p1 (getpoint "\nPlace initial circle: "))
	   (setq p2 (getpoint p1 "\nPlace last circle: "))
	   (or (setq pl (car (nentselp p1)))
	       (setq pl (car (nentselp p2))))
	   (setq p1 (vlax-curve-getClosestPointTo pl p1))
	   (setq d1 (vlax-curve-getDistAtPoint pl p1))
	   (setq p2 (vlax-curve-getClosestPointTo pl p2))
	   (setq d2 (vlax-curve-getDistAtPoint pl p2))
	   (if (< d1 d2)
	     (setq o1 < o2 +)
	     (setq o1 > o2 -))
	   (entmake (list (cons 0 "CIRCLE") (cons 10 p2) (cons 40 r)))
	   )
    (while (o1 d1 d2)
      (entmake (list (cons 0 "CIRCLE") (cons 10 (vlax-curve-getPointAtDist pl d1)) (cons 40 r)))
      (setq d1 (o2 d1 (nth (LM:randrange 0 (1- (length d))) d)))))
  (princ)
  )

 

Message 13 of 42

Moshe-A
Mentor
Mentor

@Anonymous ,

 

here is a modified version supporting arcs plus adopting your distance list.

also i add a prompt for the circle radius so you can set a new value each invocation.

 

make sure you select a large curve to accept your distance list.

 

Moshe

 

 

;; Rand  -  Lee Mac
;; PRNG implementing a linear congruential generator with
;; parameters derived from the book 'Numerical Recipes'

(defun LM:rand ( / a c m )
    (setq m   4294967296.0
          a   1664525.0
          c   1013904223.0
          $xn (rem (+ c (* a (cond ($xn) ((getvar 'date))))) m)
    )
    (/ $xn m)
)


;; Random in Range  -  Lee Mac
;; Returns a pseudo-random integral number in a given range (inclusive)

(defun LM:randrange ( a b )
    (+ (min a b) (fix (* (LM:rand) (1+ (abs (- a b))))))
)

(defun c:arpth (/ initialization askdist wcs->ucs randomize ; local functions
                  defrad RANDTRY RADIUS FIXVAL ss0 ss1 pick ename p0 p1 d0 d1 d2 seg len rnd dirMode bool)

 (defun initialization ()
  ; constant declaration
  (setq RANDTRY 96)   ; max radomize tries
  ; fix dist values 
  (setq FIXVAL '(20.0 30.0 40.0 50.0 60.0)) 

  (if (= (getvar "userr4") 0.0)
   (setq defrad (setvar "userr4" 2.0))
   (setq defrad (getvar "userr4")) 
  )
 ); initialization

 (defun askdist (def / ask)
  (initget (+ 2 4))
  (if (not (setq ask (getdist (strcat "\nCircle radius <" (rtos def 2 2) ">: "))))
   (setq ask def)
   (setq def ask)
  )
 ); askdist
  
 (defun wcs->ucs (pt)
  (trans pt 0 1)
 )
  
 (defun randomize (/ n r)
  (setq n 0)
  (while (and
           (< n RANDTRY) ; make sure not enter infinite loop
           (< (setq r (nth (LM:randrange 0 (length FIXVAL)) FIXVAL)) (* RADIUS 2))
         )
   (setq n (1+ n)) 
  )

  (if (= n RANDTRY)
   (alert "randomize fail to generate a reasonable number.")  
   r)
 ); randomize

 ; here start c:arpth 
 (setvar "cmdecho" 0)
 (command "._undo" "_begin")

 (initialization)
 (setvar "userr4" (setq radius (askdist defrad)))

 (while (setq ss0 (ssget ":s:e+." '((0 . "*line,arc")))) ; line,polyline,lwpolyline,spline + ARCs can be picked here
  (setq pick (ssnamex ss0))
  (setq ename (cadar pick))
  (setq p0 (cadr (last (car pick))))

  (setq d0 0.0)
  (setq d1 (vlax-curve-getDistAtParam ename (vlax-curve-getParamAtPoint ename (vlax-curve-getClosestPointTo ename p0))))
  (setq d2 (vlax-curve-getDistAtParam ename (vlax-curve-getEndParam ename)))

  (if (setq dirMode (< d1 (- d2 d1)))
   (setq bool '< seg 0.0 upto d2)
   (setq bool '> seg d2  upto 0.0)
  )
   
  (setq rnd t len d2)
  (setq ss1 (ssadd)) ; for group

  (while (and rnd (eval (list bool seg upto)))
   (setq p1 (wcs->ucs (vlax-curve-getPointAtDist ename seg)))
   (command "._circle" p1 RADIUS)
   (ssadd (entlast) ss1) 

   (if (setq rnd (randomize))
    (if dirMode 
     (setq seg (+ seg rnd))
     (setq seg (- len (setq d0 (+ d0 rnd))))
    ); if
   ); if
  ); while

  (command "._group" "" "*" "" "_si" ss1)
  (setq ss1 nil) 
 ); while

 (command "._undo" "_end") 
 (setvar "cmdecho" 1) 
 (princ)  
); c:arpth
  

 

 

 

Message 14 of 42

Anonymous
Not applicable

@ВeekeeCZ 

@Moshe-A 

Thank you VERY much! 💙😊🍻

0 Likes
Message 15 of 42

pbejse
Mentor
Mentor

Another

 

(defun c:Crayon ( / LM:rand LM:randrange _DistList rad ss en eLent sym d)
  
  ;; Rand  -  Lee Mac
  ;; PRNG implementing a linear congruential generator with
  ;; parameters derived from the book 'Numerical Recipes'
  
  (defun LM:rand ( / a c m )
    (setq m   4294967296.0
	  a   1664525.0
	  c   1013904223.0
	  $xn (rem (+ c (* a (cond ($xn) ((getvar 'date))))) m))
    (/ $xn m))
  
  (defun LM:randrange ( a b )
    (+ (min a b) (fix (* (LM:rand) (1+ (abs (- a b)))))))
  
(Defun _DistList (data / opt d)
(setq inc 0)(initget "Yes New")
(cond
 ( (and data
     (eq (setq opt (Getkword (strcat  "\nUse Previous data :[Yes/New]"
				      (vl-prin1-to-string data) "<New>?"))) "Yes"))
    data
  )
 ( (and data (/= opt "Yes"))
  	(_DistList nil)
  )
 ( (null data)
   (while (and (null (initget 6))
	       (setq d (getdist (strcat "\nEnter Distance " (itoa (setq inc (1+ inc)))))))
  	(print (reverse (setq data (cons d data))))
  	)
     )
  )
 )
(and
	(setq rad 2.0 values ( _DistList values))		 
	(while 	(setq ss (ssget "_+.:S:E" '((0 . "*LINE,ARC"))))
		(setq en (cadar (ssnamex ss)))
		(setq nsp (vlax-curve-getClosestPointTo en (cadr (last (car (ssnamex ss))))))
	  	(setq eLent (vlax-curve-getDistAtPoint en (Vlax-curve-GetEndpoint en)))  			
	  	(setq sym (if (< (vlax-curve-getDistAtPoint en nsp) (* eLent 0.5))
			    (progn (setq eLent 0) +) -))

	  	(while (and (setq d (nth (LM:randrange 0 (1- (length values))) values))
			 	(setq pt (vlax-curve-getPointAtDist en (setq eLent (sym eLent d)))))
	  	 	 (entmake (list (cons 0 "CIRCLE") (cons 10 pt) (cons 40 rad)))
		  )
	  )
	)
  (princ)
  )

 

 

Similar approach as @ВeekeeCZ : added extra features like prompting for distance values

 

Command: CRAYON
Enter Distance 18
(8.0)
Enter Distance 26.3
(8.0 6.3)
Enter Distance 35.2
(8.0 6.3 5.2);< shows current listing
Enter Distance 4
Select objects: 
Select objects: <- continue selection

Command:  CRAYON
Use Previous data :[Yes/New](8.0 6.3 5.2)<New>? Y ;<--- Shows current data
Select objects:

Command:  CRAYON
Use Previous data :[Yes/New](8.0 6.3 5.2)<New>?N <--- type in new data
Enter Distance 14
(4.0)
Enter Distance 28
(4.0 8.0)
Enter Distance 35.2
(4.0 8.0 5.2)
Enter Distance 4
Select objects:

 

HTH

 

 

Message 16 of 42

Anonymous
Not applicable

Thank you.
In my case I don't need to change the values, but sure it's useful see the code and keep it for the future. 😉

0 Likes
Message 17 of 42

pbejse
Mentor
Mentor

@Anonymous wrote:

Thank you.
In my case I don't need to change the values, but sure it's useful see the code and keep it for the future. 😉


 

No worries mega-mini, was just thinking since you mention it needs to be random, whats more random than the capability to provide diffferent distance.  We can however set the initial values?

 

Anyways, glad you like it.

 

 

 

 

0 Likes
Message 18 of 42

Anonymous
Not applicable

In my case, a really improved could be the possibility to edit manually some distance after the circles have been drawed.

Example (setted distances: 15 18 21 24).
Command drawed four circle with distances 21, 18, 18, 24. Distance between the first and the last circle is 81 (21+18+18+24). I would be able di change the second distance (maybe with an input textbox) moving all the follwing  step. So i could manually change distances 21, 15, 18, 24 and moving the third and the fourth circles, distance between the first and the last circle should be 78 now.


0 Likes
Message 19 of 42

ВeekeeCZ
Consultant
Consultant

@Anonymous wrote:

In my case, a really improved could be the possibility to edit manually some distance after the circles have been drawed.

Example (setted distances: 15 18 21 24).
Command drawed four circle with distances 21, 18, 18, 24. Distance between the first and the last circle is 81 (21+18+18+24). I would be able di change the second distance (maybe with an input textbox) moving all the follwing  step. So i could manually change distances 21, 15, 18, 24 and moving the third and the fourth circles, distance between the first and the last circle should be 78 now.



 

Did you end up with my random version of routine? Or which one?

The described process...

- are you doing this fine-tuning right away with every single 'array placement'?

- if the routine zoom-in to your segment and pop-up list of actual values to you to edit... would that be ok? Or do you need to make some kind of measurements before the edits?

 

I'm thinking of this "edit" screen at the end of the routine... there would be listed the actual values.. you'll set what you want and it will be applied on the circles. But it's a modal dialog.

 

Z9E3zK5E_0-1604318309477.png

 

Edit: Do you need to see those circles drawn at all? Won't be enough to give you just numbers - you know, overall length and randomly generated numbers...   That might be easier to do...

 

 

0 Likes
Message 20 of 42

pbejse
Mentor
Mentor

@Anonymous wrote:


Example (setted distances: 15 18 21 24).
Command drawed four circle with distances 21, 18, 18, 24. Distance between the first and the last circle is 81 ....should be 78 now.


 

I guess "random" means any order of the four given distance [ 15 18 21 24 ] but no repeats Yes? what about the next group after that? or does it mean when you reach the total of the distance list, the program terminates regardless how long the selected object is?

 

Please show us how it really should look  @Anonymous  🙂