TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: ArgV on December 06, 2009, 04:17:18 PM

Title: Insertionpoint of complex object WITHOUT using nentsel
Post by: ArgV on December 06, 2009, 04:17:18 PM
I am trying to get the data list of a block in the blocks collection, but it only gives me the basic info, and not the information I really want from it like the insertionPoint property or the rotation property.

Is there a reason why, and is there a way to get this info from a nested block without having to pick it on screen?

I'm trying to update a directory full of drawings with new blocks using objectDBX, so I'm limited to what I can do.

Heres the part I'm having problems with..
(getName is a sub-routine that checks for x-refs and anonymous or dynamic blocks)

Code: [Select]

(vlax-for block blocks
;; get it's name
(setq name (strcase (getName block)))
(if
   (and ;; the name does not have a "*" or is not model_space or paper_space
     (/= (substr name 1 1) "*")
     (not (wcmatch name "*SPACE*"))
     )
   
   ;; loop through the good list
   ;; if the block is in the badList, insert the good block in it's place

   (while (< cntr (length badList))
     (if
       (= (nth cntr badList) name)
       (progn

(setq blockItem (apply 'vla-item (list blocks name))

                           [b];;Arrrgh!! VLISP will not give the standard information on a block that is nested!
;;I want the insertion point and rotation of this block! [/b]

       insertionPoint (vla-get-insertionpoint blockItem);<- won't work
       rotation (vla-get-rotation blockItem));<-won't work
(vla-insertblock insertionPoint (nth cntr goodList) 1 1 1 rotation)
)
       )
     (setq cntr (1+ cntr))
     )
   )
(setq cntr 1)
)

Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: Lee Mac on December 06, 2009, 04:29:58 PM
Use something like this:

Code: [Select]
(vlax-for obj (vla-item (vla-get-blocks (vla-get-ActiveDocument (vlax-get-acad-object))) "Block Name")
  (if (eq "AcDbBlockReference" (vla-get-objectname obj))
    (vla-get-insertionpoint obj)))

Hope this helps
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: ArgV on December 07, 2009, 10:04:38 AM
Use something like this:

Code: [Select]
(vlax-for obj (vla-item (vla-get-blocks (vla-get-ActiveDocument (vlax-get-acad-object))) "Block Name")
  (if (eq "AcDbBlockReference" (vla-get-objectname obj))
    (vla-get-insertionpoint obj)))

Hope this helps

I know this will get an insertionpoint of one of the blocks INSIDE of this main block, but can it get the insertionPoint of the larger block?

thank you much.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: Keith™ on December 07, 2009, 10:16:15 AM
Ok, I am confused ...

You want to know the insertion point of a block from within the blocks collection ... well ... there isn't really an insertion point for a block within the blocks collection. The blocks collection is the collection of all the blocks defined in the drawing, not necessarily those inserted into the drawing. Until a block is inserted, there isn't an insertion point ... there is an Origin point .. i.e. the point at which the insertion point is defined when inserted. The origin is the same as the INSBASE. Perhaps that is what you are looking for.

If you are looking to modify a nested block, you have to read that main block definition and iterate through the objects to find the one you want. Then your nested block will not be a block, but will instead be a blockreference, and as such will have an insertion point.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: ArgV on December 07, 2009, 10:27:14 AM
Ok, I am confused ...

You want to know the insertion point of a block from within the blocks collection ... well ... there isn't really an insertion point for a block within the blocks collection. The blocks collection is the collection of all the blocks defined in the drawing, not necessarily those inserted into the drawing. Until a block is inserted, there isn't an insertion point ... there is an Origin point .. i.e. the point at which the insertion point is defined when inserted. The origin is the same as the INSBASE. Perhaps that is what you are looking for.

If you are looking to modify a nested block, you have to read that main block definition and iterate through the objects to find the one you want. Then your nested block will not be a block, but will instead be a blockreference, and as such will have an insertion point.

I'm just replacing one large assembly with another one. but to insert the new "better" block, I need to know the insertionPoint and rotation of the original block I'm trying to replace. However, the block I'm trying to replace is a large block with blocks inside of it (nested). So, when I go through the blocks collection, I get the large block, but it does not have an insertionPoint property or rotation property, only basic stuff, and a "count" property which makes it obvious that it's nested.

does that mean I just use the origin property for this block?
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: CAB on December 07, 2009, 10:37:24 AM
Note that there are BLOCKs which are the definitions stored in the Block Collection.
Then there are INSERTs which are visible objects in the Drawing. These are pointers back to the Block collection but do contain attribute info where as the Block Definitions contain Attribute Definitions.

How clear is the ? :)

