Aligning copies

Aligning copies

Anonymous
Not applicable
1,243 Views
8 Replies
Message 1 of 9

Aligning copies

Anonymous
Not applicable

Hello, 

I made a quick command that asks you how many copies are you intending on creating of a group, asks the width of the group and let's you select it.

 

(defun c:CR (/ n blk a)
(setq n (getint "\nHow many groups to add?"))
(setq b (getreal "\nWhat is the group width?"))
	(setq blk (entsel "\nSelect the group to copy: ")) 
	(repeat n
		(command "copy" blk "" "" "")
		(command "move" blk "" "" b)
	)
	
	(print "Copies created.")
	(princ)
	)

The code is a loop that copies the group in the exact place that it is and then moves it. 

I have two problems: 

1- I need it to move in a 0 degrees line.

2- Instead of asking the user the width, can i extract it from the block that is inside the group? (there's an attribute with that information. )

I hope the image can help to understand the problem

rvsi.png

 

0 Likes
Accepted solutions (2)
1,244 Views
8 Replies
Replies (8)
Message 2 of 9

dbhunia
Advisor
Advisor
Accepted solution

something like .......

 

(defun c:CR ( / n b b1 blk)
(setq n (getint "\nHow many groups to add?"))
(setq b (getreal "\nWhat is the group width?"))
(setq blk (entsel "\nSelect the group to copy: ")) 
(setq b1 b)
	(repeat n
		(command "copy" blk  "" "_none" '(0 0 0) "@")
		(command "move" (entlast) "" "_none" '(0 0 0) "_none" (polar '(0 0 0) 0.0 b1))
		(setq b1 (+ b b1))
	)
	(print "Copies created.")
	(princ)
)

Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 3 of 9

Kent1Cooper
Consultant
Consultant

ARRAY will do that with no code.

 

But if you want the width extracted for you from what's selected, which ARRAY won't do, is it [are they?] really a GROUP, or is it a BLOCK?  [I haven't opened the drawing...]  Since you use (entsel), and from other things about the code, I assume a Block, which is easy enough to get the width of [if it's at an orthogonal rotation angle*], but if it's a Group, there is a way to get the overall width [and height] of more than one object.  >Here< is one that draws a box  around them, but you can use just the get-the-extents parts, and use only the X-direction size.

 

[* If a Block is at a non-orthogonal rotation angle, its bounding box will be larger than its visible extents -- write back if you want an explanation.]

Kent Cooper, AIA
0 Likes
Message 4 of 9

Kent1Cooper
Consultant
Consultant

If not for the Block with lots of Attributes, which expands the bounding box of the group beyond its visible width, this works [try removing that Block from the Group and running it]:

(defun C:WHATEVER (/ ss n eLL eUR LL UR)
  (prompt "\nSelect Group to Array rightward: ")
  (if (setq ss (ssget ":S"))
    (progn ; then
      (repeat (setq n (sslength ss))
        (vla-getboundingbox (vlax-ename->vla-object (ssname ss (setq n (1- n)))) 'minpt 'maxpt)
        (setq
          eLL (vlax-safearray->list minpt)
          eUR (vlax-safearray->list maxpt)
          LL (if LL (mapcar 'min eLL LL) eLL)
          UR (if UR (mapcar 'max eUR UR) eUR)
        ); setq
      ); repeat
      (command "_.array" ss "" "_rectangular" 1 pause (- (car UR) (car LL)))
    ); progn
    (prompt "\nNothing selected."); else
  ); if
  (princ)
); defun

It figures the overall collective bounding box with the (repeat) function.  The Array command provides its own prompt for the number of copies.

 

The problem is with all those invisible Attributes that expand the extents far beyond the visible extents of the pieces in the Group.  If the configuration of such things is always similar, it could be made to ignore any Blocks in finding the collective extents, or even to use only the bounding box of any closed Polyline it finds, or some other limitation that will provide consistent results relative to the expected actual objects involved.

Kent Cooper, AIA
0 Likes
Message 5 of 9

Anonymous
Not applicable

Thanks for the replies, I simplified it a little like this and works wonders, although without tackling the second problem:

(defun c:CR ( / n b b1 blk)
(setq n (getint "\nHow many groups to add?"))
(setq b (getreal "\nWhat is the group width?"))
(setq blk (entsel "\nSelect the group to copy: ")) 
(setq b1 b)
	(repeat n
		(command "copy" blk "" "" "")
		(command "move" blk "" "" (polar '(0 0) 0.0 b))
	)
	(print "Copies created.")
	(princ)
)

But now i was trying it to move 90 degrees and can't do it for the life of me. Do you have any tips (imagine if the original rectangle was in a vertical position instead an horizontal one)?

0 Likes
Message 6 of 9

dbhunia
Advisor
Advisor

@Anonymous wrote:

............

But now i was trying it to move 90 degrees and can't do it for the life of me. Do you have any tips (imagine if the original rectangle was in a vertical position instead an horizontal one)?


Try this... (for any angle)

 

(defun c:CR ( / n b a blk osm)
	(setq n (getint "\nHow many groups to add: "))
	(setq b (getreal "\nWhat is the group width: "))
	(setq a (getangle "\nWhat is the Angle: "))
	(setq blk (entsel "\nSelect the group to copy: ")) 
	(setq osm (getvar 'OSMODE))
	(if (and n b a blk)
		(progn
			(setvar 'CMDECHO 0)(command "_.undo" "_begin")(setvar 'OSMODE 0)
			(repeat n
				(command "_.copy" blk "" "" "")
				(command "_.move" blk "" "" (polar '(0 0) a b))
			)
			(setvar 'OSMODE osm)(command "_.undo" "_end")(setvar 'CMDECHO 1)
			(princ "\nCopies created...")
		)
	)
	(princ)
)

 

or.......

 

(defun c:CR ( / n b a b1 blk osm)
	(setq n (getint "\nHow many groups to add: "))
	(setq b (getreal "\nWhat is the group width: "))
	(setq a (getangle "\nWhat is the Angle: "))
	(setq blk (entsel "\nSelect the group to copy: ")) 
	(setq osm (getvar 'OSMODE))
	(if (and n b a blk)
		(progn
			(setvar 'CMDECHO 0)(command "_.undo" "_begin")(setvar 'OSMODE 0)
			(setq b1 b)
			(repeat n
				(command "copy" blk "" "" (polar '(0 0) a b1))
				(setq b1 (+ b b1))
			)
			(setvar 'OSMODE osm)(command "_.undo" "_end")(setvar 'CMDECHO 1)
			(princ "\nCopies created...")
		)
	)
	(princ)
)

Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 7 of 9

Kent1Cooper
Consultant
Consultant
Accepted solution

@Anonymous wrote:

....

....
		(command "move" blk "" "" (polar '(0 0) 0.0 b))
....

But now i was trying it to move 90 degrees ....


 

If you want a dedicated command to do it upward instead of to the right, rather than being asked for the angle within a shared command, you can just change that command definition to ask for height instead of width, and replace the line above with:

....

  (command "move" blk "" "" (polar '(0 0) (/ pi 2) b))

....

 

You could make separate commands for any direction you want.

 

But I still vote for using the ordinary ARRAY command.

Kent Cooper, AIA
0 Likes
Message 8 of 9

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

....

The problem is with all those invisible Attributes that expand the extents far beyond the visible extents of the pieces in the Group.  If the configuration of such things is always similar, it could be made to ... use only the bounding box of any closed Polyline it finds....


 

This does that, except that it uses the first  Polyline it finds [whether or not closed -- it could have that restriction added, and/or the number of sides, etc., if there could be more than one Polyline in a Group].  So it isn't bothered by the invisible Attributes, and does the spacing correctly.  But that means the kinds of things in the Group need to be always similar in nature to your example.  It could base it on the Hatch pattern instead, if that's more consistent, or something else.

 

And it asks you in which orthogonal direction you want more Groups added.  [It could be any angle, given some criteria about the resulting relationship.]  It's up to you to control where the Block's visible Attribute sits in relation to the rest -- for example, if you use the Up or Down choice here with your sample Group, the rectangles in the Groups will touch, and that Block will show [in all but one of them at an end] inside  the adjacent Group's rectangle.

 

Lightly tested:

(defun C:WHATEVER (/ ss n dir ent LL UR gotit)
  (prompt "\nSelect Group to Array: ")
  (if (setq ss (ssget ":S"))
    (progn ; then
      (initget 1 "Left Right Up Down")
      (setq
        n (sslength ss)
        dir (getkword "\nArrayed in what direction [Left/Right/Up/Down]: ")
      ); setq
      (while (not gotit)
        (setq ent (ssname ss (setq n (1- n))))
        (if (= (cdr (assoc 0 (entget ent))) "LWPOLYLINE")
          (progn
            (vla-getboundingbox (vlax-ename->vla-object ent) 'minpt 'maxpt)
            (setq
              LL (vlax-safearray->list minpt)
              UR (vlax-safearray->list maxpt)
              delta (mapcar '- UR LL) ; XY of difference across corners
              gotit T ; stop (while) loop
            ); setq
          ); progn
        ); if
      ); while
      (command "_.array" ss "" "_rectangular")
      (if (wcmatch dir "Left,Right")
        (command 1 (1+ (getint "\nAdd how many ? "))); then [1 row, ask for columns]
        (command (1+ (getint "\nAdd how many? ")) 1); else [ask for rows, 1 column]
      ); if
      (command
        (cond
          ((= dir "Left") (- (car delta)))
          ((= dir "Right") (car delta))
          ((= dir "Up") (cadr delta))
          ((= dir "Down") (- (cadr delta)))
        ); cond
      ); command
    ); progn
    (prompt "\nNothing selected."); else
  ); if
  (princ)
); defun
Kent Cooper, AIA
0 Likes
Message 9 of 9

Anonymous
Not applicable

Thanks, your angle solution did it for me, guess i need to study polars again 🙂
About your array answer, I will definitely check it out down the road, this is more a stop-gap solution.

0 Likes