Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Copy entities at predefined distances

16 REPLIES 16
SOLVED
Reply
Message 1 of 17
kameron1967
526 Views, 16 Replies

Copy entities at predefined distances

Hi guys,

 

Can you help me with a routine that does the followings:

1) Prompts me to choose the entity or entities to copy

2) Once selected, it will copy the entities 500', 1000', 1500', 2000', 2500', 3000' at 90 degree angle or at the direction of the Y coordinate.

 

Also, this could be in the same routine, but it functions slightly differently.  I'd like to be able to make a copy of whichever entities and once selected, have it create 4 copies at 100', 200', 300' and 300' to the right of the item (generally only one block or reference).  I also need the copies rotated at predefined degrees: 2nd copy to be rotated at 180 degree, 3rd copy to be rotated 90 degrees and 4th copy to be rotated -90 degrees.

 

Thanks in advance.

16 REPLIES 16
Message 2 of 17
Kent1Cooper
in reply to: kameron1967


@kameron1967 wrote:

.... 

Can you help me with a routine that does the followings:

1) Prompts me to choose the entity or entities to copy

2) Once selected, it will copy the entities 500', 1000', 1500', 2000', 2500', 3000' at 90 degree angle or at the direction of the Y coordinate.

....


That sounds exactly like what a rectangular Array with 1 column, 7 rows, and a row spacing of 500' would do.  Is what you want to do somehow different from an Array?

Kent Cooper, AIA
Message 3 of 17
kameron1967
in reply to: Kent1Cooper

Yes, something like that.  Except the 2nd routine is slightly different - with the rotation specified, Kent.  Thanks.

Message 4 of 17
kameron1967
in reply to: Kent1Cooper

I wanted to just type in YY and have whatever entities that I picked to be copied at the specified distances. Same as the XX, but the copies are then rotated. These will generally be either a block or an xref.

 

Update:  I don't mind using the array command.  But if you or anyone can help with the 2nd routine, that woud be great.  Thanks! 🙂

Message 5 of 17
Kent1Cooper
in reply to: kameron1967


@kameron1967 wrote:

.... 

Also, this could be in the same routine, but it functions slightly differently.  I'd like to be able to make a copy of whichever entities and once selected, have it create 4 copies at 100', 200', 300' and 300' to the right of the item (generally only one block or reference).  I also need the copies rotated at predefined degrees: 2nd copy to be rotated at 180 degree, 3rd copy to be rotated 90 degrees and 4th copy to be rotated -90 degrees.

....


[I think my first Reply was before your Edit was posted with the second routine.]  I would assume the last distance should be 400'.  If it's only one Block or Xref, can the Rotation base points be their insertion points, assuming those are at or close to the middle of each one?  If it's sometimes more than one thing [or one thing that has no insertion point], what should be the base point for Rotation of each copy?  The middle of the collective bounding box?  The insertion point of some Block or Xref that's part of the selection if there is one?  What if there's more than one thing in the selection with an insertion point?  Etc.

Kent Cooper, AIA
Message 6 of 17
Kent1Cooper
in reply to: kameron1967


@kameron1967 wrote:

I wanted to just type in YY and have whatever entities that I picked to be copied at the specified distances. .... 

Update:  I don't mind using the array command.  ....


If you do the same thing repeatedly with the same relationship, a routine can certainly be built that would handle the Arraying part for you with only object selection on the part of the User.  I may give it a try in combination with the "XX" idea after getting answers to the questions about that.

Kent Cooper, AIA
Message 7 of 17
kameron1967
in reply to: Kent1Cooper

Yes, Kent. Last distance is 400’. I use it for UP/DOWN/LEFT/RIGHT configuration of a block/xref. Yes, it certainly can have its insertion point as the rotation point and there is only one block that I’m dealing with at one time. If it’s not too complex, you can certainly use the middle of the collective bounding box for something that is not a block or xref entity. If there are more than one insertion points, you can definitely just go with the middle of the bounding box. I can make use of that, if you are up to it. Otherwise, working with one block/xref’s insertion point would be sufficient for me, Kent. Thanks again! 🙂
Message 8 of 17
stevor
in reply to: kameron1967

