What I would do is extract the insertions points, block names, xyz factors (if applicable), delete the objects (blocks), then reinsert the correct block at the correct insertion point unless you need any other special needs. I have something for text but not blocks.
Depends on what the "objects" are. Most AutoCAD entities have a location/base point that can be modified, effectively "moving" the object. If these are blocks, no need to delete anything; just store the first insertion point, change the insertion point of the second object to the insertion point of the first, then change the insertion point of the first object to the stored location. If these are custom objects from third-party software, you may not have the means to do this.
Have a look into the (entget...), (subst...), and (entmod...) functions. If you are feeling inquisitive, have a look into using calls to vla-methods to do this with VLISP; less code overall but requires a better understanding of what is being done.
But it also depends on how much code you want to type. Your route adds more code in my opinion and you forgot to add the entupd function also in your post. But to each his own. You can have multiple programs that do the same thing. But the true test if it works for you because that is the only thing that matters.
@pjtjr wrote:
....What I want to do is take two items (light fixtures) and swap their positions on the drawing. ....
If they're Blocks, with the same kind of relationship to their insertion points so that you can use those as displacement definition points, then in simplest terms, you can do this:
(defun C:BS (/ b1 b2 b1ins b2ins) ; = Block Swap
(setq
b1 (car (entsel "\nSelect first Block: "))
b2 (car (entsel "\nSelect second Block: "))
b1ins (cdr (assoc 10 (entget b1)))
b2ins (cdr (assoc 10 (entget b2)))
)
(command
"_.move" b1 "" "none" b1ins "none" b2ins
"_.move" b2 "" "none" b2ins "none" b1ins
)
)
If they're something else, or if their relationships to their insertion points are too different, you could do something like find the middle of the bounding box of each, and use those to define the displacement, or maybe some other approaches.
Just what I was thinking of but except you used move. Nice, simple code and no need to wear out your fingers typing cause I am a terrible typist. Fat finger syndrome.
@Anonymous wrote:What I would do is extract the insertions points, block names, xyz factors (if applicable), delete the objects (blocks), then reinsert the correct block at the correct insertion point.....
If you do it that way, you would also need to extract their rotation angles and Layers. And if they have any Attributes, you would need to extract their values, and assign them again in the reinsertions somehow. All of those complications are why I would be inclined to simply Move them. That way, you don't need to get anything from them except their insertion points. Scales and rotation and Layers and Attributes are retained, their Block names are irrelevant, draw order is unaffected if that matters, even something weirder such as that they were Inserted in different Coordinate Systems wouldn't matter, etc., etc. But it does depend on the insertion points being valid as displacement definers. Still, even if they're not, using something like the middles of their bounding boxes to Move them would still work without the need to extract and re-use any other information from them.
@pjtjr wrote:
Kent, That is exactly what I was thinking. Just don't have the grasp on lisp to put it down that way. The blocks I'm dealing with are pretty simple so there shouldn't be an issue with the insertion point stuff. Thanks again.
You're welcome. If you want to get more sophisticated about it, you can add an entity-type and/or a locked-Layer check on the selection, and error handling, and all that other stuff.
My next question would be: How do I make the function work with two blocks that I have already selected?
You are correct, Sir. I was just looking at it as the OP stated them (blocks) being simple light fixtures and me assuming that they would be on the same layer and such.
@pjtjr wrote:My next question would be: How do I make the function work with two blocks that I have already selected?
If you have them in a selection set made with (ssget) or (ssadd) or something [let's call it ss], and there's nothing else in that selection set:
(setq
b1 (ssname ss 0))
b2 (ssname ss 1))
....
and the rest the same.
If you have their entity names separately stored in variables, just remove the lines setting b1 & b2, and replace b1 & b2 in the rest of the code with the variable names you've already got.
I used VL to avoid the issue of annotative blocks in some cad versions.
(defun c:Test (/ ss lst)
(vl-load-com)
(if (setq ss (ssget "_:L" '((0 . "INSERT"))))
(if (eq (sslength ss) 2)
(mapcar 'vla-put-insertionpoint
(setq lst (mapcar '(lambda (i) (vlax-ename->vla-object (ssname ss i))) '(0 1)))
(mapcar 'vla-get-insertionpoint (reverse lst))
)
(princ "Selection amount must be equal to 2!")
)
)
(princ)
)
@tony1935e wrote:
....WE NEED THIS TO BE A COMMAND. ....
AutoCAD may not yet have made a swapping command, but others have. For instance, go here, and either use the one it's about at the top of the page [if it suits you] or get my latest Swap.lsp file attached at the fifth comment [which overcomes shortcomings of the top-of-page routine noted in earlier comments]. You can swap whole selection sets, not just individual objects, and of any type(s) [not just the Blocks that are the thrust of most of this thread]. And if either selection consists of just one object with some logical reference point [such as a Block's insertion point, or a Circle's center], you can just hit Enter to accept that offered default as the Swap reference location if you like, rather than picking a reference point.
[By the way, if your ranting is intended to prod AutoDesk into incorporating something like this into AutoCAD, this is not the place to do it. This is a User Forum -- we're just other users like you. There is some degree of participation by AutoDesk employees, but mostly along the lines of help in usage, not in the product-development arena.]