Last Friday, talking about "DrawOrder", Dean Saadallah wrote: "there is a lisp called FLOAT posted all over this NG if you want to try it." --------------------------------------------------------------------- I did´t find the program. Where should I search fot it. Jesús Padilla
Hi Dean: I suposed Float was a "more developed" program. I use: (VL-CMDF "UNDO" "MARK" "COPYBASE" '(0 0 0) #SS-OR "" "PASTECLIP" '(0 0 0) "ERASE" #SS-OR "" );VL-CMDF But when the layer is locked, you can copy but you can´t delete them, so that, I get more entities. I will fix it. Thanks. JPadilla
Dean, There's a hidden bomb in that procedure: leaders don't like being copied and lose their tails. Only fix that I can see is to search the sset for leaders and actually rebuild them. It's on my list of Things To Do Real Soon Now. rs
Okay, try this: (defun c:fup( / ) ;float objects without copy. (setq sset (ssget)) (if sset (progn (setq x (sslength sset)) (setq count -1) (while (< count x) (setq count (1+ count)) (setq y (entget (ssname sset count))) (entdel (ssname sset count)) (entmake y) ) ) ) (princ))
TCEBob, Your program errors with,"bad argument type: lentityp nil" because the while loop runs once too often. A simpler alternative: (defun c:float ( / ss idx ename ) (setq ss (ssget)) (setq idx 0) (if ss (repeat (sslength ss) (setq ename (ssname ss idx)) (entmake (entget ename)) (entdel ename) (setq idx (1+ idx)) ) ) (princ) ) Joe Burke
Cadlantic's LORDER does it all with your choice of using draworder vs. recreate, grabbing associated objects, and a cute dialog to organize, save, and recall named layer order files. I see it needs an update to check for locked layers and better layout treatment <to-do list>.
(entmake) is not a good idea. I think Tony warned us of that recently because of things like optional 6 and 62 codes that may be missing. My warning is w/r/t complex entities like heavy polylines or blocks with attributes that would require digging into via (entnext), plus the references to associated entities would be broken. (command "_.copy" ...) should work just fine.
Hi John Thanks for the info. I wondered if there might be some pitfalls with entmake in this case. Similar caution using (vlax-invoke vobj 'Copy) rather than entmake? Help says, "you should not attempt to use this method (meaning Copy) on AttributeReference objects." Joe Burke
(entmake (entget ename)) This does not copy an entity. Not only does it not copy an entity, it can corrupt a drawing if the entity passed to entget has an extension dictionary. In that case, the resulting 'copy' of that entity that is produced by (entmake) will have the *same* extension dictionary, which effectively results in a "multiply-owned object" scenario, whereby a single object has more than one owner (a major no-no!). This can eventually lead to a corrupt, and possibly unrecoverable drawing. You need to use the ActiveX API to copy objects. Yet another reason why LISP is a dead end.
The WHOLE statement was <The newsreader server searches around here are useless, use the browser access instead>. The google search to which you pointed is a BROWSER search. An example of a newsreader server search is if I used Outlook Express to search. -- RDI (remove the exclamation from the email address) Since when? http://groups.google.com/groups?q=float.lsp
Allow me to correct myself. (entmake) will fail if there is an extension dictionary in the entity data list, so (entmake (entget ...)) does not work at all in that case, which is not as bad as corrupting a drawing, but nonetheless makes (entmake (entget ...)) a conceptually invalid construct, since manipulation of the result of (entget) is mandatory. I would have expected (entmake) to ignore an extension dictionary in the input data list, but it just fails unconditionally instead.
Let me correct myself again. (entmake) appears to fail when the list contains an extension dictionary, but actually doesn't fail, it just returns NIL and creates the entity without an extension dictionary. Of course, that makes it even more obvious that (entmake (entget ...)) does not 'copy' entities. Try using (vla-copy) on an entity with an extension dictionary, and you'll see that the dictionary is copied as well.
Tony, Do you see any problems with this approach? Is this brand of LISP dead? ;-) (defun c:float (/ lockedlayers relocklst *error* doc) ;;D. C. Broad, Jr. 1/23/2004 ;;This routine will not float main entities on locked ;;layers. ;;Error routine ensures that any unlocked layers are re-locked. (defun *error* (msg) (foreach layer relocklst (vla-put-lock layer :vlax-true)) (if msg (princ msg)) (vla-endundomark doc) (princ)) (setq doc (vla-get-activedocument(vlax-get-acad-object))) (vla-startundomark doc) (setq lockedlayers "") ;;make a list of locked layers. Unlock them temporarily ;;for this operation because nested objects on locked layers ;;can cause problems. Use the locked layer names as a filter ;;list for object selection. (vlax-for layer (vla-get-layers doc) (if (= :vlax-true (vla-get-lock layer)) (progn (setq lockedlayers (strcat (vla-get-name layer) "," lockedlayers) ) (vla-put-lock layer :vlax-false) (setq relocklst (cons layer relocklst))))) ;;Disallow selection of objects on locked layers (ssget (list (cons 8 (strcat "~" lockedlayers)))) ;;Copy and delete (vlax-for obj (vla-get-activeselectionset doc) (vla-copy obj) (vla-delete obj)) ;;Restore layer settings (*error* nil) )
Correction (if added) (defun c:float (/ lockedlayers relocklst *error* doc) ;;D. C. Broad, Jr. 1/23/2004 ;;This routine will not float main entities on locked ;;layers. ;;Error routine ensures that any unlocked layers are re-locked. (defun *error* (msg) (foreach layer relocklst (vla-put-lock layer :vlax-true)) (if msg (princ msg)) (vla-endundomark doc) (princ)) (setq doc (vla-get-activedocument(vlax-get-acad-object))) (vla-startundomark doc) (setq lockedlayers "") ;;make a list of locked layers. Unlock them temporarily ;;for this operation because nested objects on locked layers ;;can cause problems. Use the locked layer names as a filter ;;list for object selection. (vlax-for layer (vla-get-layers doc) (if (= :vlax-true (vla-get-lock layer)) (progn (setq lockedlayers (strcat (vla-get-name layer) "," lockedlayers) ) (vla-put-lock layer :vlax-false) (setq relocklst (cons layer relocklst))))) ;;Disallow selection of objects on locked layers (if (ssget (list (cons 8 (strcat "~" lockedlayers)))) ;;Copy and delete (vlax-for obj (vla-get-activeselectionset doc) (vla-copy obj) (vla-delete obj))) ;;Restore layer settings (*error* nil) )
I see plenty of problems with vla-copy over just plain (command "copy"....) especially with regard to leaders. Would copyobjects be better?
Yes. Copyobjects preserves the links between copied objects. (defun c:float (/ lockedlayers relocklst *error* doc objlst) ;;D. C. Broad, Jr. 1/23/2004 ;;This routine will not float main entities on locked ;;layers. ;;Error routine ensures that any unlocked layers are re-locked. (defun *error* (msg) (foreach layer relocklst (vla-put-lock layer :vlax-true)) (if msg (princ msg)) (vla-endundomark doc) (princ)) (setq doc (vla-get-activedocument(vlax-get-acad-object))) (vla-startundomark doc) (setq lockedlayers "") ;;make a list of locked layers. Unlock them temporarily ;;for this operation because nested objects on locked layers ;;can cause problems. Use the locked layer names as a filter ;;list for object selection. (vlax-for layer (vla-get-layers doc) (if (= :vlax-true (vla-get-lock layer)) (progn (setq lockedlayers (strcat (vla-get-name layer) "," lockedlayers) ) (vla-put-lock layer :vlax-false) (setq relocklst (cons layer relocklst))))) ;;Disallow selection of objects on locked layers (if (ssget (list (cons 8 (strcat "~" lockedlayers)))) ;;Copy and delete (progn (vlax-for obj (vla-get-activeselectionset doc) (setq objlst (cons obj objlst))) (vlax-invoke doc 'copyobjects objlst) (foreach obj objlst (vla-delete obj)))) ;;Restore layer settings (*error* nil) )
Yep! Is this brand of LISP dead? ;-) The (entxxxxx) style of LISP programming is dead. Even this approach is flawed, because it breaks inter- object references that may be stored in extension dictionaries, specifically in cases where both the referenced and the referencing objects are being "floated".
Actually, I'm afraid the answer is "Yes and No", or just a classic case of catch 22. You can deal with inter-object references using Copyobjects in cases where the referenced and the referencing objects are both involved in the same operation, but on the other hand, you would also be breaking any other reference to any object that is copied, if the referencing object(s) are not involved in the same deep clone operation. I'm afraid this is simply not an operation you can do in LISP or ActiveX, in a way that addresses all of the issues. For anyone that's interested, AcadX has a method that can solve the problem. The AcadXApplication object's SwapIds() method exchanges the objectid/handle and extension dictionaries of two database-resident objects, and provides a way to preserve inter-object references when copying objects for this kind of purpose. With it, you can use CopyObjects to clone a set of entities, then swap the objectids/handles and extension dictionaries of the original source objects with the copies, before deleting the source objects. IAcadXApplication.SwapIds(First as IAcadObject, Second as IAcadObject [, SwapXData as Boolean = False] [, SwapXDict as Boolean = False] ) First and Second are two objects whose data is to be exchanged. If SwapXData is true, then the Xdata of the two objects is also exchanged. If SwapXDict is true, then the extension dictionaries of both objects are swapped.