Re: Shouldn't Cairo use/offer degrees rather than radians?
Ray Gardener <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
Why not leave the Cairo API alone and implement a utility library analogous to GLU for OpenGL and that way handy degree-based transform functions can be put there. Ray On 7/11/2017 3:42 PM, Bill Spitzak wrote: > Your matrix for 45 degrees has equal values in all 4 entries. When > this matrix is mulitplied by itself you get a matrix made of > 0.9999999999999998 and 0.0. (That value is actually > 1.0-2.220446049250313e-16). > > If you use the normal sin and cos values (which are unequal to each > other) you get 1.0 and 2.220446049250313e-16 which is the same > magnitude of error. > > However squaring 0.9999999999999998 gets a number further away from > 1.0, while squaring 2.220446049250313e-16 goes closer to zero. For > many operations (such as further multiplies, getting the determinant, > etc) this means the second matrix is more accurate. > >>> You wanted two rotates by 45 degrees to be perfect. >> Uh, no? Two rotates by 45 degrees illustrate a _compromise_. The >> degree of rotation will generally be a perfect 90 degrees because of all >> rotation matrix elements having the same magnitude, the total magnitude >> (determinant of the scaling matrix I think) will lightly be slightly >> more wrong than the magnitude of the radian API (which likely also fails >> to be 1 due to sin/cos of M_PI/4 in floating point also being >> approximations). > As I tried to show above the answer current Cairo gets for pi/4 is > better than the one you get for 45 degrees. Your function could be > improved by using sin and cos rather than trying to do sin(pi/2-a) in > place of cos in order to make sin and cos equal for 45 degrees. > >> Did you even read the patch and its rationale? Or are you making up >> that straw man on the fly? Multiples of 90 degrees are perfect. There >> are currently several fast paths in Cairo's code paths which actually >> _check_ for that kind of perfection. > I agree there are fast paths that are not allowing such errors in the > matrix, and that changing cairo_rotate to detect angles near n*pi/2 > and produce 1.0 and 0.0 would probably be a much faster fix than > trying to track down all the fast path mistakes. It would also remove > suprises in the matrix for users. > > >>> The exact same value is stored whether the rotation is sent as degrees >>> or radians. >> DID YOU LOOK AT THE PATCH????? I cannot believe you did when you state >> this. > Yes your patch in effect finds the quadrant the angle is in. It > substitutes sin(pi/2-x) for cos(x) in order to make a right angle have > a cos of 0.0, however as stated above I believe this is a mistake as > the determinant of the matrix is not 1.0 for other angles. > > My version instead finds the closest axis (or the quadrant if you > rotate by 45 degrees). The angle passed to sin/cos is in the range > -pi/4..pi/4. This allows the normal sin/cos functions to be used. Here > it is (in python sorry): > > from math import * > M_PI_2 = pi/2 > > # this is needed to avoid producing negative zero: > def neg(x): > return -x if x else 0.0 > > def sincos(a): > axis = round(a / M_PI_2) > fromaxis = a - axis * M_PI_2 > s = sin(fromaxis) > c = cos(fromaxis) > x = int(axis) & 3 > if (x==0): return( s, c) > elif (x==1): return( c, neg(s)) > elif (x==2): return(neg(s), neg(c)) > else: return(neg(c), s) > > If you think degrees would help then substitute 90 for M_PI_2 and put > fromaxis*(M_PI_2/90) to the sin and cos function calls. Though > intuitively it seems like 90*round(a/90) is somehow more accurate than > M_PI_2*round(a/M_PI_2) I have not been able to find a value where this > actually happens so I don't believe the degree version is necessary. > >>> 2. Add an api to rotate so the x axis passes through an x,y point (and >>> possibly scales by hypot(x,y)). This would provide an "accurate" >>> rotate for a whole lot of cases that actually come up in real >>> graphics. >> For multiples of 90 degrees, you can "trivially" just specify the >> transform matrix, yet nobody does. This is not how people think, and we >> are talking about an API for people. > I propose cairo_rotate_atan(x) and cairo_rotate_atan2(x,y) which are > exactly the same as cairo_rotate(atan(x)) and cairo_rotate(atan2(x,y)) > except for greater accuracy. The hope is that it is obvious how to fix > code that is using atan to get the angle. You are right that no matter > what happens, lots of code is going to continue to use > cairo_rotate(M_PI/2), so I think fixing that function is a good idea. -- cairo mailing list [email protected] https://lists.cairographics.org/mailman/listinfo/cairo