Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Save a selection window

21 REPLIES 21
SOLVED
Reply
Message 1 of 22
gccdaemon
1220 Views, 21 Replies

Save a selection window

I'm working on a routine to copy objects from blocks and x-refs into the current drawing using refedit. I've got 2 big problems:

 

1. I need to save the CP selection window so it can be applied to each selected x-ref / block.

2. When running the refedit routine, I need to change the settings for "Create unique layer, style, and block names" and "Lock objects not in working set" but can't seem to find where these variables are.

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
21 REPLIES 21
Message 2 of 22
Gary_J_Orr
in reply to: gccdaemon

the settings appear to be the same as for the bind command (according to this screwed up new help system, boy I miss my organized tree for navigating help): BINDTYPE 0=unique 1=not unique...

For the selection window (if saving the selected object(s) doesn't give you what you need then try collecting and storing the points prior to running the actual function using getpoint for the first point of the window and getcorner for the second point (using the first point as your startpoint argument), then passing those points to your selection function as well as whatever downstream function where you need them again.
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 3 of 22
dbroad
in reply to: gccdaemon

If you obtain the selection with ssget, then the method of selection and the points that are used in the CP method are accessible for each object in the selection set by (ssnamex ss #)

 

 

Architect, Registered NC, VA, SC, & GA.
Message 4 of 22
gccdaemon
in reply to: gccdaemon

I don't know much about (SSNAMEX, so maybe I can bounce some stuff off of you.

 

Say I use (command "._Select" "CP"), how would I save the pointlist to be used later?

 

Here is what I have so far. I'm not done with this yet mind you, so any help would be greatly appreciated.

 

 

 

(defun c:XCOPY (/ SS POINTLIST XREF ZBASE CMD XRLIST BNDY XROBJECT)
    (setq ZBASE "0,0,0")
    (setq CMD (getvar "cmdecho"))
    (setvar "cmdecho" 0)
    (STARTUNDO (ACADDOC))
    (princ "\nCommand: Select copy area:")
    (setq BNDY (C:GETWINDOW))
    (princ "\nCommand: Pick X-Refs or Blocks to copy objects from:")
    (setq XRLIST (ssget '((-4 . "<or") (0 . "BLOCK") (0 . "INSERT") (-4 . "or>"))))
    (if (= null XRLIST)
        (while (= null XRLIST)
                  (princ "\nCommand: No XREF/BLOCK selected:")
                  (ssget (setq XRLIST (ssget '((-4 . "<or") (0 . "BLOCK") (0 . "INSERT") (-4 . "or>"))))))
        (foreach XREF XRLIST
          (PROGN (setq inc (sslength XRLIST))
                       (setq XREF (cons (ssname XRLIST (setq inc (1- inc))) 1))
                       (command "-refedit" XREF "O" "N" "WP" BNDY "N"
                                       "_copy" "ALL" "" ZBASE ZBASE
                                       "_refset" "R" "ALL" ""
                                       "_refclose" "D" "Y"))))
  (ENDUNDO (ACADDOC))
  (princ "\nCommand: Done")
  (setvar "cmdecho" CMD)
  (princ)
)

 

(defun C:GETWINDOW (/ )
  (command "._Select" "CP")
  (setq POINTLIST ())
  (princ)

  (POINTLIST)
)

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 5 of 22
Gary_J_Orr
in reply to: gccdaemon

oops, I somehow jumper to a crossing window with my earlier suggestion instead of the crossing poly that you're after so I need to change my suggestion.
Given what I believe that you are trying to do (grab the entities from an xref or block) that fall within or cross a given area I would perhaps suggest actually creating a polygon, then grab that PG with entlast, then step through it's point entities using entnext, adding the point values of each into your pointlist. I guess that a pg might be handy later if you want to trim some of the retrieved entities later, but if not you can always delete it after aquiring the points.
You can then feed the pointlist to your ssget function(s).
search help for each of the functions that I have listed to help you understand them if need be. Otherwise... well... it's friday and I expect to be busy this evening and hungover tm but will check back to see if you have it solved eventually 😉
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 6 of 22
Gary_J_Orr
in reply to: Gary_J_Orr

Without actually diagnosing your code (which does need a bit of review) here is a method of aquiring a reusable set of points, call with: (setq VarNam (Selpoly)) where VarNam is the name of your desired pointlist variable:

 

;|
define reusable point list with a user defined 3D polyline
This is in "long-form": it uses more variables than needed for illustration
|;
(defun SelPoly ( / MainEnt SubEnt EntData EntyType PointList)
  ;create a 3dpoly (which lets us use entnext for points)
  (command "_3DPOLY")
  (while (= 1 (getvar "cmdactive")) (command Pause))
  ;get the entity that we just created
  (setq MainEnt (entlast))
  ;get the first vertice of the 3dpoly
  (setq SubEnt (entnext MainEnt))
  ;get the entity definition data of the vertice
  (setq EntData (entget SubEnt))
  ;get the entity type from the data to test against
  (setq EntyType (cdr (assoc 0 EntData)))
  ;start our point list using the "point" value form the "10" group
  (setq PointList (list (cdr (assoc 10 EntData))))
  (while (/= "SEQEND" EntyType)
    ;get the next vertice of the 3dpoly
    (setq SubEnt (entnext SubEnt))
    ;get the entity definition data of the vertice
    (setq EntData (entget SubEnt))
    ;get the entity type from the data
    (setq EntyType (cdr (assoc 0 EntData)))
    ;add to our point list if it's a vertice
    (if (/= "SEQEND" EntyType)
      (setq PointList (append (list (cdr (assoc 10 EntData))) PointList))
      )
    )
  ;get rid of the temp 3dpoly
  (entdel MainEnt)
  ;send our list back to the calling function
  (princ PointList)
  )

 

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 7 of 22
Gary_J_Orr
in reply to: Gary_J_Orr

This version uses a LWpolyline (it also includes the "trans" function that I omitted on the last version to ensure that the points translate to the active coordinate system):

 

;|
define reusable point list with a user defined LW polyline
This is in "long-form": it uses more variables than needed for illustration
lwpolylines store points in multiple "10" group codes so we will parse through the data
|;
(defun SelPoly ( / MainEnt EntData EntyPoint PointList)
  ;create a 3dpoly (which lets us use entnext for points)
  (command "_pline")
  (while (= 1 (getvar "cmdactive")) (command Pause))
  ;get the entity that we just created
  (setq MainEnt (entlast))
  ;get the entity definition data
  (setq EntData (entget MainEnt))
  ;get the point value from the first "10" group
  (setq EntyPoint (cdr (assoc 10 EntData)))
  ;translate the point from object Coordinate to current coordinate system
  (setq EntyPoint (trans EntyPoint MainEnt 1))
  ;start our point list using the point
  (setq PointList (list EntyPoint))
  ;shorten our list for the next point by cutting out the previous point
  (setq EntData (cdr (member (assoc 10 EntData) EntData)))
  ;create a test value for the assoc group
  (setq TestAssoc (member (assoc 10 Entdata) EntData))
  ;start a loop for the remaining points
  (while (/= nil TestAssoc)
    ;get the point value from the first "10" group
    (setq EntyPoint (cdr (assoc 10 EntData)))
    ;translate the point from object Coordinate to current coordinate system
    (setq EntyPoint (trans EntyPoint MainEnt 1))
    ;start our point list using the point
    (setq PointList (append (list EntyPoint) PointList))
    ;shorten our list for the next point by cutting out the previous point
    (setq EntData (cdr (member (assoc 10 EntData) EntData)))
    ;reset test value for the assoc group
    (setq TestAssoc (member (assoc 10 Entdata) EntData))
    )
  ;get rid of the temp LWpoly
  (entdel MainEnt)
  ;send our list back to the calling function
  (princ PointList)
  )

 

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 8 of 22
dbroad
in reply to: gccdaemon

Though I recommend using ssget, rather than the select command, I realize that the interactivity of the blue and green regions is lacking. To run the select command within a lisp program requires flexibility in input. Managing a generalized select command would mean running a loop of pauses and checking the status of CMDACTIVE or CMDNAMES. By limiting the selection to CP, only user points need to be captured. Within the point selection loop, the points can be stored in a list. There is no need to set the list to nil if the symbol that stores the list is local. The problem is that to access the selection set created by the select command, you need to use (ssget "p"). But that is a very unreliable method. It may select the objects just selected but if none were selected, it will use the last selection that returned objects. That would be a difficult to check logic flaw in the program. (I know of no way to delete the previous selection set, BTW  )So even though one uses select command for input feedback, the ssget command still needs to be used to create a reliable selection set.

The function below should work reliably. If the selection fails, a nil result is returned. If the selection succeeds, it returns a 2 element list (selection set <list of points>)

;;D. C. Broad, Jr.
;;Return a Crossing Polygon set and the list of points where interactivity
;;simulates the select command.
;;Disadvantage. Adds a command to the undo stack.
;;Call with (ssgetcp "My selection prompt") (defun ssgetcp (prmpt / lst pt ss) (prompt prmpt) (command "._select" "_cp") (while (and (setq pt (getpoint)) (listp pt)) (command pt) (setq lst (cons pt lst))) (command "" "");finish selection (if (setq ss (ssget "cp" lst)) (progn (sssetfirst nil ss) (list ss lst))) )

 

 I leave it up to you to figure out how to integrate this into your larger application.

Architect, Registered NC, VA, SC, & GA.
Message 9 of 22
gccdaemon
in reply to: gccdaemon

I'm going to try these suggestions out with the list not localized so I can pull it in the main routine when i need. I'll get back with you on results. Sorry for all the frustration, and thanks for bearing with me!

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 10 of 22
dbroad
in reply to: gccdaemon

There is no reason to change the function to remove lst localization.

 

(setq ssc (ssnamec "my prompt"))  will pass the selection set and the list of points to the calling function.  Always localize and pass via return value, (which in this case is a list with the selection set and the list of points.  The calling function would only need to use (setq pts (cadr ssc)) to get the list of points.

Architect, Registered NC, VA, SC, & GA.
Message 11 of 22
gccdaemon
in reply to: dbroad

About the localization, I wanted to integrate what you had into the current routine and localize it there. I don't think i need the selection set from the select command (or do I?), so I revised it so i get just the point list and pass the point list on to the refedit command. Sorry if it seems like I'm being stubbon, maybe I'm just misunderstanding?

 

So here is what I've got so far, and I'm getting an error "; error: bad argument type: lselsetp nil"

 

(defun c:XCOPY (/ SS PNT POINTLIST INC XR XREF XRLIST CMD BNDY XROBJECT)
;   (setq CMD (getvar "cmdecho"))
;   (setvar "cmdecho" 0)
    (STARTUNDO (ACADDOC))
    (princ "\nCommand: Select copy area:")
    (progn (command "._select" "_cp")
        (while (and (setq PNT (getpoint))
                 (listp PNT)
) ;AND
           (command PNT)
             (setq POINTLIST (cons PNT POINTLIST))
) ;WHILE
         (command "" ""))
    (princ "\nCommand: Select X-Refs or Blocks to copy objects from:")
    (setq XR (ssget '((-4 . "<or") (0 . "BLOCK") (0 . "INSERT") (-4 . "or>"))))
    (repeat (setq INC (sslength XRLIST))
        (setq XRLIST (cons (ssname XR (setq INC (1- INC))) 1))
) ;REPEAT
;   (if (= null XRLIST)
;       (progn (princ "\nCommand: No XREF/BLOCK selected:")
;                (setq XR (ssget '((-4 . "<or") (0 . "BLOCK") (0 . "INSERT") (-4 . "or>")))
;                 (repeat (setq INC (sslength XRLIST))
;                     (setq XRLIST (cons (ssname XR (setq INC (1- INC))) 1))
; ) ;REPEAT
; ) ;PROGN
   (foreach XREF XRLIST
       (progn (command "refedit" XREF "O" "N" "WP" POINTLIST "N")
                 (command "_copy" "ALL" "" "0,0,0" "0,0,0")
                 (command "_refset" "R" "ALL" "")
                  (command "_refclose" "D" "Y")
) ;PROGN
) ; FOREACH
; ) ;IF
    (ENDUNDO (ACADDOC))
    (princ "\nCommand: Done")
;   (setvar "cmdecho" CMD)
    (princ)
)

 

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 12 of 22
hmsilva
in reply to: gccdaemon

Hi Andrew,

perhaps something like this

(defun c:XCOPY (/ CMD INC OLD_PIK PNT POINTLIST SS SS1 XR XRLIST)
;   (setq CMD (getvar "cmdecho"))
;   (setvar "cmdecho" 0)
  (setq old_pik (getvar 'PICKFIRST))
  (setvar 'PICKFIRST 1)
    ;(STARTUNDO (ACADDOC))
    (princ "\nCommand: Select copy area:")
    (progn (command "._select" "_cp")
              (while (and (setq PNT (getpoint))
                              (listp PNT)
                       ) ;AND
                       (command PNT)
                       (setq POINTLIST (cons PNT POINTLIST))
             ) ;WHILE
             (command "" ""))
    (princ "\nCommand: Select X-Refs or Blocks to copy objects from:")
    (setq XR (ssget '((-4 . "<or") (0 . "BLOCK") (0 . "INSERT") (-4 . "or>"))));;(sslength XRLIST)
    (repeat (setq INC (sslength XR))
               (setq XRLIST (cons (ssname XR (setq INC (1- INC)))XRLIST))
    ) ;REPEAT
;   (if (= null XRLIST)
;       (progn (princ "\nCommand: No XREF/BLOCK selected:")
;                 (setq XR (ssget '((-4 . "<or") (0 . "BLOCK") (0 . "INSERT") (-4 . "or>")))
;                 (repeat (setq INC (sslength XRLIST))
;                            (setq XRLIST (cons (ssname XR (setq INC (1- INC))) 1))
;                 ) ;REPEAT
;       ) ;PROGN
        (foreach XREF XRLIST
	  (setq ss (ssadd XREF))
	  (sssetfirst nil ss)
	  (command "-refedit" "O" "N" "WP" (foreach pt POINTLIST (command pt)) "" "N")
	  (setq ss1 (ssget "_WP" POINTLIST))
	  (command "_copy" ss1 "" "0,0,0" "0,0,0")
	  (command "_refset" "R" "ALL" "")
	  (command "_refclose" "D");;"Y"
	  (setq ss nil)
        ) ; FOREACH
;   ) ;IF
    ;(ENDUNDO (ACADDOC))
    (princ "\nCommand: Done")
  (setvar 'PICKFIRST old_pik)
;   (setvar "cmdecho" CMD)
    (princ)
)

 

HTH

Henrique

EESignature

Message 13 of 22
gccdaemon
in reply to: gccdaemon

It does work, but when testing, it's not selecting all the objects in the window like it's moving too fast for the selection process in the refedit command or it's throwing some point out in the middle of nowhere. Infact, the close point of the refedit window appears to be the culprit. Also, when there are multiple refedit instances (XREFS & BLOCKS) it's creating duplicate objects of the already copied object sets even though I have "Lock objects not in working set" selected (by the way is this a variable that I can manipulate?).

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 14 of 22
Gary_J_Orr
in reply to: gccdaemon

For the duplicating of objects I have found that turning your Osnaps off (setvar "osmode" 0) resolves it.

for the ability to ensure that you have the "Lock Objects..." set... There is no variable that I can find, therefore you will have to consider the registry:

 

;;; here is what you are targeting
;;;[HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\R18.2\ACAD-A001:409\Profiles\<<Unnamed Profile>>\Dialogs\RefeditDialog]
;;;"UniqueSymbolNames"=dword:00000000
;;;"DisplayAttDefs"=dword:00000000
;;;"LockObjects"=dword:00000001
;;;"SelectNested"=dword:00000000
;;;"X"=dword:000002ee
;;;"Y"=dword:00000191
;;;"Width"=dword:000001a4
;;;"Height"=dword:00000171
  
  ;required for any "VLxxx" function
  (vl-load-com)
  ;to set, first define the regkey string to the dialog
  (setq CURUSERSTR (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\Profiles\\" (getvar "cprofile") "\\Dialogs\\RefeditDialog"))
  ;as with everything we store the value to reset later (
  (setq oldLock (vl-registry-read CURUSERSTR "LockObjects"))
  ;set the desired value, it's a "DWORD" object so it needs a number
  (vl-registry-write CURUSERSTR "LockObjects" 0)
  ;to reset
  (vl-registry-write CURUSERSTR "LockObjects" oldLock)

 -Gary

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 15 of 22
gccdaemon
in reply to: Gary_J_Orr

I already added the osmode variable to the mix, but I can definately use this registry stuff over and over as I'm familiar with regedit. I replied to your e-mail with current code and a lengthy explaination...lol.

 

 

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 16 of 22
Gary_J_Orr
in reply to: gccdaemon

I replied with an "extended version" that I've been playing with...
Make a copy of your file and check it out...
I took the "easy" road for undo: placed an "Undo" "begin" at the start and an "undo" "end" for one step undo's... I'm fond of this approach while playing around since it allows me to type: "Undo" "end" "undo" if it crashes on me and I don't have an error handler defined yet 😉
-G
Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 17 of 22
gccdaemon
in reply to: Gary_J_Orr

Seeing as the selection window issue has been solved I'm going to go ahead and mark this thread as solved. Thanks to everyone for their input. I will continue to keep posting here to resolve the rest of the problems though, and will post final working code when completed for anyone that wants it.

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 18 of 22
Gary_J_Orr
in reply to: gccdaemon

Hey, I found a work around for the "Lock Objects" setting not being initialized and posted it to the thread that I started to try to get Adesk's attention (if I leave it "unsolved" they will eventually look at it:

 

http://forums.autodesk.com/t5/Visual-LISP-AutoLISP-and-General/This-is-going-to-feel-like-a-repost-b...

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)
Message 19 of 22
gccdaemon
in reply to: Gary_J_Orr

Here is a working product Gary and I worked on. Feel free to modify, rewrite, change, append, or revise as you see fit. I would ask that you post any of these modifications so others learning lisp can grow and hone their skills as well. Thanks to ALL that responded, you've all been a great help!

Andrew Ingram
Civil 3D x64 2019
Win 10 x64 Pro
Intel Xeon E5-1620
32 GB Ram
Message 20 of 22
Gary_J_Orr
in reply to: gccdaemon

Andrew,

by switching to the direct processing of the selection set over the earlier "foreach..." version it no longer needs the:

 (repeat (setq INC (sslength XR))
  (setq XRLIST (cons (ssname XR (setq INC (1- INC)))XRLIST)))

that generates the list to process.

also: I left out another "cleanup issue" in the "while" loop to reset for the next run and to ensure that we dump the overhead early on the last run (should be added right after the (setq XREF nil) line:

(setq REMSET nil)

 

And I still like my polyline version (well, the abbreviated version that was in-line) better for gathering the points since you can see the whole of the working area that you are generating.

 

But hey, this was your concept so the end result should be yours 😉

I'm glad that you finally have a working version.

-G

 

Gary J. Orr
(Your Friendly Neighborhood) CADD/BIM/VDC Applications Manager
http://www.linkedin.com/in/garyorr

aka (current and past user names):
Gary_J_Orr (GOMO Stuff 2008-Present); OrrG (Forum Studio 2005-2008); Gary J. Orr (LHB Inc 2002-2005); Orr, Gary J. (Gossen Livingston 1997-2002)

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost