Does anyone know how to sort a selectionset by x coordinate? I assume when one selects objects, the selectionset is ordered based on selection order, I'd like to have mine set up so that it sorts from xlow to x high.
|
Does anyone know how to sort a selectionset by x coordinate? I assume when one selects objects, the selectionset is ordered based on selection order, I'd like to have mine set up so that it sorts from xlow to x high.
- Create list of enames.
- (vl-sort lst (function (lambda (a b) (> (cadr (assoc 10 (entget a))) (cadr (assoc 10 (entget b)))))))
- Create new selection set with ssadd.
- Step (foreach) through sorted (#2) list and ssadd enames to newly created selection set.
Thanks for the direction, I'm still having issues though. Perhaps I'm not building my list properly, but for some reason the lambda function grabs the first item, then tries to grab the entire rest of the list as the second item, That obviously doesnt work, as it cant grab the entdata from a list of entities. How do you suggest creating the list, I know that there are multiple ways of doing it, I'm using (setq lst (list ss lst)) which based on my results isnt the proper way to do it.
here is the error I'm receiving
; error: bad argument type: lentityp (nil)
Nevermind, I figured it out. I had to set each item as a list, then append my lists together. Works great!
Thanks Alan for the help!
Last edited by ccowgill; 2012-03-08 at 02:58 PM. Reason: Solution found
Untested, but try this...
Code:(defun _SortSSByXValue (ss / lst i e add) (if (eq (type ss) 'PICKSET) (progn (repeat (setq i (sslength ss)) (setq lst (cons (cons (setq e (ssname ss (setq i (1- i)))) (cadr (asoc 10 (entget e))) ) lst ) ) ) (setq add (ssadd)) (foreach e (vl-sort lst (function (lambda (a b) (< (cdr a) (cdr b))))) (ssadd (car e) add)) (if (> (sslength add) 0) add ) ) ) )
Here's the portion of the code I ended up usingCode:(setq ss (ssget '((0 . "TEXT") (8 . "C-ROAD-STAN-OFFS")))) ;_ select all objects (setvar "osmode" 64) (setq stp (getpoint "\nSelect insert point of first text obj")) ;_ select start point (setq count1 (sslength ss) count 1 xcoord (- (car stp) 0.135) ss1 (ssadd) ss4 (list (ssname ss (1- count))) ss6 (ssadd) ) ;_ end of setq (while (<= (1+ count) count1) ;SORT LIST BY X COORD LOW TO HIGH (setq ss3 (list (ssname ss count))) (setq ss4 (append ss4 ss3)) (setq count (1+ count)) ) ;_ end of while (vl-sort ss4 (function (lambda (a b) (> (cadr (assoc 11 (entget a))) (cadr (assoc 11 (entget b)))))) ) ;_ end of vl-sort (setq count 0 counta 1 ) ;_ end of setq (foreach ss5 (reverse ss4) (setq ss6 (ssadd ss5 ss6)) )
yes, but so is the rest of my program, and it looks cool when it runs:
http://screencast.com/t/8zeIbpsH
I'll take a look at it and try to steamline it in a bit. It was just something I tried to throw together quickly so we could save some time on a job.
I would factor out the the process of extracting the coordinates away from the sort function - the coordinates will not change during the sorting so there isn't much need to get them over and over. Consider extracting the coordinates to a separate list first (perhaps even just the X-coordinate but include the Y if its needed as a tie-breaker), then calling for the sort.
I like to segregate the functionality of each step of the function so that I can build very general toolbox functions that allow me to make changes. Like here I convert a selection set to a list, change the list into a list of sublists including the xyz coordinates of the entities, sort by the x y and z coordinates (either up or down), convert the list of sublists back to a list of entities and then into a selection set. I like the list of sublists structure and use this sort function all the time.I also like storing selections sets as lists of entities or objects.
2 cents.
Peter
Code:(defun sortListofSublistsbyItemX (lstOfSublists intItem intDirection) (if (> intDirection 0) (vl-sort lstOfSublists '(lambda (X Y) (< (nth intItem X) (nth intItem Y)))) (vl-sort lstOfSublists '(lambda (X Y) (> (nth intItem X) (nth intItem Y)))) ) ) (defun SelectionSetToList (ssSelections / intCount lstReturn) (if (and ssSelections (= (type ssSelections) 'PICKSET) ) (repeat (setq intCount (sslength ssSelections)) (setq intCount (1- intCount) lstReturn (cons (ssname ssSelections intCount) lstReturn) ) ) ) (reverse lstReturn) ) (defun ListToSelectionSet (lstOfEntities / ssReturn) (if lstOfEntities (foreach entItem lstOfEntities (if (= (type entItem) 'ENAME) (if ssReturn (setq ssReturn (ssadd entItem ssReturn)) (setq ssReturn (ssadd entItem)) ) ) ) ) ssReturn ) (defun SortSelectionSetByXYZ (ssSelections / lstOfSelections lstOfSublists lstSelections) (if (and (setq lstSelections (SelectionSetToList ssSelections)) (setq lstOfSublists (mapcar '(lambda (X)(cons X (cdr (assoc 10 (entget X))))) lstSelections)) (setq lstOfSublists (sortlistofsublistsbyitemX lstOfSublists 3 1)) (setq lstOfSublists (sortlistofsublistsbyitemX lstOfSublists 2 1)) (setq lstOfSublists (sortlistofsublistsbyitemX lstOfSublists 1 1)) (setq ssSelections (listtoselectionset (mapcar 'car lstOfSublists))) ) ssSelections ) )
AutomateCAD