Hi,
The easier way is to select a nested entity (maybe in a nested block) with nentsel or nentselp so that you directly get the transformation matrix to convert the insertion point (just care if the selected entity is an attribute or not).
;;; VXV Returns the dot product of 2 vectors
(defun vxv (v1 v2) (apply '+ (mapcar '* v1 v2)))
;; TRP Transpose a matrix -Doug Wilson-
(defun trp (m) (apply 'mapcar (cons 'list m)))
;; MXV Apply a transformation matrix to a vector -Vladimir Nesterovsky-
(defun mxv (m v) (mapcar '(lambda (r) (vxv r v)) m))
;; BUTLAST Returns a list but last item
(defun butlast (l) (reverse (cdr (reverse l))))
;; InsPtWcsCoords
;; Returns the insertion point of the parent block in WCS coordinates
;;
;; Argument : a list as returned by nentsel or nentselp
(defun InsPtWcsCoords (nent / pt mat)
(if (= "ATTRIB" (cdr (assoc 0 (entget (car nent)))))
(setq own (cdr (assoc 330 (entget (car nent))))
pt (cdr (assoc 10 (entget own)))
)
)
(if (< 2 (length nent))
(setq mat (if (= 3 (length (caaddr nent)))
(caddr nent)
(mapcar 'butlast (trp (caddr nent)))
)
)
)
(if mat
(if pt
(mapcar '+ (last mat) (mxv (trp (butlast mat)) pt))
(last mat)
)
(trans pt own 0)
)
)
(defun c:test (/ nent)
(if (setq nent (nentsel "\nSelect a nested block: "))
(entmake (list '(0 . "POINT") (cons 10 (InsPtWcsCoords nent)) '(62 . 30)))
)
(princ)
)
If you want to start from the 'parent' block reference, you'll have to build the transformation matrix for this reference (with RefGeom) and then, recursively iterate its definition components looking for block references, build the matrix combine it with the parent one, transform the insertion point and iterate ist definition...
;; VXV Returns the dot product of 2 vectors
(defun vxv (v1 v2) (apply '+ (mapcar '* v1 v2)))
;; TRP Transpose a matrix -Doug Wilson-
(defun trp (m) (apply 'mapcar (cons 'list m)))
;; MXV Apply a transformation matrix to a vector -Vladimir Nesterovsky-
(defun mxv (m v) (mapcar '(lambda (r) (vxv r v)) m))
;; Multiply two matrices by Vladimir Nesterovsky
(defun mxm (m q) (mapcar (function (lambda (r) (mxv (trp q) r))) m))
;; RefGeom
;; Returns a list which first item is the 3X3 tranformation matrix and second item is
;; the insertion point of a block reference in its owner (space or block definition)
(defun RefGeom (ename / elst ang norm mat)
(setq elst (entget ename)
ang (cdr (assoc 50 elst))
norm (cdr (assoc 210 elst))
)
(list
(setq mat
(mxm
(mapcar (function (lambda (v) (trans v 0 norm T)))
'((1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0))
)
(mxm
(list (list (cos ang) (- (sin ang)) 0.0)
(list (sin ang) (cos ang) 0.0)
'(0.0 0.0 1.0)
)
(list (list (cdr (assoc 41 elst)) 0.0 0.0)
(list 0.0 (cdr (assoc 42 elst)) 0.0)
(list 0.0 0.0 (cdr (assoc 43 elst)))
)
)
)
)
(trans
(mapcar
'-
(cdr (assoc 10 elst))
(mxv mat
(cdr (assoc 10 (tblsearch "BLOCK" (cdr (assoc 2 elst)))))
)
)
norm
0
)
)
)
;; NestedRefs
;; Returns a list of all nested blocks insertion point coordinates (WCS)
;; Each list item has form: (blockName X Y Z)
(defun NestedRefs (br / getNested pt lst)
(defun getNested (br geom / name btr ent elst glst pt)
(setq name (cdr (assoc 2 (entget br)))
btr (tblsearch "block" name)
ent (cdr (assoc -2 btr))
)
(while ent
(setq elst (entget ent))
(if (= "INSERT" (cdr (assoc 0 elst)))
(progn
(setq glst (refgeom ent))
(setq pt (mapcar '+ (cadr geom) (mxv (car geom) (cadr glst)))
lst (cons (cons (cdr (assoc 2 elst)) pt) lst)
)
(getNested ent (list (mxm (car geom) (car glst)) pt))
)
)
(setq ent (entnext ent))
)
)
(getNested br (refgeom br))
lst
)
(defun c:test2 (/ br)
(if (setq br (car (entsel "\nSelect a block: ")))
(foreach p (mapcar 'cdr (NestedRefs br))
(entmake (list '(0 . "POINT") (cons 10 p) '(62 . 3)))
)
)
)