Selection of a rectangle instead of asking for two corners

Selection of a rectangle instead of asking for two corners

Anonymous
Not applicable
4,857 Views
31 Replies
Message 1 of 32

Selection of a rectangle instead of asking for two corners

Anonymous
Not applicable

Dear all,

I got a lisp code that can generate required no of rows and columns inside a two corners of a rectangle. But I need a change in that it should ask for selection for rectangle irrespective of  the rectangle is in straight or in inclination position

(defun C:LRR (/ c1 c2 wid ht rows cols blk); = Lights in Rectangular [& orthogonal] Room

  (setq

    c1 (getpoint "\nCorner of room: ")

    c2 (getpoint "\nOpposite corner: ")

    wid (abs (- (car c1) (car c2)))

    ht (abs (- (cadr c1) (cadr c2)))

    rows (getint "\nNumber of rows (---): ")

    cols (getint "\nNumber of columns (|||): ")

    blk (cdr (assoc 2 (entget (car (entsel "\n Select Block")))))

  ); setq

  (command

    "_.minsert" blk

    (mapcar '+ ; insertion point

      (list (min (car c1) (car c2)) (min (cadr c1) (cadr c2))); lower left of room

 

      (list (/ wid cols 2) (/ ht rows 2)); fractions of width/height

    ); mapcar

    "" "" "" ; X, Y, rotation defaults -- edit if needed

    rows cols (/ ht rows) (/ wid cols); numbers and spacings

  ); command

  (princ)); defun

0 Likes
Replies (31)
Message 2 of 32

dbhunia
Advisor
Advisor
Accepted solution

Hi,

 

What I understand from your post ........

 

1  You want to select a rectangle use "(Setq selection (ssget '((0 . "LWPOLYLINE"))))" and then "(setq Data (ssname selection 0)) "

 

2  After that you need the corners, so use this to get those.....

 

(defun Rec_Cor_Extr (key cor / val cor_list)
(foreach val cor
(if (eq key (car val)) (setq cor_list (cons (cdr val) cor_list)))
)
(reverse cor_list)
)

 

And then use "(setq lst (Rec_Cor_Extr 10 (entget data)))" you will get corners.....

 

Now manipulate with your required corners......

 

 

 


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

Moshe-A
Mentor
Mentor
Accepted solution

hi,

 

this will select only 4 nodes closed lwpolylines  

(did not test it)

 

enjoy

moshe

 

 

