1*0Sstevel@tonic-gate# 2*0Sstevel@tonic-gate# Trigonometric functions, mostly inherited from Math::Complex. 3*0Sstevel@tonic-gate# -- Jarkko Hietaniemi, since April 1997 4*0Sstevel@tonic-gate# -- Raphael Manfredi, September 1996 (indirectly: because of Math::Complex) 5*0Sstevel@tonic-gate# 6*0Sstevel@tonic-gate 7*0Sstevel@tonic-gaterequire Exporter; 8*0Sstevel@tonic-gatepackage Math::Trig; 9*0Sstevel@tonic-gate 10*0Sstevel@tonic-gateuse 5.006; 11*0Sstevel@tonic-gateuse strict; 12*0Sstevel@tonic-gate 13*0Sstevel@tonic-gateuse Math::Complex qw(:trig); 14*0Sstevel@tonic-gate 15*0Sstevel@tonic-gateour($VERSION, $PACKAGE, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gate@ISA = qw(Exporter); 18*0Sstevel@tonic-gate 19*0Sstevel@tonic-gate$VERSION = 1.02; 20*0Sstevel@tonic-gate 21*0Sstevel@tonic-gatemy @angcnv = qw(rad2deg rad2grad 22*0Sstevel@tonic-gate deg2rad deg2grad 23*0Sstevel@tonic-gate grad2rad grad2deg); 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gate@EXPORT = (@{$Math::Complex::EXPORT_TAGS{'trig'}}, 26*0Sstevel@tonic-gate @angcnv); 27*0Sstevel@tonic-gate 28*0Sstevel@tonic-gatemy @rdlcnv = qw(cartesian_to_cylindrical 29*0Sstevel@tonic-gate cartesian_to_spherical 30*0Sstevel@tonic-gate cylindrical_to_cartesian 31*0Sstevel@tonic-gate cylindrical_to_spherical 32*0Sstevel@tonic-gate spherical_to_cartesian 33*0Sstevel@tonic-gate spherical_to_cylindrical); 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate@EXPORT_OK = (@rdlcnv, 'great_circle_distance', 'great_circle_direction'); 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate%EXPORT_TAGS = ('radial' => [ @rdlcnv ]); 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gatesub pi2 () { 2 * pi } 40*0Sstevel@tonic-gatesub pip2 () { pi / 2 } 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gatesub DR () { pi2/360 } 43*0Sstevel@tonic-gatesub RD () { 360/pi2 } 44*0Sstevel@tonic-gatesub DG () { 400/360 } 45*0Sstevel@tonic-gatesub GD () { 360/400 } 46*0Sstevel@tonic-gatesub RG () { 400/pi2 } 47*0Sstevel@tonic-gatesub GR () { pi2/400 } 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate# 50*0Sstevel@tonic-gate# Truncating remainder. 51*0Sstevel@tonic-gate# 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gatesub remt ($$) { 54*0Sstevel@tonic-gate # Oh yes, POSIX::fmod() would be faster. Possibly. If it is available. 55*0Sstevel@tonic-gate $_[0] - $_[1] * int($_[0] / $_[1]); 56*0Sstevel@tonic-gate} 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate# 59*0Sstevel@tonic-gate# Angle conversions. 60*0Sstevel@tonic-gate# 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gatesub rad2rad($) { remt($_[0], pi2) } 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gatesub deg2deg($) { remt($_[0], 360) } 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gatesub grad2grad($) { remt($_[0], 400) } 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gatesub rad2deg ($;$) { my $d = RD * $_[0]; $_[1] ? $d : deg2deg($d) } 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gatesub deg2rad ($;$) { my $d = DR * $_[0]; $_[1] ? $d : rad2rad($d) } 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gatesub grad2deg ($;$) { my $d = GD * $_[0]; $_[1] ? $d : deg2deg($d) } 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gatesub deg2grad ($;$) { my $d = DG * $_[0]; $_[1] ? $d : grad2grad($d) } 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gatesub rad2grad ($;$) { my $d = RG * $_[0]; $_[1] ? $d : grad2grad($d) } 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gatesub grad2rad ($;$) { my $d = GR * $_[0]; $_[1] ? $d : rad2rad($d) } 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gatesub cartesian_to_spherical { 81*0Sstevel@tonic-gate my ( $x, $y, $z ) = @_; 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate my $rho = sqrt( $x * $x + $y * $y + $z * $z ); 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate return ( $rho, 86*0Sstevel@tonic-gate atan2( $y, $x ), 87*0Sstevel@tonic-gate $rho ? acos( $z / $rho ) : 0 ); 88*0Sstevel@tonic-gate} 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gatesub spherical_to_cartesian { 91*0Sstevel@tonic-gate my ( $rho, $theta, $phi ) = @_; 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate return ( $rho * cos( $theta ) * sin( $phi ), 94*0Sstevel@tonic-gate $rho * sin( $theta ) * sin( $phi ), 95*0Sstevel@tonic-gate $rho * cos( $phi ) ); 96*0Sstevel@tonic-gate} 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gatesub spherical_to_cylindrical { 99*0Sstevel@tonic-gate my ( $x, $y, $z ) = spherical_to_cartesian( @_ ); 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate return ( sqrt( $x * $x + $y * $y ), $_[1], $z ); 102*0Sstevel@tonic-gate} 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gatesub cartesian_to_cylindrical { 105*0Sstevel@tonic-gate my ( $x, $y, $z ) = @_; 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate return ( sqrt( $x * $x + $y * $y ), atan2( $y, $x ), $z ); 108*0Sstevel@tonic-gate} 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gatesub cylindrical_to_cartesian { 111*0Sstevel@tonic-gate my ( $rho, $theta, $z ) = @_; 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate return ( $rho * cos( $theta ), $rho * sin( $theta ), $z ); 114*0Sstevel@tonic-gate} 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gatesub cylindrical_to_spherical { 117*0Sstevel@tonic-gate return ( cartesian_to_spherical( cylindrical_to_cartesian( @_ ) ) ); 118*0Sstevel@tonic-gate} 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gatesub great_circle_distance { 121*0Sstevel@tonic-gate my ( $theta0, $phi0, $theta1, $phi1, $rho ) = @_; 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate $rho = 1 unless defined $rho; # Default to the unit sphere. 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate my $lat0 = pip2 - $phi0; 126*0Sstevel@tonic-gate my $lat1 = pip2 - $phi1; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate return $rho * 129*0Sstevel@tonic-gate acos(cos( $lat0 ) * cos( $lat1 ) * cos( $theta0 - $theta1 ) + 130*0Sstevel@tonic-gate sin( $lat0 ) * sin( $lat1 ) ); 131*0Sstevel@tonic-gate} 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gatesub great_circle_direction { 134*0Sstevel@tonic-gate my ( $theta0, $phi0, $theta1, $phi1 ) = @_; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate my $distance = &great_circle_distance; 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate my $lat0 = pip2 - $phi0; 139*0Sstevel@tonic-gate my $lat1 = pip2 - $phi1; 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate my $direction = 142*0Sstevel@tonic-gate acos((sin($lat1) - sin($lat0) * cos($distance)) / 143*0Sstevel@tonic-gate (cos($lat0) * sin($distance))); 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate $direction = pi2 - $direction 146*0Sstevel@tonic-gate if sin($theta1 - $theta0) < 0; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate return rad2rad($direction); 149*0Sstevel@tonic-gate} 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate1; 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate__END__ 154*0Sstevel@tonic-gate=pod 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate=head1 NAME 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gateMath::Trig - trigonometric functions 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate=head1 SYNOPSIS 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate use Math::Trig; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate $x = tan(0.9); 165*0Sstevel@tonic-gate $y = acos(3.7); 166*0Sstevel@tonic-gate $z = asin(2.4); 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate $halfpi = pi/2; 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate $rad = deg2rad(120); 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate=head1 DESCRIPTION 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gateC<Math::Trig> defines many trigonometric functions not defined by the 175*0Sstevel@tonic-gatecore Perl which defines only the C<sin()> and C<cos()>. The constant 176*0Sstevel@tonic-gateB<pi> is also defined as are a few convenience functions for angle 177*0Sstevel@tonic-gateconversions. 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate=head1 TRIGONOMETRIC FUNCTIONS 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gateThe tangent 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate=over 4 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate=item B<tan> 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate=back 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gateThe cofunctions of the sine, cosine, and tangent (cosec/csc and cotan/cot 190*0Sstevel@tonic-gateare aliases) 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gateB<csc>, B<cosec>, B<sec>, B<sec>, B<cot>, B<cotan> 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gateThe arcus (also known as the inverse) functions of the sine, cosine, 195*0Sstevel@tonic-gateand tangent 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gateB<asin>, B<acos>, B<atan> 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gateThe principal value of the arc tangent of y/x 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gateB<atan2>(y, x) 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gateThe arcus cofunctions of the sine, cosine, and tangent (acosec/acsc 204*0Sstevel@tonic-gateand acotan/acot are aliases) 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gateB<acsc>, B<acosec>, B<asec>, B<acot>, B<acotan> 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gateThe hyperbolic sine, cosine, and tangent 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gateB<sinh>, B<cosh>, B<tanh> 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gateThe cofunctions of the hyperbolic sine, cosine, and tangent (cosech/csch 213*0Sstevel@tonic-gateand cotanh/coth are aliases) 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gateB<csch>, B<cosech>, B<sech>, B<coth>, B<cotanh> 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gateThe arcus (also known as the inverse) functions of the hyperbolic 218*0Sstevel@tonic-gatesine, cosine, and tangent 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gateB<asinh>, B<acosh>, B<atanh> 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gateThe arcus cofunctions of the hyperbolic sine, cosine, and tangent 223*0Sstevel@tonic-gate(acsch/acosech and acoth/acotanh are aliases) 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gateB<acsch>, B<acosech>, B<asech>, B<acoth>, B<acotanh> 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gateThe trigonometric constant B<pi> is also defined. 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate$pi2 = 2 * B<pi>; 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate=head2 ERRORS DUE TO DIVISION BY ZERO 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gateThe following functions 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate acoth 236*0Sstevel@tonic-gate acsc 237*0Sstevel@tonic-gate acsch 238*0Sstevel@tonic-gate asec 239*0Sstevel@tonic-gate asech 240*0Sstevel@tonic-gate atanh 241*0Sstevel@tonic-gate cot 242*0Sstevel@tonic-gate coth 243*0Sstevel@tonic-gate csc 244*0Sstevel@tonic-gate csch 245*0Sstevel@tonic-gate sec 246*0Sstevel@tonic-gate sech 247*0Sstevel@tonic-gate tan 248*0Sstevel@tonic-gate tanh 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gatecannot be computed for all arguments because that would mean dividing 251*0Sstevel@tonic-gateby zero or taking logarithm of zero. These situations cause fatal 252*0Sstevel@tonic-gateruntime errors looking like this 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate cot(0): Division by zero. 255*0Sstevel@tonic-gate (Because in the definition of cot(0), the divisor sin(0) is 0) 256*0Sstevel@tonic-gate Died at ... 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gateor 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate atanh(-1): Logarithm of zero. 261*0Sstevel@tonic-gate Died at... 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gateFor the C<csc>, C<cot>, C<asec>, C<acsc>, C<acot>, C<csch>, C<coth>, 264*0Sstevel@tonic-gateC<asech>, C<acsch>, the argument cannot be C<0> (zero). For the 265*0Sstevel@tonic-gateC<atanh>, C<acoth>, the argument cannot be C<1> (one). For the 266*0Sstevel@tonic-gateC<atanh>, C<acoth>, the argument cannot be C<-1> (minus one). For the 267*0Sstevel@tonic-gateC<tan>, C<sec>, C<tanh>, C<sech>, the argument cannot be I<pi/2 + k * 268*0Sstevel@tonic-gatepi>, where I<k> is any integer. 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate=head2 SIMPLE (REAL) ARGUMENTS, COMPLEX RESULTS 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gatePlease note that some of the trigonometric functions can break out 273*0Sstevel@tonic-gatefrom the B<real axis> into the B<complex plane>. For example 274*0Sstevel@tonic-gateC<asin(2)> has no definition for plain real numbers but it has 275*0Sstevel@tonic-gatedefinition for complex numbers. 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gateIn Perl terms this means that supplying the usual Perl numbers (also 278*0Sstevel@tonic-gateknown as scalars, please see L<perldata>) as input for the 279*0Sstevel@tonic-gatetrigonometric functions might produce as output results that no more 280*0Sstevel@tonic-gateare simple real numbers: instead they are complex numbers. 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gateThe C<Math::Trig> handles this by using the C<Math::Complex> package 283*0Sstevel@tonic-gatewhich knows how to handle complex numbers, please see L<Math::Complex> 284*0Sstevel@tonic-gatefor more information. In practice you need not to worry about getting 285*0Sstevel@tonic-gatecomplex numbers as results because the C<Math::Complex> takes care of 286*0Sstevel@tonic-gatedetails like for example how to display complex numbers. For example: 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate print asin(2), "\n"; 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gateshould produce something like this (take or leave few last decimals): 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate 1.5707963267949-1.31695789692482i 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gateThat is, a complex number with the real part of approximately C<1.571> 295*0Sstevel@tonic-gateand the imaginary part of approximately C<-1.317>. 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate=head1 PLANE ANGLE CONVERSIONS 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate(Plane, 2-dimensional) angles may be converted with the following functions. 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate $radians = deg2rad($degrees); 302*0Sstevel@tonic-gate $radians = grad2rad($gradians); 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate $degrees = rad2deg($radians); 305*0Sstevel@tonic-gate $degrees = grad2deg($gradians); 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate $gradians = deg2grad($degrees); 308*0Sstevel@tonic-gate $gradians = rad2grad($radians); 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gateThe full circle is 2 I<pi> radians or I<360> degrees or I<400> gradians. 311*0Sstevel@tonic-gateThe result is by default wrapped to be inside the [0, {2pi,360,400}[ circle. 312*0Sstevel@tonic-gateIf you don't want this, supply a true second argument: 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate $zillions_of_radians = deg2rad($zillions_of_degrees, 1); 315*0Sstevel@tonic-gate $negative_degrees = rad2deg($negative_radians, 1); 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gateYou can also do the wrapping explicitly by rad2rad(), deg2deg(), and 318*0Sstevel@tonic-gategrad2grad(). 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate=head1 RADIAL COORDINATE CONVERSIONS 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gateB<Radial coordinate systems> are the B<spherical> and the B<cylindrical> 323*0Sstevel@tonic-gatesystems, explained shortly in more detail. 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gateYou can import radial coordinate conversion functions by using the 326*0Sstevel@tonic-gateC<:radial> tag: 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate use Math::Trig ':radial'; 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z); 331*0Sstevel@tonic-gate ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z); 332*0Sstevel@tonic-gate ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z); 333*0Sstevel@tonic-gate ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z); 334*0Sstevel@tonic-gate ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi); 335*0Sstevel@tonic-gate ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi); 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gateB<All angles are in radians>. 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate=head2 COORDINATE SYSTEMS 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gateB<Cartesian> coordinates are the usual rectangular I<(x, y, 342*0Sstevel@tonic-gatez)>-coordinates. 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gateSpherical coordinates, I<(rho, theta, pi)>, are three-dimensional 345*0Sstevel@tonic-gatecoordinates which define a point in three-dimensional space. They are 346*0Sstevel@tonic-gatebased on a sphere surface. The radius of the sphere is B<rho>, also 347*0Sstevel@tonic-gateknown as the I<radial> coordinate. The angle in the I<xy>-plane 348*0Sstevel@tonic-gate(around the I<z>-axis) is B<theta>, also known as the I<azimuthal> 349*0Sstevel@tonic-gatecoordinate. The angle from the I<z>-axis is B<phi>, also known as the 350*0Sstevel@tonic-gateI<polar> coordinate. The `North Pole' is therefore I<0, 0, rho>, and 351*0Sstevel@tonic-gatethe `Bay of Guinea' (think of the missing big chunk of Africa) I<0, 352*0Sstevel@tonic-gatepi/2, rho>. In geographical terms I<phi> is latitude (northward 353*0Sstevel@tonic-gatepositive, southward negative) and I<theta> is longitude (eastward 354*0Sstevel@tonic-gatepositive, westward negative). 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gateB<BEWARE>: some texts define I<theta> and I<phi> the other way round, 357*0Sstevel@tonic-gatesome texts define the I<phi> to start from the horizontal plane, some 358*0Sstevel@tonic-gatetexts use I<r> in place of I<rho>. 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gateCylindrical coordinates, I<(rho, theta, z)>, are three-dimensional 361*0Sstevel@tonic-gatecoordinates which define a point in three-dimensional space. They are 362*0Sstevel@tonic-gatebased on a cylinder surface. The radius of the cylinder is B<rho>, 363*0Sstevel@tonic-gatealso known as the I<radial> coordinate. The angle in the I<xy>-plane 364*0Sstevel@tonic-gate(around the I<z>-axis) is B<theta>, also known as the I<azimuthal> 365*0Sstevel@tonic-gatecoordinate. The third coordinate is the I<z>, pointing up from the 366*0Sstevel@tonic-gateB<theta>-plane. 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate=head2 3-D ANGLE CONVERSIONS 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gateConversions to and from spherical and cylindrical coordinates are 371*0Sstevel@tonic-gateavailable. Please notice that the conversions are not necessarily 372*0Sstevel@tonic-gatereversible because of the equalities like I<pi> angles being equal to 373*0Sstevel@tonic-gateI<-pi> angles. 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate=over 4 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate=item cartesian_to_cylindrical 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z); 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate=item cartesian_to_spherical 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z); 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate=item cylindrical_to_cartesian 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z); 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate=item cylindrical_to_spherical 390*0Sstevel@tonic-gate 391*0Sstevel@tonic-gate ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z); 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gateNotice that when C<$z> is not 0 C<$rho_s> is not equal to C<$rho_c>. 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate=item spherical_to_cartesian 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi); 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate=item spherical_to_cylindrical 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi); 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gateNotice that when C<$z> is not 0 C<$rho_c> is not equal to C<$rho_s>. 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate=back 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate=head1 GREAT CIRCLE DISTANCES AND DIRECTIONS 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gateYou can compute spherical distances, called B<great circle distances>, 410*0Sstevel@tonic-gateby importing the great_circle_distance() function: 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate use Math::Trig 'great_circle_distance'; 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate $distance = great_circle_distance($theta0, $phi0, $theta1, $phi1, [, $rho]); 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gateThe I<great circle distance> is the shortest distance between two 417*0Sstevel@tonic-gatepoints on a sphere. The distance is in C<$rho> units. The C<$rho> is 418*0Sstevel@tonic-gateoptional, it defaults to 1 (the unit sphere), therefore the distance 419*0Sstevel@tonic-gatedefaults to radians. 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gateIf you think geographically the I<theta> are longitudes: zero at the 422*0Sstevel@tonic-gateGreenwhich meridian, eastward positive, westward negative--and the 423*0Sstevel@tonic-gateI<phi> are latitudes: zero at the North Pole, northward positive, 424*0Sstevel@tonic-gatesouthward negative. B<NOTE>: this formula thinks in mathematics, not 425*0Sstevel@tonic-gategeographically: the I<phi> zero is at the North Pole, not at the 426*0Sstevel@tonic-gateEquator on the west coast of Africa (Bay of Guinea). You need to 427*0Sstevel@tonic-gatesubtract your geographical coordinates from I<pi/2> (also known as 90 428*0Sstevel@tonic-gatedegrees). 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate $distance = great_circle_distance($lon0, pi/2 - $lat0, 431*0Sstevel@tonic-gate $lon1, pi/2 - $lat1, $rho); 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gateThe direction you must follow the great circle can be computed by the 434*0Sstevel@tonic-gategreat_circle_direction() function: 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate use Math::Trig 'great_circle_direction'; 437*0Sstevel@tonic-gate 438*0Sstevel@tonic-gate $direction = great_circle_direction($theta0, $phi0, $theta1, $phi1); 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gateThe result is in radians, zero indicating straight north, pi or -pi 441*0Sstevel@tonic-gatestraight south, pi/2 straight west, and -pi/2 straight east. 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gateNotice that the resulting directions might be somewhat surprising if 444*0Sstevel@tonic-gateyou are looking at a flat worldmap: in such map projections the great 445*0Sstevel@tonic-gatecircles quite often do not look like the shortest routes-- but for 446*0Sstevel@tonic-gateexample the shortest possible routes from Europe or North America to 447*0Sstevel@tonic-gateAsia do often cross the polar regions. 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate=head1 EXAMPLES 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gateTo calculate the distance between London (51.3N 0.5W) and Tokyo 452*0Sstevel@tonic-gate(35.7N 139.8E) in kilometers: 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate use Math::Trig qw(great_circle_distance deg2rad); 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate # Notice the 90 - latitude: phi zero is at the North Pole. 457*0Sstevel@tonic-gate @L = (deg2rad(-0.5), deg2rad(90 - 51.3)); 458*0Sstevel@tonic-gate @T = (deg2rad(139.8),deg2rad(90 - 35.7)); 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate $km = great_circle_distance(@L, @T, 6378); 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gateThe direction you would have to go from London to Tokyo 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate use Math::Trig qw(great_circle_direction); 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate $rad = great_circle_direction(@L, @T); 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate=head2 CAVEAT FOR GREAT CIRCLE FORMULAS 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gateThe answers may be off by few percentages because of the irregular 471*0Sstevel@tonic-gate(slightly aspherical) form of the Earth. The formula used for 472*0Sstevel@tonic-gategrear circle distances 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate lat0 = 90 degrees - phi0 475*0Sstevel@tonic-gate lat1 = 90 degrees - phi1 476*0Sstevel@tonic-gate d = R * arccos(cos(lat0) * cos(lat1) * cos(lon1 - lon01) + 477*0Sstevel@tonic-gate sin(lat0) * sin(lat1)) 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gateis also somewhat unreliable for small distances (for locations 480*0Sstevel@tonic-gateseparated less than about five degrees) because it uses arc cosine 481*0Sstevel@tonic-gatewhich is rather ill-conditioned for values close to zero. 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate=head1 BUGS 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gateSaying C<use Math::Trig;> exports many mathematical routines in the 486*0Sstevel@tonic-gatecaller environment and even overrides some (C<sin>, C<cos>). This is 487*0Sstevel@tonic-gateconstrued as a feature by the Authors, actually... ;-) 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gateThe code is not optimized for speed, especially because we use 490*0Sstevel@tonic-gateC<Math::Complex> and thus go quite near complex numbers while doing 491*0Sstevel@tonic-gatethe computations even when the arguments are not. This, however, 492*0Sstevel@tonic-gatecannot be completely avoided if we want things like C<asin(2)> to give 493*0Sstevel@tonic-gatean answer instead of giving a fatal runtime error. 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate=head1 AUTHORS 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gateJarkko Hietaniemi <F<jhi@iki.fi>> and 498*0Sstevel@tonic-gateRaphael Manfredi <F<Raphael_Manfredi@pobox.com>>. 499*0Sstevel@tonic-gate 500*0Sstevel@tonic-gate=cut 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate# eof 503