Lisp to insert block at specific location and layer

Lisp to insert block at specific location and layer

Anonymous
Not applicable
7,472 Views
40 Replies
Message 1 of 41

Lisp to insert block at specific location and layer

Anonymous
Not applicable

I am interested in a lisp that will insert a block "4x6" (Which requires no scaling) and place it at both ends of a selected line. offset 2" from that line and give the option of which side of that line they will be placed.  finally the inserted "4x6" will be placed on the "s-plan-rcol" layer.   I've included an image for disired result. No scaling or annotations or anything, just would like to show posts at the end of shear walls without having to place them manually.

 

thanks for any help

0 Likes
Accepted solutions (1)
7,473 Views
40 Replies
Replies (40)
Message 2 of 41

ВeekeeCZ
Consultant
Consultant

Try this. Its for start, because it must be clarified how to deal with the insertion point of the block... you'll see... (in your picture it looks like mirrored?)

 

(defun C:ins46 ( / ss)
  (if (and (princ "\nSingle line needed,")
	   (setq ss (ssget "_+.:E:S" '((0 . "LINE")))))
    (command "_.-INSERT" "4x6" (cdr (assoc 10 (entget (ssname ss 0)))) 1 "" 0
	     "_.-INSERT" "4x6" (cdr (assoc 11 (entget (ssname ss 0)))) 1 "" 0
	     "_.OFFSET" "_E" "_Y" 2 (ssname ss 0) PAUSE ""
	     "_.OFFSET" "_E" "_N" "" "_Exit"
	     "_.CHPROP" "_L" "" "_LA" "s-plan-rcol" ""))
  (princ)
)

 

I assumed that OFFSET function you want in ERASE mode. 

Is it possibility that layer does not exists?

0 Likes
Message 3 of 41

Anonymous
Not applicable

Thanks for your response.. 

 

so as I used it the results are close.

 

1) it is inserting the 4x6 however it is placing the inserted block on whatecver the current layer is.  I'm looking for the blocks to end up on layer s-plan-rcol. 

2) the line that is picked is being offset 2", the linetype is being changed and the layer is changed to layer "s-plans-rcol", I need the line to remain unchanged in location and all properties. It is the block that I want to be inserted 2" off the line not the line to be moved.

3) on the left side of the line the block is positioned perfectly, if it were mirrored to other side that would be a perfect location for the right side.

4) the line I am pick is the what is to be the length of a shear wall which requires posts at both ends...  sometimes the shear wall is on the outside of the wall and sometimes its in the inside.  this is why I would like to be able to pick the side of the line that the 4x6 are going to land on.

 

the only difference that I can see thus far with regards to vertically and horizontally that the blocks when placed to the vertical they need to be rotated 90 degrees..

 

 

a great start though.. I very much appreciate your help.... this will save sooo much time in the end. 

 

0 Likes
Message 4 of 41

ВeekeeCZ
Consultant
Consultant

Sorry, I read it too fast ..

I don't know how to mirror inserting block... so I made other way...

 