When blocks are created you usually pick an "Base Point". When blocks are Inserted you pick an "Insertion Point" which is stored in the INSERT not the Block.

When you replace a BLOCK in the Block Collection the INSERT(s) in the DWG are updated with this new information but should retain the INSERT information like Insert Point, scale & rotation.

(I think I got that correct)  8-)

AND:
Defining a BLOCK requires a BASE POINT which relates to the objects you included in the Block Definition. This is a point that is relative to the objects in the block.
When you insert a block you create an INSERT object & it's display in the DWG is relative to the Insert Point. The Insert Point is where the Base Point is offset to & the objects in the Block are now displayed relative to there Insert Point.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: Keith™ on December 07, 2009, 10:39:15 AM
That is exactly why I am saying I am confused ...
Are you trying to redefine "large assembly" or are you trying to replace a single insertion of "large assembly" with a new "better" block? They are not the same thing. To redefine "large assembly" you need to iterate through the block definition (the one in the blocks collection) and redefine each element you want to change. If you are merely trying to replace an inserted block (i.e. a block reference) you cannot do that from the block collection. You can only do that by finding the block insertion in the drawing ModelSpace collection or PaperSpace collection ... or ssget the block reference ... and then operate on that block reference ...

Remember, programmatically a block and a block reference are very different creatures.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: gile on December 07, 2009, 10:39:21 AM
Hi,

To undertand how nested blocks work, you can compare a block definition and the Modelspace (wich is a block definition sort of)

When you insert a block reference in model space its insertion point is about WCS (if the block normal is 0,0,1 ; OCS otherwise, see here (http://www.theswamp.org/index.php?topic=13526.0))

A nested block ia a block reference inserted in a block definition and it's insertion point is about the Block definition coordinate system which origin is the base point of the 'parent' block definition.

Now, with a simple example "A" bloc is nested in "B" block.
"A" insertion point in "B" is 2,3,0 if you insert "B" in model space at 10,10,0 without any rotation or scaling the insertion point of "A" in model space is 12,13,0 ("A" insertion point + "B" insertion point).
If "B" is rotated or scaled when inserting or in case of multiple nesting levels, getting "A" insertion point coordinates in model space is mor complex. The easiest way to calculate these coordinates is to use a transformation matrix as this returned by nentselp.
If you want to avoid using nentsel(p), you should have to calculate this matrix.

You can see here (http://www.theswamp.org/index.php?topic=27402.msg329826#msg329826) or there (http://www.theswamp.org/index.php?topic=26591.msg320739#msg320739) and more searching for RCS2WCS.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: Keith™ on December 07, 2009, 10:47:12 AM
gile,
You are correct, however, block "B" will have an insertion point within block "A" ... and will return an insertion point in relation to OCS. Only if the user needs WCS will nentselp or another calculation of a transformation martrix be needed.

It sounds to me like the task is merely to replace a block insertion with another block. If that is the case, which we still don't have a clear answer, merely redefining the block in the blocks collection will work, OR insert the new block at the insertion point of the BlockReference in ModelSpace or PaperSpace.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: ArgV on December 07, 2009, 11:57:21 AM
Note that there are BLOCKs which are the definitions stored in the Block Collection.
Then there are INSERTs which are visible objects in the Drawing. These are pointers back to the Block collection but do contain attribute info where as the Block Definitions contain Attribute Definitions.

How clear is the ? :)

When blocks are created you usually pick an "Base Point". When blocks are Inserted you pick an "Insertion Point" which is stored in the INSERT not the Block.

When you replace a BLOCK in the Block Collection the INSERT(s) in the DWG are updated with this new information but should retain the INSERT information like Insert Point, scale & rotation.

(I think I got that correct)  8-)

AND:
Defining a BLOCK requires a BASE POINT which relates to the objects you included in the Block Definition. This is a point that is relative to the objects in the block.
When you insert a block you create an INSERT object & it's display in the DWG is relative to the Insert Point. The Insert Point is where the Base Point is offset to & the objects in the Block are now displayed relative to there Insert Point.


Hmph. These blocks have attributes and everything. Perhaps I should just rename the block to the name of the block I'm inserting, and then insert the new block and update. ?

This other stuff is going to drive me nuts.

Suppose I have a block "A". block "A" contains blocks "B", "C", "D", "E", and "F". I don't care about B - F, I just want the point in which to insert block "A", which contains a re-definition (as it were) of the old "A" block.

I've been working with Java the last 3 months, and forgot what I used to know about blocks!

Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: ArgV on December 07, 2009, 12:03:05 PM
gile,
You are correct, however, block "B" will have an insertion point within block "A" ... and will return an insertion point in relation to OCS. Only if the user needs WCS will nentselp or another calculation of a transformation martrix be needed.

It sounds to me like the task is merely to replace a block insertion with another block. If that is the case, which we still don't have a clear answer, merely redefining the block in the blocks collection will work, OR insert the new block at the insertion point of the BlockReference in ModelSpace or PaperSpace.

Ok. I have old block. Old block has changed. I want drawing to reflect these changes with the new "improved" block. It's a pretty common operation, however I'm using objectDBX, and going through several thousand drawings to do so.

Pulling from an excel spreadsheet, if it finds a block the same name as cell A1, it replaces it with an insert by the name in B1. And so on and so fourth through each block in each drawing.

Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: Keith™ on December 07, 2009, 12:11:20 PM
Ok, so you want to redefine a block ... lets call it block "A" ... to do this, you want to get the insertion point of block "A" so you can put the new block in its place. Great .. now we are getting somewhere ... except you can't do that using a block from the blocks collection .. that is merely the definition of a block ...

To use an insertion point, you have to have an "INSERT" .. which is a BlockReference, you have a "BLKDEF" i.e. Block ...

You have a few options:
A) Select all of the inserted blocks in the drawing, either through an iteration of every element in the drawing, or by opening the drawing and using a select call to find them all, then get the insertion point of each INSERT and put your new INSERT there.

