PageRenderTime 109ms CodeModel.GetById 13ms app.highlight 77ms RepoModel.GetById 1ms app.codeStats 1ms

/webportal/src/main/webapp/scripts/proj4js-combined.js

http://alageospatialportal.googlecode.com/
JavaScript | 4987 lines | 2984 code | 537 blank | 1466 comment | 547 complexity | 4f9fc4de15ecf4ff75223155d283a4c8 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2  proj4js.js -- Javascript reprojection library. 
   3  
   4  Authors:      Mike Adair madairATdmsolutions.ca
   5                Richard Greenwood richATgreenwoodmap.com
   6                Didier Richard didier.richardATign.fr
   7                Stephen Irons
   8  License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html 
   9                Note: This program is an almost direct port of the C library
  10                Proj4.
  11*/
  12/* ======================================================================
  13    proj4js.js
  14   ====================================================================== */
  15
  16/*
  17Author:       Mike Adair madairATdmsolutions.ca
  18              Richard Greenwood rich@greenwoodmap.com
  19License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html
  20
  21$Id: Proj.js 2956 2007-07-09 12:17:52Z steven $
  22*/
  23
  24/**
  25 * Namespace: Proj4js
  26 *
  27 * Proj4js is a JavaScript library to transform point coordinates from one 
  28 * coordinate system to another, including datum transformations.
  29 *
  30 * This library is a port of both the Proj.4 and GCTCP C libraries to JavaScript. 
  31 * Enabling these transformations in the browser allows geographic data stored 
  32 * in different projections to be combined in browser-based web mapping 
  33 * applications.
  34 * 
  35 * Proj4js must have access to coordinate system initialization strings (which
  36 * are the same as for PROJ.4 command line).  Thes can be included in your 
  37 * application using a <script> tag or Proj4js can load CS initialization 
  38 * strings from a local directory or a web service such as spatialreference.org.
  39 *
  40 * Similarly, Proj4js must have access to projection transform code.  These can
  41 * be included individually using a <script> tag in your page, built into a 
  42 * custom build of Proj4js or loaded dynamically at run-time.  Using the
  43 * -combined and -compressed versions of Proj4js includes all projection class
  44 * code by default.
  45 *
  46 * Note that dynamic loading of defs and code happens ascynchrously, check the
  47 * Proj.readyToUse flag before using the Proj object.  If the defs and code
  48 * required by your application are loaded through script tags, dynamic loading
  49 * is not required and the Proj object will be readyToUse on return from the 
  50 * constructor.
  51 * 
  52 * All coordinates are handled as points which have a .x and a .y property
  53 * which will be modified in place.
  54 *
  55 * Override Proj4js.reportError for output of alerts and warnings.
  56 *
  57 * See http://trac.osgeo.org/proj4js/wiki/UserGuide for full details.
  58*/
  59
  60/**
  61 * Global namespace object for Proj4js library
  62 */
  63Proj4js = {
  64
  65    /**
  66     * Property: defaultDatum
  67     * The datum to use when no others a specified
  68     */
  69    defaultDatum: 'WGS84',                  //default datum
  70
  71    /** 
  72    * Method: transform(source, dest, point)
  73    * Transform a point coordinate from one map projection to another.  This is
  74    * really the only public method you should need to use.
  75    *
  76    * Parameters:
  77    * source - {Proj4js.Proj} source map projection for the transformation
  78    * dest - {Proj4js.Proj} destination map projection for the transformation
  79    * point - {Object} point to transform, may be geodetic (long, lat) or
  80    *     projected Cartesian (x,y), but should always have x,y properties.
  81    */
  82    transform: function(source, dest, point) {
  83        if (!source.readyToUse || !dest.readyToUse) {
  84            this.reportError("Proj4js initialization for "+source.srsCode+" not yet complete");
  85            return point;
  86        }
  87        
  88        // Workaround for Spherical Mercator
  89        if ((source.srsProjNumber =="900913" && dest.datumCode != "WGS84") ||
  90            (dest.srsProjNumber == "900913" && source.datumCode != "WGS84")) {
  91            var wgs84 = Proj4js.WGS84;
  92            this.transform(source, wgs84, point);
  93            source = wgs84;
  94        }
  95
  96        // Transform source points to long/lat, if they aren't already.
  97        if ( source.projName=="longlat") {
  98            point.x *= Proj4js.common.D2R;  // convert degrees to radians
  99            point.y *= Proj4js.common.D2R;
 100        } else {
 101            if (source.to_meter) {
 102                point.x *= source.to_meter;
 103                point.y *= source.to_meter;
 104            }
 105            source.inverse(point); // Convert Cartesian to longlat
 106        }
 107
 108        // Adjust for the prime meridian if necessary
 109        if (source.from_greenwich) { 
 110            point.x += source.from_greenwich; 
 111        }
 112
 113        // Convert datums if needed, and if possible.
 114        point = this.datum_transform( source.datum, dest.datum, point );
 115
 116        // Adjust for the prime meridian if necessary
 117        if (dest.from_greenwich) {
 118            point.x -= dest.from_greenwich;
 119        }
 120
 121        if( dest.projName=="longlat" ) {             
 122            // convert radians to decimal degrees
 123            point.x *= Proj4js.common.R2D;
 124            point.y *= Proj4js.common.R2D;
 125        } else  {               // else project
 126            dest.forward(point);
 127            if (dest.to_meter) {
 128                point.x /= dest.to_meter;
 129                point.y /= dest.to_meter;
 130            }
 131        }
 132        return point;
 133    }, // transform()
 134
 135    /** datum_transform()
 136      source coordinate system definition,
 137      destination coordinate system definition,
 138      point to transform in geodetic coordinates (long, lat, height)
 139    */
 140    datum_transform : function( source, dest, point ) {
 141
 142      // Short cut if the datums are identical.
 143      if( source.compare_datums( dest ) ) {
 144          return point; // in this case, zero is sucess,
 145                    // whereas cs_compare_datums returns 1 to indicate TRUE
 146                    // confusing, should fix this
 147      }
 148
 149      // Explicitly skip datum transform by setting 'datum=none' as parameter for either source or dest
 150      if( source.datum_type == Proj4js.common.PJD_NODATUM
 151          || dest.datum_type == Proj4js.common.PJD_NODATUM) {
 152          return point;
 153      }
 154
 155      // If this datum requires grid shifts, then apply it to geodetic coordinates.
 156      if( source.datum_type == Proj4js.common.PJD_GRIDSHIFT )
 157      {
 158        alert("ERROR: Grid shift transformations are not implemented yet.");
 159        /*
 160          pj_apply_gridshift( pj_param(source.params,"snadgrids").s, 0,
 161                              point_count, point_offset, x, y, z );
 162          CHECK_RETURN;
 163
 164          src_a = SRS_WGS84_SEMIMAJOR;
 165          src_es = 0.006694379990;
 166        */
 167      }
 168
 169      if( dest.datum_type == Proj4js.common.PJD_GRIDSHIFT )
 170      {
 171        alert("ERROR: Grid shift transformations are not implemented yet.");
 172        /*
 173          dst_a = ;
 174          dst_es = 0.006694379990;
 175        */
 176      }
 177
 178      // Do we need to go through geocentric coordinates?
 179      if( source.es != dest.es || source.a != dest.a
 180          || source.datum_type == Proj4js.common.PJD_3PARAM
 181          || source.datum_type == Proj4js.common.PJD_7PARAM
 182          || dest.datum_type == Proj4js.common.PJD_3PARAM
 183          || dest.datum_type == Proj4js.common.PJD_7PARAM)
 184      {
 185
 186        // Convert to geocentric coordinates.
 187        source.geodetic_to_geocentric( point );
 188        // CHECK_RETURN;
 189
 190        // Convert between datums
 191        if( source.datum_type == Proj4js.common.PJD_3PARAM || source.datum_type == Proj4js.common.PJD_7PARAM ) {
 192          source.geocentric_to_wgs84(point);
 193          // CHECK_RETURN;
 194        }
 195
 196        if( dest.datum_type == Proj4js.common.PJD_3PARAM || dest.datum_type == Proj4js.common.PJD_7PARAM ) {
 197          dest.geocentric_from_wgs84(point);
 198          // CHECK_RETURN;
 199        }
 200
 201        // Convert back to geodetic coordinates
 202        dest.geocentric_to_geodetic( point );
 203          // CHECK_RETURN;
 204      }
 205
 206      // Apply grid shift to destination if required
 207      if( dest.datum_type == Proj4js.common.PJD_GRIDSHIFT )
 208      {
 209        alert("ERROR: Grid shift transformations are not implemented yet.");
 210        // pj_apply_gridshift( pj_param(dest.params,"snadgrids").s, 1, point);
 211        // CHECK_RETURN;
 212      }
 213      return point;
 214    }, // cs_datum_transform
 215
 216    /**
 217     * Function: reportError
 218     * An internal method to report errors back to user. 
 219     * Override this in applications to report error messages or throw exceptions.
 220     */
 221    reportError: function(msg) {
 222      //console.log(msg);
 223    },
 224
 225/**
 226 *
 227 * Title: Private Methods
 228 * The following properties and methods are intended for internal use only.
 229 *
 230 * This is a minimal implementation of JavaScript inheritance methods so that 
 231 * Proj4js can be used as a stand-alone library.
 232 * These are copies of the equivalent OpenLayers methods at v2.7
 233 */
 234 
 235/**
 236 * Function: extend
 237 * Copy all properties of a source object to a destination object.  Modifies
 238 *     the passed in destination object.  Any properties on the source object
 239 *     that are set to undefined will not be (re)set on the destination object.
 240 *
 241 * Parameters:
 242 * destination - {Object} The object that will be modified
 243 * source - {Object} The object with properties to be set on the destination
 244 *
 245 * Returns:
 246 * {Object} The destination object.
 247 */
 248    extend: function(destination, source) {
 249      destination = destination || {};
 250      if(source) {
 251          for(var property in source) {
 252              var value = source[property];
 253              if(value !== undefined) {
 254                  destination[property] = value;
 255              }
 256          }
 257      }
 258      return destination;
 259    },
 260
 261/**
 262 * Constructor: Class
 263 * Base class used to construct all other classes. Includes support for 
 264 *     multiple inheritance. 
 265 *  
 266 */
 267    Class: function() {
 268      var Class = function() {
 269          this.initialize.apply(this, arguments);
 270      };
 271  
 272      var extended = {};
 273      var parent;
 274      for(var i=0; i<arguments.length; ++i) {
 275          if(typeof arguments[i] == "function") {
 276              // get the prototype of the superclass
 277              parent = arguments[i].prototype;
 278          } else {
 279              // in this case we're extending with the prototype
 280              parent = arguments[i];
 281          }
 282          Proj4js.extend(extended, parent);
 283      }
 284      Class.prototype = extended;
 285      
 286      return Class;
 287    },
 288
 289    /**
 290     * Function: bind
 291     * Bind a function to an object.  Method to easily create closures with
 292     *     'this' altered.
 293     * 
 294     * Parameters:
 295     * func - {Function} Input function.
 296     * object - {Object} The object to bind to the input function (as this).
 297     * 
 298     * Returns:
 299     * {Function} A closure with 'this' set to the passed in object.
 300     */
 301    bind: function(func, object) {
 302        // create a reference to all arguments past the second one
 303        var args = Array.prototype.slice.apply(arguments, [2]);
 304        return function() {
 305            // Push on any additional arguments from the actual function call.
 306            // These will come after those sent to the bind call.
 307            var newArgs = args.concat(
 308                Array.prototype.slice.apply(arguments, [0])
 309            );
 310            return func.apply(object, newArgs);
 311        };
 312    },
 313    
 314/**
 315 * The following properties and methods handle dynamic loading of JSON objects.
 316 *
 317    /**
 318     * Property: scriptName
 319     * {String} The filename of this script without any path.
 320     */
 321    scriptName: "proj4js-combined.js",
 322
 323    /**
 324     * Property: defsLookupService
 325     * AJAX service to retreive projection definition parameters from
 326     */
 327    defsLookupService: 'http://spatialreference.org/ref',
 328
 329    /**
 330     * Property: libPath
 331     * internal: http server path to library code.
 332     */
 333    libPath: null,
 334
 335    /**
 336     * Function: getScriptLocation
 337     * Return the path to this script.
 338     *
 339     * Returns:
 340     * Path to this script
 341     */
 342    getScriptLocation: function () {
 343        if (this.libPath) return this.libPath;
 344        var scriptName = this.scriptName;
 345        var scriptNameLen = scriptName.length;
 346
 347        var scripts = document.getElementsByTagName('script');
 348        for (var i = 0; i < scripts.length; i++) {
 349            var src = scripts[i].getAttribute('src');
 350            if (src) {
 351                var index = src.lastIndexOf(scriptName);
 352                // is it found, at the end of the URL?
 353                if ((index > -1) && (index + scriptNameLen == src.length)) {
 354                    this.libPath = src.slice(0, -scriptNameLen);
 355                    break;
 356                }
 357            }
 358        }
 359        return this.libPath||"";
 360    },
 361
 362    /**
 363     * Function: loadScript
 364     * Load a JS file from a URL into a <script> tag in the page.
 365     * 
 366     * Parameters:
 367     * url - {String} The URL containing the script to load
 368     * onload - {Function} A method to be executed when the script loads successfully
 369     * onfail - {Function} A method to be executed when there is an error loading the script
 370     * loadCheck - {Function} A boolean method that checks to see if the script 
 371     *            has loaded.  Typically this just checks for the existance of
 372     *            an object in the file just loaded.
 373     */
 374    loadScript: function(url, onload, onfail, loadCheck) {
 375      var script = document.createElement('script');
 376      script.defer = false;
 377      script.type = "text/javascript";
 378      script.id = url;
 379      script.src = url;
 380      script.onload = onload;
 381      script.onerror = onfail;
 382      script.loadCheck = loadCheck;
 383      if (/MSIE/.test(navigator.userAgent)) {
 384        script.onreadystatechange = this.checkReadyState;
 385      }
 386      document.getElementsByTagName('head')[0].appendChild(script);
 387    },
 388    
 389    /**
 390     * Function: checkReadyState
 391     * IE workaround since there is no onerror handler.  Calls the user defined 
 392     * loadCheck method to determine if the script is loaded.
 393     * 
 394     */
 395    checkReadyState: function() {
 396      if (this.readyState == 'loaded') {
 397        if (!this.loadCheck()) {
 398          this.onerror();
 399        } else {
 400          this.onload();
 401        }
 402      }
 403    }
 404};
 405
 406/**
 407 * Class: Proj4js.Proj
 408 *
 409 * Proj objects provide transformation methods for point coordinates
 410 * between geodetic latitude/longitude and a projected coordinate system. 
 411 * once they have been initialized with a projection code.
 412 *
 413 * Initialization of Proj objects is with a projection code, usually EPSG codes,
 414 * which is the key that will be used with the Proj4js.defs array.
 415 * 
 416 * The code passed in will be stripped of colons and converted to uppercase
 417 * to locate projection definition files.
 418 *
 419 * A projection object has properties for units and title strings.
 420 */
 421Proj4js.Proj = Proj4js.Class({
 422
 423  /**
 424   * Property: readyToUse
 425   * Flag to indicate if initialization is complete for this Proj object
 426   */
 427  readyToUse: false,   
 428  
 429  /**
 430   * Property: title
 431   * The title to describe the projection
 432   */
 433  title: null,  
 434  
 435  /**
 436   * Property: projName
 437   * The projection class for this projection, e.g. lcc (lambert conformal conic,
 438   * or merc for mercator).  These are exactly equivalent to their Proj4 
 439   * counterparts.
 440   */
 441  projName: null,
 442  /**
 443   * Property: units
 444   * The units of the projection.  Values include 'm' and 'degrees'
 445   */
 446  units: null,
 447  /**
 448   * Property: datum
 449   * The datum specified for the projection
 450   */
 451  datum: null,
 452  /**
 453   * Property: x0
 454   * The x coordinate origin
 455   */
 456  x0: 0,
 457  /**
 458   * Property: y0
 459   * The y coordinate origin
 460   */
 461  y0: 0,
 462
 463  /**
 464   * Constructor: initialize
 465   * Constructor for Proj4js.Proj objects
 466  *
 467  * Parameters:
 468  * srsCode - a code for map projection definition parameters.  These are usually
 469  * (but not always) EPSG codes.
 470  */
 471  initialize: function(srsCode) {
 472      this.srsCodeInput = srsCode;
 473      // DGR 2008-08-03 : support urn and url
 474      if (srsCode.indexOf('urn:') == 0) {
 475          //urn:ORIGINATOR:def:crs:CODESPACE:VERSION:ID
 476          var urn = srsCode.split(':');
 477          if ((urn[1] == 'ogc' || urn[1] =='x-ogc') &&
 478              (urn[2] =='def') &&
 479              (urn[3] =='crs')) {
 480              srsCode = urn[4]+':'+urn[urn.length-1];
 481          }
 482      } else if (srsCode.indexOf('http://') == 0) {
 483          //url#ID
 484          var url = srsCode.split('#');
 485          if (url[0].match(/epsg.org/)) {
 486            // http://www.epsg.org/#
 487            srsCode = 'EPSG:'+url[1];
 488          } else if (url[0].match(/RIG.xml/)) {
 489            //http://librairies.ign.fr/geoportail/resources/RIG.xml#
 490            //http://interop.ign.fr/registers/ign/RIG.xml#
 491            srsCode = 'IGNF:'+url[1];
 492          }
 493      }
 494      this.srsCode = srsCode.toUpperCase();
 495      if (this.srsCode.indexOf("EPSG") == 0) {
 496          this.srsCode = this.srsCode;
 497          this.srsAuth = 'epsg';
 498          this.srsProjNumber = this.srsCode.substring(5);
 499      // DGR 2007-11-20 : authority IGNF
 500      } else if (this.srsCode.indexOf("IGNF") == 0) {
 501          this.srsCode = this.srsCode;
 502          this.srsAuth = 'IGNF';
 503          this.srsProjNumber = this.srsCode.substring(5);
 504      // DGR 2008-06-19 : pseudo-authority CRS for WMS
 505      } else if (this.srsCode.indexOf("CRS") == 0) {
 506          this.srsCode = this.srsCode;
 507          this.srsAuth = 'CRS';
 508          this.srsProjNumber = this.srsCode.substring(4);
 509      } else {
 510          this.srsAuth = '';
 511          this.srsProjNumber = this.srsCode;
 512      }
 513      this.loadProjDefinition();
 514  },
 515  
 516/**
 517 * Function: loadProjDefinition
 518 *    Loads the coordinate system initialization string if required.
 519 *    Note that dynamic loading happens asynchronously so an application must 
 520 *    wait for the readyToUse property is set to true.
 521 *    To prevent dynamic loading, include the defs through a script tag in
 522 *    your application.
 523 *
 524 */
 525    loadProjDefinition: function() {
 526      //check in memory
 527      if (Proj4js.defs[this.srsCode]) {
 528        this.defsLoaded();
 529        return;
 530      }
 531
 532      //else check for def on the server
 533      var url = Proj4js.getScriptLocation() + 'defs/' + this.srsAuth.toUpperCase() + this.srsProjNumber + '.js';
 534      Proj4js.loadScript(url, 
 535                Proj4js.bind(this.defsLoaded, this),
 536                Proj4js.bind(this.loadFromService, this),
 537                Proj4js.bind(this.checkDefsLoaded, this) );
 538    },
 539
 540/**
 541 * Function: loadFromService
 542 *    Creates the REST URL for loading the definition from a web service and 
 543 *    loads it.
 544 *
 545 */
 546    loadFromService: function() {
 547      //else load from web service
 548      var url = Proj4js.defsLookupService +'/' + this.srsAuth +'/'+ this.srsProjNumber + '/proj4js/';
 549      Proj4js.loadScript(url, 
 550            Proj4js.bind(this.defsLoaded, this),
 551            Proj4js.bind(this.defsFailed, this),
 552            Proj4js.bind(this.checkDefsLoaded, this) );
 553    },
 554
 555/**
 556 * Function: defsLoaded
 557 * Continues the Proj object initilization once the def file is loaded
 558 *
 559 */
 560    defsLoaded: function() {
 561      this.parseDefs();
 562      this.loadProjCode(this.projName);
 563    },
 564    
 565/**
 566 * Function: checkDefsLoaded
 567 *    This is the loadCheck method to see if the def object exists
 568 *
 569 */
 570    checkDefsLoaded: function() {
 571      if (Proj4js.defs[this.srsCode]) {
 572        return true;
 573      } else {
 574        return false;
 575      }
 576    },
 577
 578 /**
 579 * Function: defsFailed
 580 *    Report an error in loading the defs file, but continue on using WGS84
 581 *
 582 */
 583   defsFailed: function() {
 584      Proj4js.reportError('failed to load projection definition for: '+this.srsCode);
 585      Proj4js.defs[this.srsCode] = Proj4js.defs['WGS84'];  //set it to something so it can at least continue
 586      this.defsLoaded();
 587    },
 588
 589/**
 590 * Function: loadProjCode
 591 *    Loads projection class code dynamically if required.
 592 *     Projection code may be included either through a script tag or in
 593 *     a built version of proj4js
 594 *
 595 */
 596    loadProjCode: function(projName) {
 597      if (Proj4js.Proj[projName]) {
 598        this.initTransforms();
 599        return;
 600      }
 601
 602      //the URL for the projection code
 603      var url = Proj4js.getScriptLocation() + 'projCode/' + projName + '.js';
 604      Proj4js.loadScript(url, 
 605              Proj4js.bind(this.loadProjCodeSuccess, this, projName),
 606              Proj4js.bind(this.loadProjCodeFailure, this, projName), 
 607              Proj4js.bind(this.checkCodeLoaded, this, projName) );
 608    },
 609
 610 /**
 611 * Function: loadProjCodeSuccess
 612 *    Loads any proj dependencies or continue on to final initialization.
 613 *
 614 */
 615    loadProjCodeSuccess: function(projName) {
 616      if (Proj4js.Proj[projName].dependsOn){
 617        this.loadProjCode(Proj4js.Proj[projName].dependsOn);
 618      } else {
 619        this.initTransforms();
 620      }
 621    },
 622
 623 /**
 624 * Function: defsFailed
 625 *    Report an error in loading the proj file.  Initialization of the Proj
 626 *    object has failed and the readyToUse flag will never be set.
 627 *
 628 */
 629    loadProjCodeFailure: function(projName) {
 630      Proj4js.reportError("failed to find projection file for: " + projName);
 631      //TBD initialize with identity transforms so proj will still work?
 632    },
 633    
 634/**
 635 * Function: checkCodeLoaded
 636 *    This is the loadCheck method to see if the projection code is loaded
 637 *
 638 */
 639    checkCodeLoaded: function(projName) {
 640      if (Proj4js.Proj[projName]) {
 641        return true;
 642      } else {
 643        return false;
 644      }
 645    },
 646
 647/**
 648 * Function: initTransforms
 649 *    Finalize the initialization of the Proj object
 650 *
 651 */
 652    initTransforms: function() {
 653      Proj4js.extend(this, Proj4js.Proj[this.projName]);
 654      this.init();
 655      this.readyToUse = true;
 656  },
 657
 658/**
 659 * Function: parseDefs
 660 * Parses the PROJ.4 initialization string and sets the associated properties.
 661 *
 662 */
 663  parseDefs: function() {
 664      this.defData = Proj4js.defs[this.srsCode];
 665      var paramName, paramVal;
 666      if (!this.defData) {
 667        return;
 668      }
 669      var paramArray=this.defData.split("+");
 670
 671      for (var prop=0; prop<paramArray.length; prop++) {
 672          var property = paramArray[prop].split("=");
 673          paramName = property[0].toLowerCase();
 674          paramVal = property[1];
 675
 676          switch (paramName.replace(/\s/gi,"")) {  // trim out spaces
 677              case "": break;   // throw away nameless parameter
 678              case "title":  this.title = paramVal; break;
 679              case "proj":   this.projName =  paramVal.replace(/\s/gi,""); break;
 680              case "units":  this.units = paramVal.replace(/\s/gi,""); break;
 681              case "datum":  this.datumCode = paramVal.replace(/\s/gi,""); break;
 682              case "nadgrids": this.nagrids = paramVal.replace(/\s/gi,""); break;
 683              case "ellps":  this.ellps = paramVal.replace(/\s/gi,""); break;
 684              case "a":      this.a =  parseFloat(paramVal); break;  // semi-major radius
 685              case "b":      this.b =  parseFloat(paramVal); break;  // semi-minor radius
 686              // DGR 2007-11-20
 687              case "rf":     this.rf = parseFloat(paramVal); break; // inverse flattening rf= a/(a-b)
 688              case "lat_0":  this.lat0 = paramVal*Proj4js.common.D2R; break;        // phi0, central latitude
 689              case "lat_1":  this.lat1 = paramVal*Proj4js.common.D2R; break;        //standard parallel 1
 690              case "lat_2":  this.lat2 = paramVal*Proj4js.common.D2R; break;        //standard parallel 2
 691              case "lat_ts": this.lat_ts = paramVal*Proj4js.common.D2R; break;      // used in merc and eqc
 692              case "lon_0":  this.long0 = paramVal*Proj4js.common.D2R; break;       // lam0, central longitude
 693              case "alpha":  this.alpha =  parseFloat(paramVal)*Proj4js.common.D2R; break;  //for somerc projection
 694              case "lonc":   this.longc = paramVal*Proj4js.common.D2R; break;       //for somerc projection
 695              case "x_0":    this.x0 = parseFloat(paramVal); break;  // false easting
 696              case "y_0":    this.y0 = parseFloat(paramVal); break;  // false northing
 697              case "k_0":    this.k0 = parseFloat(paramVal); break;  // projection scale factor
 698              case "k":      this.k0 = parseFloat(paramVal); break;  // both forms returned
 699              case "r_a":    this.R_A = true; break;                 // sphere--area of ellipsoid
 700              case "zone":   this.zone = parseInt(paramVal); break;  // UTM Zone
 701              case "south":   this.utmSouth = true; break;  // UTM north/south
 702              case "towgs84":this.datum_params = paramVal.split(","); break;
 703              case "to_meter": this.to_meter = parseFloat(paramVal); break; // cartesian scaling
 704              case "from_greenwich": this.from_greenwich = paramVal*Proj4js.common.D2R; break;
 705              // DGR 2008-07-09 : if pm is not a well-known prime meridian take
 706              // the value instead of 0.0, then convert to radians
 707              case "pm":     paramVal = paramVal.replace(/\s/gi,"");
 708                             this.from_greenwich = Proj4js.PrimeMeridian[paramVal] ?
 709                                Proj4js.PrimeMeridian[paramVal] : parseFloat(paramVal);
 710                             this.from_greenwich *= Proj4js.common.D2R; 
 711                             break;
 712              case "no_defs": break; 
 713              default: //alert("Unrecognized parameter: " + paramName);
 714          } // switch()
 715      } // for paramArray
 716      this.deriveConstants();
 717  },
 718
 719/**
 720 * Function: deriveConstants
 721 * Sets several derived constant values and initialization of datum and ellipse
 722 *     parameters.
 723 *
 724 */
 725  deriveConstants: function() {
 726      if (this.nagrids == '@null') this.datumCode = 'none';
 727      if (this.datumCode && this.datumCode != 'none') {
 728        var datumDef = Proj4js.Datum[this.datumCode];
 729        if (datumDef) {
 730          this.datum_params = datumDef.towgs84 ? datumDef.towgs84.split(',') : null;
 731          this.ellps = datumDef.ellipse;
 732          this.datumName = datumDef.datumName ? datumDef.datumName : this.datumCode;
 733        }
 734      }
 735      if (!this.a) {    // do we have an ellipsoid?
 736          var ellipse = Proj4js.Ellipsoid[this.ellps] ? Proj4js.Ellipsoid[this.ellps] : Proj4js.Ellipsoid['WGS84'];
 737          Proj4js.extend(this, ellipse);
 738      }
 739      if (this.rf && !this.b) this.b = (1.0 - 1.0/this.rf) * this.a;
 740      if (Math.abs(this.a - this.b)<Proj4js.common.EPSLN) {
 741        this.sphere = true;
 742        this.b= this.a;
 743      }
 744      this.a2 = this.a * this.a;          // used in geocentric
 745      this.b2 = this.b * this.b;          // used in geocentric
 746      this.es = (this.a2-this.b2)/this.a2;  // e ^ 2
 747      this.e = Math.sqrt(this.es);        // eccentricity
 748      if (this.R_A) {
 749        this.a *= 1. - this.es * (Proj4js.common.SIXTH + this.es * (Proj4js.common.RA4 + this.es * Proj4js.common.RA6));
 750        this.a2 = this.a * this.a;
 751        this.b2 = this.b * this.b;
 752        this.es = 0.;
 753      }
 754      this.ep2=(this.a2-this.b2)/this.b2; // used in geocentric
 755      if (!this.k0) this.k0 = 1.0;    //default value
 756
 757      this.datum = new Proj4js.datum(this);
 758  }
 759});
 760
 761Proj4js.Proj.longlat = {
 762  init: function() {
 763    //no-op for longlat
 764  },
 765  forward: function(pt) {
 766    //identity transform
 767    return pt;
 768  },
 769  inverse: function(pt) {
 770    //identity transform
 771    return pt;
 772  }
 773};
 774
 775/**
 776  Proj4js.defs is a collection of coordinate system definition objects in the 
 777  PROJ.4 command line format.
 778  Generally a def is added by means of a separate .js file for example:
 779
 780    <SCRIPT type="text/javascript" src="defs/EPSG26912.js"></SCRIPT>
 781
 782  def is a CS definition in PROJ.4 WKT format, for example:
 783    +proj="tmerc"   //longlat, etc.
 784    +a=majorRadius
 785    +b=minorRadius
 786    +lat0=somenumber
 787    +long=somenumber
 788*/
 789Proj4js.defs = {
 790  // These are so widely used, we'll go ahead and throw them in
 791  // without requiring a separate .js file
 792  'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees",
 793  'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees",
 794  'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees",
 795  'EPSG:3785': "+title= Google Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs"
 796};
 797Proj4js.defs['GOOGLE'] = Proj4js.defs['EPSG:3785'];
 798Proj4js.defs['EPSG:900913'] = Proj4js.defs['EPSG:3785'];
 799Proj4js.defs['EPSG:102113'] = Proj4js.defs['EPSG:3785'];
 800
 801Proj4js.common = {
 802  PI : 3.141592653589793238, //Math.PI,
 803  HALF_PI : 1.570796326794896619, //Math.PI*0.5,
 804  TWO_PI : 6.283185307179586477, //Math.PI*2,
 805  FORTPI : 0.78539816339744833,
 806  R2D : 57.29577951308232088,
 807  D2R : 0.01745329251994329577,
 808  SEC_TO_RAD : 4.84813681109535993589914102357e-6, /* SEC_TO_RAD = Pi/180/3600 */
 809  EPSLN : 1.0e-10,
 810  MAX_ITER : 20,
 811  // following constants from geocent.c
 812  COS_67P5 : 0.38268343236508977,  /* cosine of 67.5 degrees */
 813  AD_C : 1.0026000,                /* Toms region 1 constant */
 814
 815  /* datum_type values */
 816  PJD_UNKNOWN  : 0,
 817  PJD_3PARAM   : 1,
 818  PJD_7PARAM   : 2,
 819  PJD_GRIDSHIFT: 3,
 820  PJD_WGS84    : 4,   // WGS84 or equivalent
 821  PJD_NODATUM  : 5,   // WGS84 or equivalent
 822  SRS_WGS84_SEMIMAJOR : 6378137.0,  // only used in grid shift transforms
 823
 824  // ellipoid pj_set_ell.c
 825  SIXTH : .1666666666666666667, /* 1/6 */
 826  RA4   : .04722222222222222222, /* 17/360 */
 827  RA6   : .02215608465608465608, /* 67/3024 */
 828  RV4   : .06944444444444444444, /* 5/72 */
 829  RV6   : .04243827160493827160, /* 55/1296 */
 830
 831// Function to compute the constant small m which is the radius of
 832//   a parallel of latitude, phi, divided by the semimajor axis.
 833// -----------------------------------------------------------------
 834  msfnz : function(eccent, sinphi, cosphi) {
 835      var con = eccent * sinphi;
 836      return cosphi/(Math.sqrt(1.0 - con * con));
 837  },
 838
 839// Function to compute the constant small t for use in the forward
 840//   computations in the Lambert Conformal Conic and the Polar
 841//   Stereographic projections.
 842// -----------------------------------------------------------------
 843  tsfnz : function(eccent, phi, sinphi) {
 844    var con = eccent * sinphi;
 845    var com = .5 * eccent;
 846    con = Math.pow(((1.0 - con) / (1.0 + con)), com);
 847    return (Math.tan(.5 * (this.HALF_PI - phi))/con);
 848  },
 849
 850// Function to compute the latitude angle, phi2, for the inverse of the
 851//   Lambert Conformal Conic and Polar Stereographic projections.
 852// ----------------------------------------------------------------
 853  phi2z : function(eccent, ts) {
 854    var eccnth = .5 * eccent;
 855    var con, dphi;
 856    var phi = this.HALF_PI - 2 * Math.atan(ts);
 857    for (i = 0; i <= 15; i++) {
 858      con = eccent * Math.sin(phi);
 859      dphi = this.HALF_PI - 2 * Math.atan(ts *(Math.pow(((1.0 - con)/(1.0 + con)),eccnth))) - phi;
 860      phi += dphi;
 861      if (Math.abs(dphi) <= .0000000001) return phi;
 862    }
 863    alert("phi2z has NoConvergence");
 864    return (-9999);
 865  },
 866
 867/* Function to compute constant small q which is the radius of a 
 868   parallel of latitude, phi, divided by the semimajor axis. 
 869------------------------------------------------------------*/
 870  qsfnz : function(eccent,sinphi) {
 871    var con;
 872    if (eccent > 1.0e-7) {
 873      con = eccent * sinphi;
 874      return (( 1.0- eccent * eccent) * (sinphi /(1.0 - con * con) - (.5/eccent)*Math.log((1.0 - con)/(1.0 + con))));
 875    } else {
 876      return(2.0 * sinphi);
 877    }
 878  },
 879
 880/* Function to eliminate roundoff errors in asin
 881----------------------------------------------*/
 882  asinz : function(x) {
 883    if (Math.abs(x)>1.0) {
 884      x=(x>1.0)?1.0:-1.0;
 885    }
 886    return Math.asin(x);
 887  },
 888
 889// following functions from gctpc cproj.c for transverse mercator projections
 890  e0fn : function(x) {return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));},
 891  e1fn : function(x) {return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));},
 892  e2fn : function(x) {return(0.05859375*x*x*(1.0+0.75*x));},
 893  e3fn : function(x) {return(x*x*x*(35.0/3072.0));},
 894  mlfn : function(e0,e1,e2,e3,phi) {return(e0*phi-e1*Math.sin(2.0*phi)+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi));},
 895
 896  srat : function(esinp, exp) {
 897    return(Math.pow((1.0-esinp)/(1.0+esinp), exp));
 898  },
 899
 900// Function to return the sign of an argument
 901  sign : function(x) { if (x < 0.0) return(-1); else return(1);},
 902
 903// Function to adjust longitude to -180 to 180; input in radians
 904  adjust_lon : function(x) {
 905    x = (Math.abs(x) < this.PI) ? x: (x - (this.sign(x)*this.TWO_PI) );
 906    return x;
 907  },
 908
 909// IGNF - DGR : algorithms used by IGN France
 910
 911// Function to adjust latitude to -90 to 90; input in radians
 912  adjust_lat : function(x) {
 913    x= (Math.abs(x) < this.HALF_PI) ? x: (x - (this.sign(x)*this.PI) );
 914    return x;
 915  },
 916
 917// Latitude Isometrique - close to tsfnz ...
 918  latiso : function(eccent, phi, sinphi) {
 919    if (Math.abs(phi) > this.HALF_PI) return +Number.NaN;
 920    if (phi==this.HALF_PI) return Number.POSITIVE_INFINITY;
 921    if (phi==-1.0*this.HALF_PI) return -1.0*Number.POSITIVE_INFINITY;
 922
 923    var con= eccent*sinphi;
 924    return Math.log(Math.tan((this.HALF_PI+phi)/2.0))+eccent*Math.log((1.0-con)/(1.0+con))/2.0;
 925  },
 926
 927  fL : function(x,L) {
 928    return 2.0*Math.atan(x*Math.exp(L)) - this.HALF_PI;
 929  },
 930
 931// Inverse Latitude Isometrique - close to ph2z
 932  invlatiso : function(eccent, ts) {
 933    var phi= this.fL(1.0,ts);
 934    var Iphi= 0.0;
 935    var con= 0.0;
 936    do {
 937      Iphi= phi;
 938      con= eccent*Math.sin(Iphi);
 939      phi= this.fL(Math.exp(eccent*Math.log((1.0+con)/(1.0-con))/2.0),ts)
 940    } while (Math.abs(phi-Iphi)>1.0e-12);
 941    return phi;
 942  },
 943
 944// Needed for Gauss Schreiber
 945// Original:  Denis Makarov (info@binarythings.com)
 946// Web Site:  http://www.binarythings.com
 947  sinh : function(x)
 948  {
 949    var r= Math.exp(x);
 950    r= (r-1.0/r)/2.0;
 951    return r;
 952  },
 953
 954  cosh : function(x)
 955  {
 956    var r= Math.exp(x);
 957    r= (r+1.0/r)/2.0;
 958    return r;
 959  },
 960
 961  tanh : function(x)
 962  {
 963    var r= Math.exp(x);
 964    r= (r-1.0/r)/(r+1.0/r);
 965    return r;
 966  },
 967
 968  asinh : function(x)
 969  {
 970    var s= (x>= 0? 1.0:-1.0);
 971    return s*(Math.log( Math.abs(x) + Math.sqrt(x*x+1.0) ));
 972  },
 973
 974  acosh : function(x)
 975  {
 976    return 2.0*Math.log(Math.sqrt((x+1.0)/2.0) + Math.sqrt((x-1.0)/2.0));
 977  },
 978
 979  atanh : function(x)
 980  {
 981    return Math.log((x-1.0)/(x+1.0))/2.0;
 982  },
 983
 984// Grande Normale
 985  gN : function(a,e,sinphi)
 986  {
 987    var temp= e*sinphi;
 988    return a/Math.sqrt(1.0 - temp*temp);
 989  }
 990
 991};
 992
 993/** datum object
 994*/
 995Proj4js.datum = Proj4js.Class({
 996
 997  initialize : function(proj) {
 998    this.datum_type = Proj4js.common.PJD_WGS84;   //default setting
 999    if (proj.datumCode && proj.datumCode == 'none') {
1000      this.datum_type = Proj4js.common.PJD_NODATUM;
1001    }
1002    if (proj && proj.datum_params) {
1003      for (var i=0; i<proj.datum_params.length; i++) {
1004        proj.datum_params[i]=parseFloat(proj.datum_params[i]);
1005      }
1006      if (proj.datum_params[0] != 0 || proj.datum_params[1] != 0 || proj.datum_params[2] != 0 ) {
1007        this.datum_type = Proj4js.common.PJD_3PARAM;
1008      }
1009      if (proj.datum_params.length > 3) {
1010        if (proj.datum_params[3] != 0 || proj.datum_params[4] != 0 ||
1011            proj.datum_params[5] != 0 || proj.datum_params[6] != 0 ) {
1012          this.datum_type = Proj4js.common.PJD_7PARAM;
1013          proj.datum_params[3] *= Proj4js.common.SEC_TO_RAD;
1014          proj.datum_params[4] *= Proj4js.common.SEC_TO_RAD;
1015          proj.datum_params[5] *= Proj4js.common.SEC_TO_RAD;
1016          proj.datum_params[6] = (proj.datum_params[6]/1000000.0) + 1.0;
1017        }
1018      }
1019    }
1020    if (proj) {
1021      this.a = proj.a;    //datum object also uses these values
1022      this.b = proj.b;
1023      this.es = proj.es;
1024      this.ep2 = proj.ep2;
1025      this.datum_params = proj.datum_params;
1026    }
1027  },
1028
1029  /****************************************************************/
1030  // cs_compare_datums()
1031  //   Returns 1 (TRUE) if the two datums match, otherwise 0 (FALSE).
1032  compare_datums : function( dest ) {
1033    if( this.datum_type != dest.datum_type ) {
1034      return false; // false, datums are not equal
1035    } else if( this.a != dest.a || Math.abs(this.es-dest.es) > 0.000000000050 ) {
1036      // the tolerence for es is to ensure that GRS80 and WGS84
1037      // are considered identical
1038      return false;
1039    } else if( this.datum_type == Proj4js.common.PJD_3PARAM ) {
1040      return (this.datum_params[0] == dest.datum_params[0]
1041              && this.datum_params[1] == dest.datum_params[1]
1042              && this.datum_params[2] == dest.datum_params[2]);
1043    } else if( this.datum_type == Proj4js.common.PJD_7PARAM ) {
1044      return (this.datum_params[0] == dest.datum_params[0]
1045              && this.datum_params[1] == dest.datum_params[1]
1046              && this.datum_params[2] == dest.datum_params[2]
1047              && this.datum_params[3] == dest.datum_params[3]
1048              && this.datum_params[4] == dest.datum_params[4]
1049              && this.datum_params[5] == dest.datum_params[5]
1050              && this.datum_params[6] == dest.datum_params[6]);
1051    } else if( this.datum_type == Proj4js.common.PJD_GRIDSHIFT ) {
1052      return strcmp( pj_param(this.params,"snadgrids").s,
1053                     pj_param(dest.params,"snadgrids").s ) == 0;
1054    } else {
1055      return true; // datums are equal
1056    }
1057  }, // cs_compare_datums()
1058
1059  /*
1060   * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
1061   * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
1062   * according to the current ellipsoid parameters.
1063   *
1064   *    Latitude  : Geodetic latitude in radians                     (input)
1065   *    Longitude : Geodetic longitude in radians                    (input)
1066   *    Height    : Geodetic height, in meters                       (input)
1067   *    X         : Calculated Geocentric X coordinate, in meters    (output)
1068   *    Y         : Calculated Geocentric Y coordinate, in meters    (output)
1069   *    Z         : Calculated Geocentric Z coordinate, in meters    (output)
1070   *
1071   */
1072  geodetic_to_geocentric : function(p) {
1073    var Longitude = p.x;
1074    var Latitude = p.y;
1075    var Height = p.z ? p.z : 0;   //Z value not always supplied
1076    var X;  // output
1077    var Y;
1078    var Z;
1079
1080    var Error_Code=0;  //  GEOCENT_NO_ERROR;
1081    var Rn;            /*  Earth radius at location  */
1082    var Sin_Lat;       /*  Math.sin(Latitude)  */
1083    var Sin2_Lat;      /*  Square of Math.sin(Latitude)  */
1084    var Cos_Lat;       /*  Math.cos(Latitude)  */
1085
1086    /*
1087    ** Don't blow up if Latitude is just a little out of the value
1088    ** range as it may just be a rounding issue.  Also removed longitude
1089    ** test, it should be wrapped by Math.cos() and Math.sin().  NFW for PROJ.4, Sep/2001.
1090    */
1091    if( Latitude < -Proj4js.common.HALF_PI && Latitude > -1.001 * Proj4js.common.HALF_PI ) {
1092        Latitude = -Proj4js.common.HALF_PI;
1093    } else if( Latitude > Proj4js.common.HALF_PI && Latitude < 1.001 * Proj4js.common.HALF_PI ) {
1094        Latitude = Proj4js.common.HALF_PI;
1095    } else if ((Latitude < -Proj4js.common.HALF_PI) || (Latitude > Proj4js.common.HALF_PI)) {
1096      /* Latitude out of range */
1097      Proj4js.reportError('geocent:lat out of range:'+Latitude);
1098      return null;
1099    }
1100
1101    if (Longitude > Proj4js.common.PI) Longitude -= (2*Proj4js.common.PI);
1102    Sin_Lat = Math.sin(Latitude);
1103    Cos_Lat = Math.cos(Latitude);
1104    Sin2_Lat = Sin_Lat * Sin_Lat;
1105    Rn = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat));
1106    X = (Rn + Height) * Cos_Lat * Math.cos(Longitude);
1107    Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude);
1108    Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat;
1109
1110    p.x = X;
1111    p.y = Y;
1112    p.z = Z;
1113    return Error_Code;
1114  }, // cs_geodetic_to_geocentric()
1115
1116
1117  geocentric_to_geodetic : function (p) {
1118/* local defintions and variables */
1119/* end-criterium of loop, accuracy of sin(Latitude) */
1120var genau = 1.E-12;
1121var genau2 = (genau*genau);
1122var maxiter = 30;
1123
1124    var P;        /* distance between semi-minor axis and location */
1125    var RR;       /* distance between center and location */
1126    var CT;       /* sin of geocentric latitude */
1127    var ST;       /* cos of geocentric latitude */
1128    var RX;
1129    var RK;
1130    var RN;       /* Earth radius at location */
1131    var CPHI0;    /* cos of start or old geodetic latitude in iterations */
1132    var SPHI0;    /* sin of start or old geodetic latitude in iterations */
1133    var CPHI;     /* cos of searched geodetic latitude */
1134    var SPHI;     /* sin of searched geodetic latitude */
1135    var SDPHI;    /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
1136    var At_Pole;     /* indicates location is in polar region */
1137    var iter;        /* # of continous iteration, max. 30 is always enough (s.a.) */
1138
1139    var X = p.x;
1140    var Y = p.y;
1141    var Z = p.z ? p.z : 0.0;   //Z value not always supplied
1142    var Longitude;
1143    var Latitude;
1144    var Height;
1145
1146    At_Pole = false;
1147    P = Math.sqrt(X*X+Y*Y);
1148    RR = Math.sqrt(X*X+Y*Y+Z*Z);
1149
1150/*      special cases for latitude and longitude */
1151    if (P/this.a < genau) {
1152
1153/*  special case, if P=0. (X=0., Y=0.) */
1154        At_Pole = true;
1155        Longitude = 0.0;
1156
1157/*  if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
1158 *  of ellipsoid (=center of mass), Latitude becomes PI/2 */
1159        if (RR/this.a < genau) {
1160            Latitude = Proj4js.common.HALF_PI;
1161            Height   = -this.b;
1162            return;
1163        }
1164    } else {
1165/*  ellipsoidal (geodetic) longitude
1166 *  interval: -PI < Longitude <= +PI */
1167        Longitude=Math.atan2(Y,X);
1168    }
1169
1170/* --------------------------------------------------------------
1171 * Following iterative algorithm was developped by
1172 * "Institut für Erdmessung", University of Hannover, July 1988.
1173 * Internet: www.ife.uni-hannover.de
1174 * Iterative computation of CPHI,SPHI and Height.
1175 * Iteration of CPHI and SPHI to 10**-12 radian resp.
1176 * 2*10**-7 arcsec.
1177 * --------------------------------------------------------------
1178 */
1179    CT = Z/RR;
1180    ST = P/RR;
1181    RX = 1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST);
1182    CPHI0 = ST*(1.0-this.es)*RX;
1183    SPHI0 = CT*RX;
1184    iter = 0;
1185
1186/* loop to find sin(Latitude) resp. Latitude
1187 * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
1188    do
1189    {
1190        iter++;
1191        RN = this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0);
1192
1193/*  ellipsoidal (geodetic) height */
1194        Height = P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0);
1195
1196        RK = this.es*RN/(RN+Height);
1197        RX = 1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST);
1198        CPHI = ST*(1.0-RK)*RX;
1199        SPHI = CT*RX;
1200        SDPHI = SPHI*CPHI0-CPHI*SPHI0;
1201        CPHI0 = CPHI;
1202        SPHI0 = SPHI;
1203    }
1204    while (SDPHI*SDPHI > genau2 && iter < maxiter);
1205
1206/*      ellipsoidal (geodetic) latitude */
1207    Latitude=Math.atan(SPHI/Math.abs(CPHI));
1208
1209    p.x = Longitude;
1210    p.y = Latitude;
1211    p.z = Height;
1212    return p;
1213  }, // cs_geocentric_to_geodetic()
1214
1215  /** Convert_Geocentric_To_Geodetic
1216   * The method used here is derived from 'An Improved Algorithm for
1217   * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
1218   */
1219  geocentric_to_geodetic_noniter : function (p) {
1220    var X = p.x;
1221    var Y = p.y;
1222    var Z = p.z ? p.z : 0;   //Z value not always supplied
1223    var Longitude;
1224    var Latitude;
1225    var Height;
1226
1227    var W;        /* distance from Z axis */
1228    var W2;       /* square of distance from Z axis */
1229    var T0;       /* initial estimate of vertical component */
1230    var T1;       /* corrected estimate of vertical component */
1231    var S0;       /* initial estimate of horizontal component */
1232    var S1;       /* corrected estimate of horizontal component */
1233    var Sin_B0;   /* Math.sin(B0), B0 is estimate of Bowring aux variable */
1234    var Sin3_B0;  /* cube of Math.sin(B0) */
1235    var Cos_B0;   /* Math.cos(B0) */
1236    var Sin_p1;   /* Math.sin(phi1), phi1 is estimated latitude */
1237    var Cos_p1;   /* Math.cos(phi1) */
1238    var Rn;       /* Earth radius at location */
1239    var Sum;      /* numerator of Math.cos(phi1) */
1240    var At_Pole;  /* indicates location is in polar region */
1241
1242    X = parseFloat(X);  // cast from string to float
1243    Y = parseFloat(Y);
1244    Z = parseFloat(Z);
1245
1246    At_Pole = false;
1247    if (X != 0.0)
1248    {
1249        Longitude = Math.atan2(Y,X);
1250    }
1251    else
1252    {
1253        if (Y > 0)
1254        {
1255            Longitude = Proj4js.common.HALF_PI;
1256        }
1257        else if (Y < 0)
1258        {
1259            Longitude = -Proj4js.common.HALF_PI;
1260        }
1261        else
1262        {
1263            At_Pole = true;
1264            Longitude = 0.0;
1265            if (Z > 0.0)
1266            {  /* north pole */
1267                Latitude = Proj4js.common.HALF_PI;
1268            }
1269            else if (Z < 0.0)
1270            {  /* south pole */
1271                Latitude = -Proj4js.common.HALF_PI;
1272            }
1273            else
1274            {  /* center of earth */
1275                Latitude = Proj4js.common.HALF_PI;
1276                Height = -this.b;
1277                return;
1278            }
1279        }
1280    }
1281    W2 = X*X + Y*Y;
1282    W = Math.sqrt(W2);
1283    T0 = Z * Proj4js.common.AD_C;
1284    S0 = Math.sqrt(T0 * T0 + W2);
1285    Sin_B0 = T0 / S0;
1286    Cos_B0 = W / S0;
1287    Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
1288    T1 = Z + this.b * this.ep2 * Sin3_B0;
1289    Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0;
1290    S1 = Math.sqrt(T1*T1 + Sum * Sum);
1291    Sin_p1 = T1 / S1;
1292    Cos_p1 = Sum / S1;
1293    Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1);
1294    if (Cos_p1 >= Proj4js.common.COS_67P5)
1295    {
1296        Height = W / Cos_p1 - Rn;
1297    }
1298    else if (Cos_p1 <= -Proj4js.common.COS_67P5)
1299    {
1300        Height = W / -Cos_p1 - Rn;
1301    }
1302    else
1303    {
1304        Height = Z / Sin_p1 + Rn * (this.es - 1.0);
1305    }
1306    if (At_Pole == false)
1307    {
1308        Latitude = Math.atan(Sin_p1 / Cos_p1);
1309    }
1310
1311    p.x = Longitude;
1312    p.y = Latitude;
1313    p.z = Height;
1314    return p;
1315  }, // geocentric_to_geodetic_noniter()
1316
1317  /****************************************************************/
1318  // pj_geocentic_to_wgs84( p )
1319  //  p = point to transform in geocentric coordinates (x,y,z)
1320  geocentric_to_wgs84 : function ( p ) {
1321
1322    if( this.datum_type == Proj4js.common.PJD_3PARAM )
1323    {
1324      // if( x[io] == HUGE_VAL )
1325      //    continue;
1326      p.x += this.datum_params[0];
1327      p.y += this.datum_params[1];
1328      p.z += this.datum_params[2];
1329
1330    }
1331    else if (this.datum_type == Proj4js.common.PJD_7PARAM)
1332    {
1333      var Dx_BF =this.datum_params[0];
1334      var Dy_BF =this.datum_params[1];
1335      var Dz_BF =this.datum_params[2];
1336      var Rx_BF =this.datum_params[3];
1337      var Ry_BF =this.datum_params[4];
1338      var Rz_BF =this.datum_params[5];
1339      var M_BF  =this.datum_params[6];
1340      // if( x[io] == HUGE_VAL )
1341      //    continue;
1342      var x_out = M_BF*(       p.x - Rz_BF*p.y + Ry_BF*p.z) + Dx_BF;
1343      var y_out = M_BF*( Rz_BF*p.x +       p.y - Rx_BF*p.z) + Dy_BF;
1344      var z_out = M_BF*(-Ry_BF*p.x + Rx_BF*p.y +       p.z) + Dz_BF;
1345      p.x = x_out;
1346      p.y = y_out;
1347      p.z = z_out;
1348    }
1349  }, // cs_geocentric_to_wgs84
1350
1351  /****************************************************************/
1352  // pj_geocentic_from_wgs84()
1353  //  coordinate system definition,
1354  //  point to transform in geocentric coordinates (x,y,z)
1355  geocentric_from_wgs84 : function( p ) {
1356
1357    if( this.datum_type == Proj4js.common.PJD_3PARAM )
1358    {
1359      //if( x[io] == HUGE_VAL )
1360      //    continue;
1361      p.x -= this.datum_params[0];
1362      p.y -= this.datum_params[1];
1363      p.z -= this.datum_params[2];
1364
1365    }
1366    else if (this.datum_type == Proj4js.common.PJD_7PARAM)
1367    {
1368      var Dx_BF =this.datum_params[0];
1369      var Dy_BF =this.datum_params[1];
1370      var Dz_BF =this.datum_params[2];
1371      var Rx_BF =this.datum_params[3];
1372      var Ry_BF =this.datum_params[4];
1373      var Rz_BF =this.datum_params[5];
1374      var M_BF  =this.datum_params[6];
1375      var x_tmp = (p.x - Dx_BF) / M_BF;
1376      var y_tmp = (p.y - Dy_BF) / M_BF;
1377      var z_tmp = (p.z - Dz_BF) / M_BF;
1378      //if( x[io] == HUGE_VAL )
1379      //    continue;
1380
1381      p.x =        x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp;
1382      p.y = -Rz_BF*x_tmp +       y_tmp + Rx_BF*z_tmp;
1383      p.z =  Ry_BF*x_tmp - Rx_BF*y_tmp +       z_tmp;
1384    } //cs_geocentric_from_wgs84()
1385  }
1386});
1387
1388/** point object, nothing fancy, just allows values to be
1389    passed back and forth by reference rather than by value.
1390    Other point classes may be used as long as they have
1391    x and y properties, which will get modified in the transform method.
1392*/
1393Proj4js.Point = Proj4js.Class({
1394
1395    /**
1396     * Constructor: Proj4js.Point
1397     *
1398     * Parameters:
1399     * - x {float} or {Array} either the first coordinates component or
1400     *     the full coordinates
1401     * - y {float} the second component
1402     * - z {float} the third component, optional.
1403     */
1404    initialize : function(x,y,z) {
1405      if (typeof x == 'object') {
1406        this.x = x[0];
1407        this.y = x[1];
1408        this.z = x[2] || 0.0;
1409      } else if (typeof x == 'string') {
1410        var coords = x.split(',');
1411        this.x = parseFloat(coords[0]);
1412        this.y = parseFloat(coords[1]);
1413        this.z = parseFloat(coords[2]) || 0.0;
1414      } else {
1415        this.x = x;
1416        this.y = y;
1417        this.z = z || 0.0;
1418      }
1419    },
1420
1421    /**
1422     * APIMethod: clone
1423     * Build a copy of a Proj4js.Point object.
1424     *
1425     * Return:
1426     * {Proj4js}.Point the cloned point.
1427     */
1428    clone : function() {
1429      return new Proj4js.Point(this.x, this.y, this.z);
1430    },
1431
1432    /**
1433     * APIMethod: toString
1434     * Return a readable string version of the point
1435     *
1436     * Return:
1437     * {String} String representation of Proj4js.Point object. 
1438     *           (ex. <i>"x=5,y=42"</i>)
1439     */
1440    toString : function() {
1441        return ("x=" + this.x + ",y=" + this.y);
1442    },
1443
1444    /** 
1445     * APIMethod: toShortString
1446     * Return a short string version of the point.
1447     *
1448     * Return:
1449     * {String} Shortened String representation of Proj4js.Point object. 
1450     *         (ex. <i>"5, 42"</i>)
1451     */
1452    toShortString : function() {
1453        return (this.x + ", " + this.y);
1454    }
1455});
1456
1457Proj4js.PrimeMeridian = {
1458    "greenwich": 0.0,               //"0dE",
1459    "lisbon":     -9.131906111111,   //"9d07'54.862\"W",
1460    "paris":       2.337229166667,   //"2d20'14.025\"E"…

Large files files are truncated, but you can click here to view the full file