setting layers based on object selection

setting layers based on object selection

shillmanB5QQZ
Contributor Contributor
3,055 Views
37 Replies
Message 1 of 38

setting layers based on object selection

shillmanB5QQZ
Contributor
Contributor

Definite LISP newbie.  This is my first.  I know, big undertaking.  I have been working this lisp routine that you select the wall, select point on wall for the start of the break, select door width and a point on perpendicular line and it will break both lines and draw the ends of the walls in on the correct layer, and inserts the door block on the correct layer.  I have 4 possible scenarios for the wall layers, (EXST-WALL-INTR, EXST-WALL EXTER, NEW-WALL-INTR, NEW-WALL-EXTR) and 4 scenarios for the door layer (EXST-DOOR-EXTR, EXST-DOOR-INTR, NEW-DOOR-EXTR, NEW-DOOR-INTR )  I have accomplished this task . . . .  to an extent.  I have figured out setting the wall layers.  The issue is having 4 possibilities of door layers based on what wall layer is picked.   I have made 2 lisp routines, one for existing and one for new.  I would like to have one routine for all scenarios.  I am wonder if there is a way to to have one routine (Door.lisp) that can process all existing and new conditions and set appropriate layers.  I have found help from various sites on the internet to put this routine together but can seem to find an answer to what I am looking for.  Hence the reason for this post.  Here is what I have found, pieced together and figured out so far.

 