OR

B) Take the block definition (from the Blocks Collection) and delete all objects in it .. then add the items you want to that block definition.

OR

C) Insert the redefined BLOCK from a file, causing the definition to be overwritten.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: Lee Mac on December 07, 2009, 12:57:14 PM
When I posted, I was under the impression that you wanted to modify the nested block within the BLOCK definition in some way, but it now appears that you want to replace the INSERT in the drawing, at each occurrence.

As Keith points out, this can be done using a SelectionSet, or Iterating through the objects in the drawing, or if the new block is defined in the block table, then you can just substitute the name of the new block for the old in the INSERT.

Lee
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: Lee Mac on December 07, 2009, 01:16:50 PM
One more point ArgV,

You can check the available properties/methods that are applicable to an object, using either:

Code: [Select]
(vlax-dump-object <obj> t)

Or

Code: [Select]
(vlax-property-available-p <obj> 'Property)

(vlax-method-applicable-p <obj> 'Method)

And hence you will correctly find that the BLOCK Definition does not have the InsertionPoint property  :wink:

Lee
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: T.Willey on December 07, 2009, 01:25:55 PM
I would go with option B from Keith's post.

Edit: Especially if you want to go the ObjectDBX route.

Edit:  Maybe this post will give you the general idea of one way to do it.
[ http://www.theswamp.org/index.php?topic=23128.0 ]
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: CAB on December 07, 2009, 01:34:41 PM
Just playing "What If" in my head, plenty of spare room in there. :evil:

Condition 1
What if you want to replace a block A which has block C within it.
The New block B has block D within it. But block D does not exist in the DWG.

Condition 2
What if you want to replace a block A which has block C within it.
New block B has a different block C within it.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: ArgV on December 07, 2009, 06:19:03 PM
Ok, so you want to redefine a block ... lets call it block "A" ... to do this, you want to get the insertion point of block "A" so you can put the new block in its place. Great .. now we are getting somewhere ... except you can't do that using a block from the blocks collection .. that is merely the definition of a block ...

To use an insertion point, you have to have an "INSERT" .. which is a BlockReference, you have a "BLKDEF" i.e. Block ...

You have a few options:
A) Select all of the inserted blocks in the drawing, either through an iteration of every element in the drawing, or by opening the drawing and using a select call to find them all, then get the insertion point of each INSERT and put your new INSERT there.

OR

B) Take the block definition (from the Blocks Collection) and delete all objects in it .. then add the items you want to that block definition.

OR

C) Insert the redefined BLOCK from a file, causing the definition to be overwritten.

