Author Topic: Insert Enhanced Block (with ATTDEF) using entmake  (Read 4171 times)

0 Members and 1 Guest are viewing this topic.

JohnSnow

  • Newt
  • Posts: 52
Insert Enhanced Block (with ATTDEF) using entmake
« on: August 21, 2018, 03:22:38 AM »
Hi Guys,

I am wondering how we can insert an enhanced block using entmake method.
So the structure is like this
(entmake (list (cons 0 "BLOCK") (cons 2 "B1")...))
(entmake (list (cons 0 "ATTDEF") (cons 1 p1) (cons 1 "Test") (cons 2 "This is Tag") (cons 3 "This is promp")...))
(entmake (list (cons 0 "ENDBLK")))

So I have tried (entmake (list (cons 0 "INSERT") (cons 2 "B1") (cons 10 p1) (cons 50 0))) but it doen't work..
if I tried command method (command "insert" "B1" p1 1 1 0 "") It works.
Does anyone know how to do this using entmake?
Thanks

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Insert Enhanced Block (with ATTDEF) using entmake
« Reply #1 on: August 21, 2018, 03:38:06 AM »
Hi,

It looks like you're confusing attribute definition (ATTDEF) and attribute reference (ATTRIB).
An attribute definition is an entity owned by a block definition which serves as pattern to create attribute references. Attribute references are entities linked to block reference.

To enmake an attributed block reference, the pseudo code is
entmake INSERT
[entmake ATTRIB ...]
entmake SEQEND

You should get some inspiration from this routine.

