ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/disk2square.c
Revision: 3.4
Committed: Thu Oct 23 18:19:14 2014 UTC (9 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2, rad4R2P2, rad5R0, rad5R1, rad5R3
Changes since 3.3: +4 -4 lines
Log Message:
Fixed floating-point error under Windows caused by cos^2 + sin^2 > 1

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: disk2square.c,v 3.3 2011/06/09 17:09:39 greg Exp $";
3 #endif
4 /*
5 * Disk2Square.c
6 *
7 * Code by Peter Shirley and Kenneth Chiu
8 *
9 * Associated paper in ~/Documents/Others/Shirley+Chiu_JGT-97.pdf
10 *
11 * Modified interface slightly (G. Ward)
12 */
13
14 #define _USE_MATH_DEFINES
15 #include <math.h>
16
17 /*
18 This transforms points on [0,1]^2 to points on unit disk centered at
19 origin. Each "pie-slice" quadrant of square is handled as a seperate
20 case. The bad floating point cases are all handled appropriately.
21 The regions for (a,b) are:
22
23 phi = pi/2
24 -----*-----
25 |\ /|
26 | \ 2 / |
27 | \ / |
28 phi=pi* 3 * 1 *phi = 0
29 | / \ |
30 | / 4 \ |
31 |/ \|
32 -----*-----
33 phi = 3pi/2
34
35 change log:
36 26 feb 2004. bug fix in computation of phi (now this matches the paper,
37 which is correct). thanks to Atilim Cetin for catching this.
38 */
39
40
41 /* Map a [0,1]^2 square to a unit radius disk */
42 void
43 SDsquare2disk(double ds[2], double seedx, double seedy)
44 {
45
46 double phi, r;
47 double a = 2.*seedx - 1; /* (a,b) is now on [-1,1]^2 */
48 double b = 2.*seedy - 1;
49
50 if (a > -b) { /* region 1 or 2 */
51 if (a > b) { /* region 1, also |a| > |b| */
52 r = a;
53 phi = (M_PI/4.) * (b/a);
54 }
55 else { /* region 2, also |b| > |a| */
56 r = b;
57 phi = (M_PI/4.) * (2. - (a/b));
58 }
59 }
60 else { /* region 3 or 4 */
61 if (a < b) { /* region 3, also |a| >= |b|, a != 0 */
62 r = -a;
63 phi = (M_PI/4.) * (4. + (b/a));
64 }
65 else { /* region 4, |b| >= |a|, but a==0 and b==0 could occur. */
66 r = -b;
67 if (b != 0.)
68 phi = (M_PI/4.) * (6. - (a/b));
69 else
70 phi = 0.;
71 }
72 }
73 r *= 0.9999999999999; /* prophylactic against MS sin()/cos() impl. */
74 ds[0] = r * cos(phi);
75 ds[1] = r * sin(phi);
76
77 }
78
79 /* Map point on unit disk to a unit square in [0,1]^2 range */
80 void
81 SDdisk2square(double sq[2], double diskx, double disky)
82 {
83 double r = sqrt( diskx*diskx + disky*disky );
84 double phi = atan2( disky, diskx );
85 double a, b;
86
87 if (phi < -M_PI/4) phi += 2*M_PI; /* in range [-pi/4,7pi/4] */
88 if ( phi < M_PI/4) { /* region 1 */
89 a = r;
90 b = phi * a / (M_PI/4);
91 }
92 else if ( phi < 3*M_PI/4 ) { /* region 2 */
93 b = r;
94 a = -(phi - M_PI/2) * b / (M_PI/4);
95 }
96 else if ( phi < 5*M_PI/4 ) { /* region 3 */
97 a = -r;
98 b = (phi - M_PI) * a / (M_PI/4);
99 }
100 else { /* region 4 */
101 b = -r;
102 a = -(phi - 3*M_PI/2) * b / (M_PI/4);
103 }
104
105 sq[0] = a*(0.5/0.9999999999999) + 0.5;
106 sq[1] = b*(0.5/0.9999999999999) + 0.5;
107 }