TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started 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
-
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:
(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:
(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
-
This works ( I hate dealing with variants in Lisp, it's unnatural ).
(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"
)
)
-
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.
-
Thanks Tim,
Using your idea, I tried this:
(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:
(#<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 :-)
-
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/)
-
Thanks Tim,
Using your idea, I tried this:
(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.
-
Ahh, of course... the 3D-point is a variant... the "unnatural" type :P
School-boy error :-)
Thanks Tim, will give it a go :-)
-
Oh dear, I can't believe how much trouble I am having with this code :-P
I am using this:
(vlax-invoke doc 'copyobjects bLst
(vlax-invoke
(vla-get-Blocks doc) 'Add pt "NewBlock"))
But I still seem to get this:
** Error: AutoCAD.Application: Invalid owner object **
But, I can't see what I am doing that is different to your example :|
-
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.
-
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.
-
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 :-(
-
abstract from the help file on CopyObjects method
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.
-
haha... of course... I am ripping Objects from block definitions... Thanks VovKa!
-
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:
'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
-
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.
-
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
(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)
)
-
Deep Cloning?
That's done on Kamino, a few parsecs beyong the outer rim . . . they're "cloners" ya know :wink:
-
Deep Cloning?
That's done on Kamino, a few parsecs beyong the outer rim . . . they're "cloners" ya know :wink:
:lmao: :lmao:
-
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.