Code Red > AutoLISP (Vanilla / Visual)

remake blocks with attributes

(1/1)

curmudgeon:
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.

ribarm:
Here is my observation, but without example DWG its hard to tell and test...


--- Code - Auto/Visual Lisp: ---(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 ) (defun mxv ( m v ) (mapcar (function (lambda ( r ) (apply '+ (mapcar '* r v)))) m)) (setq thisblock (entget (car (entsel "\nPick Block")))      blockname (cdr (assoc 2 thisblock))      block     (tblsearch "block" blockname)      b_ename   (cdr (assoc -2 block))      enxt      (entnext (cdr (assoc -1 thisblock)))      ss        (ssadd)      insPt     (cdr (assoc 10 thisblock)) ;; I think this was wrong (setq insPt (cdr (assoc 10 (entget enxt)))) IMHO      ) (while (= "ATTRIB" (cdr (assoc 0 (entget enxt))))  (ssadd enxt ss)  (setq enxt (entnext enxt)));; ss selection set of attribute enames thisblock (while (ssname ss 0)  (setq namelist (append namelist (list (cdr (assoc 1 (entget (ssname ss 0)))))))  (setq taglist (append taglist (list (cdr (assoc 2 (entget (ssname ss 0)))))))  (ssdel (ssname ss 0) ss));; list of attribute values to save (setq attribs (mapcar 'cons taglist namelist)      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))      ent   (cdr (assoc -2 block))      xform (list               (list (* xScale (cos rotation)) (* xScale (- (sin rotation))) 0.0)              (list (* yScale (sin rotation)) (* yScale (cos rotation)) 0.0)              (list 0.0 0.0 zScale)            )      ) (while ent  (if (= "ATTDEF" (cdr (assoc 0 (setq elst (entget ent)))))            (setq attDefs (cons (cons (cdr (assoc 2 elst)) elst) attDefs)))            (setq ent (entnext ent))          ) ;; before you make new reference, I think you should remove old one(entdel (cdr (assoc -1 thisblock))) ;; my mod... (entmakex  (list (cons 0 "INSERT") (cons 8 layer) (cons 66 1) (cons 2 blockname)        (cons 10 insPt) (cons 41 xScale) (cons 42 yScale) (cons 43 zScale) (cons 50 rotation))  ) (foreach att (reverse attDefs)  (setq tag  (car att) elst (cdr att)        )(entmakex (list (cons 0 "ATTRIB") (cons 100 "AcDbEntity") (assoc 8 elst)                (cons 100 "AcDbText") (cons 10 (mapcar '+ insPt (mxv xform (cdr (assoc 10 elst)))))                (cons 40 (* yScale (cdr (assoc 40 elst))))                (cons 1 (cond ((cdr (assoc tag attribs)))                            (T (cdr (assoc 1 elst)))))                (cons 50 (+ (cdr (assoc 50 elst)) rotation)) (cons 41 1) (assoc 51 elst) (assoc 7 elst) (assoc 72 elst)                (cons 11 (mapcar '+ insPt (mxv xform (cdr (assoc 11 elst)))))                (cons 100 "AcDbAttribute") (cons 2 tag) (assoc 70 elst) (assoc 74 elst)                )            )  )(entmakex '((0 . "SEQEND")));| (entmake (list '(0 . "CIRCLE") '(100 . "AcDbEntity")'(8 .  "TEXT") '(62 . 1) '(100 . "AcDbCircle")        (cons 10 insPt) '(40 . 8)))|;(princ)) (defun c:resetattribpositioninblockmultiple ( / resetattribpositioninblock ss i ) (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 ) (defun mxv ( m v ) (mapcar (function (lambda ( r ) (apply '+ (mapcar '* r v)))) m)) (setq thisblock (entget e)      blockname (cdr (assoc 2 thisblock))      block     (tblsearch "block" blockname)      b_ename   (cdr (assoc -2 block))      enxt      (entnext (cdr (assoc -1 thisblock)))      ss        (ssadd)      insPt     (cdr (assoc 10 thisblock)) ;; I think this was wrong (setq insPt (cdr (assoc 10 (entget enxt)))) IMHO      ) (while (= "ATTRIB" (cdr (assoc 0 (entget enxt))))  (ssadd enxt ss)  (setq enxt (entnext enxt)));; ss selection set of attribute enames thisblock (while (ssname ss 0)  (setq namelist (append namelist (list (cdr (assoc 1 (entget (ssname ss 0)))))))  (setq taglist (append taglist (list (cdr (assoc 2 (entget (ssname ss 0)))))))  (ssdel (ssname ss 0) ss));; list of attribute values to save (setq attribs (mapcar 'cons taglist namelist)      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))      ent   (cdr (assoc -2 block))      xform (list               (list (* xScale (cos rotation)) (* xScale (- (sin rotation))) 0.0)              (list (* yScale (sin rotation)) (* yScale (cos rotation)) 0.0)              (list 0.0 0.0 zScale)            )      ) (while ent  (if (= "ATTDEF" (cdr (assoc 0 (setq elst (entget ent)))))            (setq attDefs (cons (cons (cdr (assoc 2 elst)) elst) attDefs)))            (setq ent (entnext ent))          ) ;; before you make new reference, I think you should remove old one(entdel (cdr (assoc -1 thisblock))) ;; my mod... (entmakex  (list (cons 0 "INSERT") (cons 8 layer) (cons 66 1) (cons 2 blockname)        (cons 10 insPt) (cons 41 xScale) (cons 42 yScale) (cons 43 zScale) (cons 50 rotation))  ) (foreach att (reverse attDefs)  (setq tag  (car att) elst (cdr att)        )(entmakex (list (cons 0 "ATTRIB") (cons 100 "AcDbEntity") (assoc 8 elst)                (cons 100 "AcDbText") (cons 10 (mapcar '+ insPt (mxv xform (cdr (assoc 10 elst)))))                (cons 40 (* yScale (cdr (assoc 40 elst))))                (cons 1 (cond ((cdr (assoc tag attribs)))                            (T (cdr (assoc 1 elst)))))                (cons 50 (+ (cdr (assoc 50 elst)) rotation)) (cons 41 1) (assoc 51 elst) (assoc 7 elst) (assoc 72 elst)                (cons 11 (mapcar '+ insPt (mxv xform (cdr (assoc 11 elst)))))                (cons 100 "AcDbAttribute") (cons 2 tag) (assoc 70 elst) (assoc 74 elst)                )            )  )(entmakex '((0 . "SEQEND")))) (setq ss (ssget "_:L" (list '(0 . "INSERT") '(66 . 1) (cons 410 (getvar 'ctab)))))(repeat (setq i (sslength ss))  (resetattribpositioninblock (ssname ss (setq i (1- i)))))(princ)) 
[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...]

curmudgeon:
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.

ribarm:

--- Quote from: curmudgeon on March 20, 2019, 01:21:57 PM ---...
Well, I want to get them all as a selection set. There will be around 1,000 of these in a normal drawing.
...

--- End quote ---

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.

Navigation

[0] Message Index

Go to full version