PDA

View Full Version : Create selection set of newest entities created by copy command



Borg
2004-10-29, 06:50 PM
Let's say that I select a bunch of stuff and copy it. I want to make a selection set
of the new stuff created by the copy command.

Thanks for any and all suggestions. :

CAB2k
2004-10-29, 09:22 PM
You can use this

;;============================================================
; Rune Wold and Michael Puckett - modified
; e.g. usage (setq marker (ALE_LASTENT))
;; Function to get the absolute last entity in the database
;; Returns nil is drawing is completely empty
(defun ALE_LastEnt ( / EntNam OutVal)
(and
(setq OutVal (entlast)); if there is an entity in drawing
(while (setq EntNam (entnext OutVal))
(setq OutVal EntNam)
)
)
OutVal
)
;;============================================================
;; Function to get new items after EntNam in the database
(defun ALE_Ss-After (EntNam / EntNxt SelSet)
(cond
( (not EntNam) (ssget "_X") ); dwg was empty
( (setq EntNxt (entnext EntNam)); get new items
(setq SelSet (ssadd EntNxt))
(while (setq EntNxt (entnext EntNxt))
(if (entget EntNxt) (ssadd EntNxt SelSet))
)
SelSet
)
)
)
;=========================================================

;;=====================================================================
;;=================== Code to get New objects ========================
;;=====================================================================
(setq elast (ALE_LastEnt)); get last entity in database
(setq newbies (ssadd)) ; create an empty selection set
;;
;; Do your array or paste command
;;
(setq newbies (ALE_Ss-After elast))
;; newbies is a selection set of all items created by your command.
;;=====================================================================

Borg
2004-10-29, 09:25 PM
Thanks. I'll give it a try next week.

eddyhgng
2004-11-01, 07:47 AM
how about

(setq sel (ssget))
(command "copy" sel "" "0,0" "0,0" "move" "P" "" pause pause)
(setq sel2 (ssget "p"))

stig.madsen
2004-11-01, 01:42 PM
how about

(setq sel (ssget))
(command "copy" sel "" "0,0" "0,0" "move" "P" "" pause pause)
(setq sel2 (ssget "p"))
No point, really .. sel2 will contain the same selection as sel. I see only two ways, one of which is given above by Ab2draft. The other way is using the ActiveX methods Copy and CopyObjects, which will both return the copied object(s).

Mike.Perry
2004-11-01, 03:28 PM
No point, really .. sel2 will contain the same selection as sel.
Hi

Have you actually tried what "eddyhgng" posted, I think you might be surprised....

Have a good one, Mike

CAB2k
2004-11-01, 03:41 PM
I was surprised, it did work. Not sure I understand why?

stig.madsen
2004-11-01, 05:27 PM
Hi

Have you actually tried what "eddyhgng" posted, I think you might be surprised....

Have a good one, Mike
Yes, line by line. It moves the original objects so that it appears to be the new objects being selected .. kinda like an optical illusion.

Mike.Perry
2004-11-01, 06:03 PM
Yes, line by line. It moves the original objects so that it appears to be the new objects being selected .. kinda like an optical illusion.
Hi Stig

Can you please explain, you've lost me (not difficult I know).

:beer: Mike

Borg
2004-11-01, 06:19 PM
Reply to Eddyhgng:

Thanks for your input.
What I'm trying to do is create a rector(this part is done) that reacts on the copy command.
It will then iterate through all of the new objects created by said command to check for blocks of a particular name.

I should be able to incorporate the code AB2DRAFT to make this happens.
Your code is valid but I don't wan't to redefine the copy command.

stig.madsen
2004-11-01, 06:19 PM
Sure Mike. The task was to "make a selection set of the new stuff created by the copy command" - not to return the original objects. This makes perfect sense because the original objects can be involved in intelligent operations, which can be depending on handles, enames, selections, groups, attribute data, draworder or whatever .. making it a good thing to keep the originals untouched.

(setq sel (ssget))
-> sets sel to contain some objects

(command "copy" sel "" "0,0" "0,0" "move" "P" "" pause pause)
-> copies objects in sel - then moves previously selected objects, which are equal to the objects in sel

(setq sel2 (ssget "p"))
-> grabs previously selected objects, which again are equal to the original objects in sel


We are used to move the new objects within the COPY command. This snippet simply plays a trick on us because it moves the original objects instead. Check the enames in sel and sel2 .. they will be identical.

Here's a small thing to print out enames from a selection set:


(defun EntsOut (ss / a)
(setq a 0)
(repeat (sslength ss)
(princ (ssname ss a)) (terpri)(setq a (1+ a)))
(princ)
)

Mike.Perry
2004-11-01, 06:35 PM
Hi Stig

Thanks for the clear explanation (even I understood that).

:beer: Mike

ps I should've known better to tackle a LISP Master....

kennet.sjoberg
2004-11-01, 10:59 PM
And here is an other way to understand
- draw a line, dimension the line with associative dimension
copy the line and then move previous . . . bee unhappy
- draw a line, dimension the line with associative dimension
copy the line with copy2 and then move previous . . . bee happy


