marko_ribar Posted August 10, 2015 Posted August 10, 2015 I am for more XYZ sorts from min. coordinate up to max. By the way this is my ugliest code in my library but it works... So if you know how to use vl-sort / vl-sort-i with lambda function for this operation you have my greatest respect... (defun c:sortpts ( / sortpts ss i p ) (defun sortpts ( pl / pz plz plzs py ply plys plyn plyns plln pllx plll pll ) (setq pl (vl-sort pl '(lambda ( a b ) (< (caddr a) (caddr b))))) (setq pz (caddar pl)) (foreach p pl (if (equal pz (caddr p) 1e- (setq plz (cons p plz)) (setq plzs (cons plz plzs) pz (caddr p) plz nil plz (cons p plz))) ) (setq plzs (cons plz plzs)) (setq plzs (reverse plzs)) (foreach plz plzs (setq plz (vl-sort plz '(lambda ( a b ) (< (cadr a) (cadr b))))) (setq plys (cons plz plys)) ) (setq plys (reverse plys)) (foreach ply plys (setq py (cadar ply)) (foreach p ply (if (equal py (cadr p) 1e- (setq plyn (cons p plyn)) (setq plyns (cons plyn plyns) py (cadr p) plyn nil plyn (cons p plyn))) ) (setq plyns (cons plyn plyns)) (setq plyns (reverse plyns)) (setq plln (cons plyns plln)) (setq plyn nil plyns nil) ) (setq plln (reverse plln)) (foreach pllz plln (foreach plly pllz (setq pllx (vl-sort plly '(lambda ( a b ) (< (car a) (car b))))) (setq plll (cons pllx plll)) ) (setq plll (reverse plll)) (setq pll (cons plll pll)) (setq plll nil) ) (setq pll (reverse pll)) (apply 'append (apply 'append pll)) ) (setq ss (ssget '((0 . "POINT")))) (repeat (setq i (sslength ss)) (setq p (cdr (assoc 10 (entget (ssname ss (setq i (1- i))))))) (setq pl (cons p pl)) ) (setq pl (sortpts pl)) (prompt "\nSorted pts list is stored in variable pl - you can call it with !pl - before next call of (c:sortpts) you are obligated to (setq pl nil)") (princ) ) M.R. Quote
Lee Mac Posted August 10, 2015 Posted August 10, 2015 I am for more XYZ sorts from min. coordinate up to max. By the way this is my ugliest code in my library but it works... So if you know how to use vl-sort / vl-sort-i with lambda function for this operation you have my greatest respect... I think this will give the same result: (defun sortpts2 ( lst ) (vl-sort lst '(lambda ( a b ) (if (equal (caddr a) (caddr b) 1e- (if (equal (cadr a) (cadr b) 1e- (< (car a) (car b)) (< (cadr a) (cadr b)) ) (< (caddr a) (caddr b)) ) ) ) ) Test: _$ (repeat 256 (setq l (cons (list (LM:rand) (LM:rand) (LM:rand)) l))) ((0.423375 0.318337 0.799594) ... < 254 more entries > ... (0.716023 0.838241 0.0144724)) _$ (equal (sortpts l) (sortpts2 l)) T Quote
Lee Mac Posted August 10, 2015 Posted August 10, 2015 Or, more succinctly: (defun sortpts3 ( lst ) (vl-sort lst '(lambda ( a b ) (apply '< (vl-some '(lambda ( a b ) (if (not (equal a b 1e-) (list a b))) (reverse a) (reverse b) ) ) ) ) ) Quote
rlx Posted August 11, 2015 Posted August 11, 2015 (edited) Lee , my brain just killed itself by jumping out of the window after looking at your code , thanx for that Edited August 12, 2015 by rlx Quote
Happy Hobbit Posted October 14, 2015 Posted October 14, 2015 (edited) Recently I was lucky enough to be introduced to DXF codes on this forum by Lee Mac & am enjoying seeing how it works As an experiment I'm trying to sort a list by the x coordinates I've tried using a min statement within a repeat loop, but it always returns the lowest x coordinate of the entities within the variable s (bit obvious really) Soooo, what it needs is a loop to sort the entities into x order & put it into a variable, when that entity has been allocated it gets crossed off & the remaining four evaluated. I have 5 separate text entities to try it out on. H a r r y If selected out of order I get something like rHrya, which I think is a place in Narnia (defun c:xcoor ( / i n s ) (setq s (ssget "_:L" '((0 . "TEXT,MTEXT")))) (princ (strcat (itoa (sslength s)) " Items Selected")) (setq n (sslength s)) (repeat (setq i (sslength s)) (princ (strcat "\nX = "(rtos(car (cdr (assoc 11 (entget (ssname s (setq i (1- i))))))))" "));; Prints the X coordinate of the entities (princ (cdr (assoc 1 (entget (ssname s (setq n (1- n)))))));; Prints the contents of all the strings together ) (princ) ) Thanking you in anticipation PS bet the answer involves one of those fiendish incomprehensible lambda thingys :-/ Edited October 14, 2015 by Happy Hobbit Quote
Lee Mac Posted October 14, 2015 Posted October 14, 2015 Here is how I might approach it (untested): (defun c:xcoor ( / e i l s x ) (if (setq s (ssget '((0 . "TEXT,MTEXT")))) (progn (repeat (setq i (sslength s)) (setq e (entget (ssname s (setq i (1- i)))) x (cons (cadr (assoc 10 e)) x) l (cons (cdr (assoc 1 e)) l) ) ) (print (mapcar '(lambda ( n ) (nth n l)) (vl-sort-i x '<))) ) ) (princ) ) Feel free to ask if you don't understand an expression / section of code. Quote
Happy Hobbit Posted October 14, 2015 Posted October 14, 2015 Quick Q: Any reason why assoc 10 & not assoc 11? My guess is that because it's a generic sorting exercise rather than a precise accumulation of x coordinates for text Quote
Lee Mac Posted October 14, 2015 Posted October 14, 2015 Any reason why assoc 10 & not assoc 11? DXF group 11 for MText is the text direction vector; DXF group 11 for Text only represents the text alignment point for justifications other than 'Left'. DXF group 10 is the insertion point for both Text & MText (note: insertion point =/= text alignment point for Text). Quote
Happy Hobbit Posted October 14, 2015 Posted October 14, 2015 I gather that it sets the print function to the left - right order. Is there anyway to create a new list from variable s that puts the entities (i.e. 7ffffb53cf0 7ffdf~ 7ff~ ) in left - right order & therefore can be used for other functions? Quote
Lee Mac Posted October 14, 2015 Posted October 14, 2015 Is there anyway to create a new list from variable s that puts the entities (i.e. 7ffffb53cf0 7ffdf~ 7ff~ ) in left - right order & therefore can be used for other functions? Sure - the list held by variable 'l' can contain any data, providing the list is compiled in the same order as the list used as the sorting index (variable 'x'): (defun c:xcoor ( / e i l s x ) (if (setq s (ssget '((0 . "TEXT,MTEXT")))) (progn (repeat (setq i (sslength s)) (setq e (ssname s (setq i (1- i))) x (cons (cadr (assoc 10 (entget e))) x) l (cons e l) ) ) (print (mapcar '(lambda ( n ) (nth n l)) (vl-sort-i x '<))) ) ) (princ) ) Quote
Happy Hobbit Posted October 14, 2015 Posted October 14, 2015 Thank you Lee, I didn't even know it is possible to re-order (sort?) a list. I think I must owe you many pints of Fullers ESB or Youngs Special by now. I'd have replied earlier but folk keep needing their pesky drawings done. Draughting keeps getting in the way of my new interest - lisps Quote
Happy Hobbit Posted October 15, 2015 Posted October 15, 2015 (edited) Please may I ask one last Q Lee? Variable n which decrements to get the corresponding number for nth... In the case of selecting A B C D E the initial value is 4 in the lambda statement to get the 5th character of the reversed list [E D C B A], it then decrements 3 2 1 0 with each run of the loop. Where does it get it's initial value from for the first loop? (mapcar '(lambda ( n ) (nth n L)) (vl-sort-i x '<))) Addenda: I've just realised that (print (mapcar '(lambda ( n ) (nth n l)) (vl-sort-i x '<))) isn't even in the loop ???? Edited October 15, 2015 by Happy Hobbit Quote
Lee Mac Posted October 15, 2015 Posted October 15, 2015 Variable n which decrements to get the corresponding number for nth... In the case of selecting A B C D E the initial value is 4 in the lambda statement to get the 5th character of the reversed list [E D C B A], it then decrements 3 2 1 0 with each run of the loop. Where does it get it's initial value from for the first loop? (mapcar '(lambda ( n ) (nth n L)) (vl-sort-i x '<))) Addenda: I've just realised that (print (mapcar '(lambda ( n ) (nth n l)) (vl-sort-i x '<))) isn't even in the loop ???? The lambda argument n is not being decremented - this symbol is assigned each index in the list returned by the vl-sort-i function (which has been supplied to the mapcar function). Please note that these operations are performed outside of the repeat loop, as the vl-sort-i function is sorting the list of x-coordinate values compiled within the loop. Quote
Happy Hobbit Posted October 15, 2015 Posted October 15, 2015 The lambda argument n is not being decremented - this symbol is assigned each index in the list returned by the vl-sort-i function (which has been supplied to the mapcar function). Please note that these operations are performed outside of the repeat loop, as the vl-sort-i function is sorting the list of x-coordinate values compiled within the loop. I'm gonna take up crochet instead **SOB** Seriously, thank you Lee, I need to read up your mapcar & lambda tutorial before I feel confident of understanding how it works. I'm a tenacious old beggar so I shall persevere Quote
Lee Mac Posted October 15, 2015 Posted October 15, 2015 I'm gonna take up crochet instead **SOB** Seriously, thank you Lee, I need to read up your mapcar & lambda tutorial before I feel confident of understanding how it works. I'm a tenacious old beggar so I shall persevere You're most welcome Harry - and certainly don't give up on trying to understand it (crochet sounds boring anyway), when the penny drops you'll look back on it and think it was simple. If you need a more in-depth explanation, or have a specific question regarding an expression, feel free to ask and I'll be happy to explain if I get time. Lee Quote
Happy Hobbit Posted October 17, 2015 Posted October 17, 2015 (edited) Please Lee, can you explain the significance of n in the bit: (lambda ( [color="red"]n[/color] ) Is it just a local variable for the lambda function? I think I've got the rest: Mapcar: In plain English "Do this FUNCTION to every member of this list or these lists" FUNCTION in the below is: 'strcat (mapcar 'strcat '( "M" "X") '( "e" "m" ) '("rr" "a" ) '("y" "s")) (mapcar 'strcat '( "B" "H") '( "a" "u" ) '("h" "m" ) '("!" "b") '("" "u") '("" "g!")) FUNCTION in the below is: '(lambda (num) (+ num 2)) With (+ num 2)) doing the operations: (setq lst '(1 2 3 4 5)) (mapcar '(lambda (n) (+ n 2)) lst) Edited October 18, 2015 by Happy Hobbit Minor corrections and formatting changes. Quote
Lee Mac Posted October 17, 2015 Posted October 17, 2015 From your examples, it looks like you have a good understanding of how mapcar operates; the 'n' within the lambda function represents the argument or parameter for the lambda function - if the function is passed as the function argument for a mapcar expression, this symbol will be assigned the value of every item in the list supplied to mapcar. Quote
Happy Hobbit Posted October 18, 2015 Posted October 18, 2015 It's actually far simpler than I thought (and how it looks), although I had to do quite a lot of reading before the light went on. Thank you very much indeed Lee, I shall be bookmarking this page for future reference Harry H Quote
Lee Mac Posted October 18, 2015 Posted October 18, 2015 Excellent to hear Harry, it's always satisfying when something finally clicks. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.