<EDIT: added zScale arg>
Code - Auto/Visual Lisp: [Select]
  1. ;;; InsertBlockWithAttributes (Gilles Chanteau)
  2. ;;; Creates a new block reference with attributes using entmake
  3. ;;;
  4. ;;; Arguments
  5. ;;; blockName : name of the block definition
  6. ;;; inspt     : insertion point
  7. ;;; layer     : insertion layer
  8. ;;; xScale    : X scale
  9. ;;; yScale    : Y scale
  10. ;;; zScale    : Z scale
  11. ;;; rotation  : rotation (radians)
  12. ;;; attribs   : list of dotted pairs containing the attribute values (TAG . Value)
  13. (defun InsertBlockWithAttributes (blockName insPt layer xScale yScale zScale rotation attribs / mxv block ent attDefs tag elst)
  14.  
  15.   (defun mxv (m v)
  16.     (mapcar (function (lambda (r) (apply '+ (mapcar '* r v))))
  17.             m
  18.     )
  19.   )
  20.  
  21.   (if (setq block (tblsearch "block" blockName))
  22.     (progn
  23.       (setq ent   (cdr (assoc -2 block))
  24.             xform (list (list (* xScale (cos rotation)) (* xScale (- (sin rotation))) 0.)
  25.                         (list (* yScale (sin rotation)) (* yScale (cos rotation)) 0.)
  26.                         (list 0. 0. zScale)
  27.                   )
  28.       )
  29.       (while ent
  30.         (if (= "ATTDEF" (cdr (assoc 0 (setq elst (entget ent)))))
  31.           (setq attDefs (cons (cons (cdr (assoc 2 elst)) elst) attDefs))
  32.         )
  33.         (setq ent (entnext ent))
  34.       )
  35.       (entmakex
  36.         (list
  37.           (cons 0 "INSERT")
  38.           (cons 8 layer)
  39.           (cons 66 1)
  40.           (cons 2 blockName)
  41.           (cons 10 insPt)
  42.           (cons 41 xScale)
  43.           (cons 42 yScale)
  44.           (cons 43 zScale)
  45.           (cons 50 rotation)
  46.         )
  47.       )
  48.  
  49.       (foreach att (reverse attDefs)
  50.         (setq tag  (car att)
  51.               elst (cdr att)
  52.         )
  53.         (entmakex
  54.           (list
  55.             (cons 0 "ATTRIB")
  56.             (cons 100 "AcDbEntity")
  57.             (assoc 8 elst)
  58.             (cons 100 "AcDbText")
  59.             (cons 10 (mapcar '+ inspt (mxv xform (cdr (assoc 10 elst)))))
  60.             (cons 40 (* yScale (cdr (assoc 40 elst))))
  61.             (cons 1
  62.                   (cond ((cdr (assoc tag attribs)))
  63.                         (T (cdr (assoc 1 elst)))
  64.                   )
  65.             )
  66.             (cons 50 rotation)
  67.             (cons 41 (/ xScale yscale))
  68.             (assoc 51 elst)
  69.             (assoc 7 elst)
  70.             (assoc 72 elst)
  71.             (cons 11 (mapcar '+ inspt (mxv xform (cdr (assoc 11 elst)))))
  72.             (cons 100 "AcDbAttribute")
  73.             (assoc 280 elst)
  74.             (cons 2 tag)
  75.             (assoc 70 elst)
  76.             (assoc 74 elst)
  77.             (assoc 280 (reverse elst))
  78.           )
  79.         )
  80.       )
  81.       (entmakex '((0 . "SEQEND")))
  82.       (entlast)
  83.     )
  84.   )
  85. )
« Last Edit: August 21, 2018, 10:13:05 AM by gile »
Speaking English as a French Frog

JohnSnow

  • Newt
  • Posts: 52
Re: Insert Enhanced Block (with ATTDEF) using entmake
« Reply #2 on: August 21, 2018, 07:59:24 AM »
Hi,

It looks like you're confusing attribute definition (ATTDEF) and attribute reference (ATTRIB).
An attribute definition is an entity owned by a block definition which serves as pattern to create attribute references. Attribute references are entities linked to block reference.

To enmake an attributed block reference, the pseudo code is
entmake INSERT
[entmake ATTRIB ...]
entmake SEQEND

You should get some inspiration from this routine.

Code - Auto/Visual Lisp: [Select]
  1. ;;; InsertBlockWithAttributes (Gilles Chanteau)
  2. ;;; Creates a new block reference with attributes using entmake
  3. ;;;
  4. ;;; Arguments
  5. ;;; blockName : name of the block definition
  6. ;;; inspt     : insertion point
  7. ;;; layer     : insertion layer
  8. ;;; xScale    : X scale
  9. ;;; yScale    : Y scale
  10. ;;; rotation  : rotation (radians)
  11. ;;; attribs   : list of dotted pairs containing the attribute values (TAG . Value)
  12. (defun InsertBlockWithAttributes (blockName insPt layer xScale yScale rotation attribs / mxv block ent attDefs insert tag elst)
  13.  
  14.   (defun mxv (m v)
  15.     (mapcar (function (lambda (r) (apply '+ (mapcar '* r v))))
  16.             m
  17.     )
  18.   )
  19.  
  20.   (if (setq block (tblsearch "block" blockName))
  21.     (progn
  22.       (setq ent   (cdr (assoc -2 block))
  23.             xform (list (list (* xScale (cos rotation)) (* xScale (- (sin rotation))) 0.)
  24.                         (list (* yScale (sin rotation)) (* yScale (cos rotation)) 0.)
  25.                         (list 0. 0. 1.)
  26.                   )
  27.       )
  28.       (while ent
  29.         (if (= "ATTDEF" (cdr (assoc 0 (setq elst (entget ent)))))
  30.           (setq attDefs (cons (cons (cdr (assoc 2 elst)) elst) attDefs))
  31.         )
  32.         (setq ent (entnext ent))
  33.       )
  34.       (setq insert (entmakex
  35.                      (list
  36.                        (cons 0 "INSERT")
  37.                        (cons 8 layer)
  38.                        (cons 66 1)
  39.                        (cons 2 blockName)
  40.                        (cons 10 insPt)
  41.                        (cons 41 xScale)
  42.                        (cons 42 yScale)
  43.                        (cons 43 1.0)
  44.                        (cons 50 rotation)
  45.                      )
  46.                    )
  47.       )
  48.  
  49.       (foreach att (reverse attDefs)
  50.         (setq tag  (car att)
  51.               elst (cdr att)
  52.         )
  53.         (entmakex
  54.           (list
  55.             (cons 0 "ATTRIB")
  56.             (cons 100 "AcDbEntity")
  57.             (assoc 8 elst)
  58.             (cons 100 "AcDbText")
  59.             (cons 10 (mapcar '+ inspt (mxv xform (cdr (assoc 10 elst)))))
  60.             (cons 40 (* yScale (cdr (assoc 40 elst))))
  61.             (cons 1
  62.                   (cond ((cdr (assoc tag attribs)))
  63.                         (T (cdr (assoc 1 elst)))
  64.                   )
  65.             )
  66.             (cons 50 rotation)
  67.             (cons 41 (/ xScale yscale))
  68.             (assoc 51 elst)
  69.             (assoc 7 elst)
  70.             (assoc 72 elst)
  71.             (cons 11 (mapcar '+ inspt (mxv xform (cdr (assoc 11 elst)))))
  72.             (cons 100 "AcDbAttribute")
  73.             (assoc 280 elst)
  74.             (cons 2 tag)
  75.             (assoc 70 elst)
  76.             (assoc 74 elst)
  77.             (assoc 280 (reverse elst))
  78.           )
  79.         )
  80.       )
  81.       (entmakex '((0 . "SEQEND")))
  82.       (entlast)
  83.     )
  84.   )
  85. )


Thanks Gile. Very helpful information. Sounds a bit tricky.

One thing I don't quite understand is what are the group codes like 2, 3, 40 in ATTDEF for? I know they mean tag, promp and height but when we entmake ATTRIB they will be override.

For example,

if I do (entmake (list (cons 0 "ATTDEF") (cons 10 p1) (cons 70 0) (cons 1 "") (cons 2 "ID") (cons 3 "ID INPUT") (cons 40 3) ))

follow by (entmake (list (cons 0 "ATTRIB") (cons 10 p1) (cons 1 "THIS IS A TEST") (cons 2 "New Tag") (cons 40 2.5) (cons 70 0)))

The tag of the block will be "New Tag" instead of "ID" and the promp "ID INPUT" that I defined in ATTDEF does not exist anymore. So does that mean we can put whatever in group codes 2, 3, 40 etc in ATTDEF considering they will be replaced by ATTRIB anyway?

Just a bit confused by that.

« Last Edit: August 21, 2018, 08:04:57 AM by JohnSnow »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Insert Enhanced Block (with ATTDEF) using entmake
« Reply #3 on: August 21, 2018, 08:47:13 AM »
As said upper the attribute definition is a template sort of. At this programming level, there's none automatic link between an attribute defininition and an attribute reference.
You can create a block reference which do not have any attribute reference despite the block definition contains attribute definitions. And, as you noticed, you can also create a block reference which have attribute references different from the attribute definitions contained in the block definition.
At upper level, the ATTSYNC command re-creates the attribute references according to the attribute definitions, as done with the code I posted  (in the (foreach att (reverse attDefs) ...) loop, the 'elst' variable is a list containing the DXF data of the attribute definitions used to 'entmake' the attribute reference).
« Last Edit: August 21, 2018, 09:12:05 AM by gile »
Speaking English as a French Frog

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Insert Enhanced Block (with ATTDEF) using entmake
« Reply #4 on: August 24, 2018, 07:25:07 AM »
Thumbs up for the subfoo Gile, I didn't knew such thing already existed !
This was my attempt from the last year -

Code - Auto/Visual Lisp: [Select]
  1. ; (VanillaINSERT (getpoint) "VLD_Tag" (getvar 'ctab))
  2. (defun VanillaINSERT ( p nm spc / GetBlkAttDefProps atts r )
  3.   ; '(87 114 105 116 116 101 110 32 66 121 32 71 114 114 114)
  4.   (setq GetBlkAttDefProps
  5.     (lambda ( bnm / e enx typ L )
  6.       (and
  7.         (setq e (tblobjname "BLOCK" bnm))
  8.         (= 2 (logand 2 (cdr (assoc 70 (setq enx (entget e))))))
  9.         (setq e (cdr (assoc -2 enx)))
  10.         (while (and e (setq enx (entget e)) (/= "SEQEND" (setq typ (cdr (assoc 0 enx)))))
  11.           (if (= "ATTDEF" typ) (setq L (cons (vl-remove-if-not (function (lambda (x) (member (car x) '(1 2 3 7 10 11 40)))) enx) L)))
  12.           (setq e (entnext e))
  13.         ); while
  14.       ); and
  15.       (reverse L)
  16.     ); lambda
  17.   ); setq GetBlkAttDefProps
  18.  
  19.   (cond
  20.     ( (tblsearch "BLOCK" nm) (setq atts (GetBlkAttDefProps nm))
  21.       (if
  22.         (setq r
  23.           (mapcar 'entmake
  24.             (append
  25.               (list
  26.                 (append
  27.                   '((0 . "INSERT")(100 . "AcDbEntity")(67 . 0)) (list (cons 410 spc)) (list (cons 8 (getvar 'clayer))) '((100 . "AcDbBlockReference"))
  28.                   (list (cons 66 (if atts 1 0)) (cons 2 nm) (cons 10 p))
  29.                   '((41 . 1.)(42 . 1.)(43 . 1.)(50 . 0.0)(70 . 0)(71 . 0)(44 . 0.0)(45 . 0.0)(210 0.0 0.0 1.0))
  30.                 ); append
  31.               ); list
  32.               (if atts  
  33.                 (mapcar
  34.                   (function
  35.                     (lambda (x / pt10 pt11 )
  36.                       (setq pt10 (mapcar '+ p (cdr (assoc 10 x))))
  37.                       (setq pt11 (mapcar '+ p (cdr (assoc 11 x))))
  38.                       (append
  39.                         '((0 . "ATTRIB")(100 . "AcDbEntity")(67 . 0))
  40.                         (list (cons 410 spc))
  41.                         '((8 . "0"))
  42.                         '((100 . "AcDbText"))
  43.                         (list (cons 10 pt10))
  44.                         (list (assoc 40 x))
  45.                         (list (assoc 1 x))
  46.                         '((50 . 0.0)(41 . 1.0)(51 . 0.0))
  47.                         (list (cons 7 (cond ((cdr (assoc 7 x))) ("Standard"))))
  48.                         '((71 . 0)(72 . 1))
  49.                         (list (cons 11 pt11))
  50.                         '((210 0.0 0.0 1.0)(100 . "AcDbAttribute")(280 . 0)) (list (assoc 2 x)) '((70 . 0)(73 . 0)(74 . 2)(280 . 1))
  51.                       ); append
  52.                     ); lambda (x)
  53.                   ); function
  54.                   atts
  55.                 ); mapcar
  56.               ); if atts
  57.               (list (append '((0 . "SEQEND")(100 . "AcDbEntity")(67 . 0)) (list (cons 410 spc)) '((8 . "0")) ))
  58.             ); append
  59.           ); mapcar
  60.         ); setq r
  61.         ( (lambda ( c / ) (setvar 'cmdecho 0) (if acet-attsync (acet-attsync nm) (vl-cmdf "_.ATTSYNC" "_N" nm)) (setvar 'cmdecho c)) (getvar 'cmdecho) )
  62.       ); if
  63.       r
  64.     ); (tblsearch "BLOCK" nm)
  65.   ); cond
  66. ); defun VanillaINSERT

Example call:
Code - Auto/Visual Lisp: [Select]
  1. (VanillaINSERT (getpoint "\nSpecify insertion point: ") "MyBlockName" (getvar 'ctab))
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

amhere

  • Mosquito
  • Posts: 8
Re: Insert Enhanced Block (with ATTDEF) using entmake
« Reply #5 on: January 19, 2024, 12:33:39 AM »

;;; attribs   : list of dotted pairs containing the attribute values (TAG . Value)


Hi Sir,
Can you give me a example code that uses this "attribs" variable to create a block with name: "MV", tagname: "XYScale", value: "10x2"?
I only know a little about lisp.

dexus

  • Bull Frog
  • Posts: 204
Re: Insert Enhanced Block (with ATTDEF) using entmake
« Reply #6 on: January 19, 2024, 02:20:00 AM »

;;; attribs   : list of dotted pairs containing the attribute values (TAG . Value)


Hi Sir,
Can you give me a example code that uses this "attribs" variable to create a block with name: "MV", tagname: "XYScale", value: "10x2"?
I only know a little about lisp.
Nice function gile!
And nice of you to find it amhere.

Here is an example of your question:
Code - Auto/Visual Lisp: [Select]
  1. (insertblockwithattributes
  2.   "MV"      ; blockName
  3.   '(0 0 0)  ; insertion point
  4.   "0"       ; insertion layer
  5.   1.0       ; X scale
  6.   1.0       ; Y scale
  7.   0         ; rotation (radians)
  8.   (list     ; attribs
  9.     (cons "XYScale" "10x2")
  10.     (cons "Tagname" "Value") ; Example how to add more than one
  11.   )
  12. )

amhere

  • Mosquito
  • Posts: 8
Re: Insert Enhanced Block (with ATTDEF) using entmake
« Reply #7 on: January 19, 2024, 03:01:44 AM »
Thank you so much, dexus!