TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Crank on July 26, 2008, 10:55:21 AM

Title: Can't find the annotative scales of dynamic blocks.
Post by: Crank on July 26, 2008, 10:55:21 AM
I'm trying to find the annotative scales of a selected entity.

With this code the scales for most entities can be found:
Code: [Select]
(defun get_all_scales (ent / annotative lijst n schalen)
(setq annotative (cdr (assoc 360 ent)))

(if annotative (progn
(setq lijst (entget (cdr (assoc 350 (entget (cdr (assoc 360 (entget annotative))))))))

(foreach n (collect 350 lijst)
(setq schalen (cons
(cdr (assoc 300 (entget (cdr (assoc 340 (entget n))))))
schalen
)
)
)

schalen
))
)
(defun collect (key lijst / n return)
(foreach n lijst
(if (= key (car n))
(setq return (cons (cdr n) return))
)
)
return
)

(defun c:test (/ ent scalelist)
(setq ent (entget (car (entsel))))
(if ent (setq scalelist (get_all_scales ent)))
(if scalelist
(princ scalelist)
;else
(alert "\nNo annoscales")
)
(princ)
)
However, on dynamic blocks it crashes, because group 350 isn't present.
No problem, it's possible to make an exeption for dynamic blocks, but where is the data stored of the annotative scales? I can't find it... Perhaps someone can point me in the right direction.

Any help is appriciated.
Title: Re: Can't find the annotative scales of dynamic blocks.
Post by: Crank on July 27, 2008, 03:09:16 AM
Found it  :-)
Annotative dynamic blocks do have two 360-groups. You need the one that belongs to AcDbContextDataManager, so you can use:
Code: [Select]
(defun get_ent_scales (ent / annotative lijst n schalen collect)
  (defun collect (key lijst / n return)
    (foreach n lijst
      (if (= key (car n))
        (setq return (cons (cdr n) return))
      )
    )
    return
  )

  (setq annotative (cdr (assoc 360 ent)))

  (if annotative (progn
    (setq lijst
      (entget (cdr (assoc 350
        (entget (cdr (assoc 360
          [color=red](member '(3 . "AcDbContextDataManager")[/color][color=green]; Get the right 360-code[/color]
            (entget annotative)
          [color=red])[/color]
        )))
      )))
    )

    (foreach n (collect 350 lijst)
      (setq schalen
                    (cons
                      (cdr (assoc 300 (entget (cdr (assoc 340 (entget n))))))
                      schalen
                    )
      )
    )
    schalen
  ))
)
Title: Re: Can't find the annotative scales of dynamic blocks.
Post by: ASMI on July 27, 2008, 12:14:48 PM
You can to retrieve "ACDB_ANNOTATIONSCALES" dictionary of block and walk around XRecords:

