TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Lee Mac on July 24, 2009, 05:46:23 PM

Title: Deep Cloning
Post by: Lee Mac on July 24, 2009, 05:46:23 PM
I am in the middle of trying to figure out how to add existing objects to a block defintion through VL.

I have stumbled across this:

http://www.theswamp.org/index.php?topic=29366.0 (http://www.theswamp.org/index.php?topic=29366.0)

And I see that LE uses vla-copyobjects.

After reading up on this function, I see it uses something called "deep cloning".

What, may I ask, is that?

Lee
Title: Re: Deep Cloning
Post by: Lee Mac on July 24, 2009, 06:09:36 PM
On this same topic, I have tried to make the block using this method, but can't seem to get it to work. I keep getting an error: "Invalid Owner Object".

Here is the current method I am trying:

Code: [Select]
      (vla-copyobjects doc
        (vlax-make-variant
          (vlax-safearray-fill
            (vlax-make-safearray
              vlax-vbObject (cons 0 (1- (length bLst)))) bLst))
            (setq bdef
              (vla-add
                (vla-get-Blocks doc)
                  (vlax-3D-point pt) "NewBlock"))

Where bLst is a list of VLA-Objects, doc is the ActiveDocument.

I have also tried this:

Code: [Select]

      (vla-copyobjects doc
        (vlax-make-variant
          (vlax-safearray-fill
            (vlax-make-safearray
              vlax-vbObject (cons 0 (1- (length bLst)))) bLst))
        (vlax-make-variant
          (vlax-safearray-fill
            (vlax-make-safearray
              vlax-vbObject '(0 . 0))
            (setq bdef
              (vla-add
                (vla-get-Blocks doc)
                  (vlax-3D-point pt) "NewBlock")))))

Also, with no luck.

Any help is appreciated.

Lee
Title: Re: Deep Cloning
Post by: T.Willey on July 24, 2009, 06:20:42 PM
This works ( I hate dealing with variants in Lisp, it's unnatural ).

Code: [Select]
(vlax-invoke
    (vla-get-Activedocument (vlax-get-Acad-Object))
    'CopyObjects
    (list (vlax-ename->vla-object (car (entsel))))
    (vlax-invoke
        (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-Acad-Object)))
        'Add
        '(0. 0. 0.)
        "Testing"
    )
)
Title: Re: Deep Cloning
Post by: T.Willey on July 24, 2009, 06:24:25 PM
Deep cloning to me is coping on the lowest level.  If you deep clone a block, then you have to copy all the objects that make up the object.  I think deep cloning only really refers to complex entities, but I know nothing about it, so that it with a grain of salt.  You might do better to search the .Net or Arx groups.  Someone might have posted a good explanation in there.  Search here and the Adesk group.
Title: Re: Deep Cloning
Post by: Lee Mac on July 24, 2009, 06:26:25 PM
Thanks Tim,

Using your idea, I tried this:

Code: [Select]
     (vlax-invoke doc 'copyobjects bLst
        (vlax-invoke
          (vla-get-Blocks doc) 'Add
            (vlax-3D-point pt) "NewBlock"))

But I got the Error: "Exception Occurred".

Would it make a difference what my objects are?

For example, the variable bLst looks like this:

Code: [Select]
(#<VLA-OBJECT IAcadAttribute 186894ec> #<VLA-OBJECT IAcadAttribute 1868956c>
#<VLA-OBJECT IAcadAttribute 186895ec> #<VLA-OBJECT IAcadAttribute 1868936c>
#<VLA-OBJECT IAcadAttribute 186893ec> #<VLA-OBJECT IAcadAttribute 1868946c>
#<VLA-OBJECT IAcadAttribute 1868906c> #<VLA-OBJECT IAcadAttribute 1868926c>
#<VLA-OBJECT IAcadAttribute 186892ec> #<VLA-OBJECT IAcadAttribute 18688fec>
#<VLA-OBJECT IAcadAttribute 1868916c> #<VLA-OBJECT IAcadAttribute 18688f6c>
#<VLA-OBJECT IAcadAttribute 1814a964> #<VLA-OBJECT IAcadAttribute 1814ae64>
#<VLA-OBJECT IAcadAttribute 1814b2e4> #<VLA-OBJECT IAcadAttribute 185e7f7c>
#<VLA-OBJECT IAcadLWPolyline 0e6af944> #<VLA-OBJECT IAcadAttribute 185e7f7c>
#<VLA-OBJECT IAcadLWPolyline 0e6af944> #<VLA-OBJECT IAcadAttribute 185e7f7c>
#<VLA-OBJECT IAcadLWPolyline 0e6af944> #<VLA-OBJECT IAcadAttribute 185e7f7c>
#<VLA-OBJECT IAcadLWPolyline 0e6af944> #<VLA-OBJECT IAcadAttribute 185e7f7c>
#<VLA-OBJECT IAcadLWPolyline 0e6af944> #<VLA-OBJECT IAcadLWPolyline 18303f3c>
#<VLA-OBJECT IAcadLWPolyline 183031bc> #<VLA-OBJECT IAcadLWPolyline 1830315c>
#<VLA-OBJECT IAcadLWPolyline 18302cdc> #<VLA-OBJECT IAcadLWPolyline 18302bbc>
#<VLA-OBJECT IAcadLWPolyline 18302dfc> #<VLA-OBJECT IAcadLWPolyline 1830357c>
#<VLA-OBJECT IAcadLWPolyline 1830585c>)

Thanks for your response Tim, you are very helpful  :-)
Title: Re: Deep Cloning
Post by: Lee Mac on July 24, 2009, 06:28:58 PM
Deep cloning to me is coping on the lowest level.  If you deep clone a block, then you have to copy all the objects that make up the object.  I think deep cloning only really refers to complex entities, but I know nothing about it, so that it with a grain of salt.  You might do better to search the .Net or Arx groups.  Someone might have posted a good explanation in there.  Search here and the Adesk group.

I found this from a Java site, I suppose the same thing applies for LISP:

http://technologiquepanorama.wordpress.com/2009/01/11/what-is-deep-copy/ (http://technologiquepanorama.wordpress.com/2009/01/11/what-is-deep-copy/)
Title: Re: Deep Cloning
Post by: T.Willey on July 24, 2009, 06:38:37 PM
Thanks Tim,

Using your idea, I tried this:

Code: [Select]
     (vlax-invoke doc 'copyobjects bLst
        (vlax-invoke
          (vla-get-Blocks doc) 'Add
            (vlax-3D-point pt) "NewBlock"))

But I got the Error: "Exception Occurred".

When you use ' vlax-invoke ' you use lists, so no need to convert the point to a ' vlax-3d-point '.  Take that call out, and it should work.

As far as the deep cloning, I would think the same principal would apply to most languages.

You're welcome.
Title: Re: Deep Cloning
Post by: Lee Mac on July 24, 2009, 06:40:43 PM
Ahh, of course... the 3D-point is a variant... the "unnatural" type :P

School-boy error  :-)