I'm just realizing how very little I know about how autocad actually uses and handles blocks.

A block is nothing more than a selection set that has been, uh, 'glued' together so to speak. right? So, what I think I'm hearing is that if this block I want to replace was not "inserted" but rather was formed from within the drawing, it would not have an insertionpoint, however ALL blocks have a point at which they are inserted.

I don't know, now I'm really confused. I appreciate the help, but it's not penetrating the thickness of my skull.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: ArgV on December 07, 2009, 06:21:25 PM
When I posted, I was under the impression that you wanted to modify the nested block within the BLOCK definition in some way, but it now appears that you want to replace the INSERT in the drawing, at each occurrence.

As Keith points out, this can be done using a SelectionSet, or Iterating through the objects in the drawing, or if the new block is defined in the block table, then you can just substitute the name of the new block for the old in the INSERT.

Lee

The new block does not reside in the drawing currently. They were "fixed" outside the drawing, and now the old ones need to be swapped out with the new ones, which is why I have to INSERT them, rather than just update them. (which I'm foggy on that one as well).

Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: ArgV on December 07, 2009, 06:23:51 PM
One more point ArgV,

You can check the available properties/methods that are applicable to an object, using either:

Code: [Select]
(vlax-dump-object <obj> t)

Or

Code: [Select]
(vlax-property-available-p <obj> 'Property)

(vlax-method-applicable-p <obj> 'Method)

And hence you will correctly find that the BLOCK Definition does not have the InsertionPoint property  :wink:

Lee

Yep, I got that one figured out. :) So, then, what I can't figure out is why, and what I can do to get around it. I'm getting lots of ideas, but just not able to get my mind around them. Thank you for help though. I need a deeper understanding of the autcad database and how it works I guess.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: ArgV on December 07, 2009, 06:25:46 PM
I would go with option B from Keith's post.

Edit: Especially if you want to go the ObjectDBX route.

Edit:  Maybe this post will give you the general idea of one way to do it.
[ http://www.theswamp.org/index.php?topic=23128.0 ]

which version? It looks like there are 3 posts there with different approaches. I can't use entsel obviously, I'm stuck doing it all programically. Hey, is it ok to use selection sets in objectDBX? I'm not sure, or don't remember.

I'll give those a look tonight while I'm drinkin my Gin and juice and racking my brain. ;)
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: Lee Mac on December 07, 2009, 06:26:15 PM
When present in (but not necessarily inserted into) a drawing, Blocks are defined in the Block Collection, and all the elements that make up a block (i.e. lines, circles, attdefs, etc) are a member of that definition, just as lines and circles in a drawing are a member of the Paperspace or Modelspace "block".

The block as defined in the Block Collection does not have an insertion point, as it is just a definition and is separate from ModelSpace and/or PaperSpace in which entities have Insertion Points. You can think of the block definition as another PaperSpace/ModelSpace in which the objects are defined.

When you insert a block, you are inserting a reference to the definition that is contained in the Block Collection - as if you were viewing the block collection through a Viewport might be an analogy. And now that this object is part of PaperSpace/ModelSpace it has an insertionpoint and rotation etc, just as you are likely to find for any other object.

I hope I haven't just confused the hell out of you, but if others believe my explanation to be erroneous, please chime in - I would want to be corrected if I am mistaken for the sake of my own knowledge of such things...

Lee
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: ArgV on December 07, 2009, 06:29:09 PM
When present in a drawing, Blocks are defined in the Block Collection, and all the elements that make up a block (i.e. lines, circles, attdefs, etc) are a member of that definition, just as lines and circles in a drawing are a member of the paperspace or modelspace "block".

The block as defined in the Block Collection does not have an insertion point, as it is just a definition and is separate from ModelSpace and/or PaperSpace in which entities have insertion Points. You can think of the block definition as another PaperSpace/ModelSpace in which the objects are defined.

When you insert a block, you are inserting a reference to the definition that is contained in the Block Collection - as if you were viewing the block collection through a Viewport might be an analogy. And now that this object is part of PaperSpace/ModelSpace it has an insertionpoint and rotation etc, just as you are likely to find for any other object.

I hope I haven't just confused the hell out of you, but if others believe my explanation to be erroneous, please chime in - I would want to be corrected if I am mistaken for the sake of my own knowledge of such things...

Lee

Ok, I think I can get that much. What I don't understand I guess, is why I would have a block or HOW you can get a block that doesn't have an insertion point? Is it because it's never been inserted?
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: Lee Mac on December 07, 2009, 06:31:04 PM
The new block does not reside in the drawing currently. They were "fixed" outside the drawing, and now the old ones need to be swapped out with the new ones, which is why I have to INSERT them, rather than just update them. (which I'm foggy on that one as well).

Say you have Block A inserted in the drawing, and you want to replace it with Block B (which is also defined in the drawing - i.e. contained in the block collection, but not necessarily inserted).

Then this should successfully "swap" the blocks:

Code: [Select]
(defun c:test (/ nblk ent )

  (setq nblk "test") ;; Replacement Block

  (if (tblsearch "BLOCK" nblk)
   
    (if (and (setq ent (car (entsel "\nSelect Block to be Replaced: ")))
             (eq "INSERT" (cdr (assoc 0 (entget ent)))))
     
      (entmod (subst (cons 2 nblk) (assoc 2 (entget ent)) (entget ent))))
   
    (princ "\n** Replacement Block must be defined in the drawing **"))

  (princ))
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: Lee Mac on December 07, 2009, 06:32:26 PM
When present in a drawing, Blocks are defined in the Block Collection, and all the elements that make up a block (i.e. lines, circles, attdefs, etc) are a member of that definition, just as lines and circles in a drawing are a member of the paperspace or modelspace "block".

The block as defined in the Block Collection does not have an insertion point, as it is just a definition and is separate from ModelSpace and/or PaperSpace in which entities have insertion Points. You can think of the block definition as another PaperSpace/ModelSpace in which the objects are defined.

When you insert a block, you are inserting a reference to the definition that is contained in the Block Collection - as if you were viewing the block collection through a Viewport might be an analogy. And now that this object is part of PaperSpace/ModelSpace it has an insertionpoint and rotation etc, just as you are likely to find for any other object.

I hope I haven't just confused the hell out of you, but if others believe my explanation to be erroneous, please chime in - I would want to be corrected if I am mistaken for the sake of my own knowledge of such things...

Lee

Ok, I think I can get that much. What I don't understand I guess, is why I would have a block or HOW you can get a block that doesn't have an insertion point? Is it because it's never been inserted?

A block may be present in the Block Collection, but not in the drawing itself (thats what purge was invented for.. lol), try it - insert a block, then delete it. Then check the table.
Title: Re: Insertionpoint of complex object WITHOUT using nentsel
Post by: T.Willey on December 07, 2009, 06:44:51 PM
I would go with option B from Keith's post.

Edit: Especially if you want to go the ObjectDBX route.

Edit:  Maybe this post will give you the general idea of one way to do it.
[ http://www.theswamp.org/index.php?topic=23128.0 ]

which version? It looks like there are 3 posts there with different approaches. I can't use entsel obviously, I'm stuck doing it all programically. Hey, is it ok to use selection sets in objectDBX? I'm not sure, or don't remember.

I'll give those a look tonight while I'm drinkin my Gin and juice and racking my brain. ;)

You can use any of them, but just note that the last one will change the nested blocks definition also, not just the main block.  These all work on some type of selection, so they will have to be changed in that aspect, but they should give you a good idea of how to do what you want to do.  No selection sets with drawings opened with ObjectDBX.

I think there is just confusion on the naming of objects:

Block = block definition
Insert = inserted block definition

Maybe this will help clear up some confusion with the help people are trying to provide.