Author Topic: How to translate the coordinates from Block Definition to model Space ?  (Read 4847 times)

0 Members and 1 Guest are viewing this topic.

Tharwat

  • Swamp Rat
  • Posts: 710
  • Hypersensitive
Hello .

As it is clear from the title of the thread , please feel free to share your thoughts about the issue and any input would be
more than welcome .  :-)

many thanks .

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Two ways:



1) [Requires entity selection]

Apply the transformation matrix returned by a subentity selection using the nentsel / nentselp functions.

An explanation of nentsel / nentselp matrices can be found here:

http://www.theswamp.org/index.php?topic=40546.msg458445#msg458445

You may also find the Matrix / Vector functions found at the link below quite useful for this task:

http://lee-mac.com/mathematicalfunctions.html



2) [No selection required]

Use the transformation matrix returned by 'RefGeom' (and inverse: 'RevRefGeom') by gile, which may be found at the link below, along with many examples of how to use it:

http://www.theswamp.org/index.php?topic=27508.0;all

gile has also included a 'TransNested' function, demonstrating how to apply the transformation:

http://www.theswamp.org/index.php?topic=27508.msg331150#msg331150

Another example, using gile's WCS2RCS / RCS2WCS functions:

http://www.theswamp.org/index.php?topic=27402.msg329826#msg329826


« Last Edit: March 23, 2012, 01:36:32 PM by Lee Mac »

nivuahc

  • Guest
As it is clear from the title of the thread...

I know I'm a little slow, so please be patient with me... it isn't clear, to me, what you mean. I can think of a few different ways that the title of the thread could be interpreted.  :|

What would you be trying to accomplish?

I am old, so you'll have to forgive me.  :ugly:

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
I know I'm a little slow, so please be patient with me... it isn't clear, to me, what you mean. I can think of a few different ways that the title of the thread could be interpreted.

I interpreted the thread as: "Translate Block Definition geometry coordinates to Block Reference geometry coordinates"

But maybe I have also misunderstood...

Tharwat

  • Swamp Rat
  • Posts: 710
  • Hypersensitive
I think , I should have titled the thread like this

 " HOW TO FIND THE DIFFERENCES COORDINATES BETWEEN BLOCK DEFINITION AND MODEL SPACE "

things like getting the distance between insertion point of a block up to the base point of current drawing .

Thanks

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Code: [Select]
(cadddr (caddr (nentsel)))
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
things like getting the distance between insertion point of a block up to the base point of current drawing .

Maybe this thread will help you:

http://www.theswamp.org/index.php?topic=37861.0

Tharwat

  • Swamp Rat
  • Posts: 710
  • Hypersensitive
Thank you all .

I would like to describe the idea more specifically with codes to be more straight to the point  :-)

The insertion points for the nested blocks in the selected block would be printed to the command line , so if we re-used them , we'd not get the same
insertion point in Model Space .

So this is the main issue of the thread " HOW TO FIND THE DIFFERENCES COORDINATES BETWEEN BLOCK DEFINITION AND MODEL SPACE "

Code - Auto/Visual Lisp: [Select]
  1. (defun c:TesT (/ s block)
  2. ;;; Tharwat 24. March. 2012 ;;;
  3.   (if (and (setq s (car (entsel "\n Select a block has a nested Block :")))
  4.            (tblsearch "BLOCK" (cdr (assoc 2 (entget s))))
  5.       )
  6.     (vlax-for ent (setq block
  7.                          (vla-item
  8.                            (vla-get-blocks
  9.                              (vla-get-activedocument (vlax-get-acad-object))
  10.                            )
  11.                            (cdr (assoc 2 (entget s)))
  12.                          )
  13.                   )
  14.       (if (and (eq :vlax-false (vla-get-IsXref block))
  15.                (eq :vlax-false (vla-get-IsLayout block))
  16.           )
  17.         (if (eq (vla-get-objectname ent) "AcDbBlockReference")
  18.           (print (vlax-safearray->list
  19.                    (vlax-variant-value (vla-get-insertionpoint ent))
  20.                  )
  21.           )
  22.         )
  23.       )
  24.     )
  25.     (princ)
  26.   )
  27.   (princ)
  28. )

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Study the links and information that I posted in post#2, there are many examples in those threads  :-)



By the way, in this section of your code:

Code - Auto/Visual Lisp: [Select]
  1.    (vlax-for ent (setq block
  2.                         (vla-item
  3.                           (vla-get-blocks
  4.                             (vla-get-activedocument (vlax-get-acad-object))
  5.                           )
  6.                           (cdr (assoc 2 (entget s)))
  7.                         )
  8.                  )
  9.      (if (and (eq :vlax-false (vla-get-IsXref block))
  10.               (eq :vlax-false (vla-get-IsLayout block))
  11.          )

There is no need to check whether the selected block is an XRef or Layout repeatedly for every object in the block, indeed, there is no need to check for the Layout at all, since you cannot select a Layout object using entsel.

To explain better, this is what your code is currently doing:

Code: [Select]
Look at first object in block
Check whether block is an XRef or Layout
...
Look at second object in block
Check whether block is an XRef or Layout
...
Look at third object in block
Check whether block is an XRef or Layout
...
etc.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
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).

Code: [Select]
;;; 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...

Code: [Select]
;; 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)))
    )
  )
)
Speaking English as a French Frog

Tharwat

  • Swamp Rat
  • Posts: 710
  • Hypersensitive
Re: How to translate the coordinates from Block Definition to model Space ?
« Reply #10 on: March 24, 2012, 12:11:10 PM »
Thank you Lee for your correction , I got the point  :-)

Thanks gile for your precious codes , it is very helpful and it needs a very long time for me to understand the sequence of the routine
and matrix and the translation between coordinates is not that easy ( for me at least ) . :-)

Appreciates a lot guys .

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: How to translate the coordinates from Block Definition to model Space ?
« Reply #11 on: March 24, 2012, 03:02:11 PM »
Nice work gile, (as always). In reference to your 'InsPtWcsCoords' function, I would usually just use the translation vector of the nentsel(p) transformation matrix, however, I had overlooked the case in which the user selects an ATTRIB  :-)