Code: [Select]
(defun Get_Annotation_Dictionary(vlaObj / aDic)
  (if(= :vlax-true
      (vla-get-HasExtensionDictionary vlaObj))
    (progn
      (vlax-for d(vla-GetExtensionDictionary vlaObj)
       (if(and
   (vlax-property-available-p d 'Name)
   (= "ACDB_ANNOTATIONSCALES"(vla-get-Name d))
   ); end and
(setq aDic d)
); end if
       ); end vlax-for
      ); end progn
    ); end if
 aDic
  ); end of Get_Annotation_Dictionary
Title: Re: Can't find the annotative scales of dynamic blocks.
Post by: Crank on July 27, 2008, 03:21:37 PM
Thanks ASMI,

Though I already solved it in ALISP, I wanted to try yours.

I don't know much about VLISP, but when I use:
Code: [Select]
(defun c:test (/ obj lijst)
(setq obj (vlax-ename->vla-object (car (entsel))))
(setq lijst (Get_Annotation_Dictionary obj))
)
I always get nil as the result. What am I doing wrong?
Title: Re: Can't find the annotative scales of dynamic blocks.
Post by: Jeff_M on July 27, 2008, 05:08:22 PM
Hi Crank,
ASMI left out a step it appears. This gets the correct Dictionary:
Code: [Select]
(defun Get_Annotation_Dictionary (vlaObj / aDic)
  (if(= :vlax-true
      (vla-get-HasExtensionDictionary vlaObj))
    (progn
      (vlax-for d(vla-GetExtensionDictionary vlaObj)
       (if(and
   (vlax-property-available-p d 'Name)
   (= "AcDbContextDataManager" (vla-get-Name d))
   ); end and
(vlax-for e d
   (if (and
(vlax-property-available-p e 'Name)
(= "ACDB_ANNOTATIONSCALES" (vla-get-Name e))
)
     (setq aDic e)
     )
   )
); end if
       ); end vlax-for
      ); end progn
    ); end if
  aDic
  ); end of Get_Annotation_Dictionary
However, the resulting objects don't seem to be exposed enough in the API for what you want:
Quote from: Autocad
; IAcadObject: The standard interface for a basic AutoCAD object
; Property values:
;   Application (RO) = #<VLA-OBJECT IAcadApplication 00d74d3c>
;   Document (RO) = #<VLA-OBJECT IAcadDocument 092a2c10>
;   Handle (RO) = "369C"
;   HasExtensionDictionary (RO) = 0
;   ObjectID (RO) = 2125842016
;   ObjectName (RO) = "AcDbBlkRefObjectContextData"
;   OwnerID (RO) = 2125841792
; Methods supported:
;   Delete ()
;   GetExtensionDictionary ()
;   GetXData (3)
;   SetXData (2)
Title: Re: Can't find the annotative scales of dynamic blocks.
Post by: Crank on July 28, 2008, 04:10:28 AM
Thanks Jeff, that works.

It's good to have this by the side. Annoscales aren't documented in the DXF-manual and it wouldn't surprise me if Autodesk desides to do it different in a next release.
Title: Re: Can't find the annotative scales of dynamic blocks.
Post by: ASMI on July 28, 2008, 10:12:38 AM
Quote
However, the resulting objects don't seem to be exposed enough in the API for what you want:

Need to extract XRecords. I do not want to make it long ActiveX way and use (vlax-vla-object->ename.

Code: [Select]
(defun Get_Ann_Scales_List(vlaObj / aDic oLst)
  (if(= :vlax-true
      (vla-get-HasExtensionDictionary vlaObj))
    (progn
      (vlax-for d(vla-GetExtensionDictionary vlaObj)
       (if(and
   (vlax-property-available-p d 'Name)
   (= "AcDbContextDataManager"(vla-get-Name d))
   ); end and
(setq aDic(vla-Item d "ACDB_ANNOTATIONSCALES"))
); end if
       ); end vlax-for
      (if aDic
(progn
  (vlax-for i aDic
    (setq oLst(cons
(cdr
  (assoc 42
   (entget
     (vlax-vla-object->ename i))))oLst))
    ); end vlax-for
  ); end progn
); end if
      ); end progn
    ); end if
  oLst
  ); end of Get_Ann_Scales_List

Usage:

Code: [Select]
(Get_Ann_Scales_List(vlax-ename->vla-object(car(entsel))))
(4.0 2.0 1.0)

DXF lists for (vlax-vla-object->ename i):

Scale = 1

((-1 . <Entity name: 79cbad10>) (0 . "ACDB_BLKREFOBJECTCONTEXTDATA_CLASS") (5 . "45A") (102 . "{ACAD_REACTORS") (330 . <Entity name: 79cbad08>) (102 . "}") (330 . <Entity name: 79cbad08>) (100 . "AcDbObjectContextData") (70 . 3) (290 . 1) (100 . "AcDbAnnotScaleObjectContextData") (340 . <Entity name: 7c0700e0>) (50 . 0.0) (10 960.372 265.841 0.0) (41 . 1.0)(42 . 1.0) (43 . 1.0))

Scale = 2

((-1 . <Entity name: 79c114c0>) (0 . "ACDB_BLKREFOBJECTCONTEXTDATA_CLASS") (5 . "540") (102 . "{ACAD_REACTORS") (330 . <Entity name: 79cbad08>) (102 . "}") (330 . <Entity name: 79cbad08>) (100 . "AcDbObjectContextData") (70 . 3) (290 . 0) (100 . "AcDbAnnotScaleObjectContextData") (340 . <Entity name: 7c0700e8>) (50 . 0.0) (10 960.372 265.841 0.0) (41 . 2.0) (42 . 2.0) (43 . 2.0))

Scale = 4

((-1 . <Entity name: 79c114d0>) (0 . "ACDB_BLKREFOBJECTCONTEXTDATA_CLASS") (5 . "542") (102 . "{ACAD_REACTORS") (330 . <Entity name: 79cbad08>) (102 . "}") (330 . <Entity name: 79cbad08>) (100 . "AcDbObjectContextData") (70 . 3) (290 . 0) (100 . "AcDbAnnotScaleObjectContextData") (340 . <Entity name: 7c0700f0>) (50 . 0.0) (10 960.372 265.841 0.0) (41 . 4.0) (42 . 4.0) (43 . 4.0))