;Program to cut door opening in wall and insert door on correct layer -- DoorExst.lsp
(defun c:doorexst (/ pt1 pt2 pt3 pt4 ang1 ang2 dst1 osnap1 str1 clyr wlyr bfind msg)
(setvar "cmdecho" 0)
(command "-purge" "b" "door" "n")
(setq osnap1 (getvar "osmode"))
(setq clyr (getvar "clayer"))
(defun *error* (msg)
(setvar "osmode" osnap1)
(setvar "clayer" clyr)
(princ msg)
(princ)
)
(setvar "osmode" 512) ;nearest osnap mode
(setq wlyr (entget (car (entsel "\nSelect Wall: "))));end setq
(setq pt1 (getpoint "\nSelect point on wall to start point of opening: ")) ;get first break point
(setq pt2 (getpoint pt1 "\nEnter endpoint of opening: ")) ;get second break point
(setvar "osmode" 128) ;perpend osnap mode
(setq pt3 (getpoint pt1 "\nSelect opposite side of wall: "));get 2nd line
(Setvar "osmode" 0) ;no osnap mode
(setq ang1 (angle pt1 pt3)) ;find angle btwn lines
(setq dst1 (distance pt1 pt3)) ;find dist. btwn lines
(setq pt4 (polar pt2 ang1 dst1)) ;derive pt4 on 2nd line
(setq ang2 (* (angle pt1 pt2)57.2958)) ;find angle for door insertion
(setvar "clayer" (cdr (assoc 8 wlyr);end set current layer
(command
"break" pt1 pt2 ;break 1st line
"break" pt3 pt4 ;break 2nd line
"line" pt1 pt3 "" ;close ends of lines
"line" pt2 pt4 ""
);end command
(defun intr ()
(setvar "clayer" "exst-door-intr")
);end intr
(defun extr ()
(setvar "clayer" "exst-door-extr")
);end extr
(initget "Exterior Interior");end initget
(setq str1 (getkword "Is this an Exterior or Interior door?<Exterior/Interior>:"));end str1
(if (= str1 "Exterior")
(extr)
(intr)
);end if
(defun bfind (/ bfind)
(setq bfind (tblsearch "block" "standards"))
(if (not bfind)(command "-insert" "standards.dwg=" "0,0" "" "" ""))
(princ "Standards is already inserted. ")
(command "_.erase" "l" "")
);end bfind
(bfind)
(princ)
(command "-insert" "door" pt3 1 1 ang2)
(command "draworder" "l" "" "b")
(setvar "clayer" clyr)
(setvar "osmode" osnap1)
(setvar "cmdecho" 1)
(princ)
);end doorexst

 

 

Any help would be greatly appreciated.  Also, I know the structure is probably less than desirable.  All suggestions on lisp structure are welcome as well.  New to these forums, if this needs to be move to a more appropriate location feel free to move.

 

Thanks in advance,

Scott

 

0 Likes
3,056 Views
37 Replies
Replies (37)
Message 2 of 38

pendean
Community Legend
Community Legend
Why don't you just install and run AutoCAD-ARCHITECTURE? Its free with every AutoCAD subscription for the past 2+versions now, it does all that, plus so much more, and you get actual smart doors/walls/ceilings/roofs etc. to boot.

Explore here https://www.autodesk.com/products/autocad/included-toolsets/autocad-architecture
0 Likes
Message 3 of 38

shillmanB5QQZ
Contributor
Contributor

Unfortunately that is not my call.  The firm I work for is still on AutoCAD 2010.

0 Likes
Message 4 of 38

ВeekeeCZ
Consultant
Consultant

Would you post some examples dwg?

0 Likes
Message 5 of 38

shillmanB5QQZ
Contributor
Contributor

Here is the example dwg

0 Likes
Message 6 of 38

ВeekeeCZ
Consultant
Consultant

Are you able from layer of breaking wall tell the layer of door? Like 

Do you still need to decide whether its interiour or exteriour? Isn't it given by a wall layer? 

0 Likes
Message 7 of 38

shillmanB5QQZ
Contributor
Contributor

Yes in this program selecting the wall sets the layer for drawing the ends of the walls at the cutout and determining whether the existing door goes on an interior or exterior door layer.   Where I am running into trouble is with the new door layers.  Being that I am very new to writing lisp and I am having a problem with how to incorporate the NEW doors into this routine.  Currently I have one lisp file for existing doors and one lisp file for new doors.

 

0 Likes
Message 8 of 38

ВeekeeCZ
Consultant
Consultant
Accepted solution

Not sure if I do follow... I thought it's all given by layer of cutting wall. anyway, try the code and see...

BTW don't you want to incorporate the doorsize too? 

 

(defun c:door (/ pt1 pt2 pt3 pt4 ang1 ang2 dst1 osnap1 str1 clyr wlyr bfind msg)
  
  (defun *error* (msg)
    (setvar "osmode" osnap1)
    (setvar "clayer" clyr)
    (setvar 'cmdecho 1)
    (princ msg)
    (princ)
    )
    
  (defun createifnot (lay)
    (or (tblsearch "layer" lay)
	(cond ((= lay "EXST-WALL-INTR") (command "_.-layer" "_new" "EXST-WALL-INTR" "_color" "EXST-WALL-INTR" ""))
	      (T (command "_.-layer" "_new" lay ""))))
    lay)
  
  (defun bfind ()
    (if (tblsearch "block" "door")
      (princ "Standards is already inserted. ")
      (command "-insert" "standards.dwg=" "0,0" "" "" ""
	       "_.erase" "l" ""))
    );end bfind

  ; ----------------------------------------------------------------------------------------------------------------------------
  
  (setvar "cmdecho" 0)
  (command "-purge" "b" "door" "n")
  (setq osnap1 (getvar "osmode"))
  (setq clyr (getvar "clayer"))
  
  (setvar "osmode" 512) ;nearest osnap mode
  (setq pt1 (getpoint "\nSelect point on wall to start point of opening: ")) ;get first break point
  (setq wlyr (nentselp pt1))
  (setq pt2 (getpoint pt1 "\nEnter endpoint of opening: ")) ;get second break point
  (setvar "osmode" 128) ;perpend osnap mode
  (setq pt3 (getpoint pt1 "\nSelect opposite side of wall: "));get 2nd line
  
  (setq ang1 (angle pt1 pt3)) ;find angle btwn lines
  (setq dst1 (distance pt1 pt3)) ;find dist. btwn lines
  (setq pt4 (polar pt2 ang1 dst1)) ;derive pt4 on 2nd line
  (setq ang2 (* (angle pt1 pt2) 57.2958)) ;find angle for door insertion
  (setq lay (cdr (assoc 8 (entget (car wlyr)))))
  
  (setvar "clayer" lay);end set current layer
  
  (Setvar "osmode" 0) ;no osnap mode
  (command "break" pt1 pt2 ;break 1st line
	   "break" pt3 pt4 ;break 2nd line
	   "line" pt1 pt3 "" ;close ends of lines
	   "line" pt2 pt4 ""
	   );end command
  
  ;;;  (initget "Exterior Interior");end initget
  ;;;  (setq str1 (getkword "Is this an Exterior or Interior door?<Exterior/Interior>:"));end str1
  ;;;  (if (= str1 "Exterior")
  ;;;    (extr)
  ;;;    (intr)
  ;;;    );end if
  (bfind)
  (setq lay (vl-string-subst "DOOR" "WALL" lay))
  (setvar 'clayer (createifnot lay))
  
  (command "-insert" "door" pt3 1 1 ang2)
  (command "draworder" "l" "" "b")
  (setvar "clayer" clyr)
  (setvar "osmode" osnap1)
  (setvar "cmdecho" 1)
  (princ)
  );end doorexst

 

0 Likes
Message 9 of 38

shillmanB5QQZ
Contributor
Contributor

Capture.PNG

0 Likes
Message 10 of 38

shillmanB5QQZ
Contributor
Contributor

Yes!  I would like to incorporate door size and openangle, which are both dynamic values in the door block.

0 Likes
Message 11 of 38

shillmanB5QQZ
Contributor
Contributor

I tried what you posted and got this . . . . 

 

 

Command: DOOR
No unreferenced blocks found.

Select point on wall to start point of opening:
Enter endpoint of opening:
Select opposite side of wall: No object found
No object found


*Invalid selection*
Expects a point or Window/Last/Crossing/BOX/ALL/Fence/WPolygon/CPolygon
Function cancelledSelect object: *Cancel*

0 Likes
Message 12 of 38

ВeekeeCZ
Consultant
Consultant

Now you show up. Find the line causing this trouble!

btw it works for me.

 
0 Likes
Message 13 of 38

ВeekeeCZ
Consultant
Consultant

Here's the code. I'm not versed with imperials... so test it yourself better. 

Also, have a bit issues with degree sigh of yours... "Closed" vis state works, but not the others. Either find and use the ascii num or rename the states. Good luck

 

BTW *error* func has to be localized!!

 

(vl-load-com)

(defun c:door (/ *error* cly cmd osm pt1 pt2 pt3 pt4 ang1 ang2 ent lay bfind ang)
  
  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break,end"))
      (princ (strcat "\nError: " errmsg)))
    (if cmd (setvar 'cmdecho cmd))
    (if osm (setvar 'osmode  osm))
    (if cly (setvar 'clayer  cly))
    (princ))
  
  (defun createifnot (lay)
    (or (tblsearch "layer" lay)
	(cond ((= lay "EXST-WALL-INTR") (command "_.-layer" "_new" "EXST-WALL-INTR" "_color" "EXST-WALL-INTR" ""))
	      (T (command "_.-layer" "_new" lay ""))))
    lay)
  
  (defun bfind ()
    (if (tblsearch "block" "door")
      (princ "Standards is already inserted. ")
      (command "-insert" "standards.dwg=" "0,0" "" "" ""
	       "_.erase" "l" ""))
    );end bfind
  
  ; ----------------------------------------------------------------------------------------------------------------------------
  
  (setq cmd (getvar 'cmdecho)) (setvar "cmdecho" 0)
  (command "-purge" "b" "door" "n")
  (setq osm (getvar "osmode"))
  (setq cly (getvar "clayer"))
  
  (setvar "osmode" 512) ;nearest osnap mode
  (setq pt1 (getpoint "\nSelect point on wall to start point of opening: ")) ;get first break point
  (setq ent (car (nentselp pt1)))
  (setvar "osmode" 128) ;perpend osnap mode
  (setq pt3 (getpoint pt1 "\nSelect opposite side of wall: "));get 2nd line
  
  (or *d-siz*
      (setq *d-siz* 36))
  (setq *d-siz* (cond ((getdist pt1 (strcat "\nDoor size <" (rtos *d-siz*) ">: ")))
		      (*d-siz*)))

  (or *d-ang*
      (setq *d-ang* "30"))
  (initget "30 45 60 90 0 Closed")
  (setq *d-ang* (cond ((getkword (strcat "\nOpening Angle [Closed] <" *d-ang* ">: ")))
		      (*d-ang*)))
  (setq ang (cond ((= "0" *d-ang*) 	"Closed")
		  ((= "Closed" *d-ang*) "Closed")
		  (T 			(strcat "Open " *d-ang* "o"))))
  
  (setq ang1 (angle pt1 pt3))
  (setq ang2 (- ang1 (/ pi 2))) ;find angle for door insertion
  (setq pt2 (polar pt1 ang2 *d-siz*))
  (setq pt4 (polar pt2 ang1 (distance pt1 pt3))) ;derive pt4 on 2nd line
  
  (setq lay (cdr (assoc 8 (entget ent))))
  
  (setvar "osmode" 0) ;no osnap mode
  (command "break" pt1 pt2 ;break 1st line
	   "break" pt3 pt4) ;break 2nd line
  
  (setvar "clayer" lay);end set current layer
  (command "line" pt1 pt3 "" ;close ends of lines
	   "line" pt2 pt4 ""
	   );end command
  
  (bfind)
  (setq lay (vl-string-subst "DOOR" "WALL" lay))
  (setvar 'clayer (createifnot lay))
  
  (command "-insert" "door" pt3 1 1 ang2)
  (LM:SetDynPropValue (vlax-ename->vla-object (entlast)) "DoorSize" *d-siz*)
  (LM:SetVisibilityState (vlax-ename->vla-object (entlast)) ang)
  
  (command "draworder" "l" "" "b")
  (*error* "end")
  );end doorexst








;; Block Name  -  Lee Mac
;; Returns the true (effective) name of a supplied block reference

(defun LM:blockname ( obj )
  (if (vlax-property-available-p obj 'effectivename)
    (defun LM:blockname ( obj ) (vla-get-effectivename obj))
    (defun LM:blockname ( obj ) (vla-get-name obj))
    )
  (LM:blockname obj)
  )

;; Set Dynamic Block Property Value  -  Lee Mac
;; Modifies the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; val - [any] New value for property
;; Returns: [any] New value if successful, else nil

(defun LM:setdynpropvalue ( blk prp val )
  (setq prp (strcase prp))
  (vl-some
    '(lambda ( x )
       (if (= prp (strcase (vla-get-propertyname x)))
	 (progn
	   (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
	   (cond (val) (t))
	   )
	 )
       )
    (vlax-invoke blk 'getdynamicblockproperties)
    )
  )

;; Get Dynamic Block Property Value  -  Lee Mac
;; Returns the value of a Dynamic Block property (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)

(defun LM:getdynpropvalue ( blk prp )
  (setq prp (strcase prp))
  (vl-some '(lambda ( x ) (if (= prp (strcase (vla-get-propertyname x))) (vlax-get x 'value)))
	   (vlax-invoke blk 'getdynamicblockproperties)
	   )
  )


;; Get Dynamic Block Properties  -  Lee Mac
;; Returns an association list of Dynamic Block properties & values.
;; blk - [vla] VLA Dynamic Block Reference object
;; Returns: [lst] Association list of ((<prop> . <value>) ... )

(defun LM:getdynprops ( blk )
  (mapcar '(lambda ( x ) (cons (vla-get-propertyname x) (vlax-get x 'value)))
	  (vlax-invoke blk 'getdynamicblockproperties)
	  )
  )


;; Get Dynamic Block Property Allowed Values  -  Lee Mac
;; Returns the allowed values for a specific Dynamic Block property.
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; Returns: [lst] List of allowed values for property, else nil if no restrictions

(defun LM:getdynpropallowedvalues ( blk prp )
  (setq prp (strcase prp))
  (vl-some '(lambda ( x ) (if (= prp (strcase (vla-get-propertyname x))) (vlax-get x 'allowedvalues)))
	   (vlax-invoke blk 'getdynamicblockproperties)
	   )
  )


;; Get Visibility Parameter Name  -  Lee Mac
;; Returns the name of the Visibility Parameter of a Dynamic Block (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; Returns: [str] Name of Visibility Parameter, else nil

(defun LM:getvisibilityparametername ( blk / vis )
  (if
    (and
      (vlax-property-available-p blk 'effectivename)
      (setq blk
	     (vla-item
	       (vla-get-blocks (vla-get-document blk))
	       (vla-get-effectivename blk)
	       )
	    )
      (= :vlax-true (vla-get-isdynamicblock blk))
      (= :vlax-true (vla-get-hasextensiondictionary blk))
      (setq vis
	     (vl-some
	       '(lambda ( pair )
		  (if
		    (and
		      (= 360 (car pair))
		      (= "BLOCKVISIBILITYPARAMETER" (cdr (assoc 0 (entget (cdr pair)))))
		      )
		    (cdr pair)
		    )
		  )
	       (dictsearch
		 (vlax-vla-object->ename (vla-getextensiondictionary blk))
		 "ACAD_ENHANCEDBLOCK"
		 )
	       )
	    )
      )
    (cdr (assoc 301 (entget vis)))
    )
  )


;; Get Dynamic Block Visibility State  -  Lee Mac
;; Returns the value of the Visibility Parameter of a Dynamic Block (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; Returns: [str] Value of Visibility Parameter, else nil

(defun LM:getvisibilitystate ( blk / vis )
  (if (setq vis (LM:getvisibilityparametername blk))
    (LM:getdynpropvalue blk vis)
    )
  )

;; Set Dynamic Block Visibility State  -  Lee Mac
;; Sets the Visibility Parameter of a Dynamic Block (if present) to a specific value (if allowed)
;; blk - [vla] VLA Dynamic Block Reference object
;; val - [str] Visibility State Parameter value
;; Returns: [str] New value of Visibility Parameter, else nil

(defun LM:SetVisibilityState ( blk val / vis )
  (if
    (and
      (setq vis (LM:getvisibilityparametername blk))
      (member (strcase val) (mapcar 'strcase (LM:getdynpropallowedvalues blk vis)))
      )
    (LM:setdynpropvalue blk vis val)
    )
  )

 

0 Likes
Message 14 of 38

shillmanB5QQZ
Contributor
Contributor

Thank you for the help.  All the layering is working great.  I am having issues with the "OpenAngle" value of the door block, and the rotation angle during block insertion.  I tried making some adjustments to the lisp and  totally messed up the routine.  Here is what I am getting when I try inserting a door on any angle wall other than a horizontal wall.

 

Capture.PNG

Thanks again!

0 Likes
Message 15 of 38

shillmanB5QQZ
Contributor
Contributor

0 Likes
Message 16 of 38

shillmanB5QQZ
Contributor
Contributor

Here is example drawing

0 Likes
Message 17 of 38

Kent1Cooper
Consultant
Consultant

I am looking at this line:

  (command "-insert" "door" pt3 1 1 ang2)

which includes both X and Y scale factors.  When I Insert your Door Block manually, even though it doesn't claim to be defined for uniform scaling, as a dynamic Block it wants only one.  The ones in your sample drawing have rotation angles listed in Properties at the directions of the wall Lines, but something about their being dynamic must be why they don't look like it.  [I'm not well versed in dynamic Blocks, so others could advise better than I.]

 

At least try taking the second scale factor out:

  (command "-insert" "door" pt3 1 ang2)

 

Kent Cooper, AIA
0 Likes
Message 18 of 38

shillmanB5QQZ
Contributor
Contributor

Thanks Kent1cooper,  I redefined the block to scale uniformly and took away a "1". 

 

(command "-insert" "door" pt3 1 ang2)

 

Now when I run the routine the first door (horizontal wall) is inserting correctly, 0 rotation.  The second door I inert, the one in the angled wall, is inserting at a rotation angle of 1 instead of "ang2", and the third time I try and insert the door (vertical wall) the door inserts at a rotation angle of 2 degrees. 

Capture.PNG

 

Also, the "AngleOpen" value in the block is not working either.  The prompt is only reading 90, closed.  90 is not working closed is working.  The prompt should read " 30, 45, 60, 90, Closed".  If I try and change that the routine fails to work.  Sorry to be such a pain.   I have not worked with either of the "OR" function, the "COND" function nor the "nentselp". 

 

Thanks again!

 

Very bizarre!

0 Likes
Message 19 of 38

Kent1Cooper
Consultant
Consultant

@shillmanB5QQZ wrote:

....  The second door I inert, the one in the angled wall, is inserting at a rotation angle of 1 instead of "ang2", and the third time I try and insert the door (vertical wall) the door inserts at a rotation angle of 2 degrees. 

....


On that issue, they're not at 1 and 2 degrees -- those are only rounded-for-display values.  [This is why I never have angular values displayed to the nearest whole degree.]  They are the directions of the Lines, in degrees but with the numerical value of the angles in radians.  If you're using @ВeekeeCZ 's code, ang2 is still in radians when the Insert happens.  Your original had a multiplier to convert the angle between points to degrees [there's a more precise way, but that could be close enough for your purposes].

Kent Cooper, AIA
0 Likes
Message 20 of 38

Kent1Cooper
Consultant
Consultant
Accepted solution

@shillmanB5QQZ wrote:

.... Also, the "AngleOpen" value in the block is not working either.  The prompt is only reading 90, closed.  90 is not working closed is working.  The prompt should read " 30, 45, 60, 90, Closed".  If I try and change that the routine fails to work.  .... 


I expect if you typed in one of those other values, it should "get" it.  But to be able to pick them from the prompt, they would need to be included in it, something like:

..."\nOpening Angle [30/45/60/90/0/Closed] < ....

[I haven't fully traced through what that gets used for.]

Kent Cooper, AIA
0 Likes