Costinbos77 Posted September 7, 2020 Posted September 7, 2020 (edited) Hi , if p(i) are as (491677.5042 371092.5820) , how will be possible to do the next calculations : (setq selP nil selP (ssGet '((0 . "Point"))) ) ; Select only 3 points ! (if (and (setq e0 (ssName selP 0)) (setq e1 (ssName selP 1)) (setq e2 (ssName selP 2)) ) (progn (setq p1 (trans (cdr (assoc 10 (entGet e0))) 0 1) p2 (trans (cdr (assoc 10 (entGet e1))) 0 1) p3 (trans (cdr (assoc 10 (entGet e2))) 0 1) ) ;;; (setq p1 (cdr (assoc 10 (entGet e0))) p2 (cdr (assoc 10 (entGet e1))) p3 (cdr (assoc 10 (entGet e2))) ) (if (and p1 p2 p3) ; Locale (progn (setq x1 (car p1) y1 (cadr p1) x2 (car p2) y2 (cadr p2) x3 (car p3) y3 (cadr p3) a (* (+ (* (- y2 y3) x1) (* (- x3 x2) y1) (* x2 y3) (* x3 y2 -1.) ) 2.) x (/ (+ (* (+ (* x1 x1) (* y1 y1)) (- y2 y3)) (* (+ (* x2 x2) (* y2 y2)) (- y3 y1)) (* (+ (* x3 x3) (* y3 y3)) (- y1 y2)) ) a) y (/ (+ (* (+ (* x1 x1) (* y1 y1)) (- x3 x2)) (* (+ (* x2 x2) (* y2 y2)) (- x1 x3)) (* (+ (* x3 x3) (* y3 y3)) (- x2 x1)) ) a) dX (- x x1) dY (- y y1) r (sqrt (+ (* dX dX) (* dY dY))) ) ; s (entMake (list '(0 . "Circle") (cons 8 "Lay1") '(6 . "ByLayer") '(62 . 256) (cons 10 (trans (list x y 0) 1 0) ) (cons 40 r) ) ) ; end of e ) ; prog then (prinC "\n NO 3 VALID Points ;") ) ; if )) ; if and With numbers as (1001.123 5001.123) or (61001.123 51001.123) or (100,005.123 100,006.123) it is working fine . But , with numbers bigger than 100,000 is giving wrong answers of calculations . Regards , Costin Edited September 7, 2020 by Costinbos77 Quote
marko_ribar Posted September 7, 2020 Posted September 7, 2020 What is solution - CIRCLE in relation to triangle? Picture would be fine... BTW. CAD can't calculate correct with big numbers - that's known issue... You could though try to truncate numbers by scaling coordinates of points through reference point and then finally rescale CIRCLE as result also through that same reference point... Quote
Costinbos77 Posted September 7, 2020 Author Posted September 7, 2020 Hi marko_ribar , Quote ... What is solution - CIRCLE in relation to triangle? Picture would be fine... BTW ... It is about 3 points on a circle . The real problem is : (* x1 x1) , (* y1 y1) ... because are generating big numbers . I tried to divide the number by 1000 , is not working , because exactly the last decimals are making the difference . Will work something if from a numer as 491677.5042 , I will use only the small part , as 677.5042 and at the end , to add 491000.0 . Regards, Costin Quote
marko_ribar Posted September 7, 2020 Posted September 7, 2020 (edited) Just a side thought... If solution is circumcircle of triangle, why do you need to use math formula... I'd prefer and suggest that you construct resulting circle... And also good to mention, you have built in CIRCLE command with 3P (3 point) option, so you can directly draw circle through command usage... Edited September 7, 2020 by marko_ribar Quote
Costinbos77 Posted September 7, 2020 Author Posted September 7, 2020 (edited) Quote ... you have built in CIRCLE command with 3P (3 point) option, so you can directly draw circle through command usage... ... Good point marko_ribar ! But I think will be slow for 500 circles or more . This is the result : I need the center of the circle defined by 3 points and compared with the center of the designed one. So , I reduce the values if are bigger then 100,000 : (setq selP nil selP (ssGet '((0 . "Point"))) ) ; Select only 3 points ! (if (and (setq e0 (ssName selP 0)) (setq e1 (ssName selP 1)) (setq e2 (ssName selP 2)) ) (progn (setq p1 (trans (cdr (assoc 10 (entGet e0))) 0 1) p2 (trans (cdr (assoc 10 (entGet e1))) 0 1) p3 (trans (cdr (assoc 10 (entGet e2))) 0 1) ) ;;; (setq p1 (cdr (assoc 10 (entGet e0))) p2 (cdr (assoc 10 (entGet e1))) p3 (cdr (assoc 10 (entGet e2))) ) (if (and p1 p2 p3) ; Locale (progn ;;; (setq x1 (/ (car p1) 1000.) y1 (/ (cadr p1) 1000.) x2 (/ (car p2) 1000.) y2 (/ (cadr p2) 1000.) x3 (/ (car p3) 1000.) y3 (/ (cadr p3) 1000.) (setq x1 (car p1) y1 (cadr p1) x2 (car p2) y2 (cadr p2) x3 (car p3) y3 (cadr p3) ) (if (or (> x1 100000) (> x2 100000) (> x3 100000) ) (setq x0 (* (fix (/ (min x1 x2 x3) 1000.)) 1000.) x1 (- x1 x0) x2 (- x2 x0) x3 (- x3 x0) ) (setq x0 0) ) ; if (if (or (> y1 100000) (> y2 100000) (> y3 100000) ) (setq y0 (* (fix (/ (min y1 y2 y3) 1000.)) 1000.) y1 (- y1 y0) y2 (- y2 y0) y3 (- y3 y0) ) (setq y0 0) ) ; if (setq a (* (+ (* (- y2 y3) x1) (* (- x3 x2) y1) (* x2 y3) (* x3 y2 -1.) ) 2.) x (+ (/ (+ (* (+ (* x1 x1) (* y1 y1)) (- y2 y3)) (* (+ (* x2 x2) (* y2 y2)) (- y3 y1)) (* (+ (* x3 x3) (* y3 y3)) (- y1 y2)) ) a) x0) y (+ (/ (+ (* (+ (* x1 x1) (* y1 y1)) (- x3 x2)) (* (+ (* x2 x2) (* y2 y2)) (- x1 x3)) (* (+ (* x3 x3) (* y3 y3)) (- x2 x1)) ) a) y0) ;;; x (* x 1000.) y (* y 1000.) dX (- (+ x0 x1) x) dY (- (+ y0 y1) y) r (sqrt (+ (* dX dX) (* dY dY))) ) ; s (entMake (list '(0 . "Circle") (cons 8 "Lay1") '(6 . "ByLayer") '(62 . 256) (cons 10 (trans (list x y 0) 1 0) ) (cons 40 r) ) ) ; end of e ) ; prog then (prinC "\n NO 3 VALID Points ;") ) ; if )) ; if and At the moment , it is working like that . will see next . 3.13 Dev C.mp4 Regards, Costin Edited September 7, 2020 by Costinbos77 Quote
dlanorh Posted September 7, 2020 Posted September 7, 2020 (edited) Have you tried doing your calculations as logs? (* a b) = (exp (+ (log a) (log b))). The natural logs are much smaller numbers i.e. (log 491677.5042) = 13.1056 (to 4 decimal places) to : multiply two numbers add their logs as above divide two numbers subtract their logs i.e. (/ 4.0 2.0) = (exp (- (log 4.0) (log 2.0))) sqrt = (exp (/ (log num) 2.0)) and then use exp function (antilog) to convert back to a number Edited September 8, 2020 by dlanorh clarify Quote
BIGAL Posted September 8, 2020 Posted September 8, 2020 Had a quick goggle and this was interesting http://lee-mac.com/3pointarccircle.html Includes full code example. Quote
lrm Posted September 8, 2020 Posted September 8, 2020 dlanorh, I do not think using logs gains you any precision. As you know real numbers in AutoCAD are stored as a mantissa and an exponent. The 56 bit mantissa yields about 15 significant figures of precision. The exponent uses the remaining 8 bits of the 64 bit value. A log in effect represents the mantissa and exponent as one number. It's not clear if additional bits can be used beyond 64 to store the log. It's true that with real numbers if, for example, you multiply a 10 digit number by another 10 digit number you can get a result with 20 digits of precision. The result will be rounded (truncated?) to 15 digits within AutoCAD. With logs you would add the two number resulting in a rounding of only the least significant digit. The question becomes what is the precision of the antilog of the number? I think the solution is to use a geometric solution that avoids multiplication as Lee Mac's code does by finding the intersection of the two perpendicular bisectors of the 3 points. This leads to the question of the precision of the inters function and its affect on the result. I think this could become significant if the 3 points are almost collinear as the perpendicular bisectors will be almost parallel. Quote
Costinbos77 Posted September 8, 2020 Author Posted September 8, 2020 (edited) 1. Interesting idea dlanorh . Thanks ! I was trying like this : (setq x (exp (- (log (+ (exp (+ (log (+ (exp (+ (log x1) (log x1))) (exp (+ (log y1) (log y1)))) ) (log (- y2 y3)))) (exp (+ (log (+ (exp (+ (log x2) (log x2))) (exp (+ (log y2) (log y2)))) ) (log (- y3 y1)))) (exp (+ (log (+ (exp (+ (log x3) (log x3))) (exp (+ (log y3) (log y3)))) ) (log (- y1 y2)))) ) ) (log a)) ) ) but, sometimes when : a< 0 , (- y2 y3) < 0 ... , log will not work with them . 2. Thanks BIGAL ! I will do some research on it . 3 .Thanks lrm , for your detailed answer ! Regards , Costin Edited September 8, 2020 by Costinbos77 Quote
Stefan BMR Posted September 8, 2020 Posted September 8, 2020 Salut Costin Looking at your formula, something seems off. The "a" variable almost cries for a symmetrical formula... Just saying. Maybe something like: (* (+ (* (- y2 y3) x1) (* (- y3 y1) x2) (* (- y1 y2) x3)) 2.) Works just fine for points' coordinates around 100,000.00 and a circle about 1.00 radius. Quote
Costinbos77 Posted September 8, 2020 Author Posted September 8, 2020 (edited) Hi Stefan BMR , Formulas , are fine and are working with any coordinates (see the bottom coordinates from video) . 3.13 Dev C 3.mp4 It is not a perfect solution , but , for my needs it is perfect ! It is important to work in the Origin (0 0 0) for UCS and somewhere between 300,000.0 - 600,000.0 ( national coordinates system ). The radius of circles will not be bigger than 1.5 m . My solution will have a problem when some values of coordinates will be below 100,000.0 and others will be above of 100,000.0 , which is not my case . This is why I changed the test from (> x1 100,000.0) to (> x1 100,005.0) . I don't know exactly the limit , but I know the values as 100,006.0 , are working fine . An UCS around the working area , will drop down the values of coordinates and will be no problems with big numbers in formulas . Regards , Costin Edited September 8, 2020 by Costinbos77 Quote
Stefan BMR Posted September 8, 2020 Posted September 8, 2020 So, it's not a problem with big numbers. Using the correct formula you can get the circle you need. Look at the sample below. That tiny difference in "a" value is really important for big numbers . For small numbers, it's not, but I don't get it, if you know the formula is wrong, why not change it? X1 299999.929857717 Y1 599999.8083234681 X2 299999.3306365923 Y2 600000.0352543053 X3 299998.7266854801 Y3 599999.749548545 (setq a (* (+ (* (- y2 y3) x1) (* (- x3 x2) y1) (* x2 y3) (* x3 y2 -1.) ) 2.)) (rtos a 2 16) -> 0.6165771484375 (/ x1 a) -> 486557.0 (setq a (* (+ (* (- y2 y3) x1) (* (- y3 y1) x2) (* (- y1 y2) x3)) 2.)) (rtos a 2 16) -> 0.6165121169469785 (/ x1 a) -> 486608.0 Quote
Costinbos77 Posted September 8, 2020 Author Posted September 8, 2020 Stefan BMR , the formulas are right ! Use the above code lines , and you will have the same results . Regards , Costin Quote
Stefan BMR Posted September 9, 2020 Posted September 9, 2020 Well, you are right, both formulas are the same, the terms are just rearranged! In this case, I guess the magnitude of the partial terms makes the difference. In "a" expression, (* (- y2 y3) x1) is in the same range as x1 and (* x2 y3) is 10^6 bigger, which leads to a tiny difference. With your formula in WCS, the circle is always off. With the other formula, I had no errors in my tests. Quote
Costinbos77 Posted September 9, 2020 Author Posted September 9, 2020 (edited) Hi Stefan BMR , 45 minutes ago, Stefan BMR said: ... In "a" expression, (* (- y2 y3) x1) is in the same range as x1 and (* x2 y3) is 10^6 bigger, which leads to a tiny difference. ... Good point , thanks ! Regards, Costin Edited September 9, 2020 by Costinbos77 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.