| 1 |
greg |
3.2 |
#ifndef lint |
| 2 |
greg |
3.4 |
static const char RCSid[] = "$Id: disk2square.c,v 3.3 2011/06/09 17:09:39 greg Exp $"; |
| 3 |
greg |
3.2 |
#endif |
| 4 |
greg |
3.1 |
/* |
| 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 |
greg |
3.3 |
#define _USE_MATH_DEFINES |
| 15 |
greg |
3.1 |
#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 |
greg |
3.4 |
r *= 0.9999999999999; /* prophylactic against MS sin()/cos() impl. */ |
| 74 |
greg |
3.1 |
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 |
greg |
3.4 |
sq[0] = a*(0.5/0.9999999999999) + 0.5; |
| 106 |
|
|
sq[1] = b*(0.5/0.9999999999999) + 0.5; |
| 107 |
greg |
3.1 |
} |