Here is a start, for 2nd case, changed the last 300 to a 400, to make more sense to me. ; no offset (Defun BBox_2p ( en ) (vla-getboundingbox (vlax-ename->vla-object en) 'minpt 'maxpt) (list (vlax-safearray->list minpt) (vlax-safearray->list maxpt) ) ) (DeFun mid_p (a b / c d) (setq @u"mid=p") (mapcar '(Lambda (c d) (* 0.5 (+ c d))) a b) ) (defun dxf_ (n L) (cdr (assoc n L)) ) ; Copy and rotate, boundingbox mid (Defun C:CR4 () (if (and (setq es (entsel "\n Sel Ent: ")) (setq en (car es) sp (cadr es)) (or (= "INSERT" (dxf_ 0 (entget en))) (and (princ"\n NOT Insert, is: ") (princ (dxf_ 0 (entget en))) nil)) ) (progn (setq odl2 (list 100 200 300 400 )) ; last? 300 or 400 (setq ral2 (list 0 180 90 -90 )) ; degrees, not radians (setq bbl (BBox_2p en) mp (mid_P (car bbl) (cadr bbl))) (mapcar '(lambda (od ra ) (command "copy" en "" mp (polar mp 0 od) ) (command "rotate" (entlast) "" (polar mp 0 od) ra) ) odl2 ral2 ) ) ) (princ " done" ) (princ) )
S
Message 9 of 17
stevor
in reply to: stevor

Another try of rich text, to maintain some formatting.

And an attachment, attempt.


 ; no offset
 (Defun BBox_2p ( en )
  (vla-getboundingbox (vlax-ename->vla-object en) 'minpt 'maxpt)
  (list (vlax-safearray->list minpt)
        (vlax-safearray->list maxpt) )  )
 
 (DeFun mid_p (a b / c d) (setq @u"mid=p") (mapcar '(Lambda (c d)
    (* 0.5 (+ c d))) a b) )
    
 (defun dxf_ (n L) (cdr (assoc n L)) )
 
 ; Copy and rotate, boundingbox mid
 (Defun C:CR4 ()  
  (if (and (setq es (entsel "\n Sel Ent: "))
           (setq en (car es)  sp (cadr es))
           (or (= "INSERT" (dxf_ 0 (entget en)))
               (and (princ"\n NOT Insert, is: ")
                    (princ (dxf_ 0 (entget en))) nil)) )
     (progn
      (setq odl2 (list 100 200 300 400 )) ; last? 300 or400
      (setq ral2 (list 0 180 90 -90 )) ;   
      (setq bbl (BBox_2p en)  mp (mid_P (car bbl) (cadr bbl)))
      (mapcar '(lambda (od ra )  
                 (command "copy" en "" mp (polar mp 0 od) )
                 (command "rotate" (entlast) "" (polar mp 0 od) ra)
               )
               odl2 ral2 )
     )
    )  
    (princ " done" ) (princ) )
 

S
Message 10 of 17
kameron1967
in reply to: stevor

Stevor - thanks for coming to the rescue. The routine worked as it should (for the 2nd part). I wonder if you could help me with the first part, which is to simply copy an entity and move it in the Y direction (or 90 degrees). I need about 5 copies, if possible. Thank you, sir.
Message 11 of 17
stevor
in reply to: kameron1967

You might as well learn the codework,

it is too easy to not.

For part 1,  a couple changes:

  ; Copy  in Y by  6 element distance list
 (Defun C:C6Y (/ es en sp )   (setvar 'osmode 0) ; Object Snap off
  (if (and (setq es (entsel  "\n Sel Ent at Start PT: "))
           (setq en (car es)  sp (cadr es))
           (or (= "INSERT" (dxf_ 0 (entget en)))
               (and (princ"\n NOT Insert, is: ")
                    (princ (dxf_ 0 (entget en))) nil)) )
     (progn
      ; (setq ben (Blk_Name en)) (PP_"ben")
      (setq odl1 (list 500 1000 1500 2000 2500 3000)) ; 6 elem
      ;(setq odl2 (list 100 200 300 400 )) ; last? 300 or400
      ;(setq ral2 (list 0 180 90 -90 )) ;   
      ;(setq bbl (BBox_2p en)  mp (mid_P (car bbl) (cadr bbl)))
      (mapcar '(lambda ( od )  
          (command "copy" en "" sp (polar sp (/ pi 2)  od ) )
                )    odl1 )
     )
    )  
    (princ " done-6 " ) (princ) )

S
Message 12 of 17
kameron1967
in reply to: stevor