(defun C:LRR (/ ss elist points^ c1 c2 c3 wid ht rows cols blk); = Lights in Rectangular [& orthogonal] Room

 (if (setq ss (ssget ":E:S" '((0 . "lwpolyline") (90 . 4) (70 . 1))))
  (progn
   (setq 
    elist (entget (ssname ss 0))
    points^ (vl-remove-if '(lambda (item) (not item)) (mapcar '(lambda (item) (if (= (car item) 10) (cdr item))) elist))  
    c1 (car points^)   ; first point
    c2 (cadr points^)  ; second
    c3 (caddr points^) ; third point
    wid (polar c1 (angle c1 c2) (distance c1 c2))
    ht (polar c2 (angle c2 c3) (distance c2 c3))

   ; c1 (getpoint "\nCorner of room: ")
   ; c2 (getpoint "\nOpposite corner: ")
   ; wid (abs (- (car c1) (car c2)))
   ; ht (abs (- (cadr c1) (cadr c2)))

    rows (getint "\nNumber of rows (---): ")
    cols (getint "\nNumber of columns (|||): ")
    blk (cdr (assoc 2 (entget (car (entsel "\n Select Block")))))
  ); setq

  (command

    "_.minsert" blk

    (mapcar '+ ; insertion point

      (list (min (car c1) (car c2)) (min (cadr c1) (cadr c2))); lower left of room

 

      (list (/ wid cols 2) (/ ht rows 2)); fractions of width/height

    ); mapcar

    "" "" "" ; X, Y, rotation defaults -- edit if needed

    rows cols (/ ht rows) (/ wid cols); numbers and spacings

   ); command
  ); progn
 ); if
  
 (princ)
); defun
Message 4 of 32

Anonymous
Not applicable

Could you please modify the code with your input, Sir.

0 Likes
Message 5 of 32

serag.hassouna
Advocate
Advocate

To make it more compact and correct you may do that.

  1. Selection:
    I've designed a function that selects only LWPolylines, and it handles any error situations, here it is
      ;|selpoly: this function ensures that you select a lightweight polyline, otherwise it will rewind itself till
    the user selects a lightweight polyline, it returns the polyline's entity name. |;
      (defun selpoly (msg / plobj flag)
        (setq flag T)
        (while flag
          (setq plobj (vl-catch-all-apply 'entsel (list msg)))
          (setq flag (vl-catch-all-error-p plobj))
    
          (if (and (not (eq flag T)) (not (eq plobj nil)))
    	(progn
    	  (setq plobj (car plobj)) ;"entsel" returns the entity name and the point at which the selection occured
    	  (setq flag (not (eq "LWPOLYLINE" (cdr (assoc 0 (entget plobj))))))
    	  (if flag
    	    (princ "\nObject isn't a polyline\n")
    	    (princ "\n")
    	    );end if (for that object isn't a polyline)
    	);end 2nd if [Then Part]
    	(progn
    	  (princ "\nInvalid Selection\n")
    	  (setq flag T)
    	  );End progn [Else part of the 1st if statement]
    	);end 1st if
          );end While
    
        (progn plobj);what the function returns
        );End selpoly
    then, you have to create another filter function to make sure that the selected shape is really a rectangle, this function would be like that [not tested yet]
    ;| selrec: a function that ensures that a rectangle is selected ,it rewinds itself until a 
    lwpolyline rectangle is selected. |; (defun selrec (msg / recobj flag coords len ver-p a1 a2 a3)
    (vl-load-com) (setq flag T) (while flag (setq recobj (vlax-ename->vla-object (selpoly msg))) (setq flag (not (equal (vlax-curve-getstartpoint recobj) (vlax-curve-getendpoint recobj) 1e-6)));ensure start point is the same as end point [flag will be temporarily set to FALSE] (setq coords (vlax-safearray->list (vlax-variant-value (vla-get-coordinates recobj)))) ;get coordinates ;|There are 2 conditions, the first is when coords list has 8 elements the second is when coords list has 10 elements, the second one is valid if the 1st point is typical with the last point, & the first one is valid when the 1st point is not the same as the last point. This is due to a bug in AutoCAD that doesn't coincide the start point with the last point if they are typical when the command "pl" is issued. (the case of 10 elements in coords list) This bug doesn't exist when the command "rec" is issued (the case of 8 elements in coords list)|; (if (not flag) (progn (setq len (length coords)) (cond ( (= len 8) (progn (setq ver-p (not (and (equal (nth 0 coords) (nth 6 coords) 1e-6) (equal (nth 1 coords) (nth 7 coords) 1e-6)))); 1st point /= last point (if ver-p (progn (setq a1 (angle (list (nth 0 coords) (nth 1 coords)) (list (nth 2 coords) (nth 3 coords)))) (setq a2 (angle (list (nth 2 coords) (nth 3 coords)) (list (nth 4 coords) (nth 5 coords)))) (setq a3 (angle (list (nth 4 coords) (nth 5 coords)) (list (nth 6 coords) (nth 7 coords)))) (setq flag (not (and (equal (abs (- a2 a1)) (/ pi 2) 1e-6) (equal (abs (- a3 a2)) (/ pi 2) 1e-6)))) );progn of if ver-p );if ver-p [passed the previous test], check angle condition );progn of the 1st condition );coords list has 8 elements ( (= len 10) (progn (setq ver-p (and (equal (nth 0 coords) (nth 6 coords) 1e-6) (equal (nth 1 coords) (nth 7 coords) 1e-6))); 1st point = last point (if ver-p (progn (setq a1 (angle (list (nth 0 coords) (nth 1 coords)) (list (nth 2 coords) (nth 3 coords)))) (setq a2 (angle (list (nth 2 coords) (nth 3 coords)) (list (nth 4 coords) (nth 5 coords)))) (setq a3 (angle (list (nth 4 coords) (nth 5 coords)) (list (nth 6 coords) (nth 7 coords)))) (setq flag (not (and (equal (abs (- a2 a1)) (/ pi 2) 1e-6) (equal (abs (- a3 a2)) (/ pi 2) 1e-6)))) );progn of if ver-p );if ver-p [passed the previous test], check angle condition );progn of the 2nd condition );coords list has 10 elements (t nil) );cond );progn [then part] (progn (princ "\nSelected shape is opened\n") (princ "\n") );progn [else part] );if [only if the shape is closed] );while );defun [selrec]
    Then, when you want to select a rectangle, you can simply use
    (selrec "Select rectangle")
Message 6 of 32

Anonymous
Not applicable

Could you please insert your code in to my lisp code and then please revert back.

 

Thanks,

T.Brahmanandam

0 Likes
Message 7 of 32

dbhunia
Advisor
Advisor
Accepted solution

@Anonymous wrote:

Could you please modify the code with your input, Sir.


 

Hi,

 

This code is for only Rectangular "STRAIGHT ROOM".......

 

 

(defun C:LRR (/ c1 c2 wid ht rows cols blk); = Lights in Rectangular [& orthogonal] Room
(setq OS_Ver (getvar "osmode"))
(command "osmode" 0)
(Rec_t null)
(setq rows (getint "\nNumber of rows (---): "))
(setq cols (getint "\nNumber of columns (|||): "))
(setq blk (cdr (assoc 2 (entget (car (entsel "\n Select Block"))))))
(setq c1 Left_BC)
(setq c2 Right_TC)
(setq wid (abs (- (car c1) (car c2)))
ht (abs (- (cadr c1) (cadr c2)))
); setq
(command
"_.minsert" blk
(mapcar '+ ; insertion point
(list (min (car c1) (car c2)) (min (cadr c1) (cadr c2))); lower left of room
(list (/ wid cols 2) (/ ht rows 2)); fractions of width/height
); mapcar
"" "" "" ; X, Y, rotation defaults -- edit if needed
rows cols (/ ht rows) (/ wid cols); numbers and spacings
); command
(command "osmode" OS_Ver)
(princ)
); defun
(defun Rec_Cor_Extr (key cor / val cor_list)
(foreach val cor
(if (eq key (car val)) (setq cor_list (cons (cdr val) cor_list)))
)
(reverse cor_list)
)
(defun Rec_t (null/)
(Setq selectionset (ssget))
(setq Data (ssname selectionset 0))
(setq lst (Rec_Cor_Extr 10 (entget data)))
(foreach val lst
(setq X_Cor (cons (car val) X_Cor))
(setq Y_Cor (cons (cadr val) Y_Cor))
(setq Left_BC (list (Apply 'min X_Cor) (Apply 'min Y_Cor)))
(setq Right_TC (list (Apply 'max X_Cor) (Apply 'max Y_Cor)))
)
(setq X_Cor nil)
(setq Y_Cor nil)
)

 

 

For Rectangular "INCLINED  ROOM" you have to workout through the "rotation angle"........


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

serag.hassouna
Advocate
Advocate
Accepted solution


@Anonymous
I've tested the function selrec & replaced the previous corner selection part with the coordinates taken from the rectangle.

Message 9 of 32

Anonymous
Not applicable

Thank you Sir, it's working fentastic,

Can I use it for multiple rectangles?.

 

Regards,

T.Brahmanandam.

0 Likes
Message 10 of 32

Kent1Cooper
Consultant
Consultant
Accepted solution

@Anonymous wrote:

.... But I need a change in that it should ask for selection for rectangle irrespective of  the rectangle is in straight or in inclination position....


 

For the select-a-rectangle part, that's covered in >Message 28 of the same thread< that code [of mine] came from, but it still works only for an orthogonally-oriented rectangle.

 

For a similar one that handles non-orthogonal rectangles, and works with multiple rectangles, see >here<.  It's tailored to some specifics, involving the OP's Layer and Block name requirements, but a rather easy modification would fix it for your needs -- I could play with that later, if you're not capable of altering it yourself.

 

 

Kent Cooper, AIA
Message 11 of 32

Anonymous
Not applicable

Thank you Very much,

 

I have taken your code from suggested link but not asking for no.of rows and columns. I have created 2 blocks wuth names mentioned in below code. When I used the lisp code only one block was placed in center of rectangle.

 

(setvar 'cmdecho 0)
(command "_.layer" "_make" "M-FIRE-SYMB-P" "_color" "2" "" "")
(setvar 'cmdecho 1)
(vl-load-com)

(defun SS (blkname / *error* ssia doc svnames svvals P1 rectss n ucschanged P3)

(defun *error* (errmsg)
(if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
(princ (strcat "\nError: " errmsg))
); if
(if ucschanged (command-s "_.ucs" "_previous"))
; [change to (command ... if Acad version predates (command-s) function]
(mapcar 'setvar svnames svvals); reset System Variables
(vla-endundomark doc)
(princ)
); defun - *error*

(defun ssia (/ delta LL NX NY DS1 DS2); = SS Insert & Array
(setq
delta (mapcar 'abs (mapcar '- P3 P1)); differences in XYZ list
LL (mapcar 'min P1 P3)
; Lower Left regardless of pick order or Pline start or direction
NX (+ (fix (/ (car delta) dis)) 1)
DS1 (/ (car delta) NX)
DSS1 (/ area DS1)
NY (+ (fix (/ (cadr delta) DSS1)) 1)
DS2 (/ (cadr delta) NY)
); setq
(command
"_.insert" blkname "_none" (mapcar '+ LL (list (/ DS1 2) (/ DS2 2))) "" "" ""
"_.array" "_last" "" "_r" NY NX
); command [leaves it in Array awaiting spacing(s)
(cond
((= NX 1) (command DS2))
((= NY 1) (command DS1))
(T (command DS2 DS1))
); cond
); defun -- ssia

(vla-startundomark (setq doc (vla-get-activedocument (vlax-get-acad-object))))
(setq ; System Variable saving/resetting without separate variables for each:
svnames '(cmdecho ucsfollow osmode blipmode)
svvals (mapcar 'getvar svnames)
); setq
(mapcar 'setvar svnames '(0 0)); turn off command echoing, UCS follow

(initget "Light Ordinary Extra")
(setq haz (getkword "\nSpeciefy Space Hazard Type [Light/Ordinary/Extra]: "))
(if (= haz "Light")
(setq
dis 4600
area 21000000
)
(progn

(if (= haz "Ordinary")
(setq
dis 4600
area 12000000
)
)
(progn
(if (= haz "Extra")
(setq
dis 3700
area 9000000
)
)
)
)
)
(initget "Select"); allows S as input to (getpoint) function, instead of point pick
(setq P1 (getpoint "\nFirst Corner of rectangular area for Sprinklers, or [Select]: "))
; [if in non-World UCS, returns in current UCS coordinates, not in WCS]
(if (= P1 "Select"); chose that option
(progn ; then
(prompt "\nTo distribute Sprinklers in rectangular Polylines,")
(if (setq rectss (ssget '((0 . "LWPOLYLINE") (90 . 4) (-4 . "&") (70 . 1))))
; multiple selection -- only 4-vertex closed [does not check for rectangularity]
(progn ; then
(mapcar 'setvar svnames '(0 0 0 0)); also turn off Osnap, blips
(repeat (setq n (sslength rectss)); step through selection
(setq rect (ssname rectss (setq n (1- n))))
(command "_.ucs" "_object" rect)
(setq
ucschanged T ; marker for resetting in *error*
P1 (trans (vlax-curve-getPointAtParam rect 0) 0 1); starting vertex
P3 (trans (vlax-curve-getPointAtParam rect 2) 0 1); third vertex [opposite corner]
); setq
(ssia); run the subroutine to Insert and Array
(command "_.ucs" "_previous")
(setq ucschanged nil); [turn off marker]
); repeat
); progn
(prompt "\nNo closed 4-vertex Polyline(s) selected."); else
); if
); progn
(progn ; else [picked a point]
(setq P3 (getcorner P1 "\nOpposite Corner: "))
(mapcar 'setvar svnames '(0 0 0 0)); also turn off Osnap, blips
(ssia); run the subroutine to Insert and Array
); progn
); if
(mapcar 'setvar svnames svvals); reset System Variables
(vla-endundomark doc)
(princ)
); defun -- SS

(defun C:SSP ()
(SS "M-FFSP-PE02-P")
); defun

(defun C:SSU ()
(SS "M-FFSP-UP01-P")
); defun

(prompt "\n THIS PROGRAM FOR SPRINKLER DISTRIBUTION ")
(prompt "\n START command by : SSP:PENDANT SSU:UPRIGHT ")
(prompt "\n\n CREATED by :\n ********* M.SAIED. ********* ")
(prompt "\n MODIFIED by :\n ********* Saber Elkassas & Kent Cooper. ********* ")
(princ)

0 Likes
Message 12 of 32

Anonymous
Not applicable

Dear Sir,

 

The code was working for MINSERT cad command which changes block names and applying group to array, which takes so much of time to manage them. Could you please make the following code which I got from other source to select the rectangle?. It makes me more convenient.

(PROMPT "\n THIS PROGRAM FOR DISTRIBUTION LAMP")
(PROMPT "\n START COMMAND by : ----DIL---- ")
(DEFUN C:IL ()
(SETVAR "CMDECHO" 0)
(setq os (getvar "osmode"))
(setvar "osmode" 0)
(SETQ P1 (GETPOINT "\n ENTER FIRST POINT: "))
(SETQ P3 (GETPOINT "\n ENTER SECOND POINT: "))
(SETQ BB1 (cdr (assoc 2 (entget (car (entsel "\n Select Block"))))))
(setq x1 (car p1))
(setq y1 (car (cdr p1)))
(setq x3 (car p3))
(setq y3 (car (cdr p3)))
(setq p2 (list x1 y3))
(setq p4 (list x3 y1))
(setq disx (distance p1 p4))
(setq disy (distance p1 p2))
(SETQ NX (GETINT "\n NUMBER OF X DIR."))
(SETQ XXN (/ disx (* NX 2)))
(SETQ DS1 (* XXN 2))
(SETQ NY (GETINT "\n NUMBER OF Y DIR."))
(SETQ YYN (/ disy (* NY 2)))
(SETQ DS2 (* YYN 2))
(setq xx1 (+ (car p1) XXN))
(setq yy1 (+ (car (cdr p1)) YYN))
(setq pp2 (list xx1 yy1))
(COMMAND "-layer" "m" "M-FIRE-SYMB-P" "c" "2" "" "")
(COMMAND "INSERT" BB1 pp2 "" "" "")
;(COMMAND "ARRAY" "L" "" "R" NY NX DS2 DS1)
(if (eq NX 1) (COMMAND "ARRAY" "L" "" "R" NY NX DS2))
(if (eq NY 1) (COMMAND "ARRAY" "L" "" "R" NY NX DS1))
(if (AND (/= NX 1) (/= NY 1))(COMMAND "ARRAY" "L" "" "R" NY NX DS2 DS1))
(setvar "osmode" os)
(PRIN1)
(PRIN1)
(PROMPT "\n")
(PROMPT "\n CREATED by :")
(PROMPT "\n ********* M.SAIED. ********* ")
(PRINC)
);DEFUN

0 Likes
Message 13 of 32

Kent1Cooper
Consultant
Consultant
Accepted solution

@Anonymous wrote:

.... I have taken your code from suggested link but not asking for no.of rows and columns. ....


 

You appear to have pulled code from later in that thread than the Message I linked to, after it had gotten into different levels of coverage.  But yes, it doesn't ask for rows/columns -- part of the specialization that needs to be adjusted for is that it's about sprinklers, and they are located at maximum spacings, calculating the number of rows and columns by the size of the room.

 

That raises the big question in my mind about your needs:  You asked about applying it to multiple  rectangles, but would you want the same  number of rows and columns in all of them?  That doesn't seem likely, if we can assume they would not all be the same shape.  Or would you want to select the rectangles first, and be asked about the number of rows and columns for each one?  Or should there be [as with the sprinklers] a maximum spacing, with the routine calculating the number of rows and columns for each?

Kent Cooper, AIA
Message 14 of 32

Anonymous
Not applicable

Dear Sir,

I need the code that works with multiple rooms with same rows and columns. In some case symmetrical rooms will be there. Also the first code I posted is working with MINSERT command, that changes block names and moving them into the group. It's very difficult to manage. So while searching for other code I got below code which works more perfectly for me. The below code keeps block name as it is also and not creating a groups. Each block will be performed individual.

 

Can you please make the blow code to rectangle selection. Please

 

(PROMPT "\n THIS PROGRAM FOR DISTRIBUTION LAMP")
(PROMPT "\n START COMMAND by : ----DIL---- ")
(DEFUN C:IL ()
(SETVAR "CMDECHO" 0)
(setq os (getvar "osmode"))
(setvar "osmode" 0)
(SETQ P1 (GETPOINT "\n ENTER FIRST POINT: "))
(SETQ P3 (GETPOINT "\n ENTER SECOND POINT: "))
(SETQ BB1 (cdr (assoc 2 (entget (car (entsel "\n Select Block"))))))
(setq x1 (car p1))
(setq y1 (car (cdr p1)))
(setq x3 (car p3))
(setq y3 (car (cdr p3)))
(setq p2 (list x1 y3))
(setq p4 (list x3 y1))
(setq disx (distance p1 p4))
(setq disy (distance p1 p2))
(SETQ NX (GETINT "\n NUMBER OF X DIR."))
(SETQ XXN (/ disx (* NX 2)))
(SETQ DS1 (* XXN 2))
(SETQ NY (GETINT "\n NUMBER OF Y DIR."))
(SETQ YYN (/ disy (* NY 2)))
(SETQ DS2 (* YYN 2))
(setq xx1 (+ (car p1) XXN))
(setq yy1 (+ (car (cdr p1)) YYN))
(setq pp2 (list xx1 yy1))
(COMMAND "-layer" "m" "M-FIRE-SYMB-P" "c" "2" "" "")
(COMMAND "INSERT" BB1 pp2 "" "" "")
;(COMMAND "ARRAY" "L" "" "R" NY NX DS2 DS1)
(if (eq NX 1) (COMMAND "ARRAY" "L" "" "R" NY NX DS2))
(if (eq NY 1) (COMMAND "ARRAY" "L" "" "R" NY NX DS1))
(if (AND (/= NX 1) (/= NY 1))(COMMAND "ARRAY" "L" "" "R" NY NX DS2 DS1))
(setvar "osmode" os)
(PRIN1)
(PRIN1)
(PROMPT "\n")
(PROMPT "\n CREATED by :")
(PROMPT "\n ********* M.SAIED. ********* ")
(PRINC)
);DEFUN

0 Likes
Message 15 of 32

Kent1Cooper
Consultant
Consultant
Accepted solution

@Anonymous wrote:

.... I need the code that works with multiple rooms with same rows and columns. .... while searching for other code I got below code .... Each block will be performed individual.

Can you please make the blow code to rectangle selection. Please


....

 

 

Not if you want it to also work on non-orthogonal  rectangles -- a very different requirement, but one that is handled by the other sprinkler-oriented code I linked to.  Do you still want that capability?

 

EDIT:  ALSO, do you want to be asked to select  a Block to be used, as in Message 1, or be asked to type in  a Block name, or have a Block name built in?

Kent Cooper, AIA
Message 16 of 32

Anonymous
Not applicable

Dear Sir,

 

I don't want inbuilt block name in lisp code, Now my exact requirement is to apply below code for multiple rectangles with block selection as input:

(PROMPT "\n THIS PROGRAM FOR DISTRIBUTION LAMP")
(PROMPT "\n START COMMAND by : ----DIL---- ")
(DEFUN C:IL ()
(SETVAR "CMDECHO" 0)
(setq os (getvar "osmode"))
(setvar "osmode" 0)
(SETQ P1 (GETPOINT "\n ENTER FIRST POINT: "))
(SETQ P3 (GETPOINT "\n ENTER SECOND POINT: "))
(SETQ BB1 (cdr (assoc 2 (entget (car (entsel "\n Select Block"))))))
(setq x1 (car p1))
(setq y1 (car (cdr p1)))
(setq x3 (car p3))
(setq y3 (car (cdr p3)))
(setq p2 (list x1 y3))
(setq p4 (list x3 y1))
(setq disx (distance p1 p4))
(setq disy (distance p1 p2))
(SETQ NX (GETINT "\n NUMBER OF X DIR."))
(SETQ XXN (/ disx (* NX 2)))
(SETQ DS1 (* XXN 2))
(SETQ NY (GETINT "\n NUMBER OF Y DIR."))
(SETQ YYN (/ disy (* NY 2)))
(SETQ DS2 (* YYN 2))
(setq xx1 (+ (car p1) XXN))
(setq yy1 (+ (car (cdr p1)) YYN))
(setq pp2 (list xx1 yy1))
(COMMAND "-layer" "m" "M-FIRE-SYMB-P" "c" "2" "" "")
(COMMAND "INSERT" BB1 pp2 "" "" "")
;(COMMAND "ARRAY" "L" "" "R" NY NX DS2 DS1)
(if (eq NX 1) (COMMAND "ARRAY" "L" "" "R" NY NX DS2))
(if (eq NY 1) (COMMAND "ARRAY" "L" "" "R" NY NX DS1))
(if (AND (/= NX 1) (/= NY 1))(COMMAND "ARRAY" "L" "" "R" NY NX DS2 DS1))
(setvar "osmode" os)
(PRIN1)
(PRIN1)
(PROMPT "\n")
(PROMPT "\n CREATED by :")
(PROMPT "\n ********* M.SAIED. ********* ")
(PRINC)
);DEFUN

0 Likes
Message 17 of 32

Kent1Cooper
Consultant
Consultant
Accepted solution

@Anonymous wrote:

.... I don't want inbuilt block name in lisp code .... 

 

Since I was already altering it, attached is one that asks you to select a Block, and for number of rows and columns, and gives you the choice either  to pick two opposite corners or to Select rectangles, and works with non-orthogonal ones.  HOWEVER, the way it works with non-orthogonal ones is by setting the UCS to match the Polyline.  [That also means that if the Block has "direction," it aligns with the rectangle edges.]  Because of that, in some cases "rows" and "columns" [if different numbers] will come out reversed from what you expect, because it's affected by which corner of a Polyline rectangle is the beginning, and in which direction it was drawn.  That could probably be overcome for orthogonal ones, but it raises another question:  For a non-orthogonal rectangle, how should it decide which direction should be "rows" and which should be "columns"?  One possibility, given the light-fixture or sprinkler-head applications, is that it could use whichever number is higher and apply that in whichever direction of the rectangle is longer.  Another possibility, for those not at a 45-degree angle, would be to use the edge closer to WCS horizontal as the pseudo-horizontal for rows, but that still leaves the problem of how to decide for one at 45 degrees.  But if you have some other criteria....

 

It could be made to remember the block name, and the numbers of rows and columns, and offer them as defaults on subsequent use.

Kent Cooper, AIA
0 Likes
Message 18 of 32

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:
...  For a non-orthogonal rectangle, how should it decide which direction should be "rows" and which should be "columns"?  One possibility, given the light-fixture or sprinkler-head applications, is that it could use whichever number is higher and apply that in whichever direction of the rectangle is longer.  ....

 

... or as an alternative to that, it could prompt the User not  for columns and rows, but for something like "How many in the longer direction: " and "How many in the shorter direction: ".

Kent Cooper, AIA
0 Likes
Message 19 of 32

Anonymous
Not applicable

Dear Sir,

 

Marvelous, Superb What a fabulous fantastic reply. It's worked amazingly. It exactly suited to my requirement.

 

Thanks,

T.Brahmanandam.

0 Likes
Message 20 of 32

Anonymous
Not applicable

Dear Sir,

 

I have just downloaded and tested your lisp. Working fine. I need small modification that the code should ask for block rotation and block scale. Because in some room locations I need other than default angle and also scale to be changed for some rooms. Thank you in advance Sir.

 

(vl-load-com)
(defun C:ABR ; = Array Block in Rectangle(s)
(/ *error* ABRia doc svnames svvals P1 rectss n P3)
(defun *error* (errmsg)
(if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
(princ (strcat "\nError: " errmsg))
); if
(if ucschanged (command-s "_.ucs" "_previous"))
; [change to (command ... if Acad version predates (command-s) function]
(mapcar 'setvar svnames svvals); reset System Variables
(vla-endundomark doc)
(princ)
); defun - *error*
(defun ABRia (/ delta LL NX NY colsp rowsp); = ABR Insert & Array
(setq
delta (mapcar 'abs (mapcar '- P3 P1)); differences in XYZ list
LL (mapcar 'min P1 P3)
; Lower Left regardless of pick order or Pline start or direction
colsp (/ (car delta) cols)
rowsp (/ (cadr delta) rows)
); setq
(command
"_.insert" blk "_none" (mapcar '+ LL (list (/ colsp 2) (/ rowsp 2))) "" "" ""
"_.array" "_last" "" "_r" rows cols rowsp colsp
); command
); defun -- ABRia
(vla-startundomark (setq doc (vla-get-activedocument (vlax-get-acad-object))))
(setq ; System Variable saving/resetting without separate variables for each:
svnames '(cmdecho ucsfollow osmode blipmode)
svvals (mapcar 'getvar svnames)
blk (cdr (assoc 2 (entget (car (entsel "\n Select Block")))))
rows (getint "\nNumber of columns (|||): ")
cols (getint "\nNumber of rows (---): ")
); setq
(mapcar 'setvar svnames '(0 0)); turn off command echoing, UCS follow
(initget "Select"); allows S as input to (getpoint) function, instead of point pick
(setq P1 (getpoint "\nFirst Corner of ortho-rectangular area for Blocks, or [Select]: "))
; [if in non-World UCS, returns in current UCS coordinates, not in WCS]
(if (= P1 "Select"); chose that option
(progn ; then
(prompt "\nTo Array Blocks in Rectangular Polyline(s),")
(if (setq rectss (ssget '((0 . "LWPOLYLINE") (90 . 4) (-4 . "&") (70 . 1))))
; multiple selection -- only 4-vertex closed [does not check for rectangularity]
(progn ; then
(mapcar 'setvar svnames '(0 0 0 0)); also turn off Osnap, blips
(repeat (setq n (sslength rectss)); step through selection
(setq rect (ssname rectss (setq n (1- n))))
(command "_.ucs" "_object" rect)
(setq
ucschanged T ; marker for resetting in *error*
P1 (trans (vlax-curve-getPointAtParam rect 0) 0 1); starting vertex
P3 (trans (vlax-curve-getPointAtParam rect 2) 0 1); third vertex [opposite corner]
); setq
(ABRia); run the subroutine to MINSERT
(command "_.ucs" "_previous")
(setq ucschanged nil); [turn off marker]
); repeat
); progn
(prompt "\nNo closed 4-vertex Polyline(s) selected."); else
); if
); progn
(progn ; else [picked a point]
(setq P3 (getcorner P1 "\nOpposite Corner: "))
(mapcar 'setvar svnames '(0 0 0 0)); also turn off Osnap, blips
(ABRia); run the subroutine to MINSERT
); progn
); if
(mapcar 'setvar svnames svvals); reset System Variables
(vla-endundomark doc)
(princ)
); defun -- C:ABR

0 Likes