(defun C:copy2 ( / OldCmd LastEnt SelSet1 SelSet2 Ent )
;;; Select a bunch of stuff and copy it. This one make a selection set of the new stuff,
;;; and put it in to Previous. / kennet
(setq OldCmd (getvar "CMDECHO" ) )
(setq LastEnt (entlast) ) ;; place holder
(setq SelSet1 (ssget) )
(setvar "CMDECHO" 1 )
(command "._copy" SelSet1 "" )
(while (= 1 (logand (getvar "CMDACTIVE" ) 1 ) ) (command PAUSE ) )
(setvar "CMDECHO" OldCmd )
(setq SelSet2 (ssadd) ) ;; create an empty selection set
(setq Ent LastEnt )
(while (setq Ent (entnext Ent ) ) ;; Step through new entities
(ssadd Ent SelSet2 ) ;; add to selection set
)
(command "select" SelSet2 "" )
(princ "\You will find the new stuff in Previous, try Command: move p" )
(princ)
)

: ) Happy Computing !

kennet

Tom Beauford
2004-11-03, 06:09 PM
How about using your reactor to (setq e1 (entlast), then upon close create your selection set by looping (entnext) begining with (entnext e1).

What I'm trying to do is create a rector(this part is done) that reacts on the copy command.
It will then iterate through all of the new objects created by said command to check for blocks of a particular name.

I should be able to incorporate the code AB2DRAFT to make this happens.
Your code is valid but I don't wan't to redefine the copy command.

stig.madsen
2004-11-03, 10:35 PM
The natural way to detect new objects would probably be a database reactor but you could try to have some fun with a command reactor. It's definately easier to work with. I'd just suggest that you use ActiveX for all your entity handling calls. Reason being that reactors can get serious hickups from the ENTxxx functions (especially, but not exclusively, when it needs to create objects).

Below is a simple scheme for such a reactor. It's set to fire on :vlr-commandWillStart and on :vlr-commandEnded. When a command starts, it runs the PUTCMD routine that does this:

- check to see if a COPY command is issued
- if so, get the total count of objects in the drawing (in this case, the space where the command was issued)
- put the total count of objects into its own data field

The data field of a reactor can be used for any arbitrary data that you may find suitable. It's good for carrying around data (if it can be garanteed that data doesn't go out of scope, of course).

When a command has ended, it fires again and runs the GETCMD routine. It does the following:

- check to see if a COPY command was issued
- if so, get the object count from before the COPY command did anything
- get the present count of objects in the active space
- run through each new object based on these counts
- see if it is a block and see if it matches a list of (hardcoded) names
- report any instances of new blocks of specified names

It should probably have some error catching tossed in here and there but you can play around with that part, also. To install the reactor, first run the INSTALLCMDREACTOR routine. It'll set up the reactor and assign a global variable. To kill it, use the standard VLR-REMOVE(-ALL) functions.


(defun installCmdReactor ()
(if (or (not gCmdReactor) (vl-catch-all-error-p
(vl-catch-all-apply 'vlr-added-p (list gCmdReactor)))
)
(setq gCmdReactor (vlr-command-reactor nil
'((:vlr-commandWillStart . putCmd)
(:vlr-commandEnded . getCmd)
)
)
)
)
)

(defun putCmd (vlr cmdInfo / doc space)
(cond
;; if a COPY command is detected
((member "COPY" cmdInfo)
;; then get the active space
(if (zerop (vla-get-activeSpace
(setq doc (vla-get-activedocument (vlax-get-acad-object)))))
(setq space (vla-get-paperspace doc))
(setq space (vla-get-modelspace doc))
)
;; and put the object count in the data field
(vlr-data-set vlr (1- (vla-get-count space)))
;; release some object references
(vlax-release-object space)
(vlax-release-object doc)
)
)
)

(defun getCmd (vlr cmdInfo / cnt copiedblocks doc index item space)
(cond
;; if a COPY is just done
((and (member "COPY" cmdInfo)
;; and it's data field holds a number
(numberp (setq index (vlr-data vlr)))
)
(setq copiedBlocks 0)
;; then get active space
(if (zerop
(vla-get-activeSpace
(setq doc (vla-get-activedocument (vlax-get-acad-object)))
)
)
(setq space (vla-get-paperspace doc))
(setq space (vla-get-modelspace doc))
)
;; get the current object count
(setq cnt (1- (vla-get-count space)))
;; report some silly info just for fun
(princ (strcat "\n" (itoa (- cnt index)) " object(s) created in total"))
;; step through all objects added since index
(while (<= (1+ index) cnt)
(setq item (vla-item space (setq index (1+ index))))
;; check if it's a block reference
(cond ((and (= (vla-get-objectName item) "AcDbBlockReference")
;; and if it has a name on the most-wanted list
(member (vla-get-name item) '("myBlockName" "addMoreOwnBlocksIfYouWant"))
)
;; if so, increment detected-block counter
(setq copiedBlocks (1+ copiedBlocks))
)
)
)
;; report the real stuff we want
(princ (strcat "\n" (itoa copiedBlocks) " special block(s) detected"))
;; release some object references
(vlax-release-object space)
(vlax-release-object doc)
)
)
;; just to be safe, clear the field
(vlr-data-set vlr nil)
)