Author Topic: remake blocks with attributes  (Read 2198 times)

0 Members and 1 Guest are viewing this topic.

curmudgeon

  • Newt
  • Posts: 194
remake blocks with attributes
« on: March 19, 2019, 10:12:25 PM »
Working in Autocad 2000. Large floor plans with RMUSAGE blocks - two attributes of text description, one for a room number, one for an area, and one piece of text. Over time, the attributes have been moved without moving the block - there is no nontext entity.

The attached file, reblk.lsp, I massaged from some example code. It runs. It works.
But the file gets larger, exponentially.

Why does the file keep getting larger? There is no new data.
The files recover without finding any errors, but the objects in the handle table increase faster than the number of blocks remade.
Never express yourself more clearly than you are able to think.

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: remake blocks with attributes
« Reply #1 on: March 20, 2019, 01:49:37 AM »
Here is my observation, but without example DWG its hard to tell and test...

Code - Auto/Visual Lisp: [Select]
  1. (defun c:resetattribpositioninblock ( / mxv thisblock blockname block b_ename enxt ss taglist namelist attribs elst insPt attDefs layer xScale yScale zScale ent tag xform rotation )
  2.  
  3. (defun mxv ( m v ) (mapcar (function (lambda ( r ) (apply '+ (mapcar '* r v)))) m))
  4.  
  5. (setq thisblock (entget (car (entsel "\nPick Block")))
  6.       blockname (cdr (assoc 2 thisblock))
  7.       block     (tblsearch "block" blockname)
  8.       b_ename   (cdr (assoc -2 block))
  9.       enxt      (entnext (cdr (assoc -1 thisblock)))
  10.       ss        (ssadd)
  11.       insPt     (cdr (assoc 10 thisblock)) ;; I think this was wrong (setq insPt (cdr (assoc 10 (entget enxt)))) IMHO
  12.       )
  13.  
  14. (while (= "ATTRIB" (cdr (assoc 0 (entget enxt))))
  15.   (ssadd enxt ss)
  16.   (setq enxt (entnext enxt))
  17. );; ss selection set of attribute enames thisblock
  18.  
  19. (while (ssname ss 0)
  20.   (setq namelist (append namelist (list (cdr (assoc 1 (entget (ssname ss 0)))))))
  21.   (setq taglist (append taglist (list (cdr (assoc 2 (entget (ssname ss 0)))))))
  22.   (ssdel (ssname ss 0) ss)
  23. );; list of attribute values to save
  24.  
  25. (setq attribs (mapcar 'cons taglist namelist)
  26.       xScale (cdr (assoc 41 thisblock)) yScale (cdr (assoc 42 thisblock)) zScale (cdr (assoc 43 thisblock)) rotation (cdr (assoc 50 thisblock)) layer (cdr (assoc 8 thisblock))
  27.       ent   (cdr (assoc -2 block))
  28.       xform (list
  29.               (list (* xScale (cos rotation)) (* xScale (- (sin rotation))) 0.0)
  30.               (list (* yScale (sin rotation)) (* yScale (cos rotation)) 0.0)
  31.               (list 0.0 0.0 zScale)
  32.             )
  33.       )
  34.  
  35. (while ent
  36.   (if (= "ATTDEF" (cdr (assoc 0 (setq elst (entget ent)))))
  37.             (setq attDefs (cons (cons (cdr (assoc 2 elst)) elst) attDefs)))
  38.             (setq ent (entnext ent))
  39.           )
  40.  
  41. ;; before you make new reference, I think you should remove old one
  42. (entdel (cdr (assoc -1 thisblock))) ;; my mod...
  43.  
  44.   (list (cons 0 "INSERT") (cons 8 layer) (cons 66 1) (cons 2 blockname)
  45.         (cons 10 insPt) (cons 41 xScale) (cons 42 yScale) (cons 43 zScale) (cons 50 rotation))
  46.   )
  47.  
  48. (foreach att (reverse attDefs)
  49.   (setq tag  (car att) elst (cdr att)
  50.         )
  51. (entmakex (list (cons 0 "ATTRIB") (cons 100 "AcDbEntity") (assoc 8 elst)
  52.                 (cons 100 "AcDbText") (cons 10 (mapcar '+ insPt (mxv xform (cdr (assoc 10 elst)))))
  53.                 (cons 40 (* yScale (cdr (assoc 40 elst))))
  54.                 (cons 1 (cond ((cdr (assoc tag attribs)))
  55.                             (T (cdr (assoc 1 elst)))))
  56.                 (cons 50 (+ (cdr (assoc 50 elst)) rotation)) (cons 41 1) (assoc 51 elst) (assoc 7 elst) (assoc 72 elst)
  57.                 (cons 11 (mapcar '+ insPt (mxv xform (cdr (assoc 11 elst)))))
  58.                 (cons 100 "AcDbAttribute") (cons 2 tag) (assoc 70 elst) (assoc 74 elst)
  59.                 )
  60.             )
  61.   )
  62. (entmakex '((0 . "SEQEND")))
  63. ;|
  64. (entmake (list '(0 . "CIRCLE") '(100 . "AcDbEntity")'(8 .  "TEXT") '(62 . 1) '(100 . "AcDbCircle")
  65.         (cons 10 insPt) '(40 . 8)))
  66. |;
  67. )
  68.  
  69. (defun c:resetattribpositioninblockmultiple ( / resetattribpositioninblock ss i )
  70.  
  71. (defun resetattribpositioninblock ( e / mxv thisblock blockname block b_ename enxt ss taglist namelist attribs elst insPt attDefs layer xScale yScale zScale ent tag xform rotation )
  72.  
  73. (defun mxv ( m v ) (mapcar (function (lambda ( r ) (apply '+ (mapcar '* r v)))) m))
  74.  
  75. (setq thisblock (entget e)
  76.       blockname (cdr (assoc 2 thisblock))
  77.       block     (tblsearch "block" blockname)
  78.       b_ename   (cdr (assoc -2 block))
  79.       enxt      (entnext (cdr (assoc -1 thisblock)))
  80.       ss        (ssadd)
  81.       insPt     (cdr (assoc 10 thisblock)) ;; I think this was wrong (setq insPt (cdr (assoc 10 (entget enxt)))) IMHO
  82.       )
  83.  
  84. (while (= "ATTRIB" (cdr (assoc 0 (entget enxt))))
  85.   (ssadd enxt ss)
  86.   (setq enxt (entnext enxt))
  87. );; ss selection set of attribute enames thisblock
  88.  
  89. (while (ssname ss 0)
  90.   (setq namelist (append namelist (list (cdr (assoc 1 (entget (ssname ss 0)))))))
  91.   (setq taglist (append taglist (list (cdr (assoc 2 (entget (ssname ss 0)))))))
  92.   (ssdel (ssname ss 0) ss)
  93. );; list of attribute values to save
  94.  
  95. (setq attribs (mapcar 'cons taglist namelist)
  96.       xScale (cdr (assoc 41 thisblock)) yScale (cdr (assoc 42 thisblock)) zScale (cdr (assoc 43 thisblock)) rotation (cdr (assoc 50 thisblock)) layer (cdr (assoc 8 thisblock))
  97.       ent   (cdr (assoc -2 block))
  98.       xform (list
  99.               (list (* xScale (cos rotation)) (* xScale (- (sin rotation))) 0.0)
  100.               (list (* yScale (sin rotation)) (* yScale (cos rotation)) 0.0)
  101.               (list 0.0 0.0 zScale)
  102.             )
  103.       )
  104.  
  105. (while ent
  106.   (if (= "ATTDEF" (cdr (assoc 0 (setq elst (entget ent)))))
  107.             (setq attDefs (cons (cons (cdr (assoc 2 elst)) elst) attDefs)))
  108.             (setq ent (entnext ent))
  109.           )
  110.  
  111. ;; before you make new reference, I think you should remove old one
  112. (entdel (cdr (assoc -1 thisblock))) ;; my mod...
  113.  
  114.   (list (cons 0 "INSERT") (cons 8 layer) (cons 66 1) (cons 2 blockname)
  115.         (cons 10 insPt) (cons 41 xScale) (cons 42 yScale) (cons 43 zScale) (cons 50 rotation))
  116.   )
  117.  
  118. (foreach att (reverse attDefs)
  119.   (setq tag  (car att) elst (cdr att)
  120.         )
  121. (entmakex (list (cons 0 "ATTRIB") (cons 100 "AcDbEntity") (assoc 8 elst)
  122.                 (cons 100 "AcDbText") (cons 10 (mapcar '+ insPt (mxv xform (cdr (assoc 10 elst)))))
  123.                 (cons 40 (* yScale (cdr (assoc 40 elst))))
  124.                 (cons 1 (cond ((cdr (assoc tag attribs)))
  125.                             (T (cdr (assoc 1 elst)))))
  126.                 (cons 50 (+ (cdr (assoc 50 elst)) rotation)) (cons 41 1) (assoc 51 elst) (assoc 7 elst) (assoc 72 elst)
  127.                 (cons 11 (mapcar '+ insPt (mxv xform (cdr (assoc 11 elst)))))
  128.                 (cons 100 "AcDbAttribute") (cons 2 tag) (assoc 70 elst) (assoc 74 elst)
  129.                 )
  130.             )
  131.   )
  132. (entmakex '((0 . "SEQEND")))
  133. )
  134.  
  135. (setq ss (ssget "_:L" (list '(0 . "INSERT") '(66 . 1) (cons 410 (getvar 'ctab)))))
  136. (repeat (setq i (sslength ss))
  137.   (resetattribpositioninblock (ssname ss (setq i (1- i))))
  138. )
  139. )
  140.  

[EDIT : I am not sure above will work fine with dynamic/anonymous blocks... Multiple version has filter for sel.set with '(66 . 1) which is reserved for only blocks with attributes, so xrefs are automatically filtered out - IMO...]
« Last Edit: March 24, 2019, 02:46:10 PM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

curmudgeon

  • Newt
  • Posts: 194
Re: remake blocks with attributes
« Reply #2 on: March 20, 2019, 01:21:57 PM »
Perfect !
Well, I want to get them all as a selection set. There will be around 1,000 of these in a normal drawing.

I cannot thank you enough.

Never express yourself more clearly than you are able to think.

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: remake blocks with attributes
« Reply #3 on: March 24, 2019, 02:53:42 PM »
...
Well, I want to get them all as a selection set. There will be around 1,000 of these in a normal drawing.
...

I've added additional code in my post for multiple selection, but I am not quite sure you also have dynamic/anonumous blocks for processing and if you do have, I am not sure it will work as desired - if someone with more experience could look, perhaps another revision is needed (probably there should be checking of effectivename property - but I am not sure for anonumous blocks)...

Regards, M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube