Jump to content

Lisp iterative routine in a large drawing takes for ever!


MJLM

Recommended Posts

I m working on a model which has already around 30000 elements which some of them are 9000 lines, some 4000 block definitions (actually 4, 5 individual blocks repeated) and a lot of text labels etc.

 

When I run the following routine on the model at a given point which some lines start or end at it, it takes around 40 sec for 1000 repetitions on my system to finish. When I take a small portion of the system, say 100 lines, copy and paste them to a new empty drawing which contains the same lines of the point clicked, and run it again on this point, it finishes instantly, practically in 0 time.

 

Since the 'ssget' searches for elements on a given point, I never thought the database size would really make a difference but, unfortunately, it seems it does. Also the filters used, such as 60, 62 and layer names do not seem to affect process time, that is 40 sec.

 

So, the bottom line, is there a way to alleviate this issue? Is there a way to reduce the time of repetitive processes in a large database? My routines rely extensively on the ssget command on every node checking for topology, orientation, data etc.

 

(defun c:test (/)

(setq fp (getpoint))
(setq i 0)
(repeat 1000
	(setq ss (ssget "_X" (list (cons 0 "LINE") (cons 10 fp) (cons -4 "<NOT") (cons -4 "<OR") (cons 60 1) (cons 62 250) (cons -4 "OR>") (cons -4 "NOT>") (cons -4 "<OR") (cons 8 "MainA") (cons 8 "MainB") (cons 8 "BLines") (cons -4 "OR>"))))
	(prompt (strcat "\nPass: " (itoa (setq i (1+ i)))))
)

(alert "Done!")
(princ)
)

Link to comment
Share on other sites

  • 2 weeks later...
So, no idea about this issue or happens only on me?

 

 

Yes this only happens to you ;-)

 

 

But... could you explain the function of i and the repeat loop??? The way above code works is doing the same one thousand times?

 

 

gr. Rlx

 

 

Maybe you want something like this?

 

 

(defun c:test2 ( / fp ss)
 (if (and (setq fp (getpoint "\nSelect search point : "))
   (setq ss (ssget "x"
     (list (cons 0 "LINE")(cons 10 fp)
    (cons -4 "<NOT")(cons -4 "<OR")(cons 60 1)(cons 62 250)(cons -4 "OR>")(cons -4 "NOT>")
    (cons -4 "<OR")(cons 8 "MainA")(cons 8 "MainB")(cons 8 "BLines")(cons -4 "OR>")))))
   (princ (strcat "\nNumber of lines selected : " (itoa (sslength ss))))
   (princ "\nSorry , no lines found for specified point")
 )
)


 

 

btw , you can combine layers like

 (cons 8 "MainA,MainB,BLines") 

Edited by rlx
Link to comment
Share on other sites

I will need to check this on an other system. There maybe something wrong with mine.

 

The code I wrote is only for testing. The intention was only to check the responsiveness of the system by measuring times with a stopwatch.

 

Thanks for the tip.

Link to comment
Share on other sites

I will need to check this on an other system. There maybe something wrong with mine.

 

The code I wrote is only for testing. The intention was only to check the responsiveness of the system by measuring times with a stopwatch.

 

Thanks for the tip.

 

 

You're welcome.

 

 

Also , using ssget x always means you scan the entire drawing database. So when you cut-copy-paste a section to another drawing your new datebase is much smaller. A way around this would be to ssget with a crossing around your point and then filter out the ones your need or dont need.

 

 

gr. Rlx

Link to comment
Share on other sites

A way around this would be to ssget with a crossing around your point and then filter out the ones your need or dont need.

 

I always wanted to do it this way but unfortunately I find Autocad not very helpful on this. Any passing of lines behind this point or very near will select these as well. My model is a 3D piping model and there may be some good amount of lines behind in 3D space in any direction. I managed somewhat to filter them out but it s cumbersome. I still haven't found a fruitful way to filter lines passing through the point but being behind in space in any orientation.

Link to comment
Share on other sites

Maybe this thread can give some more info on large selection sets , but sometimes its also a matter of brute force , lots of ram or optimizing the drawing itself. For example , by putting parts of your objects in their own layer so you can then freeze them so they don't get in the way. Or xref them , that sort of things.

 

 

http://www.cadtutor.net/forum/showthread.php?100061-LISP-Efficiency-for-large-selection-set

 

 

gr. Rlx

Link to comment
Share on other sites

Thanks. It may be helpful. From your last posts I kinda understand that the problem here is not my system rather the "_X" switch of the ssget command. It looks to me that I need to devise a way, if possible, to eliminate "_X" switch.

