Community
Civil 3D Customization
Welcome to Autodesk’s AutoCAD Civil 3D Forums. Share your knowledge, ask questions, and explore popular AutoCAD Civil 3D Customization topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Calculating Time of Concentration from Feature Line

8 REPLIES 8
SOLVED
Reply
Message 1 of 9
Anonymous
1072 Views, 8 Replies

Calculating Time of Concentration from Feature Line

All,

 

I'm currently trying to write a LISP function that does the following:

 

-prompts user to select a Feature Line

-prompts user to select a starting and ending point along that Feature Line

-prompts the user to enter a keyword determining which calculation formula to use (from a list of four, based on the TR-55 Hydrology manual)

-calculates the flow time based on the above

-returns the segment length, segment slope, and flow time at the Command Line

 

I've written up some code (see below) and get an error: too few arguments. Can someone take a look and see what I'm doing wrong? I'm not a good programmer so apologies in advance...

 

*ninja edit: the original problem (too few arguments) was because I foolishly didn't specify for the user to actually select a point. Added (getpoint) to the vlax-curve-getclosestpointto lines.

 

Now however I'm getting an error "no function definition: get2ddistancebetweenpoints. I know this is function exists, but I must be calling it wrong. Any help?

 

 

(defun c:conctime ( / sel obj compoint1 compoint2 seglen z1 z2 slope ftype segtime rdlen rdslope rdtime)
  (vl-load-com)
  (princ "\nSelect Feature Line: ")
  (setq sel (ssget "+.:s" '((0 . "AECC_FEATURE_LINE"))))
  (if sel
  	(progn
	  (setq obj (vlax-ename->vla-object (ssname sel 0)))
	  (princ "\nSelect Start Point: ")
	  (setq compoint1 (vlax-curve-getClosestPointTo obj))
	  (princ "\nSelect End Point: ")
	  (setq compoint2 (vlax-curve-getClosestPointTo obj))
	  (setq seglen (vlax-curve-get2dDistanceBetweenPoints compoint1 compoint2))
	  (setq z1 (caddr compoint1))
	  (setq z2 (caddr compoint2))
	  (setq slope (abs (/ (- z1 z2) seglen)))
	  (initget 1 "Sheet Unpaved Paved Channel")
	  (setq ftype (getkword " [Sheet/Unpaved/Paved/Channel]: "))
	  (cond ((= ftype "Sheet")
		 (setq segtime (* 60 (/ (* 0.007 (expt (* 0.3 seglen) 0.8)) (* 1.8276 (expt slope 0.4)))))
		 )
		((= ftype "Unpaved")
		 (setq segtime (/ seglen (* 60 (* 16.1345 (expt slope 0.5)))))
		 )
		((= ftype "Paved")
		 (setq segtime (/ seglen (* 60 (* 20.3282 (expt slope 0.5)))))
		 )
		((=ftype "Channel")
		 (setq segtime (/ seglen 360))
		 )
		)
(setq rdlen (rtos seglen 2 2))
(setq rdslope (rtos slope 2 2))
(setq rdtime (rtos segtime 2 2))
(princ rdlen)
(terpri)
(princ rdslope)
(terpri)
(princ rdtime)
(princ)
)
)
)

 

8 REPLIES 8
Message 2 of 9
hippe013
in reply to: Anonymous

Just use the distance function. 

 

Here is a list of the vlax-curve functions.

 

hippe013_0-1598565330304.png

 

Message 3 of 9
Anonymous
in reply to: hippe013

Just to double check: using that function returns the distance along the Feature Line, correct?

Message 4 of 9
hippe013
in reply to: Anonymous

The Distance function returns a two dimensional distance when the arguments are two dimensional. It returns the three dimensional distance when both of the arguments supplied are are three dimensional. 

Message 5 of 9
Anonymous
in reply to: hippe013

@hippe013 , you've been a wealth of knowledge. Thanks so much for your help!

 

I've gotten the first iteration of the LISP to work as intended, returning values that match my hand checks. So now I've moved on to the next iteration. Here I would like to be able to calculate multiple flow segments along one Feature Line. I'm basically trying to create a loop where the user clicks a start/end point and selects a flow type (as before), and those values are added to a list. This would continue until the user hits Enter, at which point the routine would spit out the sets of values like so:

 

SHEET

100.00 feet

1.27 percent slope

20.44 minutes

UNPAVED

155.04 feet

0.70 percent slope

8.47 minutes

 

etc etc. The end goal is to print those values to either an AutoCAD table, .txt file, or Excel file - but that's a topic for later.

 

Right now I'm getting an error: "bad argument type: numberp: nil." Any thoughts on what's causing it? See code below...

 

(defun c:conctime ( / sel obj compoint1 compoint2 seglen z1 z2 segslope ftype segtime rdlen rdslope rdtime seglist count1 curseg count2)
	(vl-load-com)
	(setq count1 0) ;counter for tracking number of segments
	(setq count2 0) ;counter for printing segment info
	;get Feature Line from drawing
	(princ "\nSelect Feature Line: ")
	(setq sel (ssget "+.:s" '((0 . "AECC_FEATURE_LINE")))) ;prevents selection of multiple FLs
	(if sel ;error trapping, only moves forward if selection set exists
		(progn
		(setq obj (vlax-ename->vla-object (ssname sel 0))) ;defines "obj" variable based on existing selection set
		(while
		(princ "\nSelect Start Point: ")
		(setq compoint1 (vlax-curve-getClosestPointTo obj (getpoint))) ;grabs point on object nearest to point selected, this ensures the point is actually on FL
		(princ "\nSelect End Point: ")
		(setq compoint2 (vlax-curve-getClosestPointTo obj (getpoint)))
		(setq seglen (abs (- (vlax-curve-getDistAtPoint obj compoint1) (vlax-curve-getDistAtPoint obj compoint2)))) ;defines length between selected points
		(setq z1 (caddr compoint1)) ;extract z coordinate from point
		(setq z2 (caddr compoint2))
		(setq segslope (abs (/ (- z1 z2) seglen))) ;math to get slope
		(initget 1 "Sheet Unpaved Paved Channel") ;brings up selection menu
		(setq ftype (getkword " [Sheet/Unpaved/Paved/Channel]: ")) ;sets keyword based on user selection
		(cond ((= ftype "Sheet")
			(setq segtime (* 60 (/ (* 0.007 (expt (* 0.3 seglen) 0.8)) (* 1.8276 (expt slope 0.4))))) ;math based on TR-55/2018 CONB DECDM
			)
		((= ftype "Unpaved")
			(setq segtime (/ seglen (* 60 (* 16.1345 (expt slope 0.5)))))
			)
		((= ftype "Paved")
		 	(setq segtime (/ seglen (* 60 (* 20.3282 (expt slope 0.5)))))
		 	)
		((=ftype "Channel")
		 	(setq segtime (/ seglen 360))
		 	)
		(setq rdlen (rtos seglen 2 2)) ;defines new variables rounded to two decimal places
		(setq rdslope (rtos (* segslope 100) 2 2))
		(setq rdtime (rtos segtime 2 2))
		(setq curseg (list ftype rdlen rdslope rdtime)) ;creates a list of current segment type, length, slope, time
		(setq seglist (append seglist curseg)) ;adds current segment data to overall list
		) ;cond
	(setq count1 (+ count1 1)) ;tolls the counter tracking number of segments
	) ;while
(while (< count2 (- count1 3))
		(princ (nth no seglist)) ;returns first ftype to command line
		(terpri) ;linebreak before next print
		(princ (nth (+ no 1) seglist))
		(princ " feet")
		(terpri)
		(princ (nth (+ no 2) seglist))
		(princ " percent slope")
		(terpri)
		(princ (nth (+ no 3) seglist))
		(princ " minutes")
		(setq count2 (+ count2 4))
	) ;while
	) ;progn
) ;if
		(princ) ;last print ends routine
) ;defun

 Thanks... 

Message 6 of 9
hippe013
in reply to: Anonymous

First: Add a space between = and ftype in your cond statement "((=ftype "Channel")

 

Second: Where does the 'slope' variable as used in the cond statement get its value prior to being used?

 

That could be why you get "; error: bad argument type: numberp: nil"

 

Use vlide to run your code. You can animate your code using this IDE. Where an error occurs it will leave that area highlighted making it easier to debug.

 

regards,

 

hippe013

Message 7 of 9
hippe013
in reply to: Anonymous

One more thing. 

 

Avoid dividing by an integer, unless that is what you need, but that's rarely the case.

 

Test the following on a command line:

(/ 360 11) = 32

(/ 360 11.0) = 32.7273

Message 8 of 9
Anonymous
in reply to: hippe013

Thanks for the tip about the VLIDE - you were correct about the result of the previous error. Now I'm confused about a new error haha. When I run the command I get the message "bad argument type: 2d/3d point:nil." Using the debugger on VLIDE, it pointed me to this line:

 

(setq compoint1 (vlax-curve-getClosestPointTo obj (getpoint)))

 

As the source of the error. I find this odd since that line hasn't been a problem in previous iterations. Any thoughts on why this is throwing an error? 

Message 9 of 9
hippe013
in reply to: Anonymous

What would happen if the user failed to get a point? You are handing the result of (getpoint) right over to vlax-curve-getclosestpointto without checking whether getpoint was successful or not. 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Rail Community


Autodesk Design & Make Report