Thanks, Stevor.  I wish I understand the code as well as you guys do.  I looked at the two (similar) codes and noticed some differences. But I'm not able to decipher where you specified the 90 degree angle. Much appreciated it, though.   It worked like a charm! Smiley Happy

 

Message 13 of 17
stevor
in reply to: kameron1967

As I understand it,

the Command interperter uses degrees,

while the Autolisp interperter uses radians.

 

(/ pi 2) is evaluated as half of the Pi value;

which is half of 180 degrees.

The 'pi  is a constant for 3.14....

unless otherwise defined by users,

which is unwise.

S
Message 14 of 17
Kent1Cooper
in reply to: kameron1967

Here's one that does both the vertical and horizontal/rotated copies, and works with single or multiple selected objects.  It also does some of the things differently, not that they're better ways, but just the way it would occur to me to do them.  It could use the addition of error handling, etc.

 

(defun C:CRR (/ ss edata base ent ell eur LL UR); = Column of copies and Row of Rotated copies
  (setq cmde (getvar 'cmdecho) osm (getvar 'osmode))
  (setvar 'cmdecho 0)
  (setvar 'osmode 0)
  (if (setq ss (ssget "_:L")); selection [filter out objects on locked Layers]
    (progn ; 'then
      (if
        (and
          (= (sslength ss) 1); only one object
          (wcmatch (cdr (assoc 0 (setq edata (entget (ssname ss 0))))) "INSERT,*TEXT,CIRCLE,ELLIPSE")
            ; something with insertion point or other easier-to-extract center
            ; [remove ELLIPSE if reference for partial Ellipses should be from
            ; bounding box, not center; add ARC if it should be geometric center, not from bb]
        ); amd
        (setq base (cdr (assoc 10 edata))); 'then' -- use object's reference point
        (progn; 'else' -- build collective bounding box
          (repeat (setq n (sslength ss))
            (setq ent (ssname ss (setq n (1- n))))
            (vla-getboundingbox (vlax-ename->vla-object ent) 'mi 'ma)
            (setq
              ell (vlax-safearray->list mi); = Entity's Lower Left
              eur (vlax-safearray->list ma); = Entity's Upper Right
              LL (if LL (mapcar 'min LL ell) ell)
              UR (if UR (mapcar 'max UR eur) eur)
            ); setq
          ); repeat
          (setq base (mapcar '/ (mapcar '+ LL UR) '(2 2 2))); midpoint of bb
        ); progn
      ); if [one object or multiple]
      (command "_.array" ss "" "_rectangular" 7 1 "500'"); column of copies
      (foreach rot '(0 180 270 180); angles are relative to previous copy, not to original
        (command
          "_.copy" "_previous" "" "0,0" "0,0" ; copy in place, then:
          "_.move" "_previous" "" "100',0" "" ; move P so it will still be P for next one
          "_.rotate" "_previous" "" (setq base (polar base 0 1200)) rot
        ); command
      ); foreach
    ); progn
  ); if [selection]
  (setvar 'cmdecho cmde)
  (setvar 'osmode osm)
); defun

Kent Cooper, AIA
Message 15 of 17
kameron1967
in reply to: Kent1Cooper

Kent - I finally had a chance to test your routine.  For some reason, I'm getting this prompt.  Can you please check into it?  Thanks.

 

Command: CRR

Select objects: 1 found

Select objects:
Requires number or two 2D corner points.
; error: Function cancelled

Enter the distance between rows or specify unit cell (---):

Message 16 of 17
Kent1Cooper
in reply to: kameron1967


@kameron1967 wrote:

... I'm getting this prompt.  Can you please check into it?  Thanks.

 

Command: CRR

....

Requires number or two 2D corner points.
; error: Function cancelled

Enter the distance between rows or specify unit cell (---):


That's obviously within the Array command.  It may be a version difference in the prompt sequence.  [I'm not sure, but I probably worked that out at my Acad2004 location, where I also am now, so I can't try it in Acad2015 until later.]  You could try doing an Array command manually, and check for the exact sequence of prompts and answers, and coordinate what's in the (command "_.array" ... ) line with what it takes in your version.

Kent Cooper, AIA
Message 17 of 17
kameron1967
in reply to: Kent1Cooper

I was able to get it to work by converting 500' into 6000.  Same with 100' into 1200.  Thank you for your time, Kent! Cheers!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost