TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: nivuahc on May 14, 2005, 05:19:32 PM

Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 05:19:32 PM
Okay, so I'm tinkering around with 2006 and Dynamic Blocks...

Let's say I have a dynamic block of a receptacle. Inside the dynamic block, I have a GFI type, an above counter duplex type, a plain duplex receptacle and an Isolated Ground type.

I want to know, using Visual LISP, how I can change the variant of a dynamic block from, say Duplex to GFI.

I used Michaels really great new routine (http://www.theswamp.org/phpBB2/viewtopic.php?t=5176) and found out that one of the methods available to me with a Dynamic Block is GetDynamicBlockProperties.

So I tried this:

Code: [Select]
(vla-GetDynamicBlockProperties  (vlax-ename->vla-object (car (entsel))))

And it returned this:

Code: [Select]
Select object: #<variant 8201 ...>

That tells me.... well, nothing that I can see...

So far, I haven't found anything that will let me change the state of a Dynamic Block. I'm hoping someone has already investigated this and has an idea...
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 05:30:24 PM
I dont have 2006 yet, but I had this bookmarked for futures ...
Code: [Select]
;; From: "Tony Tanzillo"
;; Newsgroups: autodesk.autocad.customization
;; Sent: Friday, May 13, 2005 6:37 AM
;; Subject: Re: DynamicBlock method

;; Get a single dynamic block property object by name

(defun GetDynBlockRefProperty (DynBlockRef Name)
   (vl-some
     '(lambda (property)
         (if (eq (vlax-get-property property 'PropertyName) Name)
            property
         )
      )
      (vlax-safearray->list
         (vlax-variant-value
            (vla-getDynamicBlockProperties DynBlockRef)
         )
      )
   )
)

;; Set the vlaue of a single dynamic block property object by name

(defun SetDynBlockRefPropertyValue (DynBlockRef Name NewValue / Property)
   (if (setq property (GetDynBlockRefProperty DynBlockref Name))
      (progn
         (vlax-put-property property 'Value NewValue)
         (vlax-release-object Property)
      )
   )
)
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 06:21:51 PM
Thanks Kerry. Hopefully, one day when I grow up, some of that will make some sense to me. :P

Seriously... does Mr. Tanzillo ever comment his code? I have no idea what's goin' on there. Take the arguments DynBlockRef and Name in the first routine...

I'm guessing that DynBlockRef is looking for a vl object, which should be a dynamic block... 'course I could be wrong. And Name, I assume, is looking for the name of the Property you're looking for? Is there a list, somewhere, of available properties that aren't visible when I run

Code: [Select]
(vlax-dump-object  (vlax-ename->vla-object (car (entsel))) T)

That returns this list (I just ran it on a dynamic block I created, just like the one I Described, so I could test this out):

Code: [Select]
; Property values:
;   Application (RO) = #<VLA-OBJECT IAcadApplication 00c2db8c>
;   Document (RO) = #<VLA-OBJECT IAcadDocument 0cfddd34>
;   EffectiveName (RO) = "receptacle"
;   Handle (RO) = "9B"
;   HasAttributes (RO) = 0
;   HasExtensionDictionary (RO) = -1
;   Hyperlinks (RO) = #<VLA-OBJECT IAcadHyperlinks 0d00efc4>
;   InsertionPoint = (21.9314 17.2553 0.0)
;   InsUnits (RO) = "Inches"
;   InsUnitsFactor (RO) = 1.0
;   IsDynamicBlock (RO) = -1
;   Layer = "0"
;   Linetype = "ByLayer"
;   LinetypeScale = 1.0
;   Lineweight = -1
;   Name = "*U5"
;   Normal = (0.0 0.0 1.0)
;   ObjectID (RO) = 2130161432
;   ObjectName (RO) = "AcDbBlockReference"
;   OwnerID (RO) = 2130160888
;   PlotStyleName = "ByLayer"
;   Rotation = 0.0
;   TrueColor = #<VLA-OBJECT IAcadAcCmColor 0d00fde0>
;   Visible = -1
;   XEffectiveScaleFactor = 1.0
;   XScaleFactor = 1.0
;   YEffectiveScaleFactor = 1.0
;   YScaleFactor = 1.0
;   ZEffectiveScaleFactor = 1.0
;   ZScaleFactor = 1.0
; Methods supported:
;   ArrayPolar (3)
;   ArrayRectangular (6)
;   ConvertToAnonymousBlock ()
;   ConvertToStaticBlock (1)
;   Copy ()
;   Delete ()
;   Explode ()
;   GetAttributes ()
;   GetBoundingBox (2)
;   GetConstantAttributes ()
;   GetDynamicBlockProperties ()
;   GetExtensionDictionary ()
;   GetXData (3)
;   Highlight (1)
;   IntersectWith (2)
;   Mirror (2)
;   Mirror3D (3)
;   Move (2)
;   ResetBlock ()
;   Rotate (2)
;   Rotate3D (3)
;   ScaleEntity (2)
;   SetXData (2)
;   TransformBy (1)
;   Update ()
T


So if I want to get the value of one of those properties, why wouldn't I just use vlax-get-property?

The only thing I see in the list above, that might have something to do with what I'm trying to accomplish, is the GetDynamicBlockProperties method. But, like I mentioned, when I do this:
Code: [Select]
(vla-GetDynamicBlockProperties  (vlax-ename->vla-object (car (entsel))))

I get this:

Code: [Select]
#<variant 8201 ...>

I tried changing the block from a GFI (which I had it set to when I ran the dump and vla-GetDynamicBlockProperties) to an above counter duplex and I ran them again. The results are identical.


What am I not seeing?
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 06:29:29 PM
I'm at a bit of a loss 'cause I dont have 2006, and not sure how the properties are put together. What's in the VBA / ActiveX help ??
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 06:30:33 PM
Do you know how to evaluate the variant value ??
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 06:32:33 PM
Quote from: AutoCAD Help file

DynamicBlockReferenceProperty object

An object containing the properties of a dynamic block.

VBA class name:
 AcadDynamicBlockReferenceProperty
 
Create using:
 N/A
 
Access via:
 BlockRef.GetDynamicBlockProperties
 

You cannot create this object; BlockRef.GetDynamicBlockProperties returns a collection of DynamicBlockReferenceProperty objects if the block reference is a dynamic block containing custom properties.

Once you have obtained a dynamic block reference property object, use the following properties to query or edit its values:

Methods
None

Properties
AllowedValues
Description
PropertyName
ReadOnly
Show
UnitsType
Value
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 06:34:38 PM
What does this give you ??
Code: [Select]

(setq bxxx (vla-GetDynamicBlockProperties  (vlax-ename->vla-object (car (entsel)))))

(vlax-safearray->list   (vlax-variant-value bxxx))
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 06:37:01 PM
Quote from: AutoCAD help file
Dynamic blocks enhance simple blocks by increasing their intelligence potential and adaptability. The internal geometry of a dynamic block instance can be adjusted independently of both its base definition and other instances. This flexibility is the central concept of dynamic blocks. Inserting an instance of a dynamic block into the current drawing creates a BlockReference object. From the block reference, you can get the DynamicBlockReferenceProperty object.

To identify a block's type, use the IsLayout, IsXRef, and IsDynamicBlock properties. If these properties are FALSE, then the block is a simple block. If the IsXRef property is TRUE, then the block is an external reference. If the IsLayout property is TRUE, then the block contains all the geometry associated with a layout. If the IsDynamicBlock property is TRUE, then the block is a dynamic block.
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 06:39:15 PM
Quote from: Kerry Brown
What does this give you ??
Code: [Select]

(setq bxxx (vla-GetDynamicBlockProperties  (vlax-ename->vla-object (car (entsel)))))

(vlax-safearray->list   (vlax-variant-value bxxx))


Code: [Select]
(#<VLA-OBJECT IAcadDynamicBlockReferenceProperty 0d025f74>)
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 06:44:08 PM
How about :

(setq objsadbl (vlax-safearray->list   (vlax-variant-value bxxx)))

(list-val objsadbl)

or

(list-val bxxx)


Code: [Select]

;;; lisp-value : Author : Vladimir Nesterovsky 2002
(defun lisp-value (val)
  (cond ((= (type val) 'variant) (lisp-value (variant-value val)))
        ((= (type val) 'safearray)
         (mapcar 'lisp-value (safearray-value val))
        )
        (t val)
  )
)
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 06:45:34 PM
I think I would need to see AC2006 and the help files to go any further with my guesses :)
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 06:51:38 PM
Quote from: Kerry Brown
How about :

(setq objsadbl (vlax-safearray->list   (vlax-variant-value bxxx)))

(list-val objsadbl)

or

(list-val bxxx)


Code: [Select]

;;; lisp-value : Author : Vladimir Nesterovsky 2002
(defun lisp-value (val)
  (cond ((= (type val) 'variant) (lisp-value (variant-value val)))
        ((= (type val) 'safearray)
         (mapcar 'lisp-value (safearray-value val))
        )
        (t val)
  )
)


When I run (list-val objsadbl) I get

Code: [Select]
; error: no function definition: LIST-VAL

When I run (lisp-value objsadbl) I get
Code: [Select]
(#<VLA-OBJECT IAcadDynamicBlockReferenceProperty 0d025f74>)

Thanks for helping me out here Kerry. This is fun.
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 06:55:00 PM
DUH !!! stupe typo ..
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 07:01:06 PM
This is from Herman Mayfarth
Code: [Select]

(defun getdynprops (obj / v)
  (vl-remove-if 'null
    (mapcar '(lambda (x)
              (if (setq v (vlax-variant-value (vla-get-value x)))
              (cons (vla-get-propertyname x) v)))
    (vlax-safearray->list
      (vlax-variant-value
        (vla-getdynamicblockproperties obj)))))
)


What happens when you feed it with the block object .. ?
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 07:28:15 PM
Oh that's sweeeeet...

Code: [Select]
Command: (getdynprops (vlax-ename->vla-object (car (entsel))))

Select object: (("Visibility" . "Isolated Ground Duplex"))
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 07:32:27 PM
hehehehe...

Code: [Select]
Command: (getdynprops (vlax-ename->vla-object (car (entsel))))


Select object: (("Visibility" . "Above Counter Duplex"))
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 07:39:07 PM
My reasons for trying to find this out in the first place...

I see a lot of potential for dynamic blocks in my current position. But I know that, in this case (something like receptacles) my users won't stand with having to insert a receptacle and then change it to the appropriate type.

I want to be able to setup a palette with each variation and, when they select it, it changes to the appropriate setting.

One of the major advantages I see with dynamic blocks, as I believe was the intent, is the elimination of so many blocks that are all similar. When I asked the rep from Autodesk if this was possible, he gave me a blank stare. I was worried that something like that might not be possible.
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 07:48:03 PM
That's the advantage I see too Chuck ..
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 11:20:22 PM
Now that I know how to get that bit of information, I need to figure out how to change it.

And, only three sips in (http://www.theswamp.org/phpBB2/viewtopic.php?t=5167&start=30) and I'm already in no shape to even try... mwuhahahahahahaha :sot:
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 11:29:52 PM
Wild assed Guess :


(SetDynBlockRefPropertyValue DynBlockObject "Visibility"  Who Cares")
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 11:33:44 PM
dude... that looks totally sweet.

does it work?

:sot:
Title: Dynamic Blocks and Visual LISP
Post by: Kerry on May 14, 2005, 11:35:07 PM
I have absolutely no idea.   MWAHAHA !!
Title: Dynamic Blocks and Visual LISP
Post by: nivuahc on May 14, 2005, 11:37:00 PM
HA! :D
Title: Dynamic Blocks and Visual LISP
Post by: whdjr on August 18, 2005, 10:49:39 AM
Quote from: nivuahc
My reasons for trying to find this out in the first place...

I see a lot of potential for dynamic blocks in my current position. But I know that, in this case (something like receptacles) my users won't stand with having to insert a receptacle and then change it to the appropriate type.

I want to be able to setup a palette with each variation and, when they select it, it changes to the appropriate setting.

One of the major advantages I see with dynamic blocks, as I believe was the intent, is the elimination of so many blocks that are all similar. When I asked the rep from Autodesk if this was possible, he gave me a blank stare. I was worried that something like that might not be possible.


Chuck,

It's much simpler than you think man.  Once you get your block the way you want it and add it to a pallette then right click on the icon in the tool pallette and select properties.  You have access to all your modifications right there.  All you need to do is make 3 or 4 copies of the same tool in the pallette and then change the properties per icon to show the desired visibility state. Cool?  yeh!

(http://www.theswamp.org/screens/whdjr/ScreenShot050.jpg)
Title: Dynamic Blocks and Visual LISP
Post by: ELOQUINTET on August 18, 2005, 03:11:54 PM
that's sweet will, wasnt aware of that ability thanks
Title: Re: Dynamic Blocks and Visual LISP
Post by: CADwoman on June 19, 2006, 09:46:48 AM
Hi, is there a way to some how link the visibility state of a dblock to the sheet set manager? So the concept is to come up some type of reactor to link the visibility state with the appropriate sheet set parameter. So for example, when the sheet set parameter changes, the visibility state of the associated dblock would change accordingly. Does this make any sense to you? thanks

Oh that's sweeeeet...

Code: [Select]
Command: (getdynprops (vlax-ename->vla-object (car (entsel))))

Select object: (("Visibility" . "Isolated Ground Duplex"))
Title: Re: Dynamic Blocks and Visual LISP
Post by: cadplayer on June 12, 2013, 06:47:25 AM
Hi!

I know thats a old thread, but my only question is:
If I can ask which coordinates have the flag position in this block
Title: Re: Dynamic Blocks and Visual LISP
Post by: irneb on June 12, 2013, 07:24:05 AM
First, that block has several visibility states. and only in some are the polar parameters available.

Next, each polar parameter has a distance and an angle parameter, so the "coordinates" are formed by 2 parameters into a polar coordinate.
Title: Re: Dynamic Blocks and Visual LISP
Post by: cadplayer on June 12, 2013, 07:52:30 AM
Yes I know that block have 3 dynamic visibility states, I try to do it with one so when I paste block via command I turn on "visibility1" parameter with name "1 Leader ON". The next step is so you said I must calculate from "1 Leader ON" paramter polarCoordinates, I donīt know how.

Code: [Select]
;; From: "Tony Tanzillo"
;; Newsgroups: autodesk.autocad.customization
;; Sent: Friday, May 13, 2005 6:37 AM
;; Subject: Re: DynamicBlock method

;; Get a single dynamic block property object by name

(defun dyGet (DynBlockRef Name)
  (vl-some
    (function (lambda (property)
        (if (eq (vlax-get-property property 'PropertyName) Name)
            property
            )
          )
        )
   
      (vlax-safearray->list
        (vlax-variant-value
            (vla-getDynamicBlockProperties DynBlockRef)
        )
      )
  )
)

;; Set the vlaue of a single dynamic block property object by name

(defun dySet (DynBlockRef Name NewValue / Property)
  (if (setq property (dyGet DynBlockref Name))
      (progn
        (vlax-put-property property 'Value NewValue)
        (vlax-release-object Property)
      )
  )
)

; Test command

(defun c:test ()
    (command "_insert" "knr" (setq pt (getpoint "\nPosition No.!")) (getvar "DIMSCALE") (getvar "DIMSCALE") 0
                                         "1"
                                         "NAME"
                                         )
                                (dySet (vlax-ename->vla-object (entlast)) "Visibility1" "1 Leader ON")
                                )



Title: Re: Dynamic Blocks and Visual LISP
Post by: cadplayer on June 12, 2013, 08:19:43 AM
Can you help me how I can manipulate angle and distance faktor in visibility state "1 Leader ON" ?!
Title: Re: Dynamic Blocks and Visual LISP
Post by: irneb on June 12, 2013, 08:37:50 AM
Be a bit more patient, I'm busy typing!

Well, open the block in Block Edit then select one of those polar parameters. Open the properties palette and it will show you the names of the distance and angle parameters of each.

Now you can get/set those the same way you do with the visibility parameter. E.g.
Code: [Select]
_$ (setq eo (vlax-ename->vla-object (entlast)) )
#<VLA-OBJECT IAcadBlockReference 000000003c393bd8>
_$ (dyget eo "1 Leader ON")
nil
_$
_$ (dyget eo "1 Leader")
nil
_$ (dyget eo "1 Leader ")
#<VLA-OBJECT IAcadDynamicBlockReferenceProperty 000000003c4e6638>
_$ (vla-get-value (dyget eo "1 Leader "))
#<variant 5 1470.23133612937>
_$ (vlax-get (dyget eo "1 Leader ") 'value)
1470.23
Note, do a normal List on the block to find out the "real" names of those. Here you can see the parameter is actually called "1 Leader " including the space.

Note though, the "coordinates" is not X,Y position from origin. It's polar, like in a radius line of a circle. So you'd need some trigonometry or using the angle and distance function to convert between Cartesian & polar coordinates. The polar (built in) function only converts from polar to xy, my guess is you want it the other way round. So:
Code - Auto/Visual Lisp: [Select]
  1. (defun xy->polar (dx dy)
  2.   (list (distance '(0.0 0.0) (list dx dy))
  3.         (angle '(0.0 0.0) (list dx dy))))
The trig method becomes a bit more complex.

Title: Re: Dynamic Blocks and Visual LISP
Post by: cadplayer on June 12, 2013, 09:14:11 AM
If I can follow you I get one parameter (distance) what is with the angle ?

I was thinking it can go so here, I get new distance and angle and manipulate them in the Block - is it wrong?

Code: [Select]
(defun c:test ()
    (command "_insert" "knr"
             (setq insPt
                      (getpoint "\n Position No.!")) (getvar "DIMSCALE") (getvar "DIMSCALE") 0
                                         "1"
                                         "NAME"
             )
    (setq dis
             (if
                 (setq angl
                          (angle insPt
                                 (setq flagPt (getpoint "\n flag point! ")))
                 )
                 (distance insPt flagPt)
              )
    )

    ; Turn on  Leader 1
    (dySet (vlax-ename->vla-object (entlast)) "Visibility1" "1 Leader ON")

    (princ)
    )
Title: Re: Dynamic Blocks and Visual LISP
Post by: irneb on June 12, 2013, 09:32:49 AM
As I said, use the list command on one of those blocks to see what those parameters are truly called:
Quote
Command: LS LIST
Select objects: 1 found

Select objects:

                  BLOCK REFERENCE  Layer: "0"
                            Space: Model space
                   Handle = 39f7
       Block Name: "knr"
   Anonymous Name: "*U9"
                at point, X= 184359.0  Y=  35574.0  Z=      0.0
   X scale factor:       1.0
   Y scale factor:       1.0
   rotation angle:   0.00
   Z scale factor:       1.0
         InsUnits: Meters
  Unit conversion:    1000.0
  Scale uniformly: No
  Allow exploding: Yes
      Visibility1: 3 Leader ON
        1 Leader :    1470.2
           Angle1:     45.00
         2 Leader:    1470.2
           Angle2:      0.00
         3 Leader:    1470.2
           Angle3:    315.00

                  ATTRIBUTE  Layer: "0"
                            Space: Model space
                   Color: 1 (red)    Linetype: "BYLAYER"
                   Handle = 39f8
             Style = "SIMPLEX8"
        Annotative: No
             Font file = simplex.shx
            center point, X= 184366.3  Y=  35344.3  Z=      0.0
            height     500.0
             value Nr
Press ENTER to continue:
              .......
So then the 1st polar parameter actually consists of the distance named "1 Leader ", AND the angle named "Angle1".

Note this angle is listed as degrees, but when you obtain its value through lisp (or set it through lisp) it only works using radians.
Title: Re: Dynamic Blocks and Visual LISP
Post by: cadplayer on June 12, 2013, 09:41:54 AM
Sorry I donīt realy understand. I get your result as you described. But how can I use results from "Textscreen list". I doesnīt find them in entget-list or I have wrong?
Title: Re: Dynamic Blocks and Visual LISP
Post by: cadplayer on June 13, 2013, 02:03:51 AM
Thanks irneb, I was tired yesterday. I could fix it.
Title: Re: Dynamic Blocks and Visual LISP
Post by: irneb on June 13, 2013, 02:32:18 AM
Sorry I donīt realy understand. I get your result as you described. But how can I use results from "Textscreen list". I doesnīt find them in entget-list or I have wrong?
Yes, that's the whole point of Tony's code - which you posted here (http://www.theswamp.org/index.php?topic=5177.msg499776#msg499776). It's using ActiveX instead of entget & entmod. That's because dynamic block properties are only accessible through ActiveX in AutoLisp.

If you want to go the entget/entmod route through the raw DXF stuff, then look into the dictionaries attached to the block insert. Some of those point to the data for these parameters. But trying to figure them out is a huge task with no extra benefit over the ActiveX methods.

So you use Tony's defuns, or any others like mine (http://sourceforge.net/p/caddons/code/HEAD/tree/Blocks/BlockData.LSP (http://sourceforge.net/p/caddons/code/HEAD/tree/Blocks/BlockData.LSP)) or Lee's (http://www.lee-mac.com/dynamicblockfunctions.html (http://www.lee-mac.com/dynamicblockfunctions.html)). They all do basically the same thing - make it easier to get / set parameter values through a single function call instead of performing multiple checks & assignments.

So using my functions, you need an ActiveX object reference to the block insertion's entity. Then you need to know the name of the Parameter or the index number.
Code: [Select]
_$ (setq bObj (vlax-ename->vla-object (entlast)))
#<VLA-OBJECT IAcadBlockReference 000000002d17f868>
_$ (Blocks:GetParameterValues bObj)
(("VISIBILITY1" . "3 Leader ON") ("1 LEADER " . 1470.23) ("ANGLE1" . 0.785398) ("ORIGIN" . #<safearray...>) ("2 LEADER" . 1470.23) ("ANGLE2" . 0.0) ("ORIGIN" . #<safearray...>) ("3 LEADER" . 1470.23) ("ANGLE3" . 5.49779) ("ORIGIN" . #<safearray...>))
_$ (Blocks:GetParamValue bObj "1 LEADER ")
1470.23
_$ (Blocks:GetParamValue bObj "ANGLE1")
0.785398
_$ (Blocks:PutParamValue bObj "ANGLE1" (* (/ 60.0 180.0) pi))
T
_$ (Blocks:PutParamValue bObj "1 LEADER " 4000.0)
T
_$ (Blocks:GetParamValue bObj "ANGLE1")
1.0472
_$ (Blocks:GetParamValue bObj "1 LEADER ")
4000.0
So here I changed the 1st leader to be at 60 degrees and 4000 units long.
Title: Re: Dynamic Blocks and Visual LISP
Post by: cadplayer on June 13, 2013, 04:21:35 AM
Very nice stuff, thank you so much for your offering :wink: