Jump to content

Recommended Posts

Posted

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.

  • Replies 40
  • Created
  • Last Reply

Top Posters In This Topic

  • Lee Mac

    16

  • Happy Hobbit

    8

  • Tharwat

    4

  • Kowal

    4

Top Posters In This Topic

Posted Images

Posted
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

Posted

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)
               )
           )
       )
   )
)

Posted (edited)

Lee , my brain just killed itself by jumping out of the window after looking at your code , thanx for that :ouch:

Edited by rlx
  • 2 months later...
Posted (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 by Happy Hobbit
Posted

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.

Posted

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

Posted
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).

Posted

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?

Posted
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)
)

Posted

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

Posted (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 by Happy Hobbit
Posted
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.

Posted
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

Posted
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

Posted (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 by Happy Hobbit
Minor corrections and formatting changes.
Posted

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.

Posted

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

Posted

Excellent to hear Harry, it's always satisfying when something finally clicks.

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...