Insert a block on a 3D position

Insert a block on a 3D position

Gdtech-Autocad
Explorer Explorer
656 Views
10 Replies
Message 1 of 11

Insert a block on a 3D position

Gdtech-Autocad
Explorer
Explorer

Hello

A drawing contains a block. I want to insert another block at the same position and rotation angle of this block using AutoLisp. It very seems simple no ?

When I make LIST of this entity I get the Insertion point:  X = 200.0000  Y = 100.0000  Z = 300.0000 which are the coordinates relative to the World UCS. The Rotation is 90°

I get the insertion point using Autolisp :

 

(setq ent(entsel "\n Select an entity: ")) ;- Let the user select a block
(setq en(car ent))                         ;- Get the entity name of the block
(setq enlist(entget en))                   ;- Get the DXF group codes
(princ "\n Entity DXF codes : ")(princ enlist)

I get this :

Entity DXF codes : ((-1 . <Entity name: b9c47cb0>) (0 . INSERT) (5 . 424) (330 . <Entity name: a6540540>) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbBlockReference) (2 . TE_DN150_P) (10 -100.000 300.000 -200.000) (41 . 1.00000) (42 . 1.00000) (43 . 1.00000) (50 . 1.57080) (70 . 1) (71 . 1) (44 . 0.E+00) (45 . 0.E+00) (210 -1.00000 0.E+00 0.E+00))

 

To get the insertion point

(setq po(cdr (assoc 10 enlist)))
(princ "\n Insertion point: ")(princ po)

 

The result is -100.000 300.000 -200.000

If I use the INSERT command to insert another block at this position it will be wrong.

 

Use the trans function perhaps ?

(setq pt (trans po 0 1))
(princ "\n Corrected insertion point: ")(princ pt)

 

The result is still the same : -100.000 300.000 -200.000

Of course, I know, the problem is between to keyboard and the seat ….  

My question : how can I get the right insertion point and rotation angle to INSERT a new block at the same location ?

 

Thanks for your help.

0 Likes
Accepted solutions (1)
657 Views
10 Replies
Replies (10)
Message 2 of 11

paullimapa
Mentor
Mentor

should work...could you share the dwg including the block you want to insert?


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 3 of 11

Gdtech-Autocad
Explorer
Explorer

Hello 

Thanks a lot for your response.

This is the file containing the block.

The corrected insertion point is not correct with this code :

 

(defun c:RPB()
  (setq ent(entsel "\n Select an entity: ")) ;- Let the user select a block 
  (setq en(car ent))                   ;- Get the entity name of the block
  (princ "\n Entity name : ")(princ en)
  (setq enlist(entget en))             ;- Get the DXF group codes
  (princ "\n Entity DXF codes : ")(princ enlist)
  (setq bn (cdr(assoc 2 enlist)))
  (princ "\n Block name: ")(princ bn)
  (setq po(cdr (assoc 10 enlist)))
  (princ "\n Insertion point: ")(princ po)
  ;==============================================================
  (setq pt (trans po 1 0))
  (princ "\n Corrected insertion point : ")(princ pt)
)
0 Likes
Message 4 of 11

paullimapa
Mentor
Mentor

looks like when the block object has been rotated in any of the other axis (x, y or z), then this code is no longer correct to get the insertion point:

(setq po(cdr(assoc 10(entget(car(entsel))))))

so you can use the following code to check the normx, normy & normz values to see if they're other than +0:

(setq en(car(entsel))) ; select entity
(setq normx (getpropertyvalue en "Normal/X") normy (getpropertyvalue en "Normal/Y") normz (getpropertyvalue en "Normal/Z")) ; get normal

or just always use the following code to get the insertion point regardless of normal x, y, z:

(setq en(car(entsel))) ; select entity
(setq po(list (getpropertyvalue en "Position/X") (getpropertyvalue en "Position/Y") (getpropertyvalue en "Position/Z"))) ; get insert point

if you're interested, the vl method is this:

(vl-load-com)
(setq obj (vlax-ename->vla-object (car(entsel)))) ; select entity and convert to vl obj
(setq norm (vlax-safearray->list (vlax-variant-value (vla-get-Normal obj)))) 
(setq normx (car norm) normy (cadr norm) normz (caddr norm)) ; get the normal x,y,z
(setq po(vlax-safearray->list (variant-value (vla-get-InsertionPoint obj)))) ; get insert point

 

 

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 5 of 11

hmsilva
Mentor
Mentor

@Gdtech-Autocad INSERTS DXF 10 are in OCS.

To get the coordenates in WCS, change:

(setq pt (trans po 1 0))

to

(setq pt (trans po (car ent) 0))

 