Thanks Tim, will give it a go  :-)
Title: Re: Deep Cloning
Post by: Lee Mac on July 24, 2009, 06:43:57 PM
Oh dear, I can't believe how much trouble I am having with this code  :-P

I am using this:

Code: [Select]
      (vlax-invoke doc 'copyobjects bLst
        (vlax-invoke
          (vla-get-Blocks doc) 'Add pt "NewBlock"))

But I still seem to get this:

Code: [Select]
** Error: AutoCAD.Application: Invalid owner object **

But, I can't see what I am doing that is different to your example  :|
Title: Re: Deep Cloning
Post by: T.Willey on July 24, 2009, 06:55:30 PM
How are you getting the objects within the list?  If you post the whole code maybe we can get a better idea of why it's not working as is.
Title: Re: Deep Cloning
Post by: Joe Burke on July 25, 2009, 04:58:31 AM
May I suggest it's not a good idea to nest functions while trying to troubleshoot a problem like this. Add the block first and assign it to a variable. Make sure that works as expected. Then do CopyObjects.
Title: Re: Deep Cloning
Post by: Lee Mac on July 25, 2009, 08:38:04 AM
May I suggest it's not a good idea to nest functions while trying to troubleshoot a problem like this. Add the block first and assign it to a variable. Make sure that works as expected. Then do CopyObjects.

Thanks Joe, I have tried this but still no luck :-(
Title: Re: Deep Cloning
Post by: VovKa on July 25, 2009, 10:02:53 AM
abstract from the help file on CopyObjects method
Quote
Objects

Variant (array of objects); input-only
The array of primary objects to be copied. All the objects must have the same owner, and the owner must belong to the database or document that is calling this method.
Title: Re: Deep Cloning
Post by: Lee Mac on July 25, 2009, 10:08:57 AM
haha... of course... I am ripping Objects from block definitions... Thanks VovKa!
Title: Re: Deep Cloning
Post by: Jürg Menzi on October 07, 2010, 08:00:36 AM
This works ( I hate dealing with variants in Lisp, it's unnatural ).

Thanks Tim, you helped me out to create a VBA solution based on your code:
Code: [Select]
'Function MeCloneBlockRef
'Description:
'     Clones a Block reference into a new Block definition.
'   Arguments:
'     - oOldBlk = Existing Block reference
'     - sNewNme = New Block name
'     - oNewBlk = New Block definition
'   Return:
'     - True = Success
'     - False = Error
'   Remarks:
'     - Based on a VisualLISP code from Tim Willey, San Fernando Valley CA, USA
'
Public Function MeCloneBlockRef(ByVal oOldBlk As AcadBlockReference, ByVal sNewNme As String, oNewBlk As AcadBlock) As Boolean
  Dim aTmpBlk(0) As Object
  Dim aNulPnt(0 To 2) As Double
  On Error Resume Next
  With ThisDrawing
    .Blocks.Item sNewNme
    If Err.Number <> 0 Then 'If Block definition doesn't exist...
      Err.Clear
      aTmpBlk(0) = oOldBlk
      aNulPnt(0) = 0#: aNulPnt(1) = 0#: aNulPnt(2) = 0#
      .CopyObjects aTmpBlk, .Blocks.Add(aNulPnt, sNewNme)
      Set oNewBlk = .Blocks.Item(sNewNme)
      MeCloneBlockRef = True
    End If
  End With
End Function

Reason:
ObjectDBX for VBA isn't supported on 64Bit OS.

Cheers
Title: Re: Deep Cloning
Post by: T.Willey on October 07, 2010, 11:14:41 AM
Good to hear Jurg, you're welcome.  I've learned a lot from your code, so it's nice I could pay you back some.
Title: Re: Deep Cloning
Post by: gile on October 07, 2010, 02:02:02 PM
Hi,

Here's a vlisp code which creates a block definition from a selection set, an insertion point and a name:

Edited code: I forgot *acdoc* and *blocks* global variables
Code: [Select]
(defun c:ss2blk    (/ name ss lst ins blk)
  (vl-load-com)
  (or *acdoc*
      (setq *acdoc* (vla-get-ActiveDocument (vlax-get-acad-object)))
  )
  (or *blocks* (setq *blocks* (vla-get-Blocks *acdoc*)))
  (if
    (and
      (setq ss (ssget))
      (setq ins (getpoint "\nSpecify insertion point: "))
    )
     (progn
       (setq name (getstring "\nEnter block name: "))
       (while (tblsearch "BLOCK" name)
     (setq
       name
        (getstring (strcat "\nA block named '"
                   name
                   "' already exists\nEnter block name: "
               )
        )
     )
       )
       (vlax-for o (setq ss (vla-get-ActiveSelectionSet *acdoc*))
     (setq lst (cons o lst))
       )
       (vla-delete ss)
       (setq blk (vla-Add *blocks* (vlax-3d-point '(0. 0. 0.)) name))
       (setq lst (vlax-invoke *acdoc* 'CopyObjects lst blk))
       (foreach    o lst
     (vla-move o
           (vlax-3d-point (trans ins 1 0))
           (vlax-3d-point '(0. 0. 0.))
     )
       )
     )
  )
  (princ)
)
Title: Re: Deep Cloning
Post by: jbuzbee on October 08, 2010, 03:12:34 PM
Deep Cloning?

That's done on Kamino, a few parsecs beyong the outer rim . . . they're "cloners" ya know  :wink:
Title: Re: Deep Cloning
Post by: Lee Mac on October 08, 2010, 03:15:13 PM
Deep Cloning?

That's done on Kamino, a few parsecs beyong the outer rim . . . they're "cloners" ya know  :wink:

 :lmao:  :lmao:
Title: Re: Deep Cloning
Post by: Jeff H on November 10, 2010, 01:31:35 AM
Here is a quick dirty explanation. If you would like me to go in more detail I will
For AutoCAD to name a few you have

Clone "Shallow Clone"      DeepClone      DeepCloneObjects         WblockClone            WblockCloneObjects


The AutoCAD commands like Copy, Mirror, Insert etc....use DeepClone.

Simple rule to be safe always use DeepClone for cloning in same drawing and WblockClone for cloning between different drawings

I get unexpected results when I use the clone method on a "visible" entity  because I believe AutoCAD checks to see if it owns any objects and if it does then it uses Deepclone

When you use DeepClone it will check if the object owns an object and if it does it will call DeepClone on that object then check if that object owns an object if so calls deepClone ............. until it reaches objects that do not own an object.
 
If I use the clone method on a block it will create a copy of the block with no entites in it.

Also deepcloning will handle translation
If copy an object with Xdata it will make sure the Xdata points to the new copy and not the original object

WblockCloneObjects is when you are copying between diffrent databases and will handle if the drawing you are copying to does not have the layer or linetype it makes a copy of that.
Deepclone is for same Database(Drawing) it make sure it points to the correct layer linetype.

There much more detail and steps involved with filing, Mapping, translating,etc...

But I will stop here so hopefully you will not figure out that I do not know what I am talking about.