Stegee137 Posted March 25, 2020 Posted March 25, 2020 I have a drawing that contains 1000's of LWPOLYLINES (with elevation) and CIRCLES (with thickness). I use the following LISP routine that I found a while ago on another forum to find the highest elevation/thickness value within a selection. (defun c:Max (/ ss i a b lst) (if (setq ss (ssget)) (progn (repeat (setq i (sslength ss)) (vla-getboundingbox (vlax-ename->vla-object (ssname ss (setq i (1- i)))) 'a 'b) (setq lst (cons (caddr (vlax-safearray->list a)) (cons (caddr (vlax-safearray->list b)) lst) ) ) ) (alert (strcat "Maximum Elevation: " (rtos (apply 'max lst)) ) ) ) ) (princ) ) The LISP works well but what I would like to be able to do is select all lines and/or circles with the maximum elevation within my selection area. Do any of you guys know how I might be able to adapt the LISP above to do this? Many thanks Quote
fuccaro Posted March 25, 2020 Posted March 25, 2020 (defun c:MaxZ( / ss0 ls i Zmax) (setq ss0 (ssget (list (cons 0 "Lwpolyline"))) ls nil i -1) (repeat (sslength ss0) (setq ls (cons (ssname ss0 (setq i (1+ i))) ls))) (setq ls1 (vl-sort ls (function (lambda (a b) (> (cdr (assoc 38 (entget a))) (cdr (assoc 38 (entget b)))))))) (setq Zmax (cdr (assoc 38 (entget (car ls1)))) ss (ssadd) i -1 fuzz 0.1) (while (equal Zmax (cdr (assoc 38 (entget (setq en (nth (setq i (1+ i)) ls1))))) fuzz) (ssadd en ss)) ) This should place all the polylines at maximum Z in the selection set ss. You may wish to adjust the fuzz distance (I set it to 0.1), so the program will find all the polylines "around" the Zmax Quote
Stegee137 Posted March 25, 2020 Author Posted March 25, 2020 Many thanks fuccaro. This only works with polylines whereas my dataset contains polylines and circles. I want to be able to select the highest object which may be a polyline (elevation) or a circle (thickness) or both. Do you think that will be possible? Quote
fuccaro Posted March 26, 2020 Posted March 26, 2020 Yes, it's possible. I will change the code to add the circle things. I was waiting to see if I am walking in the right direction. I will try to do it today. Quote
Stegee137 Posted March 26, 2020 Author Posted March 26, 2020 Much appreciated fuccaro. Yes, I think so. Basically I am assessing 1000's of lines and circles. My LISP tells me what the highest value is but I need to know where it is too hence why I would like everything with that Max Z value to be selected. Quote
fuccaro Posted March 26, 2020 Posted March 26, 2020 (defun c:MaxZ( / ) (setq ss0 (ssget (list (cons 0 "Lwpolyline,circle"))) ls nil i -1) (repeat (sslength ss0) (setq en (ssname ss0 (setq i (1+ i))) cir (= "CIRCLE" (cdr (assoc 0 (setq el (entget en))))) elev (if cir (car (reverse (assoc 10 el))) (cdr (assoc 38 el))) ls (cons (cons en elev) ls)) ) (setq ls1 (vl-sort ls '(lambda (a b) (> (cdr a) (cdr b))))) (setq Zmax (cdar ls1) ss (ssadd) i -1 fuzz 0.1) (while (equal Zmax (cdr (nth (setq i (1+ i)) ls1)) fuzz) (ssadd (car (nth i ls1)) ss)) (princ (strcat "Max z= " (rtos Zmax))) (princ) ) Quote
Stegee137 Posted March 26, 2020 Author Posted March 26, 2020 Thank you. I have just tried this but it is returning a max z value of 0 for all circles. It works correctly for the polylines but doesn't seem to select the polyline with the highest value afterwards. Am I doing something wrong? Quote
Lee Mac Posted March 26, 2020 Posted March 26, 2020 Assuming that you are genuinely referring to the thickness property of a circle (i.e. DXF group 39), as opposed to the elevation of the centre, try the following: (defun c:selhigh ( / e i l m r s x z ) (if (setq s (ssget '((0 . "LWPOLYLINE,CIRCLE")))) (progn (repeat (setq i (sslength s)) (setq i (1- i) e (ssname s i) x (entget e) ) (if (= "CIRCLE" (cdr (assoc 0 x))) (setq z (cond ((cdr (assoc 39 x)))(0))) (setq z (cdr (assoc 38 x))) ) (if (< m z) (setq m z)) (setq l (cons (cons z e) l)) ) (setq r (ssadd)) (foreach x l (if (equal (car x) m 1e-8) (ssadd (cdr x) r) ) ) (sssetfirst nil r) ) ) (princ) ) Quote
Stegee137 Posted March 26, 2020 Author Posted March 26, 2020 That is perfect Lee Mac! Does exactly what I wanted. Many thanks!! Quote
Stegee137 Posted March 26, 2020 Author Posted March 26, 2020 Sorry Lee Mac, one thing I forgot to ask - in my original LISP it had an alert to tell me what the highest value is. Is it possible to add that to this LISP? Quote
Lee Mac Posted March 26, 2020 Posted March 26, 2020 (edited) 15 minutes ago, Stegee137 said: That is perfect Lee Mac! Does exactly what I wanted. Many thanks!! Excellent - you're most welcome. 11 minutes ago, Stegee137 said: Sorry Lee Mac, one thing I forgot to ask - in my original LISP it had an alert to tell me what the highest value is. Is it possible to add that to this LISP? Certainly - the following will print the value to the command-line: (defun c:selhigh ( / e i l m r s x z ) (if (setq s (ssget '((0 . "LWPOLYLINE,CIRCLE")))) (progn (repeat (setq i (sslength s)) (setq i (1- i) e (ssname s i) x (entget e) ) (if (= "CIRCLE" (cdr (assoc 0 x))) (setq z (cond ((cdr (assoc 39 x)))(0))) (setq z (cdr (assoc 38 x))) ) (if (< m z) (setq m z)) (setq l (cons (cons z e) l)) ) (setq r (ssadd)) (foreach x l (if (equal (car x) m 1e-8) (ssadd (cdr x) r) ) ) (princ (strcat "Maximum elevation/thickness: " (rtos m))) (sssetfirst nil r) ) ) (princ) ) Change (princ (strcat ... )) to (alert (strcat ... )) if you really want a modal dialog. Edited March 26, 2020 by Lee Mac Quote
GNolder Posted May 2, 2023 Posted May 2, 2023 On 3/26/2020 at 3:50 PM, Lee Mac said: Excellent - you're most welcome. Certainly - the following will print the value to the command-line: (defun c:selhigh ( / e i l m r s x z ) (if (setq s (ssget '((0 . "LWPOLYLINE,CIRCLE")))) (progn (repeat (setq i (sslength s)) (setq i (1- i) e (ssname s i) x (entget e) ) (if (= "CIRCLE" (cdr (assoc 0 x))) (setq z (cond ((cdr (assoc 39 x)))(0))) (setq z (cdr (assoc 38 x))) ) (if (< m z) (setq m z)) (setq l (cons (cons z e) l)) ) (setq r (ssadd)) (foreach x l (if (equal (car x) m 1e-8) (ssadd (cdr x) r) ) ) (princ (strcat "Maximum elevation/thickness: " (rtos m))) (sssetfirst nil r) ) ) (princ) ) Change (princ (strcat ... )) to (alert (strcat ... )) if you really want a modal dialog. @Lee Mac I know this is an old post, but can this be adopted for a selection of ACAD points? I would like min and max values. Thanks Quote
ronjonp Posted May 2, 2023 Posted May 2, 2023 2 hours ago, GNolder said: @Lee Mac I know this is an old post, but can this be adopted for a selection of ACAD points? I would like min and max values. Thanks I know Lee will chime in at some point, but here's some quick mods you can make and it should work for elevations and Z values ( not thickness ). ;; Add POINT to the filter like so (setq s (ssget '((0 . "LWPOLYLINE,CIRCLE,POINT")))) ;; Then change this (if (= "CIRCLE" (cdr (assoc 0 x))) (setq z (cond ((cdr (assoc 39 x))) (0) ) ) (setq z (cdr (assoc 38 x))) ) ;; To this (if (wcmatch (cdr (assoc 0 x)) "CIRCLE,POINT") (setq z (last (assoc 10 x))) (setq z (cdr (assoc 38 x))) ) Quote
Lee Mac Posted May 2, 2023 Posted May 2, 2023 Thanks @ronjonp - I would have modified the code in exactly the same way. 1 Quote
GNolder Posted May 4, 2023 Posted May 4, 2023 On 5/2/2023 at 5:53 PM, Lee Mac said: Thanks @ronjonp - I would have modified the code in exactly the same way. On 5/2/2023 at 3:56 PM, ronjonp said: I know Lee will chime in at some point, but here's some quick mods you can make and it should work for elevations and Z values ( not thickness ). ;; Add POINT to the filter like so (setq s (ssget '((0 . "LWPOLYLINE,CIRCLE,POINT")))) ;; Then change this (if (= "CIRCLE" (cdr (assoc 0 x))) (setq z (cond ((cdr (assoc 39 x))) (0) ) ) (setq z (cdr (assoc 38 x))) ) ;; To this (if (wcmatch (cdr (assoc 0 x)) "CIRCLE,POINT") (setq z (last (assoc 10 x))) (setq z (cdr (assoc 38 x))) ) Thanks! It works perfectly! I cannot however, figure out how to get it to also show and highlight the minimum value. Quote
Lee Mac Posted May 4, 2023 Posted May 4, 2023 13 minutes ago, GNolder said: Thanks! It works perfectly! I cannot however, figure out how to get it to also show and highlight the minimum value. The object(s) possessing the maximum value area added to a new selection set, which is then gripped/highlighted by the sssetfirst expression at the end of the program - such selection set should also then become the previous selection. Quote
GNolder Posted May 4, 2023 Posted May 4, 2023 19 minutes ago, Lee Mac said: The object(s) possessing the maximum value area added to a new selection set, which is then gripped/highlighted by the sssetfirst expression at the end of the program - such selection set should also then become the previous selection. Thanks for the quick response. I should have started with "I'm new into autolisp". I mostly understand your response. I just don't know how to find and add the lowest value to the set so the result is Max Z= xx.xx, Min Z=xx.xx Quote
Lee Mac Posted May 4, 2023 Posted May 4, 2023 (edited) Apologies - I misread your question - to implement both the minimum & maximum, try the following: (defun c:sellowhigh ( / e i l m n r s z ) (if (setq s (ssget '((0 . "POINT")))) (progn (setq n 1e308 m -1e308) (repeat (setq i (sslength s)) (setq i (1- i) e (ssname s i) z (cadddr (assoc 10 (entget e))) ) (if (< m z) (setq m z)) (if (< z n) (setq n z)) (setq l (cons (cons z e) l)) ) (setq r (ssadd)) (foreach x l (if (or (equal (car x) m 1e-8) (equal (car x) n 1e-8)) (ssadd (cdr x) r) ) ) (princ (strcat "\nMin Z: " (rtos n) " | Max Z: " (rtos m))) (sssetfirst nil r) ) ) (princ) ) Edited May 4, 2023 by Lee Mac 1 Quote
GNolder Posted May 4, 2023 Posted May 4, 2023 27 minutes ago, Lee Mac said: Apologies - I misread your question - to implement both the minimum & maximum, try the following: (defun c:sellowhigh ( / e i l m n r s z ) (if (setq s (ssget '((0 . "POINT")))) (progn (setq n 1e308 m -1e308) (repeat (setq i (sslength s)) (setq i (1- i) e (ssname s i) z (cadddr (assoc 10 (entget e))) ) (if (< m z) (setq m z)) (if (< z n) (setq n z)) (setq l (cons (cons z e) l)) ) (setq r (ssadd)) (foreach x l (if (or (equal (car x) m 1e-8) (equal (car x) n 1e-8)) (ssadd (cdr x) r) ) ) (princ (strcat "\nMin Z: " (rtos n) " | Max Z: " (rtos m))) (sssetfirst nil r) ) ) (princ) ) @Lee Mac This is exactly what I asked for. Thank you! Can I add an option to filter the results by decimal places? Example 2dp, 3dp or 4dp 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.