Jump to content

Move objects radially from(to) center


p0peye

Recommended Posts

Hi all

I have many assemblies modeled, with the drawings done.

Now, I got a revision which requires me to change the tube diameter, but I have to "move radially" the reinforcement plates as well.

Please see the picture:

Radial Stretch.png

I have to change a tube dimension from red to green, and I have to "move radially" the yellow plates to touch the green tube.

I thought it is a common problem, so AutoCad will have a command. Didn't find it.

Ok, there must be a lisp out there. Couldn't find it either.

Did I overlook some corner? :)

Is it not too complicate for someone to make one? It certainly is for me.

 

Thanks in advance,

NN

Link to comment
Share on other sites

To be honest it's probably a case of "too simple to bother."

 

Set your UCS to one of the support plates, and move that the new position (TBH I might even be too lazy to bother with that and use a "forced" intersection snap-point: hover over your targhet radius, and click when you get an X... osnap symbol pop up before repeating for a point along the line of the plate). If I was taking a pure path of least resistance I'd then erase the other three plates and mirror the remaining one to recreate the four.

 

I might consider a polar array which leads me on to...

 

Your absolutely best "doing it properly" way would be to use one of the new "smart"/"associative" arrays, since you're using ACAD 2014. At the very least this would allow you to move one of the plates and have the other three (or more if some of your scenarios need that) adjust themselves to suit. But investigation might show you that selecting your tube as a "path" for your arrayed plates would allow you to change the radius of that and have the four plates update themselves - which is propably the LISP you were hoping for!

 

DJE

Link to comment
Share on other sites

Here is a quick slap together.

 