Edited by MJLM
Link to comment
Share on other sites

You can use the "_CW" option in combination with the filter you use for the "_X" option. So I do not understand why you use the word 'cumbersome'. But do keep in mind that the window for "_CW" must be on-screen.

 

When using the "_X" option it is worth considering filtering for the current space:

(if (= 1 (getvar 'cvport))
 (cons 410 (getvar 'ctab))
 '(410 . "Model")
)

Link to comment
Share on other sites

Are you sure you mean "_CW"? I couldn't find this option in the documentation. Probably "_CP"? An example would be great.

 

The main reason I find this way of selection 'cumbersome' is because all these 'crossing' windows/polygons or 'fence' options will select lines that are behind from the selected point in 3d space but visually cross through this point or very near. Filtering such selection is difficult if your lines are practically of any 3D orientation and the user uses his own UCS, at least to me which I am a beginner to lisp. An other reason is what you said yourself, the selected points used in the ssget command must be on-screen. This could be solved by zoom extents at the beginning of the routine but not always practical in large models when you want to run the routine multiple times to reach the desired result, at least to my perspective. But of course it is a way to do it.

Link to comment
Share on other sites

You are right. "_CW" should be "_C":

(defun c:Test ( / fp ss)
 (if
   (and
     (setq fp (getpoint "\nSelect search point : ")) ; Point in the current UCS.
     (setq ss 
       (ssget
         "_C"
         (mapcar '- fp '(0.01 0.01 0.01)) ; Small crossing also in the current UCS.
         (mapcar '+ fp '(0.01 0.01 0.01))
         (list
           '(0 . "LINE")
           '(8 . "MainA,MainB,BLines")
           '(-4 . "/=") '(62 . 250)
           ; '(60 . 0) ; Not necessary when using the "_C" option.
           '(-4 . ">,>,>") (cons 10 (mapcar '- (setq fp (trans fp 1 0)) '(1e-8 1e-8 1e-)) ;  (trans fp 1 0) to translate the point to the WCS.
           '(-4 . "<,<,<") (cons 10 (mapcar '+ fp '(1e-8 1e-8 1e-))
         )
       )
     )
   )
   (print (sslength ss))
   (print 0)
 )
 (princ)
)

Link to comment
Share on other sites

Thank you for your help but it seems my opinion about a 'cumbersome' process is not unjustified. On a simple model of connecting lines (typical piping network), one ending on the other, the routine does not work well. Looping through each line and performing ssget on its start and end point to select all other to complete the chain, the process terminates after the few first lines.

 

This is how I modified your code which is called from a main routine which loops though all lines, one by one, by ssgeting lines on start and end point and add them in a selection set. The loop terminates until there are no lines left. I copied-pasted the same code as an other instance for dxf group 11 (e.g. cons 11...).

 

I can't make out what may be the problem. I tried playing with the tolerances you put but with no result. Any ideas?

 

(defun sel_ss10 (fp_ss10 / fp_ss10 ss_10)
(if
	(setq ss_10
		(ssget
			"_C"
			(mapcar '- fp_ss10 '(0.01 0.01 0.01)) ; Small crossing also in the current UCS.
			(mapcar '+ fp_ss10 '(0.01 0.01 0.01))
			(list
				'(0 . "LINE")
				'(8 . "MainA,MainB,BLines")
				'(-4 . "/=") '(62 . 250)
				'(-4 . ">,>,>") (cons 10 (mapcar '- (setq fp_ss10 (trans fp_ss10 1 0)) '(1e-8 1e-8 1e-)) ;  (trans fp_ss10 1 0) to translate the point to the WCS.
				'(-4 . "<,<,<") (cons 10 (mapcar '+ fp_ss10 '(1e-8 1e-8 1e-))
			)
		)
	)
	ss_10
)
)

Link to comment
Share on other sites

OK, I m taking back what I wrote above. After thorough examination, the code above works fine. It was only me that I forgot that entire model in processing needed to be visible on the screen. My bad, we have said that few post above. Sorry for any confusion and thank you Roy once more for your help.

 

On a side note, to automate the process I included zoom extents and then zoom previous at the beginning and end of code to overcome this handicap of the "_C" option. I didn't like the idea for visual purposes but I had to do it. Funny thing is, the screen, at least on my system, while the routine is running, does not refresh and therefore the user does not see this zooming out and back which is, unexpectedly, a great surprise.

 

EDIT: I forgot to mention the most important. By using the "_C" option instead of the "_X" the process time was cut down to 1/4!

Edited by MJLM
Link to comment
Share on other sites

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