extract the length of arc element with division into intervals, range

extract the length of arc element with division into intervals, range

JN05
Enthusiast Enthusiast
1,554 Views
14 Replies
Message 1 of 15

extract the length of arc element with division into intervals, range

JN05
Enthusiast
Enthusiast

length in the range of {>= 0; <10}
length in the range of {>= 10; <40}
length in the range of {>= 40; infinity}.


Good morning,

 

I was faced with the task of extracting a summary of the length of the arcs divided into intervals.

Could I ask experts to help me solve such a task.

 

I would need a lisp to do this:
1) calling the command,
2) indication of objects,
3) returning through the command line the value already summarized in the range of each interval (1,2,3).

Thanks for any support.

 

Thank you for all your help in this regard.

Tomasz Stawarz, Co-owner
ZNAK Gdańsk sp. z o.o.
Gdańsk, PL.
Tomasz Stawarz is co-founder and co-owner of ZNAK Gdańsk sp. z o.o., Gdańsk, PL. Tom's speciality is Civil Infrastructure and has been working with AutoCad since 1997.
0 Likes
Accepted solutions (1)
1,555 Views
14 Replies
Replies (14)
Message 2 of 15

ВeekeeCZ
Consultant
Consultant
Accepted solution

 

(vl-load-com)

(defun c:ArcLenSummary ( / l1 l2 l3 s i e l)

  (setq l1 0 l2 0 l3 0)
  (if (setq s (ssget '((0 . "ARC"))))
    (repeat (setq i (sslength s))
      (setq e (ssname s (setq i (1- i))))
      (setq l (vlax-curve-getdistatparam e (vlax-curve-getendparam e)))
      (cond ((not l))
	    ((< l 10.)  (setq l1 (+ l l1)))
	    ((< l 40.)  (setq l2 (+ l l2)))
	    (T	 	(setq l3 (+ l l3))))))
  (mapcar 'print (mapcar 'cons '((< l 10) (< l 40) (> l 40)) (list l1 l2 l3)))
  (princ)
  )

 

Message 3 of 15

Kent1Cooper
Consultant
Consultant

Another way, that doesn't require (vl) functions, and takes advantage of the fact that certain punctuation characters can be used in variable names:

(defun C:ACL ; = Arc Categories by Length
  (/ ss n arc len)
  (setq <10 0 <40 0 >=40 0)
  (if (setq ss (ssget '((0 . "ARC"))))
    (repeat (setq n (sslength ss))
      (setq
        arc (ssname ss (setq n (1- n)))
        len (getpropertyvalue arc "Length")
      );
      (cond
        ((< len 10) (setq <10 (1+ <10)))
        ((< len 40) (setq <40 (1+ <40)))
        ((setq >=40 (1+ >=40)))
      ); cond
    ); repeat
  ); if
  (list (cons (read "<10") <10) (cons (read "<40") <40) (cons (read ">=40") >=40))
); defun

It returns a list of pairs like this:

  ((<10 . 4) (<40 . 3) (>=40 . 2))

and leaves those quantities in the <10, <40 and >=40 variables for your further use if needed.

Kent Cooper, AIA
0 Likes
Message 4 of 15

JN05
Enthusiast
Enthusiast

Thank you for your help. I tried two definitions and the code written by:Kent1Cooper seems wrong to me. Can you correct me if I'm wrong. Thank you for any help. Best regards.

 

defun C:ArcLenSummary    > ((< L 10) . 1110.24) ((< L 40) . 670.973) ((> L 40) . 1818.29)

defun C:ACL                           > ((<10 . 280) (<40 . 38) (>=40 . 25))

Tomasz Stawarz, Co-owner
ZNAK Gdańsk sp. z o.o.
Gdańsk, PL.
Tomasz Stawarz is co-founder and co-owner of ZNAK Gdańsk sp. z o.o., Gdańsk, PL. Tom's speciality is Civil Infrastructure and has been working with AutoCad since 1997.
0 Likes
Message 5 of 15

Kent1Cooper
Consultant
Consultant

Sorry, I misread the intent as being the quantity of Arc objects within each length range, rather than the total of their lengths.  I can adjust for that, later.

EDIT:  A quicker adjustment than I anticipated....

 

(defun C:ALTC ; = Arc Length Totals by Category
  (/ ss n arc len)
  (setq <10 0 <40 0 >=40 0)
  (if (setq ss (ssget '((0 . "ARC"))))
    (repeat (setq n (sslength ss))
      (setq
        arc (ssname ss (setq n (1- n)))
        len (getpropertyvalue arc "Length")
      );
      (cond
        ((< len 10) (setq <10 (+ <10 len)))
        ((< len 40) (setq <40 (+ <40 len)))
        ((setq >=40 (+ >=40 len)))
      ); cond
    ); repeat
  ); if
  (list (cons (read "<10") <10) (cons (read "<40") <40) (cons (read ">=40") >=40))
); defun

 

I gave it a different command name, in case you want to be able to use both.

Kent Cooper, AIA
0 Likes
Message 6 of 15

JN05
Enthusiast
Enthusiast

Kent,
Thank you for your help and willingness to spend time. Perhaps I will also use this function that shows the number of arcs. Thank you for any help.

Tomasz Stawarz, Co-owner
ZNAK Gdańsk sp. z o.o.
Gdańsk, PL.
Tomasz Stawarz is co-founder and co-owner of ZNAK Gdańsk sp. z o.o., Gdańsk, PL. Tom's speciality is Civil Infrastructure and has been working with AutoCad since 1997.
0 Likes
Message 7 of 15

Kent1Cooper
Consultant
Consultant

[See the Edit to Message 5.]

Kent Cooper, AIA
0 Likes
Message 8 of 15

pbejse
Mentor
Mentor

@JN05 wrote:

I was faced with the task of extracting a summary of the length of the arcs divided into intervals.

 


Looks fun, heres another way to skin a cat [ as a sub ]

by One Code Man ( programmer for fun ) 

(defun Infinityandbeyond ( data / s _str over s ei l)  
;;;	pBe Nov 2020	;;;
(setq over 0  _str (lambda (v)(vl-princ-to-string v)))
(if (setq s (ssget '((0 . "ARC"))))
	  (repeat (setq i (sslength s))
	    (setq l (vlax-get (vlax-ename->vla-object
				(ssname s (setq i (1- i)))) 'ArcLength))
	    (cond
	      ((vl-some '(lambda (v / cl)
			(if (<= l (car v))
			  	(setq data (subst (cons (car v)(+ (cdr v) l)) v data))))
			data
		     )
		)
	      ((setq Over (+ Over l)))
	      )
	    )
	)	     
	  (mapcar '(lambda (a b)
		     (print (strcat "Length in the range of {>= "
				    (_str a)
				    "; <"
				    (_str (car b))
				    "}: "
				    (_str (Cdr b))
			    )
		     )
		   )
		  (cons 0 (mapcar 'car data))
		  (append data (list (cons "infinity" over)))
	  )
	  (princ)
       )

 

Use it like this 

_$ (Infinityandbeyond '((10 . 0)(40 . 0)))
"Length in the range of {>= 0; <10}: 7.75158" 
"Length in the range of {>= 10; <40}: 80.1564" 
"Length in the range of {>= 40; <infinity}: 97.5751" 
_$ (Infinityandbeyond '((10 . 0)(30 . 0)(40 . 0)(50 . 0)))
"Length in the range of {>= 0; <10}: 7.75158" 
"Length in the range of {>= 10; <30}: 48.9954" 
"Length in the range of {>= 30; <40}: 31.1609" 
"Length in the range of {>= 40; <50}: 47.241" 
"Length in the range of {>= 50; <infinity}: 50.3341" 

 

Or you can even add a prompt for range values, but i will leave that for you to play with.

 

 

0 Likes
Message 9 of 15

pbejse
Mentor
Mentor

To make it simpler in preparation for the "prompt for range" 

(defun Infinityandbeyond ( data / data _str over s ei l)  
;;;	pBe Nov 2020	;;;
(setq data (mapcar '(lambda (a) (cons a 0)) data))
....

Then call it like this

(Infinityandbeyond '(10 40))
(Infinityandbeyond '(10 20 30 40 50))

 

We can even show a break down and a total.

 

"Length in the range of {>= 10; <20}: 
5.25 + 2.00 + 3.00 = 10.25" 

 

The possiblities are endless 

 

 

Message 10 of 15

JN05
Enthusiast
Enthusiast

Thanks. I just missed that sum.

The bill of quantities checker will see what is being added. Could you please help me get it all together into one lisp?

Thank you for all your help and time. Best regards.

Tomasz Stawarz, Co-owner
ZNAK Gdańsk sp. z o.o.
Gdańsk, PL.
Tomasz Stawarz is co-founder and co-owner of ZNAK Gdańsk sp. z o.o., Gdańsk, PL. Tom's speciality is Civil Infrastructure and has been working with AutoCad since 1997.
0 Likes
Message 11 of 15

ВeekeeCZ
Consultant
Consultant

@pbejse wrote:

To make it simpler in preparation for the "prompt for range" 

(defun Infinityandbeyond ( data / data _str over s ei l)  
;;;	pBe Nov 2020	;;;
(setq data (mapcar '(lambda (a) (cons a 0)) data))
....

Then call it like this

(Infinityandbeyond '(10 40))
(Infinityandbeyond '(10 20 30 40 50))

 

We can even show a break down and a total.

 

"Length in the range of {>= 10; <20}: 
5.25 + 2.00 + 3.00 = 10.25" 

 

The possiblities are endless 

 

 


 

Yep, this is right direction to what is do some time to time. Something like this: 

(Infinityandbeyond '(R1 R2.5 R5 R10 R30))

 

Then the result:

"Length in the radius range of {>= R5; <R30}:
5.25 + 2.00 + 3.00 = 10.25"

 
0 Likes
Message 12 of 15

pbejse
Mentor
Mentor

@ВeekeeCZ wrote:

Yep, this is right direction to what is do some time to time..

 

 

 

Yes indeed and even include options for object type

(Infinityandbeyond '(10 40) "LWPOLYLINE")
(Infinityandbeyond '(10 20 40) "LWPOLYLINE,LINE,ARC")

 

0 Likes
Message 13 of 15

pbejse
Mentor
Mentor

@JN05 wrote:

The bill of quantities checker will see what is being added.


Here's a quick mod

(defun Infinityandbeyond ( data etype / _plus s _str over s ei l)  
;;;	pBe Nov 2020	;;;
(setq _plus (lambda (lst s)(substr
	       (apply 'strcat
		      (mapcar '(lambda (str)
				 (strcat  s str) ) lst)
		      ) (1+ (strlen s))
	       ) 
	     )
	)
(setq data (mapcar '(lambda (a) (list a))  data ))
(setq _str (lambda (v)(vl-princ-to-string v)))
  
	(if (setq s (ssget (list (cons 0 etype ))))
	  (progn
		  (repeat (setq i (sslength s))
		    (setq e (ssname s (setq i (1- i))))
		    (setq l (vlax-curve-getdistatparam e (vlax-curve-getendparam e)))
		    (cond
		      ((vl-some '(lambda (v / cl)
				(if (< l (car v))
				  	(setq data (subst (append v (list l))
						      v data)))
				  	)
				data
			     )
		       )
		      ((setq Over (cons l Over))
		      )
		    )
		)	     
		(mapcar '(lambda (a b)
		     (princ "\n------------------------------------------")
		     (princ (strcat "\nLength in the range of {>= "
				    (_str a) "; <"  (_str (car b)) "}:" )
			    )
		     (princ
		       (if (setq val (cdr b))
		       		(strcat "\n\t\t" (_plus (mapcar '_str val) " + ") " = " (_str (apply '+ val)))
			 	"\t[ None Found ]"))
		     )
		  (cons 0 (mapcar 'car data))
		  (append data (list (cons "infinity" over)))
		)
	     )
	  )
     (princ)
  )

 

Then you can make command names per range and type

(defun c:ArcSummary ()(Infinityandbeyond'(10 40) "ARC"))

Command: ARCSUMMARY
Select objects: Specify opposite corner: 9 found
------------------------------------------
Length in the range of {>= 0; <10}:
   2.11634 + 3.1745 = 5.29084
------------------------------------------
Length in the range of {>= 10; <40}:
   21.5768 + 19.267 + 32.3652 + 28.9005 = 102.11
------------------------------------------
Length in the range of {>= 40; <infinity}:
   40.3987 + 86.2183 + 107.821 = 234.438
(defun c:PlineSummary ()(Infinityandbeyond'(10 20 30 40) "LWPOLYLINE"))

Command: PLINESUMMARY
Select objects: Specify opposite corner: 10 found
------------------------------------------
Length in the range of {>= 0; <10}:
   2.07658 + 8.84389 + 9.64276 + 3.11487 = 23.6781
------------------------------------------
Length in the range of {>= 10; <20}:
   13.2658 + 14.4641 = 27.73
------------------------------------------
Length in the range of {>= 20; <30}:  [ None Found ]
------------------------------------------
Length in the range of {>= 30; <40}:
   38.4718 = 38.4718
------------------------------------------
Length in the range of {>= 40; <infinity}:
   57.7077 + 66.3291 + 44.2194 = 168.256
(defun c:WhateverSummary ()(Infinityandbeyond'(10 20 30 40) "LWPOLYLINE,LINE,ARC"))

Command: WHATEVERSUMMARY
Select objects: Specify opposite corner: 35 found

------------------------------------------
Length in the range of {>= 0; <10}:
   9.84144 + 5.32298 + 2.07658 + 0.906825 + 2.11634 + 8.84389 + 9.64276 + 7.98446 + 3.11487 + 1.36024 + 3.1745 = 54.3849
------------------------------------------
Length in the range of {>= 10; <20}:
   19.267 + 14.7622 + 13.2658 + 14.4641 = 61.7592
------------------------------------------
Length in the range of {>= 20; <30}:
   21.5768 + 25.5917 + 28.1022 + 21.0488 + 28.9005 = 125.22
------------------------------------------
Length in the range of {>= 30; <40}:
   30.3151 + 31.3353 + 38.4718 + 32.3652 + 38.3876 + 31.5732 = 202.448
------------------------------------------
Length in the range of {>= 40; <infinity}:
   40.3987 + 86.2183 + 107.821 + 57.7077 + 66.3291 + 47.003 + 42.1533 + 45.4726 + 44.2194 = 537.323

HTH

0 Likes
Message 14 of 15

JN05
Enthusiast
Enthusiast

I am a beginner in programming. I don't know how to merge the two files. Should I make the files with the commands: ArcLenSummary and Infinityandbeyond as separate files. Can you help me and show me what the final LSP file should look like? Thank you very much for all your help. best regards

Tomasz Stawarz, Co-owner
ZNAK Gdańsk sp. z o.o.
Gdańsk, PL.
Tomasz Stawarz is co-founder and co-owner of ZNAK Gdańsk sp. z o.o., Gdańsk, PL. Tom's speciality is Civil Infrastructure and has been working with AutoCad since 1997.
0 Likes
Message 15 of 15

pbejse
Mentor
Mentor

@JN05 wrote:

Can you help me and show me what the final LSP file should look like? Thank you very much for all your help. best regards


I'm attaching a lisp named Infinityandbeyond.lsp

 

Command: ARCSUMMARY

Command: PLINESUMMARY

Command: WHATEVERSUMMARY

 

Keep in mind that the range is hard-coded as '(10 40) for Arc objects,  '(10 20 30 40) for LWPOLYLINES and  also for the combination of these 3 obejct type "LWPOLYLINE,LINE,ARC")

 

You have to change the range on the lisp file

(defun c:ArcSummary ()(Infinityandbeyond'(10 40) "ARC"))
(defun c:PlineSummary ()(Infinityandbeyond'(10 20 30 40) "LWPOLYLINE"))
(defun c:WhateverSummary ()(Infinityandbeyond'(10 20 30 40) "LWPOLYLINE,LINE,ARC"))

 

And like i said before, we can add a prompt for range values in the future, but we need to know if the routine works for you as it stands now

 

 

0 Likes