(defun c:moverad ()
 (setq cobj1 (vlax-ename->vla-object (car (entsel "\nSelect First Circle:"))))
 (setq cobj2 (vlax-ename->vla-object (car (entsel "\nSelect Second Circle:"))))
 (setq rad1 (vlax-get-property cobj1 'Radius))
 (setq rad2 (vlax-get-property cobj2 'Radius))
 (setq ctr1 (vlax-safearray->list (vlax-variant-value (vlax-get-property cobj1 'Center))))
 (setq ctr2 (vlax-safearray->list (vlax-variant-value (vlax-get-property cobj2 'Center))))
 (setq drad (- rad1 rad2))
 (while (setq ss (ssget))
   (setq bp (getpoint ctr1 "\nSelect Base Point:"))
   (if (> drad 0)
     (setq ang (angle bp ctr1))
     (setq ang (angle ctr1 bp))
     )
   (setq np (polar bp ang [color="red"](abs[/color] drad[color="red"])[/color]))
   (command "MOVE" ss "" bp np)
   )
 (princ)
 )

Edited by Hippe013
Added ABS as shown in red.
Link to comment
Share on other sites

To be honest it's probably a case of "too simple to bother."

 

Set your UCS to one of the support plates, and move that the new position (TBH I might even be too lazy to bother with that and use a "forced" intersection snap-point: hover over your targhet radius, and click when you get an X... osnap symbol pop up before repeating for a point along the line of the plate). If I was taking a pure path of least resistance I'd then erase the other three plates and mirror the remaining one to recreate the four.

 

I might consider a polar array which leads me on to...

 

Thank you for your reply.

The problem a bit more complicated:

- I have to modify 100+ assemblies.

- I work in Advance steel, the model is connected with drawing representation, and if I delete the objects in model and replace them with others, the dimensions on drawings and some more stuff will go loonies (I hope I got the right word - go crazy) so I have to move the existing objects.

 

Your absolutely best "doing it properly" way would be to use one of the new "smart"/"associative" arrays, since you're using ACAD 2014. At the very least this would allow you to move one of the plates and have the other three (or more if some of your scenarios need that) adjust themselves to suit. But investigation might show you that selecting your tube as a "path" for your arrayed plates would allow you to change the radius of that and have the four plates update themselves - which is propably the LISP you were hoping for!

 

DJE

 

The Associatve Arrays are great, but the objects are unfortunately created with mirror option, as the base plate is not quadrate, the angles between sup. plates are not 90 deg.

And, the last but not the least - the objects are already made. I would try to avoid the deleting of existing and making a new ones... Advance Steel drawings stuff...

Thanks anyway for your time.

 

A dynamic block would do the trick, attached is just a simple version to show how.

I guess I had to mention that I am working in Advance Steel, and that I would like to delete the already created 3d advance objects.

The ida with the dynamic block looks interesting though, and I'll experiment a bit as soon as I get the time if I can make them with advance objects.

Thank you.

 

 

@Hippe013:

 

Thank you for your code, I really appreciate it, but something went wrong whyle trying to use it:

Radial stretch example wr1.jpg

Thank again for your time,

cheers

NN

Link to comment
Share on other sites

Each "fin" would need to be selected separately. When it asks for a base point, that is the angle to which the selection would be moved.

Select outer circle:

Select Inner Circle:

Select objects in the upper right:

Select base point: (moved along line base, from base point towards center at a distance of the differences of the radii)

Select objects in the lower right:

Select Base Point:

Select objects in the lower left:

Select Base Point:

Select objects in the upper left:

Select Base Point:

Done.

Link to comment
Share on other sites

Maybe this simple code, but be careful with selecting and feeding reference points...

 

(defun c:radialmove ( / *error* pick k ent p entplst c orth pp d )

 (defun *error* ( msg )
   (if pick (setvar 'pickbox pick))
   (if orth (setvar 'orthomode orth))
   (if msg (prompt msg))
   (princ)
 )

 (command "_.ucs" "_W")
 (setq pick (getvar 'pickbox))
 (setvar 'pickbox 5)
 (setq k 0)
 (while
   (setq ent (car (entsel (strcat "\nPick entity (" (itoa (setq k (1+ k))) ") on which to perform radial move (ENTER OR RIGHT CLICK OR MISSED SELECTION WITH LEFT CLICK - FINISH)"))))
   (setq p (getpoint (strcat "\nPick or specify reference point of entity (" (itoa k) ") from which to perform radial move : ")))
   (setq entplst (cons (cons p ent) entplst))
   (if ent t nil)
 )
 (setq c (getpoint "\nPick or specify center point for radial move : "))
 (setq orth (getvar 'orthomode))
 (setvar 'orthomode 1)
 (command "_.ucs" "_3P" c (car (last entplst)) "")
 (command "_.move" (cdr (last entplst)) "" (trans (car (last entplst)) 0 1) "\\")
 (setq pp (trans (getvar 'lastpoint) 1 0))
 (command "_.ucs" "_P")
 (setq d (- (distance c (car (last entplst))) (distance c pp)))
 (setq entplst (cdr (reverse entplst)))
 (foreach entp entplst
   (command "_.move" (cdr entp) "" (car entp) (polar c (angle c (car entp)) (- (distance c (car entp)) d)))
 )
 (command "_.ucs" "_P")
 (*error* nil)
 (princ)
)

 

Another code - you can now be sure that you won't miss selection... It works with sel. sets with entities, but you can select each entity separately without being afraid that you'll miss selecting...

 

(defun c:radialmove ( / *error* k loop entss ent p i entplst c orth pp d )

 (defun *error* ( msg )
   (if orth (setvar 'orthomode orth))
   (if msg (prompt msg))
   (princ)
 )

 (command "_.ucs" "_W")
 (setq k 0)
 (setq loop t)
 (while loop
   (prompt (strcat "\nPick entity sel.set (" (itoa (setq k (1+ k))) ") on which to perform radial move (ENTER OR RIGHT CLICK - FINISH)"))
   (setq entss (ssget "_:L"))
   (if entss
     (progn
       (setq p (getpoint (strcat "\nPick or specify reference point of entity sel.set (" (itoa k) ") from which to perform radial move : ")))
       (setq i (sslength entss))
       (while (setq ent (ssname entss (setq i (1- i)))) 
         (setq entplst (cons (cons p ent) entplst))
       )
     )
     (setq loop nil)
   )
 )
 (setq c (getpoint "\nPick or specify center point for radial move : "))
 (setq orth (getvar 'orthomode))
 (setvar 'orthomode 1)
 (command "_.ucs" "_3P" c (car (last entplst)) "")
 (command "_.move" (cdr (last entplst)) "" (trans (car (last entplst)) 0 1) "\\")
 (setq pp (trans (getvar 'lastpoint) 1 0))
 (command "_.ucs" "_P")
 (setq d (- (distance c (car (last entplst))) (distance c pp)))
 (setq entplst (cdr (reverse entplst)))
 (foreach entp entplst
   (command "_.move" (cdr entp) "" (car entp) (polar c (angle c (car entp)) (- (distance c (car entp)) d)))
 )
 (command "_.ucs" "_P")
 (*error* nil)
 (princ)
)

M.R.

Edited by marko_ribar
added another code for manipulating with sel. sets
Link to comment
Share on other sites

@Hippe13:

Thanks, I selected all at once, that was the problem.

Thanks Marko, it is working also.

 

One question though for both of you:

 

Why is it necessary to select the base/reference points for every rib? - both of you have had the same approach, so I suppose it had to be that way.

All the ribs are at the same distance from the center, so why it wasn't possible to select all the ribs, select the center, the outer circle, and then the inner circle?

 

Anyway thank you both for your time and help :)

 

Cheers,

NN

 

Hvala Marko :)

Link to comment
Share on other sites

All of the "ribs" move towards the center at the same distance but at different angles towards the center. For each "rib" you need to define the angle at which to move the object towards the center.

Link to comment
Share on other sites

p0peye,

 

Do your ribs touch red circle in single reference/base points? If that's the case, you can get those points with 'Intersectwith method, and if you have only this situations with different circles and ribs touching, then it's surely possible just to select red circle and then green one and routine could finish the job... But in general case, you don't have those circles and ribs/entities could be scattered all around center point and with different distances from it, so general case routine has to look like we posted... So that's the answer, yes it has to be that way... For more info how to code your specific situations with circles, search www with : Intersestwith method... If I find some spare time, maybe I'll write it... For now you'll have to be satisfied with general approach...

 

M.R.

Hvala Marko :)

Nema na cemu, za drugi metod bitno je da rebra dodiruju krug u tacno po jednoj tacki, ako 'Intersectwith nadje 2 tacke po rebru, rezultat bi bio nejasan (CAD bi uzeo u obzir to sto mu se kaze - prva, druga, treca, ... tacka kao bazna tacka) i pomeranje bi bilo neprecizno u tom slucaju... Ako nesto nije jasno, slobodno pitaj... Bas me intersuje da li ces se snaci, "strpljenje i vreme i dudov list u svilu pretvara..."

Link to comment
Share on other sites

The dynamic block is great, but I am not sure how optimal is it to do it now with 100+ assemblies, as I mentioned that I unfortunately can't do it on one and copy/replace the others...

 

@Marko: I just saw the second code. I'll give it a try :)

Link to comment
Share on other sites

Look, p0peye... Like I told you, I thought you'll solve the problem for your specific case... I wrote all this variants : radialmove.lsp, radialcopy.lsp, radialarray.lsp and new variants of all of them like this one just for your case...

 

(defun c:radialmove ( / c ci laycoll laylst layfilt ssx i ent p entplst r )

 (vl-load-com)

 (setq c (getpoint "\nPick or specify center point for radial move : "))
 (command "_.circle" c "\\")
 (setq ci (entlast))
 (setq laycoll (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))))
 (vlax-for lay laycoll
   (if (eq (vla-get-lock lay) :vlax-false)
     (setq laylst (cons (vla-get-name lay) laylst))
   )
 )
 (setq layfilt "")
 (foreach lay laylst
   (setq layfilt (strcat "," lay layfilt))
 )
 (setq layfilt (vl-string-left-trim "," layfilt))
 (setq ssx (ssget "_X" (list (cons 8 layfilt))))
 (setq i -1)
 (while (setq ent (ssname ssx (setq i (1+ i))))
   (setq p (vlax-invoke (vlax-ename->vla-object ci) 'intersectwith (vlax-ename->vla-object ent) acextendnone))
   (if p 
     (progn
       (setq p (list (car p) (cadr p) (caddr p)))
       (setq entplst (cons (cons p ent) entplst))
     )
   )
 )
 (entdel ci)
 (command "_.circle" c "\\")
 (setq ci (entlast))
 (setq r (cdr (assoc 40 (entget ci))))
 (foreach entp entplst
   (command "_.move" (cdr entp) "" (car entp) (polar c (angle c (car entp)) r))
 )
 (entdel ci)
 (princ)
)

You can download them in attachment of this post... Hope you'll find them useful...

 

M.R.

radial move & radial copy & radial array.zip

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...