How to select even item in array

How to select even item in array

aliff_ahtenk
Enthusiast Enthusiast
2,159 Views
14 Replies
Message 1 of 15

How to select even item in array

aliff_ahtenk
Enthusiast
Enthusiast

How i make this routine lisp?

The goal is how do i select the secondly item between the array to change the size?

 

Step 1: Draw SPLINE

Step 1.JPG

 

 

Step 2: Draw CIRCLE at Start Point

Step 2.JPG

 

 

Step 3: ARRAY the CIRCLE at SPLINE as path.
Where the array object is set to be devide equally and the number of item must be odd and taken base on the length of the spline but in range of some value. As Example, the SPLINE is 955.68, then range need is 45-55, number of item is 19 nos because 955.68/50 = 19.11 round up to closed odd, 19.

Step 3.JPG

 


Step 4: Selecting the EVEN item on the ARRAY to change the diameter

Step 5.JPG

 

Step 5: Done - That all of complete step.

 

Thanks in advance for helping.

Notes: I usually used this method on item less then 20 but if the item reach up till 100 that would be a longer time to select it one by one. i simply naming the first, third, fifth,....... as odd item and second, fourth,...... as even item.

0 Likes
Accepted solutions (3)
2,160 Views
14 Replies
Replies (14)
Message 2 of 15

hosneyalaa
Advisor
Advisor

hello
possible An example drawing is attached

0 Likes
Message 3 of 15

pbejse
Mentor
Mentor
Accepted solution

@aliff_ahtenk wrote:

The goal is how do i select the secondly item between the array to change the size?

 


Select the array and enter scale factor.