Hope this helps,
Henrique

EESignature

Message 6 of 11

Gdtech-Autocad
Explorer
Explorer

Hello thanks for your help ! This is working :

(setq pt (trans po (car ent) 0))

The point pt is correct ! fantastic.

I would like to insert a new block at the same position and rotation of the original block. With the code below, the new block is inserted at the right position but not correctly rotated.

(defun c:RPB()
  (setq ent(entsel "\n Select an entity: ")) ;- Let the user select a block 
  (setq en(car ent))                   ;- Get the entity name of the block
  (princ "\n Entity name : ")(princ en)
  (setq enlist(entget en))             ;- Get the DXF group codes
  (princ "\n Entity DXF codes : ")(princ enlist)
  (setq bn (cdr(assoc 2 enlist)))
  (princ "\n Block name: ")(princ bn)
  (setq po(cdr (assoc 10 enlist))) ; OCS insertion point
  (setq pt (trans po (car ent) 0)) ; WCS insertion point
  (princ "\n WCS insertion point : ")(princ pt)
  ;==============================================================
  (setq rt(cdr (assoc 50 enlist))) ; rotation angle
  (setq rd (* rt (/ 180.0 pi)))
  (princ "\n rotation angle : ")(princ rd)
  (setq nb "TE_DN150_V") ; new block to insert
  (command "INSERT" nb pt "1" "1" rd)
)

Thanks for your time

 

0 Likes
Message 7 of 11

ВeekeeCZ
Consultant
Consultant

If are all properties the same but the blockname, you can simply rename it.

 

(vla-put-name (vlax-ename->vla-object (car (entsel "Old:"))) (cdr (assoc 2 (entget (car (entsel "New:"))))))

 

See  THIS recent thread.

Message 8 of 11

Gdtech-Autocad
Explorer
Explorer

yes there is also the BLOCKREPLACE command.

But in this case I want to add a new block, not replace the existing one.

Thanks

0 Likes
Message 9 of 11

ВeekeeCZ
Consultant
Consultant

Well, that's a pretty similar job to do - just 3 letters difference.

 

(defun c:bladd ( / e d n)
  (if (and (setq e (car (entsel "\nOld: ")))
	   (setq d (entget e))
	   (setq n (car (entsel "\nNew: ")))
	   )
    (entmake (subst (assoc 2 (entget n)) (assoc 2 d) d)))
  (princ)
  )

(defun c:blrep ( / e d n)
  (if (and (setq e (car (entsel "\nOld: ")))
	   (setq d (entget e))
	   (setq n (car (entsel "\nNew: ")))
	   )
    (entmod (subst (assoc 2 (entget n)) (assoc 2 d) d)))
  (princ)
  )

 

Message 10 of 11

Gdtech-Autocad
Explorer
Explorer

That's another way to proceed. And it works fine ! Thank you

To go further the idea is:

in the drawing select all blocks which have the name "TE_DN150_P"

at each position of these blocks (but on another layer) insert the block "TE_DN150_V" which is not in the drawing but must be inserted from the disk. This is the code that must be adapted. I suppose that the block must first be inserted in the drawing with the INSERT COMMAND. And then I do no know how to do...

(defun c:rab ()
  (setq nbn ("c:\\_DATA\\Bib\\TE_DN150_V")) ; new block name
  (setq sset (ssget "X" (list '(0 . "INSERT") '(2 . "*"))))
  (setq ne (sslength sset))
  (princ "\n====== Objects selected : ")(princ ne)
  (setq index 0)
  
  (while (< index ne)
    (setq ent (ssname sset index)) 
    (setq e (entget ent))
    (command "INSERT" nbn "0,0" "" "" "") ; first insert block from the disk
    (command "erase" "L" "") ; erase the inserted block
    ; missing code....
    (entmake (subst (assoc 2 (entget n)) (assoc 2 d) d)))
    (setq index (+ 1 index))
  )
 )

 

 

 

0 Likes
Message 11 of 11

ВeekeeCZ
Consultant
Consultant
Accepted solution

What this note means: but on another layer

 

If you don't want to change the layer, you can use this

 

(defun c:bladda ( / o n p i s)

  (setq o "TE_DN150_P"
	n "TE_DN150_V"
	p "c:\\_DATA\\Bib\\")
  
  (or (tblsearch "block" n)
      (progn (command "_.-insert" (strcat p n)) (command)))

  (if (setq s (ssget "X" (list '(0 . "INSERT") (cons 2 o))))
    (repeat (setq i (sslength s))
      (entmake (subst (cons 2 n) (cons 2 o) (entget (ssname s (setq i (1- i))))))))
  (princ)
  )