nimble87 Posted September 16, 2020 Posted September 16, 2020 Hi All, I have a portion of code that provides a segment length, is there any way to round up the output length to the nearest 5? Is it possible using RTOS or will I need to include a separate roundup function? eg: Road Crossing actual length = 16.4m, i'd like it to output 20m. (defun c:FX-ING ( / tr pref) (setq tr "0CHK X-ING TRENCH ") (setq pref (getstring CR "\nTRENCH DETAIL: ")) (command "_.Layer" "_Make" (strcat tr pref) "_Color" "210" "" "_TR" "30" "" "LType" "dashed" "" (COMMAND)) (setq prev (getvar "clayer")) (setvar "clayer" (strcat tr pref)) (command ".pline") (while (= (logand (getvar "cmdactive") 1) 1)(command pause)) (setq sg (ssget "L")) (C:midl) (C:SEGX-ING) ) ;; ROAD CROSSING Segment length (defun c:SEGX-ING (/ ls4 tl4 n ent itm obj l) (setq ls4 (ssget "P" (list (cons 8 (strcat tr pref)))) tl4 0 n (1- (sslength ls4))) (while (>= n 0) (setq ent (entget (setq itm (ssname ls4 n))) obj (cdr (assoc 0 ent)) l (cond ((= obj "LINE") (distance (cdr (assoc 10 ent))(cdr (assoc 11 ent)))) ((= obj "ARC") (* (cdr (assoc 40 ent)) (if (minusp (setq l (- (cdr (assoc 51 ent)) (cdr (assoc 50 ent))))) (+ pi pi l) l))) ((or (= obj "CIRCLE")(= obj "SPLINE")(= obj "POLYLINE") (= obj "LWPOLYLINE")(= obj "ELLIPSE")) (command "_.area" "_o" itm) (getvar "perimeter")) (T 0)) tl4 (+ tl4 l) n (1- n))) (alert (strcat "Last segment length of road crossing is " (rtos tl4))) ) Thanks in advance Quote
BIGAL Posted September 16, 2020 Posted September 16, 2020 That is a big roundup value would have thought a 1m would be more appropriate for Civil works. Lee-mac.com has a rounding function. Quote
nimble87 Posted September 16, 2020 Author Posted September 16, 2020 1 minute ago, BIGAL said: That is a big roundup value would have thought a 1m would be more appropriate for Civil works. Lee-mac.com has a rounding function. It is a large roundup, more so just for rough bill of quantities. I've been trying to incorporate Lee Macs rounding function but had no luck getting it to work, found another thread where he assisted in rounding to the nearest 100, but couldn't get that to work either. I've been trying the below, i'm just unsure where and how to include it in the code. Thanks (defun LM:roundm ( n m ) (* m (atoi (rtos (/ n (float m)) 2 0))) ) Quote
nimble87 Posted September 16, 2020 Author Posted September 16, 2020 I think I've found the problem. It uses a version of Midlen, which Lee-Mac created some years ago (very handy thanks Lee), attached for reference. This routine adds the polyline length to the midpoint of the polyline as a field. I may be wrong, but I'm thinking I need to apply the 5m roundup to the field formatting. Would love some input if Midlen can be rounded up to the nearest 5m? Thanks. MidLenV1-0.lsp Quote
BIGAL Posted September 16, 2020 Posted September 16, 2020 The code rounds up and rounds down using 1 would be best. Bit of a guess (fix (* 10.0 (lm:roundm (/ 16.4 10.0 ) 1))) you need to try Quote
lido Posted September 16, 2020 Posted September 16, 2020 Try this: (defun mult5 (nr / a b c s) (setq a (itoa (fix (+ nr 0.5))) b (strlen a) c (atoi (substr a b)) s (substr a 1 (1- b)) ) (atoi (cond ( (vl-position c (quote (0 1 2))) (strcat s "0") ) ( (vl-position c (quote (3 4 5 6 7))) (strcat s "5") ) ( T (strcat (itoa (1+ (atoi s))) "0")) ) ) ) ;;mult5 Quote
dlanorh Posted September 16, 2020 Posted September 16, 2020 Try this oldish function by Doug Broad (defun db:round ( val acc ) (* (abs acc) (fix (/ ((if (minusp val) - +) val (* (abs acc) 0.5)) (abs acc))))) Example of use (db:round 123.456 5.0) "val" is the number you want to round "acc" is the accuracy. If accuracy is an integer it returns an integer if its a real it returns a real Quote
Lee Mac Posted September 16, 2020 Posted September 16, 2020 My LM:roundm function may be used in the following way: _$ (LM:roundm 12 5) 10 _$ (LM:roundm 13 5) 15 You can implement the same logic in field formatting using the ROUND formula function, by changing this: (strcat "%<\\AcObjProp Object(%<\\_ObjId " (LM:objectid (vlax-ename->vla-object ent)) ">%)." (cond ( (= "CIRCLE" typ) "Circumference") ( (= "ARC" typ) "ArcLength") ( "Length" ) ) " \\f \"" fmt "\">%" ) To: (strcat "%<\\AcExpr (ROUND(%<\\AcObjProp Object(%<\\_ObjId " (LM:objectid (vlax-ename->vla-object ent)) ">%)." (cond ( (= "CIRCLE" typ) "Circumference") ( (= "ARC" typ) "ArcLength") ( "Length" ) ) ">%/5.0)*5.0) \\f \"" fmt "\">%" ) 2 Quote
nimble87 Posted September 16, 2020 Author Posted September 16, 2020 3 hours ago, Lee Mac said: My LM:roundm function may be used in the following way: _$ (LM:roundm 12 5) 10 _$ (LM:roundm 13 5) 15 You can implement the same logic in field formatting using the ROUND formula function, by changing this: (strcat "%<\\AcObjProp Object(%<\\_ObjId " (LM:objectid (vlax-ename->vla-object ent)) ">%)." (cond ( (= "CIRCLE" typ) "Circumference") ( (= "ARC" typ) "ArcLength") ( "Length" ) ) " \\f \"" fmt "\">%" ) To: (strcat "%<\\AcExpr (ROUND(%<\\AcObjProp Object(%<\\_ObjId " (LM:objectid (vlax-ename->vla-object ent)) ">%)." (cond ( (= "CIRCLE" typ) "Circumference") ( (= "ARC" typ) "ArcLength") ( "Length" ) ) ">%/5.0)*5.0) \\f \"" fmt "\">%" ) Thanks to all for their input, the help is greatly appreciated. Lee, your solution worked without hitch, thank you. Visually the length is rounded to the nearest multiple of 5, but the dialog box still provides the exact measurement, which is perfect for our application. Thanks again. Quote
nimble87 Posted September 16, 2020 Author Posted September 16, 2020 (edited) I've done a bit more testing and it appears the above solution works by rounding to the nearest 5, is it possible to tweak it to round up to the next 5? Rounding down will cause a few issues with quantities. ** edit: also trying to incorporate the copy to clipboard code from here--> https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/need-lisp-surface-angle-with-4-points/td-p/4595101/page/2 I'd like to copy the rounded up to 5 value to clipboard to allow pasting to excel after each command, possible? I can get them to work separately, but can't get copy to clipboard to use the rounded midlen value. Thanks. Edited September 16, 2020 by nimble87 Quote
BIGAL Posted September 16, 2020 Posted September 16, 2020 About to say the rounding down is a problem you would need a If answer < original add 2 * rounding. Still think 5 is way to much a different way may be to look at decimal if > 0.1 then add 1 to integer value. This way set a minimum value like 0.1 that can be dropped. I have personally tape measured meters of kerbing as there was a dispute about lengths. You don't want to over pay the contractor. 5's will add very quick extra in their pocket. 1 Quote
nimble87 Posted September 16, 2020 Author Posted September 16, 2020 2 minutes ago, BIGAL said: About to say the rounding down is a problem you would need a If answer < original add 2 * rounding. Still think 5 is way to much a different way may be to look at decimal if > 0.1 then add 1 to integer value. This way set a minimum value like 0.1 that can be dropped. I have personally tape measured meters of kerbing as there was a dispute about lengths. You don't want to over pay the contractor. 5's will add very quick extra in their pocket. Thanks BigAl, i'll have a play with your suggestion and see if I can make it work. I agree 5m round up does sound like a lot. I work in elec utility design, the 5m round up covers the conduit bends and also the distance to travel from buried depth to surface as we're only measuring the 2D distance. also leaves a little in the kitty to avoid contractors variations during construction due to being short on material. Quote
BIGAL Posted September 17, 2020 Posted September 17, 2020 Its probably easier divide the integer length by 10 then look at 1st decimal then can do a cond adding correct amount. 16.4 = 16 = 1.6 if .6 add .4 * 10. Quote
Lee Mac Posted September 17, 2020 Posted September 17, 2020 20 hours ago, nimble87 said: I've done a bit more testing and it appears the above solution works by rounding to the nearest 5, is it possible to tweak it to round up to the next 5? You can round up using the TRUNC function, e.g.: (strcat "%<\\AcExpr (TRUNC((%<\\AcObjProp Object(%<\\_ObjId " (LM:objectid (vlax-ename->vla-object ent)) ">%)." (cond ( (= "CIRCLE" typ) "Circumference") ( (= "ARC" typ) "ArcLength") ( "Length" ) ) ">%+4.9999999)/5.0)*5.0) \\f \"" fmt "\">%" ) Quote
nimble87 Posted September 17, 2020 Author Posted September 17, 2020 TRUNC is the winner, thanks again Lee and to Bigal, Lido and Dlanorh for your assistance as well. Quote
Lee Mac Posted September 18, 2020 Posted September 18, 2020 21 hours ago, nimble87 said: TRUNC is the winner, thanks again Lee and to Bigal, Lido and Dlanorh for your assistance as well. You're most welcome - note that there is more to the solution than replacing ROUND with TRUNC however, as these two functions operate in very different ways. Quote
nimble87 Posted September 18, 2020 Author Posted September 18, 2020 2 hours ago, Lee Mac said: You're most welcome - note that there is more to the solution than replacing ROUND with TRUNC however, as these two functions operate in very different ways. I always separate your answers and try to manipulate them to see how they work. Thanks again, did some good testing with the program with other users, works perfect. I'm sure you'll see me back when I run into the next wall! 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.