(defun c:Demo (/ aDoc Blocks)
  (setq	aDoc   (vla-get-ActiveDocument (vlax-get-acad-object))
	Blocks (vla-get-blocks aDoc)
  )

  (if (and
	(setq ss (ssget '((0 . "INSERT"))))
	(setq sf (getreal "\nEnter scale factor: "))
      )
    (repeat (setq i (sslength ss))
      (setq l 0
	    e (vlax-ename->vla-object (ssname ss (Setq i (1- i))))
      )
      (vlax-for	obj (vla-item Blocks (vla-get-EffectiveName e))
	(if (zerop (setq l (boole 6 1 l)))
	  (mapcar '(lambda (s)
		     (vlax-put obj s sf)
		   )
		  '("XScaleFactor" "YScaleFactor" "ZScaleFactor")
	  )
	)
      )
    )
  )
  (vla-regen aDoc acactiveviewport)
  (princ)

)

HTH

0 Likes
Message 4 of 15

hak_vz
Advisor
Advisor

@aliff_ahtenk   Try this. It creates circles along spline at approximate distance 50 units, and changes radius in odd-even swaps.  Pick spline, enter radius for odd and even circles and that's it.

(defun c:odd_even_circles (/ *error* adoc blocks c e eo n len r_odd r_even sc l )
	(defun *error* ( msg )
		(if (not (member msg '("Function cancelled" "quit / exit abort")))
			(princ)
		)
		(if (and adoc) (vla-endundomark adoc))
		(setvar 'cmdecho 0)
		(princ)
	)
	(setq	adoc (vla-get-ActiveDocument (vlax-get-acad-object)) blocks (vla-get-blocks adoc))
	(vla-endundomark adoc)
	(vla-startundomark adoc)
	(while (and (not (setq e (car (entsel "\nSelect spline >"))))(/= 52 (getvar "ErrNo"))))
	(setq  
		eo (vlax-ename->vla-object e) 
		sp (vlax-curve-getStartPoint eo)
		ep (vlax-curve-getEndPoint eo)
	    len (vlax-curve-getDistAtPoint eo ep)
	)
	(setq n (/ len 50))
	(cond ((> (- n (fix n)) 0.5) (setq n (1+ (fix n)))(setq n (fix n))))
	(setq r_odd (getreal "\nEnter radius of odd circles >")  r_even (getreal "\nEnter radius of odd circles >"))
	(setq c (entmakex (list (cons 0 "CIRCLE") (cons 10 (vlax-Curve-getStartPoint eo))(cons 40 r_odd))))
	(setvar 'cmdecho 0)
	(command ".arraypath" c "" e "O" sp ep "E" n "D" "X")
	(setvar 'cmdecho 1)
	(setq sc (/ r_even r_odd))
	(setq eo (vlax-ename->vla-object (entlast)) l 0)
	(vlax-for item (vla-item blocks (vla-get-EffectiveName eo))
		(if (zerop (setq l (boole 6 1 l)))
		  (mapcar '(lambda (s)(vlax-put item s sc))'("XScaleFactor" "YScaleFactor" "ZScaleFactor"))
		)
	)
  (vla-regen adoc acactiveviewport)
  (vla-endundomark adoc)
  (princ)
)

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 5 of 15

Kent1Cooper
Consultant
Consultant

That doesn't always have the total of an odd number of Circles, as first described.

The prompt for the even Circle radius should be fixed.

But mostly, the end of it looks like it's for Blocks, not Circles, and accordingly, the routine does not change the size of alternating Circles.

 

@aliff_ahtenk , would the path object ever be closed?  If so, the (vlax-curve-getDistAtPoint) function should not be used to get the length -- it will return zero if the start and end points are at the same place.  You can get the correct distance with (vlax-curve-getDistAtParam e (vlax-curve-getEndParam e)) .  [Also, you don't need a VLA-object conversion for this -- (vlax-curve...) function can take just the entity name.]

Kent Cooper, AIA
0 Likes
Message 6 of 15

Kent1Cooper
Consultant
Consultant

@aliff_ahtenk wrote:

.... As Example, the SPLINE is 955.68, then range need is 45-55 ....


Is there a criterion for what the range needs to be based on the length of the Spline [or other "path" object]?  If so, the routine could calculate the range; if not, should it always be 45-55, or should the User be asked for the target spacing, or something else?

 

Likewise for the Circle radii -- can they be calculated from something about the path, or should the User always be asked for them?

 

Also, I see no reason that a routine could not be made to work with any finite path object with linearity [Line, Circle, Arc, Spline, Ellipse, Polyline].  Should it be limited to only certain path types?

Kent Cooper, AIA
0 Likes
Message 7 of 15

Kent1Cooper
Consultant
Consultant
Accepted solution

@aliff_ahtenk wrote:

....

The goal is how do i select the secondly item between the array to change the size?

....

Step 4: Selecting the EVEN item on the ARRAY to change the diameter

.....


I would suggest a different approach.  Rather than drawing a Circle, Arraying it, then finding every other one to change their size, I would put them in at their alternating sizes directly.  This works for me [limited testing]:

 

(defun C:COE ; = Circles with Odd- & Even-position radii
  (/ spc r1 r2 path etype plen cyc div inc)
  (setq
    spc (getdist "\nTarget spacing between Circles (to be rounded): ")
    r1 (getdist "\nRadius of odd-position Circles: ")
    r2 (getdist "\nRadius of even-position Circles: ")
  ); setq
  (while
    (not
      (and
        (setq path (car (entsel "\nPath object: ")))
        (setq etype (cdr (assoc 0 (entget path))))
        (wcmatch etype "*LINE,CIRCLE,ARC,ELLIPSE")
        (not (wcmatch etype "XLINE,MLINE"))
      ); and
    ); not
    (prompt "\nNothing selected, or invalid path type.")
  ); while
  (setq
    plen (vlax-curve-getDistAtParam path (vlax-curve-getEndParam path))
    cyc (atoi (rtos (/ plen (* spc 2)) 2 0))
    div (/ plen (* cyc 2))
    inc -1
  ); setq
  (repeat (* cyc 2)
    (command "_.circle"
      "_non" (vlax-curve-getPointAtDist path (* div (setq inc (1+ inc))))
      (if (= (rem inc 2) 0) r1 r2)
    ); command
  ); repeat
  (if (not (vlax-curve-isClosed path))
    (command "_.circle" "_non" (vlax-curve-getEndPoint path) r1)
  ); if
  (princ)
)

 

If it makes the right kind of result, it can have command echoing suppressed, it could be made to remember your spacing and radii choices and offer them as defaults, it could supply initial first-use default values, it could put the Circles on the Layer of the path, or on any other Layer you want to specify, it could have *error* handling added if anything above changes something that should be set back, it could be wrapped in an Undo begin/end so U will undo all of it at once, it could be made to do it on multiple objects at once, or multiple single objects picked one at a time but within one running of the command, etc.

 

[On a closed path, it actually makes an even number of Circles, so they can alternate in size regularly even across the beginning/ending point.]

Kent Cooper, AIA
0 Likes
Message 8 of 15

ronjonp
Advisor
Advisor

One downside of modifying the array is the changes are lost on modification:

2021-09-28_15-45-28.gif

Message 9 of 15

aliff_ahtenk
Enthusiast
Enthusiast
Hai, i try your solution, it is interesting on how it work. if i adjust the spline it wil return back to its origin. so i just have to re apply the routine. thanks for that.. this are so helpfull..
0 Likes
Message 10 of 15

aliff_ahtenk
Enthusiast
Enthusiast
Hai, i already try the routine, it also easy to use.. thanks for your help. now it is easy to working it on..
0 Likes
Message 11 of 15

pbejse
Mentor
Mentor

@ronjonp wrote:

One downside of modifying the array is the changes are lost on modification:



@aliff_ahtenk wrote:
Hai, i try your solution, it is interesting on how it work. if i adjust the spline it wil return back to its origin. so i just have to re apply the routine. thanks for that.. this are so helpfull..

 

That is true @ronjonp 

 

Glad it works for you @aliff_ahtenk 

 

As a workaround we can use implied selection, right after the user adjust the array, type the command again and it should remember the previous scale factor value. or grip select if there are more than one to process.

Not the best solution but it helps

 

(defun c:2nd (/ aDoc Blocks ss l e i) 
  (setq	aDoc   (vla-get-ActiveDocument (vlax-get-acad-object))
	Blocks (vla-get-blocks aDoc)
  )
(if
  (or
   (and (setq ss (ssget "I" '((0 . "INSERT"))))
	sfDemo
	)
   (and
	(setq ss (ssget '((0 . "INSERT"))))
	(setq sfDemo (getreal "\nEnter scale factor: "))
      )
   )
    (repeat (setq i (sslength ss))
      (setq l 0
	    e (vlax-ename->vla-object (ssname ss (Setq i (1- i))))
      )
      (vlax-for	obj (vla-item Blocks (vla-get-EffectiveName e))
	(if (zerop (setq l (boole 6 1 l)))
	  (mapcar '(lambda (s)
		     (vlax-put obj s sfDemo)
		   )
		  '("XScaleFactor" "YScaleFactor" "ZScaleFactor")
	  )
	)
      )
    )
  )
  (vla-regen aDoc acactiveviewport)
  (princ)
)

 

HTH

 

0 Likes
Message 12 of 15

aliff_ahtenk
Enthusiast
Enthusiast
hmm, i not sure why it this routine cannot run, but you previous routine run correctly and already helps alot.. is it posibble if i want to fix the size of enlargement? example 100 dia for small, and 160 for large... but if 400 dia for small and large would become 460, meaning the L=S+60. L=large object, s=small object.
0 Likes
Message 13 of 15

pbejse
Mentor
Mentor

@aliff_ahtenk wrote:
hmm, i not sure why it this routine cannot run, but you previous routine run correctly and already helps alot..

 Hmmmnnn...Hmmmnnn... Thats odd. Any error message?

 

 is it posibble if i want to fix the size of enlargement? example 100 dia for small, and 160 for large... but if 400 dia for small and large would become 460, meaning the L=S+60. L=large object, s=small object.

+ 60? that means you need to know the size of the smaller circle to start with, so the prompt would be "Enter smaller circle diameter? What about it terms of percentage? would that work better for you?

 

0 Likes
Message 14 of 15

aliff_ahtenk
Enthusiast
Enthusiast
Error massage dont have.. but it okay, i just reused the first command. it shoud be done..

Hmm, yup, i only require to prompt small size and the large size diameter will be add 60 from it. if it use offset, then it offset +30. for now i will use manual calculation, then i just enter the value of scale factor..
0 Likes
Message 15 of 15

Kent1Cooper
Consultant
Consultant
Accepted solution

@aliff_ahtenk wrote:
.... is it posibble if i want to fix the size of enlargement? example 100 dia for small, and 160 for large... but if 400 dia for small and large would become 460, meaning the L=S+60. L=large object, s=small object.

In the code in Message 7, you can change one line.  Change this:

r2 (getdist "\nRadius of even-position Circles: ")

to this:

r2 (+ r1 30)
Kent Cooper, AIA
0 Likes