Jump to content

Recommended Posts

Posted

I'm trying to create a routine to check that wall ends are square ie. both equal to 90° (actually equal to each other but thats fine), it works great until objects are rotated and then the math seems to fail. If I draw a rectangle locked to the UCS with ortho on and run the code everything is fine, but if I then rotate that rectangle the code fails, using undo it works again but using rotate with a now negative (same typed value) the code still fails. I know Autocad has a problem with large numbers and I could probably cap the values by rounding to "x" amount of decimal places, but I just like to work with absolutes and my OCD doesn't like a square not being square. I have seen enough wonky waterlevels in my time, but never a piece of bent string affecting a plumbline.

So is there a better way to read angles, or is it just one of the limitations to live with.

(defun c:sqr()
(setq count 1)
  (foreach a (entget(ssname(ssget ":s:e") 0))
    (if(= 10 (car a))
       (progn
	(set (read (strcat "vp" (itoa count))) (cdr a))
	(setq count (+ count 1)))))
(progn
        (setq ang1 (abs(- (* (/ 180 pi)(angle vp1 vp2))(* (/ 180 pi)(angle vp1 vp4)))))
        (if (> ang1 180) (setq ang1 (- 360 ang1)))
        (setq ang2 (abs(- (* (/ 180 pi)(angle vp2 vp3))(* (/ 180 pi)(angle vp2 vp1)))))
        (if (> ang2 180) (setq ang2 (- 360 ang2))))
(if(= ang1 ang2)(princ "same-same ANG1 =")(princ "OH yes they are ANG1 = "))(princ (* ang1 100000000000000000000000000000000))(princ " ANG2 = ")(princ(* ang2 100000000000000000000000000000000))(princ))

 

Posted
: (sin pi)
1.22464679914735e-016

You'll have to live with it.

Posted

I was afraid of that 😱

(setq ang1 (angtos(- (angle vp1 vp2)(angle vp1 vp4)) 0 12))
        (if (> (atof ang1) 180) (setq ang1 (- 360 (atof ang1))))

I swapped out the angle calculations for this (had to go down to 12 decimal places) but it does appear to be working at that.

Posted

This is where EQUAL is your friend :)

(equal ang1 ang2 1e-8)

 

Posted

Thanks guys, I like the fuzz Factor, and thanks Lee I had an interesting afternoon playing with the code from your site about rounding.

Posted

The issue of the difficulty of getting accurate and precise angles in CAD is due to several factors.  One of them, as mentioned, is the fact that some base ten numbers cannot be exactly represented in binary.  Just as 1/3  requires an infinite number of decimal places to represent it perfectly using  the base 10 number systems, 1/10 (base 10) is an irrational fraction in binary (base 2).  Another issue is the finite number of significant figures for a coordinate (AutoCAD uses about 15 significant figures).

I think a more significant reason for angle errors in CAD is the necessary rounding required to position a line at an angle.  Getting an accurate angle for a line is further constrained by the length of the line. Consider the following.  Create two perfectly horizontal lines one 1.0 units long and the other 10000 units long.  Now rotate each line by 1°.

Here’s a sample of the results you get using list to get the coordinates of the lines to 8 decimal places.

 

angerror.thumb.JPG.96c831e5778ab7b408a6db7a4d952939.JPG

 

Note that the shorter line’s rotation is less accurate but just as precise as the long line.  Columns E and F round the coordinates to 6 decimal places  showing the effect it has on the precision of the rotation.

This example helps to show that longer lines can be rotated more accurately than shorter lines.  It is good practice to use points as far apart as possible when making angle calculations. Horizontal, vertical, and lines at 45° will be accurately positioned as will lines with a discrete pitch (eg. 3:4). 

angerror.JPG

  • Like 1
Posted

@lrm:

I think you are compounding inaccuracies.

I have tried to repeat part of your experiment relying only on Lisp.

For the L=1 line I get an angle of 0.99999999999968 degrees.

(defun KGA_Math_Rad_To_Dgr (rad)
  (* (/ rad pi) 180.0)
)

(defun c:test ( / elst pt1 pt2)
  (setq pt1 '(10003.105165110 58.231590020))
  (setq pt2 '(10004.105165110 58.231590020))
  (command "_.line" "_non" pt1 "_non" pt2 "")
  (command "_.rotate" (entlast) "" "_non" pt1 1.0)
  (setq elst (entget (entlast)))
  (setq pt1 (cdr (assoc 10 elst)))
  (setq pt2 (cdr (assoc 11 elst)))
  (princ (strcat "\nAngle=" (rtos (KGA_Math_Rad_To_Dgr (angle pt1 pt2)) 2 14)))
  (princ)
)

 

Posted

@Roy_043

Using your program with the following values the longer line's angle of rotation is more accurate which was my point.

  (setq pt1 '(10003.105165110 58.231590020))

  (setq pt2 '(10004.105165110 58.231590020))

Angle=0.99999999999968

 

  (setq pt1 '(4.105165110 58.231590020))

  (setq pt2 '(10004.105165110 58.231590020))

Angle=1.00000000000000

 

Although both ends of the shorter line are closer to 0,0,0 and therefore the absolute precision of the mantissa is greater for both ends than the far end of the longer line the longer line can be rotated more precisely.

 

 

Posted (edited)

@lrm

I think your reasoning is flawed. Irrespective of the length of the line, the number of significant figures is the same. Therefore the total accuracy is the same.

 

BTW: Obviously the start of your longer line is closer to the origin.

Edited by Roy_043
Posted

I’d like to explain via a few illustrations why the longer line can be rotated more precisely but I don’t have time right now to go into a long explanation as I am going on a trip and will be away from my computer for a week. 

 

Although the number of significant digits for both lines is the same consider the following.  Picture graph paper with a 0.1 grid.  Assume all lines draw on the graph paper must start and end at the intersection of the grid.   This is similar to storing coordinates in a CAD system but the grid can be much smaller. If AutoCAD had an integer database the grid size would remain constant no matter how long or short the line.  With a floating point data base the grid spacing gets wider as you get further from 0,0,0.  This is achieved because a floating point number uses an exponent.   Getting back to the 0.1 grid, a horizontal line 0.4 units long might have one end at 0,0,0 and the other end at 0.4,0, 0.  The smallest rotation that could be done with that line would be to put one end at 0.4, 0.1, 0.  Resulting in a line 0.4123 long at an angle of 14.0362°.  Now consider a line 40.0 long going from 0,0,0 to 40.0, 0, 0.  The smallest rotation of that line would have the end at 40.0, 0.1, 0.  This line would have a length of 40.0001 and an angle of 0.1432°.  A much smaller angle by far! I’ve left out some subtle details but the same kind of effect happens with any database no matter what the precision.  At some level of precision, rounding takes place but you have more precision in general with longer lines although the precision of the database coordinates is the same.  Of course, if the line is at a 45° angle both line will be at exactly 45° because no rounding is necessary.

Posted (edited)

@lrm

OK, you have won me over with that clear explanation. Thanks for taking the time to enlighten me.

Edited by Roy_043

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