(defun C:ins46 ( / *error* ss e pt1 pt2)

  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
      (princ (strcat "\nError: " errmsg)))
    (setvar 'CMDECHO 1)
    (princ))
  
  (setvar 'CMDECHO 0)
  (if (and (princ "\nSingle line needed,")
	   (setq ss (ssget "_+.:E:S" '((0 . "LINE"))))
	   (setq e (ssname ss 0)
		 pt1 (cdr (assoc 10 (entget e)))
		 pt2 (cdr (assoc 11 (entget e))))
	   (not (if (tblsearch "LAYER" "s-plan-rcol")
		  nil (command "_.-LAYER" "_N" "s-plan-rcol" "")))
	   (princ "\nSpecify point on side to offset: "))
    (if (eq (car pt1) (car pt2))
      (command "_.-INSERT" "4x6" "_non" pt1 1 "" (angtos (/ pi 2) (getvar 'AUNITS))
	       "_.CHPROP" "_L" "" "_LA" "s-plan-rcol" ""
	       "_.-INSERT" "4x6" "_non" (polar pt2 (angle pt2 pt1) 4) 1 "" (angtos (/ pi 2) (getvar 'AUNITS))
	       "_.CHPROP" "_L" "" "_LA" "s-plan-rcol" ""
	       "_.OFFSET" "_E" "_Y" 2 e PAUSE ""
	       "_.OFFSET" "_E" "_N" "" "_Exit")
      (command "_.-INSERT" "4x6" "_non" pt1 1 "" 0
	       "_.CHPROP" "_L" "" "_LA" "s-plan-rcol" ""
	       "_.-INSERT" "4x6" "_non" (polar pt2 (angle pt2 pt1) 4) 1 "" 0
	       "_.CHPROP" "_L" "" "_LA" "s-plan-rcol" ""
	       "_.OFFSET" "_E" "_Y" 2 e PAUSE ""
	       "_.OFFSET" "_E" "_N" "" "_Exit")))
  (setvar 'CMDECHO 0)
  (princ)
)  

Edit: Added the layer existing test. 

0 Likes
Message 5 of 41

Anonymous
Not applicable

Closer.. 🙂

 

the line being picked is keeping its properties now.. perfect.

 

it places the 4x6 block properly on the left side however it comes in on the right side shifted to the right. I believe it is using the insertion point of the block and being located at the end (right side) of the line.  Doing this shifts the posts to the right. That's why I was thinking if it were to be mirrored it would located properly. 

 

so, when I run the lisp and pick the line.. it inserts the block "4x6" as mentioned, however instead of locating them 2" off the line it locates them at the end of the line and then offsets the line 2 inches.  This is close but I want the line to remain exactly where it is and move the posts 2" off the line. 

 

It doesn't allow me to place post "4x6" above or below the line..

 

see image attached...

 

 

we are getting there though...

0 Likes
Message 6 of 41

ВeekeeCZ
Consultant
Consultant
(defun C:ins46 ( / *error* oOSMODE oAUNITS ss e pt1 pt2 mid up)

  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
      (princ (strcat "\nError: " errmsg)))
    (setvar 'AUNITS oAUNITS)
    (setvar 'OSMODE oOSMODE)
    (setvar 'CMDECHO 1)
    (princ))

  (setq oAUNITS (getvar 'AUNITS))
  (setq oOSMODE (getvar 'OSMODE))
  (setvar 'CMDECHO 0)
  (setvar 'AUNITS 3)
  (setvar 'OSMODE 0)
  
  (if (and (princ "\nSingle line needed,")
	   (setq ss (ssget "_+.:E:S" '((0 . "LINE"))))
	   (setq e (ssname ss 0)
		 pt1 (cdr (assoc 10 (entget e)))
		 pt2 (cdr (assoc 11 (entget e))))
	   (not (if (tblsearch "LAYER" "s-plan-rcol")
		  nil (command "_.-LAYER" "_N" "s-plan-rcol" ""))))
    (progn
     (initget "Up Right")
     (setq up (getkword "\nMove blocks down/left? [no, move these Up/Right] <down/left>"))
     (if (eq (car pt1) (car pt2))
       (progn
	 (command "_.-INSERT" "4x6" (polar pt1 0 -2) 1 "" (* pi 1.5)
		  "_.CHPROP" "_L" "" "_LA" "s-plan-rcol" "")
	 (if up (command "_.MIRROR" "_L" "" pt1 pt2 "_Y"))
	 (command "_.MIRROR" "_L" "" (setq mid (polar pt1 (angle pt1 pt2) (/ (distance pt1 pt2) 2)))
		                     (polar mid (+ (angle pt1 pt2) (/ pi 2)) 1)
		                     "_N"))
       (progn
	 (command "_.-INSERT" "4x6" (polar pt1 (/ pi 2) -2) 1 "" 0
		  "_.CHPROP" "_L" "" "_LA" "s-plan-rcol" "")
	 (if up (command "_.MIRROR" "_L" "" pt1 pt2 "_Y"))
	 (command "_.MIRROR" "_L" "" (setq mid (polar pt1 (angle pt1 pt2) (/ (distance pt1 pt2) 2)))
	                             (polar mid (+ (angle pt1 pt2) (/ pi 2)) 1)
	                             "_N")))))
  (setvar 'AUNITS oAUNITS)
  (setvar 'OSMODE oOSMODE)
  (setvar 'CMDECHO 0)
  (princ)
) 
0 Likes
Message 7 of 41

Kent1Cooper
Consultant
Consultant

I think I can imagine a simpler way, but first:  Where is the Insertion Point in the Block, and how is it oriented at zero rotation?  Is it the actual size of a piece of 4x6 lumber [3-1/2 x 5-1/2], or is it truly 4 drawing units x 6 drawing units in size?

Kent Cooper, AIA
0 Likes
Message 8 of 41

ВeekeeCZ
Consultant
Consultant

@Kent1Cooper wrote:

I think I can imagine a simpler way, but first:  Where is the Insertion Point in the Block, and how is it oriented at zero rotation?  Is it the actual size of a piece of 4x6 lumber [3-1/2 x 5-1/2], or is it truly 4 drawing units x 6 drawing units in size?


You're right... (angle pt1 pt2) not neccasary, perhaps you had some osnaps in your mind... maybe relative polar coords... I tried rethink.. But If you imagine something else... I would like to see... 🙂

 

@Anonymous If it's still wrong, post your 4x6 block as dwg.

 

Spoiler
(defun C:ins46 ( / *error* oOSMODE oAUNITS oCLAYER doc ss pt1 pt2 mirr)

  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
      (princ (strcat "\nError: " errmsg)))
    (setvar 'AUNITS oAUNITS)
    (setvar 'OSMODE oOSMODE)
    (setvar 'CLAYER oCLAYER)
    (setvar 'CMDECHO 1)
    (vla-endundomark doc)
    (princ))
  
  (vla-startundomark (setq doc (vla-get-activedocument (vlax-get-acad-object))))
  (setq oAUNITS (getvar 'AUNITS))
  (setq oOSMODE (getvar 'OSMODE))
  (setq oCLAYER (getvar 'CLAYER))
  (setvar 'CMDECHO 0)
  (setvar 'AUNITS 1)
  (setvar 'OSMODE 0)

  
  (if (and (princ "\nSingle line needed,")
	   (setq ss (ssget "_+.:E:S" '((0 . "LINE"))))
	   (setq pt1 (cdr (assoc 10 (entget (ssname ss 0))))
		 pt2 (cdr (assoc 11 (entget (ssname ss 0)))))
	   (not (command "_.-LAYER" "_M" "s-plan-rcol" "")))
    (if (eq (car pt1) (car pt2))
      (progn ;Vertical
	(initget "No Right")
	(setq mirr (getkword "\nPlace blocks left? [no, Right] <left>: "))
	(command "_.-INSERT" "4x6" (polar pt1 0 -2) 1 "" 270)
	(if mirr (command "_.MIRROR" "_L" "" pt1 pt2 "_Y"))
	(command "_.MIRROR" "_L" "" "_m2p" pt1 pt2 "@1<0" "_N"))
      (progn ;Horizontal
	(initget "No Up")
	(setq mirr (getkword "\nPlace blocks down? [no, Up] <down>: "))
	(command "_.-INSERT" "4x6" (polar pt1 (/ pi 2) -2) 1 "" 0)
	(if mirr (command "_.MIRROR" "_L" "" pt1 pt2 "_Y"))
	(command "_.MIRROR" "_L" "" "_m2p" pt1 pt2 "@1<90" "_N"))))

  
  (setvar 'AUNITS oAUNITS)
  (setvar 'OSMODE oOSMODE)
  (setvar 'CLAYER oCLAYER)
  (setvar 'CMDECHO 1)
  (vla-endundomark doc)
  (princ)
)
0 Likes
Message 9 of 41

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

I think I can imagine a simpler way, but first:  Where is the Insertion Point in the Block, and how is it oriented at zero rotation?  Is it the actual size of a piece of 4x6 lumber [3-1/2 x 5-1/2], or is it truly 4 drawing units x 6 drawing units in size?


From some things in Post 3 I think the Block at zero rotation is vertically oriented with its insertion point at the upper left corner.  I will assume that it represents the actual size of nominal 4x6 lumber.

 

The whole operation would be significantly simpler if you have a Block that looks like this [only the yellow and blue parts would be the actual Block content] at zero rotation and scale factors of 1:

 

4x6.png

 

Call it something different, such as ShearPost, if you want to retain your 4x6 Block definition with its [I think] corner insertion point.  That can be used as a nested Block in this new Block definition.

Kent Cooper, AIA
0 Likes
Message 10 of 41

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

....

The whole operation would be significantly simpler if you have a Block that looks like this ....


The gist of it, after all the preliminaries, controls, etc., given a Block defined as suggested, and if 'ent' is a variable holding the ENTity name of the selected Line:

 

(setq

  edata (entget ent)

  pt1 (cdr (assoc 10 edata)); start

  pt2 (cdr (assoc 11 edata)); end

  side (getpoint pt1 "\nPick to side of Line on which to add shear posts: ")

  rot (* (/ (angle (vlax-curve-getClosestPointTo ent side T)) pi) 180); ROTation angle for Insert commands

); setq

(command

  "_.insert" "ShearPost"

    "_none" (polar pt1 (angle pt1 pt2) 1.75); half-post-width in from start

    "" "" rot

  "_.insert" ""

    "_none" (polar pt2 (angle pt2 pt1) 1.75); from other end

    "" "" rot

); command

Kent Cooper, AIA
0 Likes
Message 11 of 41

Anonymous
Not applicable

Thanks for your help.

 

The 4x6 that is being used is 3 1/2" x 5 1/2".  The insertion point is the top left corner but can be where ever. renaming the post is fine as well. 

 

I noticed that when it is isn't placing the post correctly it seems to be because of the ucs is at play. in other words can we write in "ucs" "object"  "world"  and then have it reconize that selected pick of which side of the line as being "x" positive or negative and likewise for "y".  I would think this would help with proper orientation and placement?  just a thought.

 

 

0 Likes
Message 12 of 41

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... 

I noticed that when it is isn't placing the post correctly it seems to be because of the ucs is at play. in other words can we write in "ucs" "object"  "world"  and then have it reconize that selected pick of which side of the line as being "x" positive or negative and likewise for "y".  I would think this would help with proper orientation and placement?  just a thought.


My suggestion does assume the World Coordinate System.  [The UCS command should have either the "object" option or the "world" option, but not both.]  If you do work in other UCS's, it could be made to account for that.  But my suggestion, including the different Block definition, would eliminate any need to deal with whether the X and/or Y scale factors should be positive or negative [that's exactly the reason for suggesting the different Block definition, and why I said it would be so much simpler that way].  So if your overall work is always in the WCS, no messing with a temporary UCS based on the Line object would be necessary.

Kent Cooper, AIA
0 Likes
Message 13 of 41

Anonymous
Not applicable

ok, so I will create a new block and call it "shearpost" with the insertion point as you have shown it.  Do I edit the orginal lisp that I received from BeekeeCZ with the info you added below?  or could you post the completed lisp?  I'm just so new to this that I'm afraid I would edit it incorrectly.

 

 

0 Likes
Message 14 of 41

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

ok, so I will create a new block and call it "shearpost" with the insertion point as you have shown it.  ....  could you post the completed lisp?  ....


First, try this bare-bones version.  Make sure you're in the WCS first, and that you do, in fact, successfully select a Line object.  If it does what you want, the error handling, and verification of appropriate selection, and Undo begin/end, and UCS and/or Layer control if you want, and all that other stuff, can be added.

 

(defun C:TEST (/ esel ent edata pt1 pt2 side rot)

  (setq

    esel (entsel "\nSelect Line at which to add Shear Posts: ")

    ent (car esel)

    edata (entget ent)

    pt1 (cdr (assoc 10 edata)); start

    pt2 (cdr (assoc 11 edata)); end

    side (getpoint pt1 "\nPick to side of Line on which to add shear posts: ")

    rot (* (/ (angle (vlax-curve-getClosestPointTo ent side T)) pi) 180); ROTation angle for Insert commands

  ); setq

  (command

    "_.insert" "ShearPost"

      "_none" (polar pt1 (angle pt1 pt2) 1.75); half-post-width in from start

      "" "" rot

    "_.insert" ""

      "_none" (polar pt2 (angle pt2 pt1) 1.75); from other end

      "" "" rot

  ); command

); defun

Kent Cooper, AIA
0 Likes
Message 15 of 41

Anonymous
Not applicable

[cid:image001.png@01D0C2CB.78A40870]



[cid:image002.jpg@01D007E9.091AA560]

Edited by
Discussion_Admin

0 Likes
Message 16 of 41

Anonymous
Not applicable

I receive this error...  

;error: too few arguements.. 

 

 

0 Likes
Message 17 of 41

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

I receive this error...  

;error: too few arguements.. 

 

 


Sorry [that's what I get for not actually testing it]....  Change this:

 

rot (* (/ (angle (vlax-curve-getClosestPointTo ent side T)) pi) 180); ROTation angle for Insert commands

 

to this:

 

rot (* (/ (angle (vlax-curve-getClosestPointTo ent side T) side) pi) 180); ROTation angle for Insert commands

Kent Cooper, AIA
0 Likes
Message 18 of 41

Anonymous
Not applicable

ok, 

on a line drawn from left to right; it only places the posts under the line. Regardless of what side of the line I pick.

on a line drawn from right to left it isn't rotating the posts. 

 

Since often times I am working with incoming drawings there is no way to control the directions with which the lines are drawn.   

 

when it comest to a vertical line they aren't not being rotated and placed.

 

 

 

 

0 Likes
Message 19 of 41

Kent1Cooper
Consultant
Consultant

So I broke down and set up the situation.  With the correction in Post 17, it works flawlessly for me.  I'm not sure this will account for it, but have you perhaps defined your Block for uniform scaling [available in newer versions of AutoCAD than the one I have here]?  If so, it will ask for only one scale factor, so change this [twice]:

 

"" "" rot

 

to this:

 

"" rot

Kent Cooper, AIA
0 Likes
Message 20 of 41

Anonymous
Not applicable

I'm using Autocad 2015 architectural..  and I have no idea why it isn't working for me.

 

  I made the change from your last post but to no avail . It seems as though we are close but I don't know what the problem is.  You say it works great for you.. I have no clue what's different between us but thanks for you help anyway.

 

 

 

 

 

0 Likes