ekko Posted April 14, 2022 Posted April 14, 2022 (edited) The code and test graph are below Hello everyone, about finding parallel lines in the entity list, I wrote a piece of code myself that can implement the function. When the number of entities reaches 929, it runs very badly (run time 17.6 seconds) while + vl-some 17.6 seconds while + foreach 30.15 seconds while + vl-remove-if 29.42 seconds The above is the data I tested, apparently my choice is now while + vl-some . I'm a novice, I hope to get the help of the master to make it faster, thank you Edited April 14, 2022 by ekko Quote
Steven P Posted April 14, 2022 Posted April 14, 2022 Just a guess, you have a while loop and then another loop, or 929 loops and each loop is doing 929 operations, 863,000 calculations.... might be why it is slowing down? Quote
ekko Posted April 14, 2022 Author Posted April 14, 2022 31 minutes ago, Steven P said: Just a guess, you have a while loop and then another loop, or 929 loops and each loop is doing 929 operations, 863,000 calculations.... might be why it is slowing down? In fact, there are not so many loops. Even if I use while+foreach, I will loop about 17,000 times. However, the number of loops with while+vl-some should be less, because vl-some seems to stop searching when the condition is met. It should be the reason why my experiment above is faster. Well, my purpose now is to find a better way, a way to make it faster Quote
exceed Posted April 14, 2022 Posted April 14, 2022 I haven't tested, but If there are only simple straight lines, Create a degree list and entityname list. And the degree list is extracted using Lee Mac's LM:ListDupes. ( http://www.lee-mac.com/uniqueduplicate.html ) If there is a duplicate degree in the degree list, the entity name is extracted with the index no. Quote
ekko Posted April 14, 2022 Author Posted April 14, 2022 34 minutes ago, exceed said: I haven't tested, but If there are only simple straight lines, Create a degree list and entityname list. And the degree list is extracted using Lee Mac's LM:ListDupes. ( http://www.lee-mac.com/uniqueduplicate.html ) If there is a duplicate degree in the degree list, the entity name is extracted with the index no. Thank you for your suggestion, my bro. Before writing the code, I read it and borrowed the method of lee mac. Now the running speed cannot meet my requirements, but writing the above code is already the limit of my current technology. . I thought that after vl-some satisfies the condition, then delete x directly. I think this will reduce the number in the table and the number of loops. The natural speed is fast, the problem is that I don't know how to do it. Quote
Steven P Posted April 14, 2022 Posted April 14, 2022 Just for checking and seeing what it happening, could you post the bit of code that comes before parallel and creates lst - saves us 20 minutes making that up to see what is happening. Quote
ekko Posted April 14, 2022 Author Posted April 14, 2022 (edited) 23 hours ago, Steven P said: Just for checking and seeing what it happening, could you post the bit of code that comes before parallel and creates lst - saves us 20 minutes making that up to see what is happening. I have uploaded the test chart and test code, this is only part of the code, it can't see the speed in the test chart, when it runs in the complete code, the speed is very slow, I am sure that this part causes the running speed to change slow, so I'm looking for ways to make it run faster Parallel.dwg Edited April 15, 2022 by ekko Quote
mhupp Posted April 14, 2022 Posted April 14, 2022 (edited) You should run the calculations on the list building a new list with the answers. This way your only doing the calculations once and in the loops your only pulling values. (foreach e lst (setq l (cons (list e ang len) l)) ) ;;;ent angle (defun ang (e) (vlax-get-property (EtoO e) 'angle) ) Would turn (<Entity name: 4ecbaf20> <Entity name: 4ecba4e0>) into ((<Entity name: 4ecbaf20> 30 1.26) (<Entity name: 4ecba4e0> 60 2.33)) if the angles are the same then they are parallel (if (and (=\ (cadr x) (cadr e)) (equal (caddr x) (caddr e) 1)) (if (and (=\ (30) (60)) (equal (1.26) (2.33) 1)) t Edited April 14, 2022 by mhupp 1 Quote
ekko Posted April 14, 2022 Author Posted April 14, 2022 23 minutes ago, mhupp said: You should run the calculations on the list building a new list with the answers. This way your only doing the calculations once and in the loops your only pulling values. (foreach e lst (setq l (cons (list e ang len) l)) ) ;;;ent angle (defun ang (e) (vlax-get-property (EtoO e) 'angle) ) Would turn (<Entity name: 4ecbaf20> <Entity name: 4ecba4e0>) into ((<Entity name: 4ecbaf20> 30 1.26) (<Entity name: 4ecba4e0> 60 2.33)) if the angles are the same then they are parallel (if (and (=\ (cadr x) (cadr e)) (equal (caddr x) (caddr e) 1)) (if (and (=\ (60) (30)) (equal (1.26) (2.33) 1)) t (vlax-get-property (EtoO e) 'angle) function not valid for lwpolyline,In addition, I tested, two parallel lines drawn in the same direction, their angles are not the same, do I need to calculate? Quote
exceed Posted April 14, 2022 Posted April 14, 2022 (edited) A value of 180 degrees or more in the expression for parallelism is equivalent to -180 degrees. It is easily solved by putting a single if statement in front of it. In this process you will be able to purge decimal errors by rounding off. because lwpolyline can have multiple vertices, so check whether the object is a line or an lwpolyline, and if it is an lwpolyline, check if it has only two points, and if both conditions are passed, calculate the angle and put it in the list. An easy way to solve this is to explode and treat them all as lines. Edited April 14, 2022 by exceed 1 Quote
ekko Posted April 14, 2022 Author Posted April 14, 2022 8 minutes ago, exceed said: A value of 180 degrees or more in the expression for parallelism is equivalent to -180 degrees. It is easily solved by putting a single if statement in front of it. In this process you will be able to purge decimal errors by rounding off. An lw polyline can have multiple vertices, so check whether the object is a line or an lwpolyline, and if it is an lwpolyline, check if it has only two points, and if both conditions are passed, calculate the angle and put it in the list. An easy way to solve this is to explode and treat them all as lines. A value of 180 degrees or more in the expression for parallelism is equivalent to -180 degrees. It is easily solved by putting a single if statement in front of it. In this process you will be able to purge decimal errors by rounding off. because lwpolyline can have multiple vertices, so check whether the object is a line or an lwpolyline, and if it is an lwpolyline, check if it has only two points, and if both conditions are passed, calculate the angle and put it in the list. An easy way to solve this is to explode and treat them all as lines. OK, thanks Quote
ronjonp Posted April 14, 2022 Posted April 14, 2022 @ekko Are you trying to make a selection set of equal length and angle based on a pick? I ran your code and all it does is highlight your entire test drawing. Quote
ekko Posted April 14, 2022 Author Posted April 14, 2022 (edited) 21 hours ago, ronjonp said: @ekko Are you trying to make a selection set of equal length and angle based on a pick? I ran your code and all it does is highlight your entire test drawing. (foreach x parlst (mapcar '(lambda (y) (redraw y 3)) x) ) Good evening, you may not have looked at the code carefully, the program highlights the line that is parallel and has the same length, it is stored in the parlst list Forgive me, the graphs in the test chart are all satisfied parallel lines, this may mislead you into thinking that only the selected line is highlighted Edited April 15, 2022 by ekko Quote
ronjonp Posted April 14, 2022 Posted April 14, 2022 (edited) @ekko I did look at your code I'm just confused as to what you're trying to do. I would expect the result to look something like this: or this Edited April 14, 2022 by ronjonp Quote
ekko Posted April 14, 2022 Author Posted April 14, 2022 (edited) 7 minutes ago, ronjonp said: @ekko i did look at your code I'm just confused as to what you're trying to do. I would expect something like this: I'm sorry for not stating the requirement, first of all finding parallel lines is only part of the function of the program. The problem now is that when the amount of data is large, this part causes the program to run very slowly. I hope to be optimized to improve the running speed of the program I think, my program loops on the entity table 5 times, which is the key to affecting the running speed of which SStoE 2 times, while 1 time vl-some 1 time (vl-remove) 1 time Edited April 14, 2022 by ekko Quote
ronjonp Posted April 14, 2022 Posted April 14, 2022 (edited) Do a presort like so to speed this up. This took ~5s to process 130,000 lines. (defun c:foo (/ a b c e f n r s) ;; RJP » 2022-04-14 ;; Groups a list of lists of lines that have similar angles and lengths (setq f 1e-1) (cond ((setq s (ssget '((0 . "LINE")))) (setq s (mapcar '(lambda (e) (setq a (vlax-curve-getstartpoint e)) (setq b (vlax-curve-getendpoint e)) (list (rem (angle a b) pi) (distance a b) e) ) (vl-remove-if 'listp (mapcar 'cadr (ssnamex s))) ) ) ;; Presort by sum of angle and length (setq s (vl-sort s (function (lambda (r j) (< (+ (cadr r) (car r)) (+ (cadr j) (car j))))))) ;; While we have a list (while (setq a (car s)) ;; Remove first item (setq s (cdr s)) ;; Reset temp list (setq c nil) ;; Add first item to temp list 'c' (setq c (cons a c)) ;; While we have a list 's' and the angle and length is 'equal', compile temp list 'c' (while (and s (equal (car a) (caar s) f) (equal (cadr a) (cadar s) f) (setq c (cons (car s) c)) (setq s (cdr s)) ) ) ;; Result (setq r (cons c r)) ) ;;; (setq n 0) ;;; ;; Quick check ;;; (foreach l r ;;; (setq n (1+ n)) ;;; (foreach e l (entmod (append (entget (last e)) (list (cons 62 n))))) ;;; ) ) ) (princ) ) Quote Command: FOO Select objects: Specify opposite corner: 130680 found Select objects: < Elapsed time: 4.61 seconds. > Edited April 15, 2022 by ronjonp 2 1 Quote
ekko Posted April 14, 2022 Author Posted April 14, 2022 55 minutes ago, ronjonp said: Do a presort like so to speed this up. This took ~5s to process 130,000 lines. (defun c:foo (/ a b c e f n r s) ;; RJP » 2022-04-14 ;; Groups a list of lists of lines that have similar angles and lengths (setq f 1e-1) (cond ((setq s (ssget '((0 . "LINE")))) (setq s (mapcar '(lambda (e) (setq a (vlax-curve-getstartpoint e)) (setq b (vlax-curve-getendpoint e)) (list (rem (angle a b) pi) (distance a b) e) ) (vl-remove-if 'listp (mapcar 'cadr (ssnamex s))) ) ) ;; Presort by sum of angle and length (setq s (vl-sort s (function (lambda (r j) (< (+ (cadr r) (car r)) (+ (cadr j) (car j))))))) ;; While we have a list (while (setq a (car s)) ;; Get first item (setq s (cdr s)) ;; Add first item to temp list 'c' (setq c (cons a c)) ;; While we have a list 's' and the angle and length is 'equal', compile temp list 'c' (while (and s (equal (car a) (caar s) f) (equal (cadr a) (cadar s) f) (setq c (cons (car s) c)) (setq s (cdr s)) ) ) ;; Result (setq r (cons c r)) ) ;;; (setq n 0) ;;; ;; Quick check ;;; (foreach l r ;;; (setq n (1+ n)) ;;; (foreach e l (entmod (append (entget (last e)) (list (cons 62 n))))) ;;; ) ) ) (princ) ) This is a very good idea, thanks a lot Quote
ronjonp Posted April 14, 2022 Posted April 14, 2022 (edited) 35 minutes ago, ekko said: This is a very good idea, thanks a lot Glad to help If you compile the code it should be even faster... Yup .. over 2x Quote Command: FOO2 Select objects: Specify opposite corner: 130680 found Select objects: < Elapsed time: 2.094 seconds. > Edited April 14, 2022 by ronjonp 1 Quote
ronjonp Posted April 14, 2022 Posted April 14, 2022 @ekko Redownload the code .. I had forgotten to reset the temp list which gives very incorrect results. 1 Quote
ekko Posted April 14, 2022 Author Posted April 14, 2022 (edited) 7 minutes ago, ronjonp said: @ekko Redownload the code .. I had forgotten to reset the temp list which gives very incorrect results. The point is not the code, but your logic approach, you have solved my problem, I have a doubt (setq f 1e-1) I can't understand this. thanks again for your help bro wish you a happy life Edited April 14, 2022 by ekko 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.