001 //$HeadURL: $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 This file is part of deegree. 004 Copyright (C) 2001-2008 by: 005 Department of Geography, University of Bonn 006 http://www.giub.uni-bonn.de/deegree/ 007 lat/lon GmbH 008 http://www.lat-lon.de 009 010 This library is free software; you can redistribute it and/or 011 modify it under the terms of the GNU Lesser General Public 012 License as published by the Free Software Foundation; either 013 version 2.1 of the License, or (at your option) any later version. 014 This library is distributed in the hope that it will be useful, 015 but WITHOUT ANY WARRANTY; without even the implied warranty of 016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 017 Lesser General Public License for more details. 018 You should have received a copy of the GNU Lesser General Public 019 License along with this library; if not, write to the Free Software 020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 021 Contact: 022 023 Andreas Poth 024 lat/lon GmbH 025 Aennchenstr. 19 026 53177 Bonn 027 Germany 028 E-Mail: poth@lat-lon.de 029 030 Prof. Dr. Klaus Greve 031 Department of Geography 032 University of Bonn 033 Meckenheimer Allee 166 034 53115 Bonn 035 Germany 036 E-Mail: greve@giub.uni-bonn.de 037 ---------------------------------------------------------------------------*/ 038 039 package org.deegree.crs.projections; 040 041 import java.awt.geom.Rectangle2D; 042 043 044 /** 045 * The <code>Utils</code> class combines some helpfull constants and forms. 046 * 047 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 048 * 049 * @author last edited by: $Author:$ 050 * 051 * @version $Revision:$, $Date:$ 052 * 053 */ 054 055 public class ProjectionUtils { 056 057 // Very handy for setting maximum number of iterations in a for loop. 058 private final static int MAX_ITER = 10; 059 060 061 /** 062 * A small epsilon value 063 */ 064 public final static double EPS10 = 1e-10; 065 066 /** 067 * An even smaller epsilon value 068 */ 069 public final static double EPS11 = 1e-11; 070 071 /** 072 * Cotaining the value 0.5*pi 073 */ 074 public final static double HALFPI = Math.PI * 0.5; 075 076 /** 077 * Containing the value 0.25*pi 078 */ 079 public final static double QUARTERPI = Math.PI * 0.25; 080 081 /** 082 * Containing the value 2*pi 083 */ 084 public final static double TWOPI = Math.PI * 2.0; 085 086 /** 087 * Radians to Degrees (180.0/Math.PI) 088 */ 089 public final static double RTD = 180.0 / Math.PI; 090 091 /** 092 * Degrees to Radians (Math.PI/180.0) 093 */ 094 public final static double DTR = Math.PI / 180.0; 095 096 /** 097 * The max and min of the projected word map in radians (-Math.PI, -HALFPI, TWOPI, Math.PI) 098 */ 099 public final static Rectangle2D WORLD_BOUNDS_RAD = new Rectangle2D.Double( -Math.PI, -HALFPI, TWOPI, Math.PI ); 100 101 /** 102 * The max and min of the projected word map in degrees (-180, -90, 360, 180) 103 */ 104 public final static Rectangle2D WORLD_BOUNDS = new Rectangle2D.Double( -180, -90, 360, 180 ); 105 106 /** 107 * From the proj4 library, to determine small q which is needed to calculate the authalic (equal-areaed) latitude 108 * beta, on a sphere having the same surface area as the ellipsoid, relative to the ellipsoid. Snyder (3 -12). 109 * 110 * @param sinphi 111 * the sine of the angle between the positive z-axis and the line formed between the origin and P. 112 * @param e 113 * the eccentricity 114 * @return the q value from Snyder (3-12) 115 * @deprecated use {@link ProjectionUtils#calcQForAuthalicLatitude(double, double)} instead. 116 */ 117 @Deprecated 118 public static double qsfn( double sinphi, double e ) { 119 return calcQForAuthalicLatitude( sinphi, e ); 120 } 121 122 /** 123 * From the proj4 library, to determine small q which is needed to calculate the authalic (equal-areaed) latitude 124 * beta, on a sphere having the same surface area as the ellipsoid, relative to the ellipsoid. Snyder (3 -12). 125 * 126 * @param sinphi 127 * the sine of the angle between the positive z-axis and the line formed between the origin and P. 128 * @param eccentricity 129 * the eccentricity of the ellipsoid to map the sphere to. 130 * @return the q value from Snyder (3-12) 131 */ 132 public static double calcQForAuthalicLatitude( double sinphi, double eccentricity ) { 133 if ( eccentricity >= EPS10 ) { 134 double eAndSinphi = eccentricity * sinphi; 135 double es = eccentricity * eccentricity; 136 return ( 1 - es ) * ( sinphi / ( 1. - eAndSinphi * eAndSinphi ) - ( .5 / eccentricity ) * Math.log( ( 1. - eAndSinphi ) / ( 1. + eAndSinphi ) ) ); 137 } 138 // we have a sphere. 139 return ( sinphi + sinphi ); 140 } 141 142 /** 143 * Pre-calculated values for Snyder's formula (3-5) 144 */ 145 private final static double T00 = 0.5; 146 147 private final static double T01 = .20833333333333333333;/* 5/24. */ 148 149 private final static double T02 = .08333333333333333333;/* 1/12. */ 150 151 private final static double T03 = .03611111111111111111;/* 13/360 */ 152 153 private final static double T10 = .14583333333333333333;/* 7/48 */ 154 155 private final static double T11 = .12083333333333333333;/* 29/240 */ 156 157 private final static double T12 = .07039930555555555555;/* 811/11520 */ 158 159 private final static double T20 = .05833333333333333333;/* 7/120 */ 160 161 private final static double T21 = .07232142857142857142;/* 81/1120 */ 162 163 private final static double T30 = .02653149801587301587;/* 4279/161280 */ 164 165 /** 166 * Pre-Calculates the values (used for the adams? series) which will be used to calculate the phi value of an 167 * inverse projection. Snyder (3-5). 168 * 169 * @param eccentricitySquared 170 * the squared eccentricity from the ellipsoid to calculate the theta for. 171 * @return the precalculated values. 172 */ 173 public static double[] preCalcedThetaSeries( double eccentricitySquared ) { 174 double[] precalculatedSerie = new double[4]; 175 precalculatedSerie[0] = eccentricitySquared * T00; 176 177 // eccentricity^4 178 double tmp = eccentricitySquared * eccentricitySquared; 179 precalculatedSerie[0] += tmp * T01; 180 precalculatedSerie[1] = tmp * T10; 181 182 // eccentricity^6 183 tmp *= eccentricitySquared; 184 precalculatedSerie[0] += tmp * T02; 185 precalculatedSerie[1] += tmp * T11; 186 precalculatedSerie[2] = tmp * T20; 187 188 // eccentricity^8 189 tmp *= eccentricitySquared; 190 precalculatedSerie[0] += tmp * T03; 191 precalculatedSerie[1] += tmp * T12; 192 precalculatedSerie[2] += tmp * T21; 193 precalculatedSerie[3] = tmp * T30; 194 195 return precalculatedSerie; 196 } 197 198 /** 199 * Gets Phi from the given conformal latitude chi and the precalculated values (gotten from 200 * {@link ProjectionUtils#preCalcedThetaSeries(double)} ) of the adams? serie. From Snyder (3-5). 201 * 202 * @param chi 203 * the conformal latitude 204 * @param APA 205 * the precalculated values from the serie gotten from {@link ProjectionUtils#preCalcedThetaSeries(double)}. 206 * @return the Phi as a polarcoordinate on the ellipsoid or chi if the length of APA != 4. 207 */ 208 public static double calcPhiFromConformalLatitude( double chi, double[] APA ) { 209 if ( APA.length != 4 ) { 210 return chi; 211 } 212 double tmp = chi + chi; 213 return ( chi + APA[0] * Math.sin( tmp ) + APA[1] * Math.sin( tmp + tmp ) + APA[2] * Math.sin( tmp + tmp + tmp ) + APA[3] * Math.sin( tmp + tmp 214 + tmp 215 + tmp ) ); 216 } 217 218 /** 219 * P[0][0-2] = 1/3, 31/180, 517/5040, P[1][0-2] = 23/360, 251/3780 P[2][0] = 761/45360 220 */ 221 private final static double P00 = .33333333333333333333; /* 1/3 */ 222 223 private final static double P01 = .17222222222222222222; /* 31 / 180 */ 224 225 private final static double P02 = .10257936507936507936; /* 517 / 5040 */ 226 227 private final static double P10 = .06388888888888888888; /* 23/360 */ 228 229 private final static double P11 = .06640211640211640211; /* 251/3780 */ 230 231 private final static double P20 = .01641501294219154443; /* 761/45360 */ 232 233 /** 234 * Pre-Calculates the values (used for the adams? series) which will be used to calculate the authalic latitude. 235 * Snyder (3-18). 236 * 237 * @param eccentricitySquared 238 * the squared eccentricity from the ellipsoid to calculate the authalic latitude for. 239 * @return the precalculated values. 240 * @deprecated use {@link ProjectionUtils#getAuthalicLatitudeSeriesValues(double)} instead.; 241 */ 242 @Deprecated 243 public static double[] authset( double eccentricitySquared ) { 244 return getAuthalicLatitudeSeriesValues( eccentricitySquared ); 245 } 246 247 /** 248 * Pre-Calculates the values (used for the adams? series) which will be used to calculate the authalic latitude. 249 * Snyder (3-18). 250 * 251 * @param eccentricitySquared 252 * the squared eccentricity from the ellipsoid to calculate the authalic latitude for. 253 * @return the precalculated values [0] = e^2/3 + e^4*(31/180) + e^6*(517/5040), [1]= e^4*(23/360) + e^6*(251/3780) 254 * and [2] = e^6*(761/45360). 255 */ 256 public static double[] getAuthalicLatitudeSeriesValues( double eccentricitySquared ) { 257 double[] precalculatedSerie = new double[3]; 258 precalculatedSerie[0] = eccentricitySquared * P00; 259 double t = eccentricitySquared * eccentricitySquared; 260 precalculatedSerie[0] += t * P01; 261 precalculatedSerie[1] = t * P10; 262 t *= eccentricitySquared; 263 precalculatedSerie[0] += t * P02; 264 precalculatedSerie[1] += t * P11; 265 precalculatedSerie[2] = t * P20; 266 return precalculatedSerie; 267 } 268 269 /** 270 * Gets phi from the authalic latitude beta and the precalculated values of the adams? serie. From Snyder (3-18). 271 * 272 * @param beta 273 * authalic latitude. 274 * @param APA 275 * the precalculated values from the serie gotten from 276 * {@link ProjectionUtils#getAuthalicLatitudeSeriesValues(double)}. 277 * @return the phi on the ellipsoid. 278 * @deprecated use {@link ProjectionUtils#calcPhiFromAuthalicLatitude(double)} instead.; 279 */ 280 @Deprecated 281 public static double authlat( double beta, double[] APA ) { 282 return calcPhiFromAuthalicLatitude( beta, APA ); 283 } 284 285 /** 286 * Gets phi from the authalic latitude beta and the precalculated values of the adams? serie. From Snyder (3-18). 287 * 288 * @param beta 289 * authalic latitude. 290 * @param APA 291 * the precalculated values from the serie gotten from 292 * {@link ProjectionUtils#getAuthalicLatitudeSeriesValues(double)}. 293 * @return the phi on the ellipsoid. 294 */ 295 public static double calcPhiFromAuthalicLatitude( double beta, double[] APA ) { 296 double t = beta + beta; 297 return ( beta + APA[0] * Math.sin( t ) + APA[1] * Math.sin( t + t ) + APA[2] * Math.sin( t + t + t ) ); 298 } 299 300 /** 301 * Calcs the length of a vector given by two points x and y 302 * 303 * @param dx 304 * of the vector 305 * @param dy 306 * of the vector 307 * @return the length 308 */ 309 public static double length( double dx, double dy ) { 310 return Math.sqrt( dx * dx + dy * dy ); 311 } 312 313 /** 314 * This method calculates the innerpart of the conformal latitude's definition (Snyder p.15 3-1). This formula is 315 * almost equal to the calculation of the half colatitude from the conformal latitude (Snyder p.108 15-9). They only 316 * differ a sign in the first term. 317 * 318 * @param phi 319 * to calculate the conformal latitude from 320 * @param sinphi 321 * the sinus of the phi. 322 * @param eccentricity 323 * of the ellipsoid to which the phi should be made conformal to. 324 * @return the value of the innerpart of the conformal latitude formula. i.e. tan( pi/4 <b>+</b> 325 * phi/2)<b>*</b>[(1-e*sin(phi))/1+e*sin(phi))]^e/2. 326 */ 327 public static double conformalLatitudeInnerPart( double phi, double sinphi, double eccentricity ) { 328 sinphi *= eccentricity; 329 return ( Math.tan( .5 * ( HALFPI + phi ) ) ) * Math.pow( ( 1. - sinphi ) / ( 1. + sinphi ), .5 * eccentricity ); 330 } 331 332 /** 333 * This method calculates the innerpart of the conformal latitude's definition (Snyder p.15 3-1). This formula is 334 * almost equal to the calculation of the half colatitude from the conformal latitude (Snyder p.108 15-9). They only 335 * differ a sign in the first term. 336 * 337 * @param phi 338 * to calculate the conformal latitude from 339 * @param sinphi 340 * the sinus of the phi. 341 * @param eccentricity 342 * of the ellipsoid to which the phi should be made conformal to. 343 * @return the value of the innerpart of the conformal latitude formula. i.e. tan( pi/4 <b>+</b> 344 * phi/2)*[(1-e*sin(phi))/1+e*sin(phi))]^e/2. 345 * @deprecated Use {@link #conformalLatitudeInnerPart(double,double,double)} instead 346 */ 347 @Deprecated 348 public static double ssfn( double phi, double sinphi, double eccentricity ) { 349 return conformalLatitudeInnerPart( phi, sinphi, eccentricity ); 350 } 351 352 /** 353 * This method calculates the tangens of the half colatitude from the conformal latitude (Snyder p.108 15-9). 354 * 355 * @param phi 356 * to calculate the half of the co latitude of the conformal latitude from 357 * @param sinphi 358 * the sinus of the phi. 359 * @param eccentricity 360 * of the ellipsoid to which the phi should be made conformal to. 361 * @return the value of the tangens of half of the conformal latitude formula. i.e. tan( pi/4 <b>-</b> 362 * phi/2)<b>/</b>[(1-e*sin(phi))/1+e*sin(phi))]^e/2. 363 */ 364 public static double tanHalfCoLatitude( double phi, double sinphi, double eccentricity ) { 365 sinphi *= eccentricity; 366 return ( Math.tan( .5 * ( HALFPI - phi ) ) ) / Math.pow( ( 1. - sinphi ) / ( 1. + sinphi ), .5 * eccentricity ); 367 } 368 369 /** 370 * This method calculates the tangens of the half colatitude from the conformal latitude (Snyder p.108 15-9). This 371 * formula is almost equal to the calculation of the innerpart of the conformal latitude's definition (Snyder p.15 372 * 3-1). They only differ a sign in the first term. 373 * 374 * @param phi 375 * to calculate the half of the co latitude of the conformal latitude from 376 * @param sinphi 377 * the sinus of the phi. 378 * @param eccentricity 379 * of the ellipsoid to which the phi should be made conformal to. 380 * @return the value of the innerpart of the conformal latitude formula (given sign + or -). i.e. tan( pi/4 (+-) 381 * phi/2)*[(1-e*sin(phi))/1+e*sin(phi))]^e/2. 382 * @deprecated Use {@link #tanHalfCoLatitude(double,double,double)} instead 383 */ 384 @Deprecated 385 public static double tsfn( double phi, double sinphi, double eccentricity ) { 386 return tanHalfCoLatitude( phi, sinphi, eccentricity ); 387 } 388 389 /** 390 * This method can be used to calculate the value of a variable called 'm' by Snyder (Snyder p.101 14-15). 391 * 392 * @param sinphi 393 * the sinus of the phi 394 * @param cosphi 395 * the cosinus of the phi 396 * @param eccentricitySquared 397 * the value eccentricity * eccentricity. 398 * @return cos( phi) / Math.sqrt( 1 - eccentricity*eccentricity*sin(phi)*sin(phi) ). 399 * @deprecated Use {@link #calcMFromSnyder(double,double,double)} instead 400 */ 401 @Deprecated 402 public static double msfn( double sinphi, double cosphi, double eccentricitySquared ) { 403 return calcMFromSnyder( sinphi, cosphi, eccentricitySquared ); 404 } 405 406 /** 407 * This method can be used to calculate the value of a variable called 'm' by Snyder (Snyder p.101 14-15). 408 * 409 * @param sinphi 410 * the sinus of the phi 411 * @param cosphi 412 * the cosinus of the phi 413 * @param eccentricitySquared 414 * the value eccentricity * eccentricity. 415 * @return cos( phi) / Math.sqrt( 1 - eccentricity*eccentricity*sin(phi)*sin(phi) ). 416 */ 417 public static double calcMFromSnyder( double sinphi, double cosphi, double eccentricitySquared ) { 418 return cosphi / Math.sqrt( 1.0 - eccentricitySquared * sinphi * sinphi ); 419 } 420 421 /** 422 * Copied these value from proj4, I think they are reformed to fit some rule... but I don't know which rule that is 423 * :-( 424 */ 425 private final static double C00 = 1; /* 1 :-) */ 426 427 private final static double C02 = .25; /* 1/4 */ 428 429 private final static double C04 = .046875;/* 3/64 */ 430 431 private final static double C06 = .01953125;/* 5/256 */ 432 433 private final static double C08 = .01068115234375;/* 175 / 16384 */ 434 435 private final static double C22 = .75; 436 437 private final static double C44 = .46875; 438 439 private final static double C46 = .01302083333333333333; 440 441 private final static double C48 = .00712076822916666666; 442 443 private final static double C66 = .36458333333333333333; 444 445 private final static double C68 = .00569661458333333333; 446 447 private final static double C88 = .3076171875; 448 449 450 /** 451 * Pre Calculates the values for the series to calculate for a given ellipsoid with given eccentricity the distance 452 * along the meridian from the equator to a given latitude 453 * {@link #getDistanceAlongMeridian(double, double, double, double[])}. 454 * 455 * @param es 456 * the squared eccentricity of the underlying ellipsoid. 457 * @return the precalculated values for given ellipsoid. 458 * @deprecated Use {@link #getRectifiyingLatitudeValues(double)} instead 459 */ 460 @Deprecated 461 public static double[] enfn( double es ) { 462 return getRectifiyingLatitudeValues( es ); 463 } 464 465 /** 466 * Pre Calculates the values for the series to calculate for a given ellipsoid with given eccentricity the distance 467 * along the meridian from the equator to a given latitude 468 * {@link #getDistanceAlongMeridian(double, double, double, double[])}. 469 * 470 * @param es 471 * the squared eccentricity of the underlying ellipsoid. 472 * @return the precalculated values for given ellipsoid. 473 */ 474 public static double[] getRectifiyingLatitudeValues( double es ) { 475 double[] en = new double[5]; 476 en[0] = C00 - es * ( C02 + es * ( C04 + es * ( C06 + es * C08 ) ) ); 477 en[1] = es * ( C22 - es * ( C04 + es * ( C06 + es * C08 ) ) ); 478 479 double t = es * es; 480 en[2] = t * ( C44 - es * ( C46 + es * C48 ) ); 481 482 t *= es; 483 en[3] = t * ( C66 - es * C68 ); 484 485 en[4] = t * es * C88; 486 487 return en; 488 } 489 490 /** 491 * This method calcs for a a given ellispoid the distance along the meridian from the equator to latitude phi Snyder 492 * (p.17 3-21). It is used to calculate the rectifying latitude <i>mu</i>. 493 * 494 * @param phi 495 * the lattitude of the point in radians 496 * @param sphi 497 * the sinus of the latitude 498 * @param cphi 499 * the cosinus of the latitude 500 * @param en 501 * an array (of length 5) containing the precalculate values for this ellipsoid gotten from 502 * {@link #getRectifiyingLatitudeValues(double)}. 503 * @return the distance along the meridian from the equator to latitude phi. 504 * @deprecated Use {@link #getDistanceAlongMeridian(double,double,double,double[])} instead 505 */ 506 @Deprecated 507 public static double mlfn( double phi, double sphi, double cphi, double[] en ) { 508 return getDistanceAlongMeridian( phi, sphi, cphi, en ); 509 } 510 511 /** 512 * This method calcs the distance along the meridian from the equator to latitude phi for a a given ellispoid Snyder 513 * (p.17 3-21). It is used to calculate the rectifying latitude <i>mu</i>. 514 * 515 * @param phi 516 * the lattitude of the point in radians 517 * @param sphi 518 * the sinus of the latitude 519 * @param cphi 520 * the cosinus of the latitude 521 * @param en 522 * an array (of length 5) containing the precalculate values for this ellipsoid gotten from 523 * {@link #getRectifiyingLatitudeValues(double)}. 524 * @return the distance along the meridian from the equator to latitude phi. 525 */ 526 public static double getDistanceAlongMeridian( double phi, double sphi, double cphi, double[] en ) { 527 cphi *= sphi; 528 sphi *= sphi; 529 return ( en[0] * phi ) - ( cphi * ( en[1] + sphi * ( en[2] + sphi * ( en[3] + sphi * en[4] ) ) ) ); 530 } 531 532 /** 533 * This method calcs lattitude phi from a given distance along the meridian to the equator for a a given ellispoid 534 * and is therefore the inverse of the {@link #getDistanceAlongMeridian(double, double, double, double[])}. Phi is 535 * determined to EPS (1e-11) radians, which is about 1e-6 seconds. 536 * 537 * @param initialValue 538 * to calculate phi from, a good starting value is using the (distance along the meridian / y*scale) e.g. 539 * the scaled y value on the meridian. 540 * @param squaredEccentricity 541 * the squared eccentricity of the ellipsoid. 542 * @param en 543 * an array (of length 5) containing the precalculate values for this ellipsoid gotten from 544 * {@link #getRectifiyingLatitudeValues(double)}. 545 * @return the lattitude phi. 546 * @deprecated Use {@link #calcPhiFromMeridianDistance(double,double,double[])} instead 547 */ 548 @Deprecated 549 public static double inv_mlfn( double initialValue, double squaredEccentricity, double[] en ) { 550 return calcPhiFromMeridianDistance( initialValue, squaredEccentricity, en ); 551 } 552 553 /** 554 * This method calcs lattitude phi from a given distance along the meridian to the equator for a a given ellispoid 555 * and is therefore the inverse of the {@link #getDistanceAlongMeridian(double, double, double, double[])}. Phi is 556 * determined to EPS (1e-11) radians, which is about 1e-6 seconds. 557 * 558 * @param initialValue 559 * to calculate phi from, a good starting value is using the (distance along the meridian / y*scale) e.g. 560 * the scaled y value on the meridian. 561 * @param squaredEccentricity 562 * the squared eccentricity of the ellipsoid. 563 * @param en 564 * an array (of length 5) containing the precalculate values for this ellipsoid gotten from 565 * {@link #getRectifiyingLatitudeValues(double)}. 566 * @return the lattitude phi or the best approximated value if no suitable convergence was found. 567 */ 568 public static double calcPhiFromMeridianDistance( double initialValue, double squaredEccentricity, double[] en ) { 569 double k = 1. / ( 1. - squaredEccentricity ); 570 double phi = initialValue; 571 /* (from proj4: ->) rarely goes over 2 iterations */ 572 for ( int i = MAX_ITER; i != 0; i-- ) { 573 double s = Math.sin( phi ); 574 double t = 1. - squaredEccentricity * s * s; 575 t = ( getDistanceAlongMeridian( phi, s, Math.cos( phi ), en ) - initialValue ) * ( t * Math.sqrt( t ) ) * k; 576 phi -= t; 577 if ( Math.abs( t ) < EPS11 ) { 578 return phi; 579 } 580 } 581 return phi; 582 } 583 584 /** 585 * A helper method, which returns the acos from value or if value < -1 pi or value>1 0. 586 * 587 * @param value 588 * (in radians) from which the acos must be calculated 589 * @return the acos from value or if value < -1 pi or if value > 1 0. 590 */ 591 public static double acosScaled( double value ) { 592 return ( value < -1 ) ? Math.PI : ( value > 1 ) ? 0 : Math.acos( value ); 593 } 594 595 /** 596 * A helper method, which returns the asin from value or if value < -1 (-pi/2) or value>1 (pi/2). 597 * 598 * @param value 599 * (in radians) from which the asin must be calculated 600 * @return the asin from value or if value < -1 (-pi/2) or value>1 (pi/2). 601 */ 602 public static double asinScaled( double value ) { 603 return ( value < -1 ) ? -HALFPI : ( value > 1 ) ? HALFPI : Math.asin( value ); 604 } 605 606 /** 607 * A helper method modulos (pi)the given angle (in radians) until the result fits betwee -HALFPI and HALF_PI. 608 * @param angle in radians 609 * @return the angle adjusted to -pi/2 + pi/2 or 0 if the angle is NaN or Infinite. 610 */ 611 public static double normalizeLatitude(double angle) { 612 if (Double.isInfinite(angle) || Double.isNaN(angle)){ 613 return 0; 614 } 615 while (angle > HALFPI){ 616 angle -= Math.PI; 617 } 618 while (angle < -HALFPI){ 619 angle += Math.PI; 620 } 621 return angle; 622 } 623 624 /** 625 * A helper method modulos (2*pi)the given angle (in radians) until the result fits betwee -PI and PI. 626 * @param angle to be normalized 627 * @return the angle adjusted to -2*pi + pi*2 or 0 if the angle is NaN or Infinite. 628 */ 629 public static double normalizeLongitude(double angle){ 630 if (Double.isInfinite(angle) || Double.isNaN(angle)){ 631 return 0; 632 } 633 while (angle > Math.PI){ 634 angle -= TWOPI; 635 } 636 while (angle < -Math.PI){ 637 angle += TWOPI; 638 } 639 return angle; 640 } 641 }