mirror of
				https://github.com/jiawanlong/Cesium-Examples.git
				synced 2025-11-04 09:14:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1817 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			1817 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/*
 | 
						||
Author:       Mike Adair madairATdmsolutions.ca
 | 
						||
              Richard Greenwood rich@greenwoodmap.com
 | 
						||
License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html
 | 
						||
 | 
						||
$Id: Proj.js 2956 2007-07-09 12:17:52Z steven $
 | 
						||
*/
 | 
						||
 | 
						||
/**
 | 
						||
 * Namespace: Proj4js
 | 
						||
 *
 | 
						||
 * Proj4js is a JavaScript library to transform point coordinates from one 
 | 
						||
 * coordinate system to another, including datum transformations.
 | 
						||
 *
 | 
						||
 * This library is a port of both the Proj.4 and GCTCP C libraries to JavaScript. 
 | 
						||
 * Enabling these transformations in the browser allows geographic data stored 
 | 
						||
 * in different projections to be combined in browser-based web mapping 
 | 
						||
 * applications.
 | 
						||
 * 
 | 
						||
 * Proj4js must have access to coordinate system initialization strings (which
 | 
						||
 * are the same as for PROJ.4 command line).  Thes can be included in your 
 | 
						||
 * application using a <script> tag or Proj4js can load CS initialization 
 | 
						||
 * strings from a local directory or a web service such as spatialreference.org.
 | 
						||
 *
 | 
						||
 * Similarly, Proj4js must have access to projection transform code.  These can
 | 
						||
 * be included individually using a <script> tag in your page, built into a 
 | 
						||
 * custom build of Proj4js or loaded dynamically at run-time.  Using the
 | 
						||
 * -combined and -compressed versions of Proj4js includes all projection class
 | 
						||
 * code by default.
 | 
						||
 *
 | 
						||
 * Note that dynamic loading of defs and code happens ascynchrously, check the
 | 
						||
 * Proj.readyToUse flag before using the Proj object.  If the defs and code
 | 
						||
 * required by your application are loaded through script tags, dynamic loading
 | 
						||
 * is not required and the Proj object will be readyToUse on return from the 
 | 
						||
 * constructor.
 | 
						||
 * 
 | 
						||
 * All coordinates are handled as points which have a .x and a .y property
 | 
						||
 * which will be modified in place.
 | 
						||
 *
 | 
						||
 * Override Proj4js.reportError for output of alerts and warnings.
 | 
						||
 *
 | 
						||
 * See http://trac.osgeo.org/proj4js/wiki/UserGuide for full details.
 | 
						||
*/
 | 
						||
 | 
						||
/**
 | 
						||
 * Global namespace object for Proj4js library
 | 
						||
 */
 | 
						||
var Proj4js = {
 | 
						||
 | 
						||
    /**
 | 
						||
     * Property: defaultDatum
 | 
						||
     * The datum to use when no others a specified
 | 
						||
     */
 | 
						||
    defaultDatum: 'WGS84',                  //default datum
 | 
						||
 | 
						||
    /** 
 | 
						||
    * Method: transform(source, dest, point)
 | 
						||
    * Transform a point coordinate from one map projection to another.  This is
 | 
						||
    * really the only public method you should need to use.
 | 
						||
    *
 | 
						||
    * Parameters:
 | 
						||
    * source - {Proj4js.Proj} source map projection for the transformation
 | 
						||
    * dest - {Proj4js.Proj} destination map projection for the transformation
 | 
						||
    * point - {Object} point to transform, may be geodetic (long, lat) or
 | 
						||
    *     projected Cartesian (x,y), but should always have x,y properties.
 | 
						||
    */
 | 
						||
    transform: function(source, dest, point) {
 | 
						||
        if (!source.readyToUse) {
 | 
						||
            this.reportError("Proj4js initialization for:"+source.srsCode+" not yet complete");
 | 
						||
            return point;
 | 
						||
        }
 | 
						||
        if (!dest.readyToUse) {
 | 
						||
            this.reportError("Proj4js initialization for:"+dest.srsCode+" not yet complete");
 | 
						||
            return point;
 | 
						||
        }
 | 
						||
        
 | 
						||
        // Workaround for datum shifts towgs84, if either source or destination projection is not wgs84
 | 
						||
        if (source.datum && dest.datum && (
 | 
						||
            ((source.datum.datum_type == Proj4js.common.PJD_3PARAM || source.datum.datum_type == Proj4js.common.PJD_7PARAM) && dest.datumCode != "WGS84") ||
 | 
						||
            ((dest.datum.datum_type == Proj4js.common.PJD_3PARAM || dest.datum.datum_type == Proj4js.common.PJD_7PARAM) && source.datumCode != "WGS84"))) {
 | 
						||
            var wgs84 = Proj4js.WGS84;
 | 
						||
            this.transform(source, wgs84, point);
 | 
						||
            source = wgs84;
 | 
						||
        }
 | 
						||
 | 
						||
        // DGR, 2010/11/12
 | 
						||
        if (source.axis!="enu") {
 | 
						||
            this.adjust_axis(source,false,point);
 | 
						||
        }
 | 
						||
 | 
						||
        // Transform source points to long/lat, if they aren't already.
 | 
						||
        if ( source.projName=="longlat") {
 | 
						||
            point.x *= Proj4js.common.D2R;  // convert degrees to radians
 | 
						||
            point.y *= Proj4js.common.D2R;
 | 
						||
        } else {
 | 
						||
            if (source.to_meter) {
 | 
						||
                point.x *= source.to_meter;
 | 
						||
                point.y *= source.to_meter;
 | 
						||
            }
 | 
						||
            source.inverse(point); // Convert Cartesian to longlat
 | 
						||
        }
 | 
						||
 | 
						||
        // Adjust for the prime meridian if necessary
 | 
						||
        if (source.from_greenwich) { 
 | 
						||
            point.x += source.from_greenwich; 
 | 
						||
        }
 | 
						||
 | 
						||
        // Convert datums if needed, and if possible.
 | 
						||
        point = this.datum_transform( source.datum, dest.datum, point );
 | 
						||
 | 
						||
        // Adjust for the prime meridian if necessary
 | 
						||
        if (dest.from_greenwich) {
 | 
						||
            point.x -= dest.from_greenwich;
 | 
						||
        }
 | 
						||
 | 
						||
        if( dest.projName=="longlat" ) {             
 | 
						||
            // convert radians to decimal degrees
 | 
						||
            point.x *= Proj4js.common.R2D;
 | 
						||
            point.y *= Proj4js.common.R2D;
 | 
						||
        } else  {               // else project
 | 
						||
            dest.forward(point);
 | 
						||
            if (dest.to_meter) {
 | 
						||
                point.x /= dest.to_meter;
 | 
						||
                point.y /= dest.to_meter;
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        // DGR, 2010/11/12
 | 
						||
        if (dest.axis!="enu") {
 | 
						||
            this.adjust_axis(dest,true,point);
 | 
						||
        }
 | 
						||
 | 
						||
        return point;
 | 
						||
    }, // transform()
 | 
						||
 | 
						||
    /** datum_transform()
 | 
						||
      source coordinate system definition,
 | 
						||
      destination coordinate system definition,
 | 
						||
      point to transform in geodetic coordinates (long, lat, height)
 | 
						||
    */
 | 
						||
    datum_transform : function( source, dest, point ) {
 | 
						||
 | 
						||
      // Short cut if the datums are identical.
 | 
						||
      if( source.compare_datums( dest ) ) {
 | 
						||
          return point; // in this case, zero is sucess,
 | 
						||
                    // whereas cs_compare_datums returns 1 to indicate TRUE
 | 
						||
                    // confusing, should fix this
 | 
						||
      }
 | 
						||
 | 
						||
      // Explicitly skip datum transform by setting 'datum=none' as parameter for either source or dest
 | 
						||
      if( source.datum_type == Proj4js.common.PJD_NODATUM
 | 
						||
          || dest.datum_type == Proj4js.common.PJD_NODATUM) {
 | 
						||
          return point;
 | 
						||
      }
 | 
						||
 | 
						||
      // Do we need to go through geocentric coordinates?
 | 
						||
      if( source.es != dest.es || source.a != dest.a
 | 
						||
          || source.datum_type == Proj4js.common.PJD_3PARAM
 | 
						||
          || source.datum_type == Proj4js.common.PJD_7PARAM
 | 
						||
          || dest.datum_type == Proj4js.common.PJD_3PARAM
 | 
						||
          || dest.datum_type == Proj4js.common.PJD_7PARAM)
 | 
						||
      {
 | 
						||
 | 
						||
        // Convert to geocentric coordinates.
 | 
						||
        source.geodetic_to_geocentric( point );
 | 
						||
        // CHECK_RETURN;
 | 
						||
 | 
						||
        // Convert between datums
 | 
						||
        if( source.datum_type == Proj4js.common.PJD_3PARAM || source.datum_type == Proj4js.common.PJD_7PARAM ) {
 | 
						||
          source.geocentric_to_wgs84(point);
 | 
						||
          // CHECK_RETURN;
 | 
						||
        }
 | 
						||
 | 
						||
        if( dest.datum_type == Proj4js.common.PJD_3PARAM || dest.datum_type == Proj4js.common.PJD_7PARAM ) {
 | 
						||
          dest.geocentric_from_wgs84(point);
 | 
						||
          // CHECK_RETURN;
 | 
						||
        }
 | 
						||
 | 
						||
        // Convert back to geodetic coordinates
 | 
						||
        dest.geocentric_to_geodetic( point );
 | 
						||
          // CHECK_RETURN;
 | 
						||
      }
 | 
						||
 | 
						||
      return point;
 | 
						||
    }, // cs_datum_transform
 | 
						||
 | 
						||
    /**
 | 
						||
     * Function: adjust_axis
 | 
						||
     * Normalize or de-normalized the x/y/z axes.  The normal form is "enu"
 | 
						||
     * (easting, northing, up).
 | 
						||
     * Parameters:
 | 
						||
     * crs {Proj4js.Proj} the coordinate reference system
 | 
						||
     * denorm {Boolean} when false, normalize
 | 
						||
     * point {Object} the coordinates to adjust
 | 
						||
     */
 | 
						||
    adjust_axis: function(crs, denorm, point) {
 | 
						||
        var xin= point.x, yin= point.y, zin= point.z || 0.0;
 | 
						||
        var v, t;
 | 
						||
        for (var i= 0; i<3; i++) {
 | 
						||
            if (denorm && i==2 && point.z===undefined) { continue; }
 | 
						||
                 if (i==0) { v= xin; t= 'x'; }
 | 
						||
            else if (i==1) { v= yin; t= 'y'; }
 | 
						||
            else           { v= zin; t= 'z'; }
 | 
						||
            switch(crs.axis[i]) {
 | 
						||
            case 'e':
 | 
						||
                point[t]= v;
 | 
						||
                break;
 | 
						||
            case 'w':
 | 
						||
                point[t]= -v;
 | 
						||
                break;
 | 
						||
            case 'n':
 | 
						||
                point[t]= v;
 | 
						||
                break;
 | 
						||
            case 's':
 | 
						||
                point[t]= -v;
 | 
						||
                break;
 | 
						||
            case 'u':
 | 
						||
                if (point[t]!==undefined) { point.z= v; }
 | 
						||
                break;
 | 
						||
            case 'd':
 | 
						||
                if (point[t]!==undefined) { point.z= -v; }
 | 
						||
                break;
 | 
						||
            default :
 | 
						||
                alert("ERROR: unknow axis ("+crs.axis[i]+") - check definition of "+crs.projName);
 | 
						||
                return null;
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return point;
 | 
						||
    },
 | 
						||
 | 
						||
    /**
 | 
						||
     * Function: reportError
 | 
						||
     * An internal method to report errors back to user. 
 | 
						||
     * Override this in applications to report error messages or throw exceptions.
 | 
						||
     */
 | 
						||
    reportError: function(msg) {
 | 
						||
      //console.log(msg);
 | 
						||
    },
 | 
						||
 | 
						||
/**
 | 
						||
 *
 | 
						||
 * Title: Private Methods
 | 
						||
 * The following properties and methods are intended for internal use only.
 | 
						||
 *
 | 
						||
 * This is a minimal implementation of JavaScript inheritance methods so that 
 | 
						||
 * Proj4js can be used as a stand-alone library.
 | 
						||
 * These are copies of the equivalent OpenLayers methods at v2.7
 | 
						||
 */
 | 
						||
 
 | 
						||
/**
 | 
						||
 * Function: extend
 | 
						||
 * Copy all properties of a source object to a destination object.  Modifies
 | 
						||
 *     the passed in destination object.  Any properties on the source object
 | 
						||
 *     that are set to undefined will not be (re)set on the destination object.
 | 
						||
 *
 | 
						||
 * Parameters:
 | 
						||
 * destination - {Object} The object that will be modified
 | 
						||
 * source - {Object} The object with properties to be set on the destination
 | 
						||
 *
 | 
						||
 * Returns:
 | 
						||
 * {Object} The destination object.
 | 
						||
 */
 | 
						||
    extend: function(destination, source) {
 | 
						||
      destination = destination || {};
 | 
						||
      if(source) {
 | 
						||
          for(var property in source) {
 | 
						||
              var value = source[property];
 | 
						||
              if(value !== undefined) {
 | 
						||
                  destination[property] = value;
 | 
						||
              }
 | 
						||
          }
 | 
						||
      }
 | 
						||
      return destination;
 | 
						||
    },
 | 
						||
 | 
						||
/**
 | 
						||
 * Constructor: Class
 | 
						||
 * Base class used to construct all other classes. Includes support for 
 | 
						||
 *     multiple inheritance. 
 | 
						||
 *  
 | 
						||
 */
 | 
						||
    Class: function() {
 | 
						||
      var Class = function() {
 | 
						||
          this.initialize.apply(this, arguments);
 | 
						||
      };
 | 
						||
  
 | 
						||
      var extended = {};
 | 
						||
      var parent;
 | 
						||
      for(var i=0; i<arguments.length; ++i) {
 | 
						||
          if(typeof arguments[i] == "function") {
 | 
						||
              // get the prototype of the superclass
 | 
						||
              parent = arguments[i].prototype;
 | 
						||
          } else {
 | 
						||
              // in this case we're extending with the prototype
 | 
						||
              parent = arguments[i];
 | 
						||
          }
 | 
						||
          Proj4js.extend(extended, parent);
 | 
						||
      }
 | 
						||
      Class.prototype = extended;
 | 
						||
      
 | 
						||
      return Class;
 | 
						||
    },
 | 
						||
 | 
						||
    /**
 | 
						||
     * Function: bind
 | 
						||
     * Bind a function to an object.  Method to easily create closures with
 | 
						||
     *     'this' altered.
 | 
						||
     * 
 | 
						||
     * Parameters:
 | 
						||
     * func - {Function} Input function.
 | 
						||
     * object - {Object} The object to bind to the input function (as this).
 | 
						||
     * 
 | 
						||
     * Returns:
 | 
						||
     * {Function} A closure with 'this' set to the passed in object.
 | 
						||
     */
 | 
						||
    bind: function(func, object) {
 | 
						||
        // create a reference to all arguments past the second one
 | 
						||
        var args = Array.prototype.slice.apply(arguments, [2]);
 | 
						||
        return function() {
 | 
						||
            // Push on any additional arguments from the actual function call.
 | 
						||
            // These will come after those sent to the bind call.
 | 
						||
            var newArgs = args.concat(
 | 
						||
                Array.prototype.slice.apply(arguments, [0])
 | 
						||
            );
 | 
						||
            return func.apply(object, newArgs);
 | 
						||
        };
 | 
						||
    },
 | 
						||
    
 | 
						||
/**
 | 
						||
 * The following properties and methods handle dynamic loading of JSON objects.
 | 
						||
 */
 | 
						||
 
 | 
						||
    /**
 | 
						||
     * Property: scriptName
 | 
						||
     * {String} The filename of this script without any path.
 | 
						||
     */
 | 
						||
    scriptName: "proj4js.js",
 | 
						||
 | 
						||
    /**
 | 
						||
     * Property: defsLookupService
 | 
						||
     * AJAX service to retreive projection definition parameters from
 | 
						||
     */
 | 
						||
    defsLookupService: 'http://spatialreference.org/ref',
 | 
						||
 | 
						||
    /**
 | 
						||
     * Property: libPath
 | 
						||
     * internal: http server path to library code.
 | 
						||
     */
 | 
						||
    libPath: null,
 | 
						||
 | 
						||
    /**
 | 
						||
     * Function: getScriptLocation
 | 
						||
     * Return the path to this script.
 | 
						||
     *
 | 
						||
     * Returns:
 | 
						||
     * Path to this script
 | 
						||
     */
 | 
						||
    getScriptLocation: function () {
 | 
						||
        if (this.libPath) return this.libPath;
 | 
						||
        var scriptName = this.scriptName;
 | 
						||
        var scriptNameLen = scriptName.length;
 | 
						||
 | 
						||
        var scripts = document.getElementsByTagName('script');
 | 
						||
        for (var i = 0; i < scripts.length; i++) {
 | 
						||
            var src = scripts[i].getAttribute('src');
 | 
						||
            if (src) {
 | 
						||
                var index = src.lastIndexOf(scriptName);
 | 
						||
                // is it found, at the end of the URL?
 | 
						||
                if ((index > -1) && (index + scriptNameLen == src.length)) {
 | 
						||
                    this.libPath = src.slice(0, -scriptNameLen);
 | 
						||
                    break;
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return this.libPath||"";
 | 
						||
    },
 | 
						||
 | 
						||
    /**
 | 
						||
     * Function: loadScript
 | 
						||
     * Load a JS file from a URL into a <script> tag in the page.
 | 
						||
     * 
 | 
						||
     * Parameters:
 | 
						||
     * url - {String} The URL containing the script to load
 | 
						||
     * onload - {Function} A method to be executed when the script loads successfully
 | 
						||
     * onfail - {Function} A method to be executed when there is an error loading the script
 | 
						||
     * loadCheck - {Function} A boolean method that checks to see if the script 
 | 
						||
     *            has loaded.  Typically this just checks for the existance of
 | 
						||
     *            an object in the file just loaded.
 | 
						||
     */
 | 
						||
    loadScript: function(url, onload, onfail, loadCheck) {
 | 
						||
      var script = document.createElement('script');
 | 
						||
      script.defer = false;
 | 
						||
      script.type = "text/javascript";
 | 
						||
      script.id = url;
 | 
						||
      script.src = url;
 | 
						||
      script.onload = onload;
 | 
						||
      script.onerror = onfail;
 | 
						||
      script.loadCheck = loadCheck;
 | 
						||
      if (/MSIE/.test(navigator.userAgent)) {
 | 
						||
        script.onreadystatechange = this.checkReadyState;
 | 
						||
      }
 | 
						||
      document.getElementsByTagName('head')[0].appendChild(script);
 | 
						||
    },
 | 
						||
    
 | 
						||
    /**
 | 
						||
     * Function: checkReadyState
 | 
						||
     * IE workaround since there is no onerror handler.  Calls the user defined 
 | 
						||
     * loadCheck method to determine if the script is loaded.
 | 
						||
     * 
 | 
						||
     */
 | 
						||
    checkReadyState: function() {
 | 
						||
      if (this.readyState == 'loaded') {
 | 
						||
        if (!this.loadCheck()) {
 | 
						||
          this.onerror();
 | 
						||
        } else {
 | 
						||
          this.onload();
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
};
 | 
						||
 | 
						||
/**
 | 
						||
 * Class: Proj4js.Proj
 | 
						||
 *
 | 
						||
 * Proj objects provide transformation methods for point coordinates
 | 
						||
 * between geodetic latitude/longitude and a projected coordinate system. 
 | 
						||
 * once they have been initialized with a projection code.
 | 
						||
 *
 | 
						||
 * Initialization of Proj objects is with a projection code, usually EPSG codes,
 | 
						||
 * which is the key that will be used with the Proj4js.defs array.
 | 
						||
 * 
 | 
						||
 * The code passed in will be stripped of colons and converted to uppercase
 | 
						||
 * to locate projection definition files.
 | 
						||
 *
 | 
						||
 * A projection object has properties for units and title strings.
 | 
						||
 */
 | 
						||
Proj4js.Proj = Proj4js.Class({
 | 
						||
 | 
						||
  /**
 | 
						||
   * Property: readyToUse
 | 
						||
   * Flag to indicate if initialization is complete for this Proj object
 | 
						||
   */
 | 
						||
  readyToUse: false,   
 | 
						||
  
 | 
						||
  /**
 | 
						||
   * Property: title
 | 
						||
   * The title to describe the projection
 | 
						||
   */
 | 
						||
  title: null,  
 | 
						||
  
 | 
						||
  /**
 | 
						||
   * Property: projName
 | 
						||
   * The projection class for this projection, e.g. lcc (lambert conformal conic,
 | 
						||
   * or merc for mercator).  These are exactly equivalent to their Proj4 
 | 
						||
   * counterparts.
 | 
						||
   */
 | 
						||
  projName: null,
 | 
						||
  /**
 | 
						||
   * Property: units
 | 
						||
   * The units of the projection.  Values include 'm' and 'degrees'
 | 
						||
   */
 | 
						||
  units: null,
 | 
						||
  /**
 | 
						||
   * Property: datum
 | 
						||
   * The datum specified for the projection
 | 
						||
   */
 | 
						||
  datum: null,
 | 
						||
  /**
 | 
						||
   * Property: x0
 | 
						||
   * The x coordinate origin
 | 
						||
   */
 | 
						||
  x0: 0,
 | 
						||
  /**
 | 
						||
   * Property: y0
 | 
						||
   * The y coordinate origin
 | 
						||
   */
 | 
						||
  y0: 0,
 | 
						||
  /**
 | 
						||
   * Property: localCS
 | 
						||
   * Flag to indicate if the projection is a local one in which no transforms
 | 
						||
   * are required.
 | 
						||
   */
 | 
						||
  localCS: false,
 | 
						||
 | 
						||
  /**
 | 
						||
  * Property: queue
 | 
						||
  * Buffer (FIFO) to hold callbacks waiting to be called when projection loaded.
 | 
						||
  */
 | 
						||
  queue: null,
 | 
						||
 | 
						||
  /**
 | 
						||
  * Constructor: initialize
 | 
						||
  * Constructor for Proj4js.Proj objects
 | 
						||
  *
 | 
						||
  * Parameters:
 | 
						||
  * srsCode - a code for map projection definition parameters.  These are usually
 | 
						||
  * (but not always) EPSG codes.
 | 
						||
  */
 | 
						||
  initialize: function(srsCode, callback) {
 | 
						||
      this.srsCodeInput = srsCode;
 | 
						||
      
 | 
						||
      //Register callbacks prior to attempting to process definition
 | 
						||
      this.queue = [];
 | 
						||
      if( callback ){
 | 
						||
           this.queue.push( callback );
 | 
						||
      }
 | 
						||
      
 | 
						||
      //check to see if this is a WKT string
 | 
						||
      if ((srsCode.indexOf('GEOGCS') >= 0) ||
 | 
						||
          (srsCode.indexOf('GEOCCS') >= 0) ||
 | 
						||
          (srsCode.indexOf('PROJCS') >= 0) ||
 | 
						||
          (srsCode.indexOf('LOCAL_CS') >= 0)) {
 | 
						||
            this.parseWKT(srsCode);
 | 
						||
            this.deriveConstants();
 | 
						||
            this.loadProjCode(this.projName);
 | 
						||
            return;
 | 
						||
      }
 | 
						||
      
 | 
						||
      // DGR 2008-08-03 : support urn and url
 | 
						||
      if (srsCode.indexOf('urn:') == 0) {
 | 
						||
          //urn:ORIGINATOR:def:crs:CODESPACE:VERSION:ID
 | 
						||
          var urn = srsCode.split(':');
 | 
						||
          if ((urn[1] == 'ogc' || urn[1] =='x-ogc') &&
 | 
						||
              (urn[2] =='def') &&
 | 
						||
              (urn[3] =='crs')) {
 | 
						||
              srsCode = urn[4]+':'+urn[urn.length-1];
 | 
						||
          }
 | 
						||
      } else if (srsCode.indexOf('http://') == 0) {
 | 
						||
          //url#ID
 | 
						||
          var url = srsCode.split('#');
 | 
						||
          if (url[0].match(/epsg.org/)) {
 | 
						||
            // http://www.epsg.org/#
 | 
						||
            srsCode = 'EPSG:'+url[1];
 | 
						||
          } else if (url[0].match(/RIG.xml/)) {
 | 
						||
            //http://librairies.ign.fr/geoportail/resources/RIG.xml#
 | 
						||
            //http://interop.ign.fr/registers/ign/RIG.xml#
 | 
						||
            srsCode = 'IGNF:'+url[1];
 | 
						||
          }
 | 
						||
      }
 | 
						||
      this.srsCode = srsCode.toUpperCase();
 | 
						||
      if (this.srsCode.indexOf("EPSG") == 0) {
 | 
						||
          this.srsCode = this.srsCode;
 | 
						||
          this.srsAuth = 'epsg';
 | 
						||
          this.srsProjNumber = this.srsCode.substring(5);
 | 
						||
      // DGR 2007-11-20 : authority IGNF
 | 
						||
      } else if (this.srsCode.indexOf("IGNF") == 0) {
 | 
						||
          this.srsCode = this.srsCode;
 | 
						||
          this.srsAuth = 'IGNF';
 | 
						||
          this.srsProjNumber = this.srsCode.substring(5);
 | 
						||
      // DGR 2008-06-19 : pseudo-authority CRS for WMS
 | 
						||
      } else if (this.srsCode.indexOf("CRS") == 0) {
 | 
						||
          this.srsCode = this.srsCode;
 | 
						||
          this.srsAuth = 'CRS';
 | 
						||
          this.srsProjNumber = this.srsCode.substring(4);
 | 
						||
      } else {
 | 
						||
          this.srsAuth = '';
 | 
						||
          this.srsProjNumber = this.srsCode;
 | 
						||
      }
 | 
						||
      
 | 
						||
      this.loadProjDefinition();
 | 
						||
  },
 | 
						||
  
 | 
						||
/**
 | 
						||
 * Function: loadProjDefinition
 | 
						||
 *    Loads the coordinate system initialization string if required.
 | 
						||
 *    Note that dynamic loading happens asynchronously so an application must 
 | 
						||
 *    wait for the readyToUse property is set to true.
 | 
						||
 *    To prevent dynamic loading, include the defs through a script tag in
 | 
						||
 *    your application.
 | 
						||
 *
 | 
						||
 */
 | 
						||
    loadProjDefinition: function() {
 | 
						||
      //check in memory
 | 
						||
      if (Proj4js.defs[this.srsCode]) {
 | 
						||
        this.defsLoaded();
 | 
						||
        return;
 | 
						||
      }
 | 
						||
 | 
						||
      //else check for def on the server
 | 
						||
      var url = Proj4js.getScriptLocation() + 'defs/' + this.srsAuth.toUpperCase() + this.srsProjNumber + '.js';
 | 
						||
      Proj4js.loadScript(url, 
 | 
						||
                Proj4js.bind(this.defsLoaded, this),
 | 
						||
                Proj4js.bind(this.loadFromService, this),
 | 
						||
                Proj4js.bind(this.checkDefsLoaded, this) );
 | 
						||
    },
 | 
						||
 | 
						||
/**
 | 
						||
 * Function: loadFromService
 | 
						||
 *    Creates the REST URL for loading the definition from a web service and 
 | 
						||
 *    loads it.
 | 
						||
 *
 | 
						||
 */
 | 
						||
    loadFromService: function() {
 | 
						||
      //else load from web service
 | 
						||
      var url = Proj4js.defsLookupService +'/' + this.srsAuth +'/'+ this.srsProjNumber + '/proj4js/';
 | 
						||
      Proj4js.loadScript(url, 
 | 
						||
            Proj4js.bind(this.defsLoaded, this),
 | 
						||
            Proj4js.bind(this.defsFailed, this),
 | 
						||
            Proj4js.bind(this.checkDefsLoaded, this) );
 | 
						||
    },
 | 
						||
 | 
						||
/**
 | 
						||
 * Function: defsLoaded
 | 
						||
 * Continues the Proj object initilization once the def file is loaded
 | 
						||
 *
 | 
						||
 */
 | 
						||
    defsLoaded: function() {
 | 
						||
      this.parseDefs();
 | 
						||
      this.loadProjCode(this.projName);
 | 
						||
    },
 | 
						||
    
 | 
						||
/**
 | 
						||
 * Function: checkDefsLoaded
 | 
						||
 *    This is the loadCheck method to see if the def object exists
 | 
						||
 *
 | 
						||
 */
 | 
						||
    checkDefsLoaded: function() {
 | 
						||
      if (Proj4js.defs[this.srsCode]) {
 | 
						||
        return true;
 | 
						||
      } else {
 | 
						||
        return false;
 | 
						||
      }
 | 
						||
    },
 | 
						||
 | 
						||
 /**
 | 
						||
 * Function: defsFailed
 | 
						||
 *    Report an error in loading the defs file, but continue on using WGS84
 | 
						||
 *
 | 
						||
 */
 | 
						||
   defsFailed: function() {
 | 
						||
      Proj4js.reportError('failed to load projection definition for: '+this.srsCode);
 | 
						||
      Proj4js.defs[this.srsCode] = Proj4js.defs['WGS84'];  //set it to something so it can at least continue
 | 
						||
      this.defsLoaded();
 | 
						||
    },
 | 
						||
 | 
						||
/**
 | 
						||
 * Function: loadProjCode
 | 
						||
 *    Loads projection class code dynamically if required.
 | 
						||
 *     Projection code may be included either through a script tag or in
 | 
						||
 *     a built version of proj4js
 | 
						||
 *
 | 
						||
 */
 | 
						||
    loadProjCode: function(projName) {
 | 
						||
      if (Proj4js.Proj[projName]) {
 | 
						||
        this.initTransforms();
 | 
						||
        return;
 | 
						||
      }
 | 
						||
 | 
						||
      //the URL for the projection code
 | 
						||
      var url = Proj4js.getScriptLocation() + 'projCode/' + projName + '.js';
 | 
						||
      Proj4js.loadScript(url, 
 | 
						||
              Proj4js.bind(this.loadProjCodeSuccess, this, projName),
 | 
						||
              Proj4js.bind(this.loadProjCodeFailure, this, projName), 
 | 
						||
              Proj4js.bind(this.checkCodeLoaded, this, projName) );
 | 
						||
    },
 | 
						||
 | 
						||
 /**
 | 
						||
 * Function: loadProjCodeSuccess
 | 
						||
 *    Loads any proj dependencies or continue on to final initialization.
 | 
						||
 *
 | 
						||
 */
 | 
						||
    loadProjCodeSuccess: function(projName) {
 | 
						||
      if (Proj4js.Proj[projName].dependsOn){
 | 
						||
        this.loadProjCode(Proj4js.Proj[projName].dependsOn);
 | 
						||
      } else {
 | 
						||
        this.initTransforms();
 | 
						||
      }
 | 
						||
    },
 | 
						||
 | 
						||
 /**
 | 
						||
 * Function: defsFailed
 | 
						||
 *    Report an error in loading the proj file.  Initialization of the Proj
 | 
						||
 *    object has failed and the readyToUse flag will never be set.
 | 
						||
 *
 | 
						||
 */
 | 
						||
    loadProjCodeFailure: function(projName) {
 | 
						||
      Proj4js.reportError("failed to find projection file for: " + projName);
 | 
						||
      //TBD initialize with identity transforms so proj will still work?
 | 
						||
    },
 | 
						||
    
 | 
						||
/**
 | 
						||
 * Function: checkCodeLoaded
 | 
						||
 *    This is the loadCheck method to see if the projection code is loaded
 | 
						||
 *
 | 
						||
 */
 | 
						||
    checkCodeLoaded: function(projName) {
 | 
						||
      if (Proj4js.Proj[projName]) {
 | 
						||
        return true;
 | 
						||
      } else {
 | 
						||
        return false;
 | 
						||
      }
 | 
						||
    },
 | 
						||
 | 
						||
/**
 | 
						||
 * Function: initTransforms
 | 
						||
 *    Finalize the initialization of the Proj object
 | 
						||
 *
 | 
						||
 */
 | 
						||
    initTransforms: function() {
 | 
						||
      Proj4js.extend(this, Proj4js.Proj[this.projName]);
 | 
						||
      this.init();
 | 
						||
      this.readyToUse = true;
 | 
						||
      if( this.queue ) {
 | 
						||
        var item;
 | 
						||
        while( (item = this.queue.shift()) ) {
 | 
						||
          item.call( this, this );
 | 
						||
        }
 | 
						||
      }
 | 
						||
  },
 | 
						||
 | 
						||
/**
 | 
						||
 * Function: parseWKT
 | 
						||
 * Parses a WKT string to get initialization parameters
 | 
						||
 *
 | 
						||
 */
 | 
						||
 wktRE: /^(\w+)\[(.*)\]$/,
 | 
						||
 parseWKT: function(wkt) {
 | 
						||
    var wktMatch = wkt.match(this.wktRE);
 | 
						||
    if (!wktMatch) return;
 | 
						||
    var wktObject = wktMatch[1];
 | 
						||
    var wktContent = wktMatch[2];
 | 
						||
    var wktTemp = wktContent.split(",");
 | 
						||
    var wktName;
 | 
						||
    if (wktObject.toUpperCase() == "TOWGS84") {
 | 
						||
      wktName = wktObject;  //no name supplied for the TOWGS84 array
 | 
						||
    } else {
 | 
						||
      wktName = wktTemp.shift();
 | 
						||
    }
 | 
						||
    wktName = wktName.replace(/^\"/,"");
 | 
						||
    wktName = wktName.replace(/\"$/,"");
 | 
						||
    
 | 
						||
    /*
 | 
						||
    wktContent = wktTemp.join(",");
 | 
						||
    var wktArray = wktContent.split("],");
 | 
						||
    for (var i=0; i<wktArray.length-1; ++i) {
 | 
						||
      wktArray[i] += "]";
 | 
						||
    }
 | 
						||
    */
 | 
						||
    
 | 
						||
    var wktArray = new Array();
 | 
						||
    var bkCount = 0;
 | 
						||
    var obj = "";
 | 
						||
    for (var i=0; i<wktTemp.length; ++i) {
 | 
						||
      var token = wktTemp[i];
 | 
						||
      for (var j=0; j<token.length; ++j) {
 | 
						||
        if (token.charAt(j) == "[") ++bkCount;
 | 
						||
        if (token.charAt(j) == "]") --bkCount;
 | 
						||
      }
 | 
						||
      obj += token;
 | 
						||
      if (bkCount === 0) {
 | 
						||
        wktArray.push(obj);
 | 
						||
        obj = "";
 | 
						||
      } else {
 | 
						||
        obj += ",";
 | 
						||
      }
 | 
						||
    }
 | 
						||
    
 | 
						||
    //do something based on the type of the wktObject being parsed
 | 
						||
    //add in variations in the spelling as required
 | 
						||
    switch (wktObject) {
 | 
						||
      case 'LOCAL_CS':
 | 
						||
        this.projName = 'identity'
 | 
						||
        this.localCS = true;
 | 
						||
        this.srsCode = wktName;
 | 
						||
        break;
 | 
						||
      case 'GEOGCS':
 | 
						||
        this.projName = 'longlat'
 | 
						||
        this.geocsCode = wktName;
 | 
						||
        if (!this.srsCode) this.srsCode = wktName;
 | 
						||
        break;
 | 
						||
      case 'PROJCS':
 | 
						||
        this.srsCode = wktName;
 | 
						||
        break;
 | 
						||
      case 'GEOCCS':
 | 
						||
        break;
 | 
						||
      case 'PROJECTION':
 | 
						||
        this.projName = Proj4js.wktProjections[wktName]
 | 
						||
        break;
 | 
						||
      case 'DATUM':
 | 
						||
        this.datumName = wktName;
 | 
						||
        break;
 | 
						||
      case 'LOCAL_DATUM':
 | 
						||
        this.datumCode = 'none';
 | 
						||
        break;
 | 
						||
      case 'SPHEROID':
 | 
						||
        this.ellps = wktName;
 | 
						||
        this.a = parseFloat(wktArray.shift());
 | 
						||
        this.rf = parseFloat(wktArray.shift());
 | 
						||
        break;
 | 
						||
      case 'PRIMEM':
 | 
						||
        this.from_greenwich = parseFloat(wktArray.shift()); //to radians?
 | 
						||
        break;
 | 
						||
      case 'UNIT':
 | 
						||
        this.units = wktName;
 | 
						||
        this.unitsPerMeter = parseFloat(wktArray.shift());
 | 
						||
        break;
 | 
						||
      case 'PARAMETER':
 | 
						||
        var name = wktName.toLowerCase();
 | 
						||
        var value = parseFloat(wktArray.shift());
 | 
						||
        //there may be many variations on the wktName values, add in case
 | 
						||
        //statements as required
 | 
						||
        switch (name) {
 | 
						||
          case 'false_easting':
 | 
						||
            this.x0 = value;
 | 
						||
            break;
 | 
						||
          case 'false_northing':
 | 
						||
            this.y0 = value;
 | 
						||
            break;
 | 
						||
          case 'scale_factor':
 | 
						||
            this.k0 = value;
 | 
						||
            break;
 | 
						||
          case 'central_meridian':
 | 
						||
            this.long0 = value*Proj4js.common.D2R;
 | 
						||
            break;
 | 
						||
          case 'latitude_of_origin':
 | 
						||
            this.lat0 = value*Proj4js.common.D2R;
 | 
						||
            break;
 | 
						||
          case 'more_here':
 | 
						||
            break;
 | 
						||
          default:
 | 
						||
            break;
 | 
						||
        }
 | 
						||
        break;
 | 
						||
      case 'TOWGS84':
 | 
						||
        this.datum_params = wktArray;
 | 
						||
        break;
 | 
						||
      //DGR 2010-11-12: AXIS
 | 
						||
      case 'AXIS':
 | 
						||
        var name= wktName.toLowerCase();
 | 
						||
        var value= wktArray.shift();
 | 
						||
        switch (value) {
 | 
						||
          case 'EAST' : value= 'e'; break;
 | 
						||
          case 'WEST' : value= 'w'; break;
 | 
						||
          case 'NORTH': value= 'n'; break;
 | 
						||
          case 'SOUTH': value= 's'; break;
 | 
						||
          case 'UP'   : value= 'u'; break;
 | 
						||
          case 'DOWN' : value= 'd'; break;
 | 
						||
          case 'OTHER':
 | 
						||
          default     : value= ' '; break;//FIXME
 | 
						||
        }
 | 
						||
        if (!this.axis) { this.axis= "enu"; }
 | 
						||
        switch(name) {
 | 
						||
          case 'x': this.axis=                         value + this.axis.substr(1,2); break;
 | 
						||
          case 'y': this.axis= this.axis.substr(0,1) + value + this.axis.substr(2,1); break;
 | 
						||
          case 'z': this.axis= this.axis.substr(0,2) + value                        ; break;
 | 
						||
          default : break;
 | 
						||
        }
 | 
						||
      case 'MORE_HERE':
 | 
						||
        break;
 | 
						||
      default:
 | 
						||
        break;
 | 
						||
    }
 | 
						||
    for (var i=0; i<wktArray.length; ++i) {
 | 
						||
      this.parseWKT(wktArray[i]);
 | 
						||
    }
 | 
						||
 },
 | 
						||
 | 
						||
/**
 | 
						||
 * Function: parseDefs
 | 
						||
 * Parses the PROJ.4 initialization string and sets the associated properties.
 | 
						||
 *
 | 
						||
 */
 | 
						||
  parseDefs: function() {
 | 
						||
      this.defData = Proj4js.defs[this.srsCode];
 | 
						||
      var paramName, paramVal;
 | 
						||
      if (!this.defData) {
 | 
						||
        return;
 | 
						||
      }
 | 
						||
      var paramArray=this.defData.split("+");
 | 
						||
 | 
						||
      for (var prop=0; prop<paramArray.length; prop++) {
 | 
						||
          var property = paramArray[prop].split("=");
 | 
						||
          paramName = property[0].toLowerCase();
 | 
						||
          paramVal = property[1];
 | 
						||
 | 
						||
          switch (paramName.replace(/\s/gi,"")) {  // trim out spaces
 | 
						||
              case "": break;   // throw away nameless parameter
 | 
						||
              case "title":  this.title = paramVal; break;
 | 
						||
              case "proj":   this.projName =  paramVal.replace(/\s/gi,""); break;
 | 
						||
              case "units":  this.units = paramVal.replace(/\s/gi,""); break;
 | 
						||
              case "datum":  this.datumCode = paramVal.replace(/\s/gi,""); break;
 | 
						||
              case "nadgrids": this.nagrids = paramVal.replace(/\s/gi,""); break;
 | 
						||
              case "ellps":  this.ellps = paramVal.replace(/\s/gi,""); break;
 | 
						||
              case "a":      this.a =  parseFloat(paramVal); break;  // semi-major radius
 | 
						||
              case "b":      this.b =  parseFloat(paramVal); break;  // semi-minor radius
 | 
						||
              // DGR 2007-11-20
 | 
						||
              case "rf":     this.rf = parseFloat(paramVal); break; // inverse flattening rf= a/(a-b)
 | 
						||
              case "lat_0":  this.lat0 = paramVal*Proj4js.common.D2R; break;        // phi0, central latitude
 | 
						||
              case "lat_1":  this.lat1 = paramVal*Proj4js.common.D2R; break;        //standard parallel 1
 | 
						||
              case "lat_2":  this.lat2 = paramVal*Proj4js.common.D2R; break;        //standard parallel 2
 | 
						||
              case "lat_ts": this.lat_ts = paramVal*Proj4js.common.D2R; break;      // used in merc and eqc
 | 
						||
              case "lon_0":  this.long0 = paramVal*Proj4js.common.D2R; break;       // lam0, central longitude
 | 
						||
              case "alpha":  this.alpha =  parseFloat(paramVal)*Proj4js.common.D2R; break;  //for somerc projection
 | 
						||
              case "lonc":   this.longc = paramVal*Proj4js.common.D2R; break;       //for somerc projection
 | 
						||
              case "x_0":    this.x0 = parseFloat(paramVal); break;  // false easting
 | 
						||
              case "y_0":    this.y0 = parseFloat(paramVal); break;  // false northing
 | 
						||
              case "k_0":    this.k0 = parseFloat(paramVal); break;  // projection scale factor
 | 
						||
              case "k":      this.k0 = parseFloat(paramVal); break;  // both forms returned
 | 
						||
              case "r_a":    this.R_A = true; break;                 // sphere--area of ellipsoid
 | 
						||
              case "zone":   this.zone = parseInt(paramVal,10); break;  // UTM Zone
 | 
						||
              case "south":   this.utmSouth = true; break;  // UTM north/south
 | 
						||
              case "towgs84":this.datum_params = paramVal.split(","); break;
 | 
						||
              case "to_meter": this.to_meter = parseFloat(paramVal); break; // cartesian scaling
 | 
						||
              case "from_greenwich": this.from_greenwich = paramVal*Proj4js.common.D2R; break;
 | 
						||
              // DGR 2008-07-09 : if pm is not a well-known prime meridian take
 | 
						||
              // the value instead of 0.0, then convert to radians
 | 
						||
              case "pm":     paramVal = paramVal.replace(/\s/gi,"");
 | 
						||
                             this.from_greenwich = Proj4js.PrimeMeridian[paramVal] ?
 | 
						||
                                Proj4js.PrimeMeridian[paramVal] : parseFloat(paramVal);
 | 
						||
                             this.from_greenwich *= Proj4js.common.D2R; 
 | 
						||
                             break;
 | 
						||
              // DGR 2010-11-12: axis
 | 
						||
              case "axis":   paramVal = paramVal.replace(/\s/gi,"");
 | 
						||
                             var legalAxis= "ewnsud";
 | 
						||
                             if (paramVal.length==3 &&
 | 
						||
                                 legalAxis.indexOf(paramVal.substr(0,1))!=-1 &&
 | 
						||
                                 legalAxis.indexOf(paramVal.substr(1,1))!=-1 &&
 | 
						||
                                 legalAxis.indexOf(paramVal.substr(2,1))!=-1) {
 | 
						||
                                this.axis= paramVal;
 | 
						||
                             } //FIXME: be silent ?
 | 
						||
                             break
 | 
						||
              case "no_defs": break; 
 | 
						||
              default: //alert("Unrecognized parameter: " + paramName);
 | 
						||
          } // switch()
 | 
						||
      } // for paramArray
 | 
						||
      this.deriveConstants();
 | 
						||
  },
 | 
						||
 | 
						||
/**
 | 
						||
 * Function: deriveConstants
 | 
						||
 * Sets several derived constant values and initialization of datum and ellipse
 | 
						||
 *     parameters.
 | 
						||
 *
 | 
						||
 */
 | 
						||
  deriveConstants: function() {
 | 
						||
      if (this.nagrids == '@null') this.datumCode = 'none';
 | 
						||
      if (this.datumCode && this.datumCode != 'none') {
 | 
						||
        var datumDef = Proj4js.Datum[this.datumCode];
 | 
						||
        if (datumDef) {
 | 
						||
          this.datum_params = datumDef.towgs84 ? datumDef.towgs84.split(',') : null;
 | 
						||
          this.ellps = datumDef.ellipse;
 | 
						||
          this.datumName = datumDef.datumName ? datumDef.datumName : this.datumCode;
 | 
						||
        }
 | 
						||
      }
 | 
						||
      if (!this.a) {    // do we have an ellipsoid?
 | 
						||
          var ellipse = Proj4js.Ellipsoid[this.ellps] ? Proj4js.Ellipsoid[this.ellps] : Proj4js.Ellipsoid['WGS84'];
 | 
						||
          Proj4js.extend(this, ellipse);
 | 
						||
      }
 | 
						||
      if (this.rf && !this.b) this.b = (1.0 - 1.0/this.rf) * this.a;
 | 
						||
      if (this.rf === 0 || Math.abs(this.a - this.b)<Proj4js.common.EPSLN) {
 | 
						||
        this.sphere = true;
 | 
						||
        this.b= this.a;
 | 
						||
      }
 | 
						||
      this.a2 = this.a * this.a;          // used in geocentric
 | 
						||
      this.b2 = this.b * this.b;          // used in geocentric
 | 
						||
      this.es = (this.a2-this.b2)/this.a2;  // e ^ 2
 | 
						||
      this.e = Math.sqrt(this.es);        // eccentricity
 | 
						||
      if (this.R_A) {
 | 
						||
        this.a *= 1. - this.es * (Proj4js.common.SIXTH + this.es * (Proj4js.common.RA4 + this.es * Proj4js.common.RA6));
 | 
						||
        this.a2 = this.a * this.a;
 | 
						||
        this.b2 = this.b * this.b;
 | 
						||
        this.es = 0.;
 | 
						||
      }
 | 
						||
      this.ep2=(this.a2-this.b2)/this.b2; // used in geocentric
 | 
						||
      if (!this.k0) this.k0 = 1.0;    //default value
 | 
						||
      //DGR 2010-11-12: axis
 | 
						||
      if (!this.axis) { this.axis= "enu"; }
 | 
						||
 | 
						||
      this.datum = new Proj4js.datum(this);
 | 
						||
  }
 | 
						||
});
 | 
						||
 | 
						||
Proj4js.Proj.longlat = {
 | 
						||
  init: function() {
 | 
						||
    //no-op for longlat
 | 
						||
  },
 | 
						||
  forward: function(pt) {
 | 
						||
    //identity transform
 | 
						||
    return pt;
 | 
						||
  },
 | 
						||
  inverse: function(pt) {
 | 
						||
    //identity transform
 | 
						||
    return pt;
 | 
						||
  }
 | 
						||
};
 | 
						||
Proj4js.Proj.identity = Proj4js.Proj.longlat;
 | 
						||
 | 
						||
/**
 | 
						||
  Proj4js.defs is a collection of coordinate system definition objects in the 
 | 
						||
  PROJ.4 command line format.
 | 
						||
  Generally a def is added by means of a separate .js file for example:
 | 
						||
 | 
						||
    <SCRIPT type="text/javascript" src="defs/EPSG26912.js"></SCRIPT>
 | 
						||
 | 
						||
  def is a CS definition in PROJ.4 WKT format, for example:
 | 
						||
    +proj="tmerc"   //longlat, etc.
 | 
						||
    +a=majorRadius
 | 
						||
    +b=minorRadius
 | 
						||
    +lat0=somenumber
 | 
						||
    +long=somenumber
 | 
						||
*/
 | 
						||
Proj4js.defs = {
 | 
						||
  // These are so widely used, we'll go ahead and throw them in
 | 
						||
  // without requiring a separate .js file
 | 
						||
  'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees",
 | 
						||
  'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees",
 | 
						||
  'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees",
 | 
						||
  'EPSG:3875': "+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"
 | 
						||
};
 | 
						||
Proj4js.defs['EPSG:3785'] = Proj4js.defs['EPSG:3875'];  //maintain backward compat, official code is 3875
 | 
						||
Proj4js.defs['GOOGLE'] = Proj4js.defs['EPSG:3875'];
 | 
						||
Proj4js.defs['EPSG:900913'] = Proj4js.defs['EPSG:3875'];
 | 
						||
Proj4js.defs['EPSG:102113'] = Proj4js.defs['EPSG:3875'];
 | 
						||
 | 
						||
Proj4js.common = {
 | 
						||
  PI : 3.141592653589793238, //Math.PI,
 | 
						||
  HALF_PI : 1.570796326794896619, //Math.PI*0.5,
 | 
						||
  TWO_PI : 6.283185307179586477, //Math.PI*2,
 | 
						||
  FORTPI : 0.78539816339744833,
 | 
						||
  R2D : 57.29577951308232088,
 | 
						||
  D2R : 0.01745329251994329577,
 | 
						||
  SEC_TO_RAD : 4.84813681109535993589914102357e-6, /* SEC_TO_RAD = Pi/180/3600 */
 | 
						||
  EPSLN : 1.0e-10,
 | 
						||
  MAX_ITER : 20,
 | 
						||
  // following constants from geocent.c
 | 
						||
  COS_67P5 : 0.38268343236508977,  /* cosine of 67.5 degrees */
 | 
						||
  AD_C : 1.0026000,                /* Toms region 1 constant */
 | 
						||
 | 
						||
  /* datum_type values */
 | 
						||
  PJD_UNKNOWN  : 0,
 | 
						||
  PJD_3PARAM   : 1,
 | 
						||
  PJD_7PARAM   : 2,
 | 
						||
  PJD_GRIDSHIFT: 3,
 | 
						||
  PJD_WGS84    : 4,   // WGS84 or equivalent
 | 
						||
  PJD_NODATUM  : 5,   // WGS84 or equivalent
 | 
						||
  SRS_WGS84_SEMIMAJOR : 6378137.0,  // only used in grid shift transforms
 | 
						||
 | 
						||
  // ellipoid pj_set_ell.c
 | 
						||
  SIXTH : .1666666666666666667, /* 1/6 */
 | 
						||
  RA4   : .04722222222222222222, /* 17/360 */
 | 
						||
  RA6   : .02215608465608465608, /* 67/3024 */
 | 
						||
  RV4   : .06944444444444444444, /* 5/72 */
 | 
						||
  RV6   : .04243827160493827160, /* 55/1296 */
 | 
						||
 | 
						||
// Function to compute the constant small m which is the radius of
 | 
						||
//   a parallel of latitude, phi, divided by the semimajor axis.
 | 
						||
// -----------------------------------------------------------------
 | 
						||
  msfnz : function(eccent, sinphi, cosphi) {
 | 
						||
      var con = eccent * sinphi;
 | 
						||
      return cosphi/(Math.sqrt(1.0 - con * con));
 | 
						||
  },
 | 
						||
 | 
						||
// Function to compute the constant small t for use in the forward
 | 
						||
//   computations in the Lambert Conformal Conic and the Polar
 | 
						||
//   Stereographic projections.
 | 
						||
// -----------------------------------------------------------------
 | 
						||
  tsfnz : function(eccent, phi, sinphi) {
 | 
						||
    var con = eccent * sinphi;
 | 
						||
    var com = .5 * eccent;
 | 
						||
    con = Math.pow(((1.0 - con) / (1.0 + con)), com);
 | 
						||
    return (Math.tan(.5 * (this.HALF_PI - phi))/con);
 | 
						||
  },
 | 
						||
 | 
						||
// Function to compute the latitude angle, phi2, for the inverse of the
 | 
						||
//   Lambert Conformal Conic and Polar Stereographic projections.
 | 
						||
// ----------------------------------------------------------------
 | 
						||
  phi2z : function(eccent, ts) {
 | 
						||
    var eccnth = .5 * eccent;
 | 
						||
    var con, dphi;
 | 
						||
    var phi = this.HALF_PI - 2 * Math.atan(ts);
 | 
						||
    for (var i = 0; i <= 15; i++) {
 | 
						||
      con = eccent * Math.sin(phi);
 | 
						||
      dphi = this.HALF_PI - 2 * Math.atan(ts *(Math.pow(((1.0 - con)/(1.0 + con)),eccnth))) - phi;
 | 
						||
      phi += dphi;
 | 
						||
      if (Math.abs(dphi) <= .0000000001) return phi;
 | 
						||
    }
 | 
						||
    alert("phi2z has NoConvergence");
 | 
						||
    return (-9999);
 | 
						||
  },
 | 
						||
 | 
						||
/* Function to compute constant small q which is the radius of a 
 | 
						||
   parallel of latitude, phi, divided by the semimajor axis. 
 | 
						||
------------------------------------------------------------*/
 | 
						||
  qsfnz : function(eccent,sinphi) {
 | 
						||
    var con;
 | 
						||
    if (eccent > 1.0e-7) {
 | 
						||
      con = eccent * sinphi;
 | 
						||
      return (( 1.0- eccent * eccent) * (sinphi /(1.0 - con * con) - (.5/eccent)*Math.log((1.0 - con)/(1.0 + con))));
 | 
						||
    } else {
 | 
						||
      return(2.0 * sinphi);
 | 
						||
    }
 | 
						||
  },
 | 
						||
 | 
						||
/* Function to eliminate roundoff errors in asin
 | 
						||
----------------------------------------------*/
 | 
						||
  asinz : function(x) {
 | 
						||
    if (Math.abs(x)>1.0) {
 | 
						||
      x=(x>1.0)?1.0:-1.0;
 | 
						||
    }
 | 
						||
    return Math.asin(x);
 | 
						||
  },
 | 
						||
 | 
						||
// following functions from gctpc cproj.c for transverse mercator projections
 | 
						||
  e0fn : function(x) {return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));},
 | 
						||
  e1fn : function(x) {return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));},
 | 
						||
  e2fn : function(x) {return(0.05859375*x*x*(1.0+0.75*x));},
 | 
						||
  e3fn : function(x) {return(x*x*x*(35.0/3072.0));},
 | 
						||
  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));},
 | 
						||
 | 
						||
  srat : function(esinp, exp) {
 | 
						||
    return(Math.pow((1.0-esinp)/(1.0+esinp), exp));
 | 
						||
  },
 | 
						||
 | 
						||
// Function to return the sign of an argument
 | 
						||
  sign : function(x) { if (x < 0.0) return(-1); else return(1);},
 | 
						||
 | 
						||
// Function to adjust longitude to -180 to 180; input in radians
 | 
						||
  adjust_lon : function(x) {
 | 
						||
    x = (Math.abs(x) < this.PI) ? x: (x - (this.sign(x)*this.TWO_PI) );
 | 
						||
    return x;
 | 
						||
  },
 | 
						||
 | 
						||
// IGNF - DGR : algorithms used by IGN France
 | 
						||
 | 
						||
// Function to adjust latitude to -90 to 90; input in radians
 | 
						||
  adjust_lat : function(x) {
 | 
						||
    x= (Math.abs(x) < this.HALF_PI) ? x: (x - (this.sign(x)*this.PI) );
 | 
						||
    return x;
 | 
						||
  },
 | 
						||
 | 
						||
// Latitude Isometrique - close to tsfnz ...
 | 
						||
  latiso : function(eccent, phi, sinphi) {
 | 
						||
    if (Math.abs(phi) > this.HALF_PI) return +Number.NaN;
 | 
						||
    if (phi==this.HALF_PI) return Number.POSITIVE_INFINITY;
 | 
						||
    if (phi==-1.0*this.HALF_PI) return -1.0*Number.POSITIVE_INFINITY;
 | 
						||
 | 
						||
    var con= eccent*sinphi;
 | 
						||
    return Math.log(Math.tan((this.HALF_PI+phi)/2.0))+eccent*Math.log((1.0-con)/(1.0+con))/2.0;
 | 
						||
  },
 | 
						||
 | 
						||
  fL : function(x,L) {
 | 
						||
    return 2.0*Math.atan(x*Math.exp(L)) - this.HALF_PI;
 | 
						||
  },
 | 
						||
 | 
						||
// Inverse Latitude Isometrique - close to ph2z
 | 
						||
  invlatiso : function(eccent, ts) {
 | 
						||
    var phi= this.fL(1.0,ts);
 | 
						||
    var Iphi= 0.0;
 | 
						||
    var con= 0.0;
 | 
						||
    do {
 | 
						||
      Iphi= phi;
 | 
						||
      con= eccent*Math.sin(Iphi);
 | 
						||
      phi= this.fL(Math.exp(eccent*Math.log((1.0+con)/(1.0-con))/2.0),ts)
 | 
						||
    } while (Math.abs(phi-Iphi)>1.0e-12);
 | 
						||
    return phi;
 | 
						||
  },
 | 
						||
 | 
						||
// Needed for Gauss Schreiber
 | 
						||
// Original:  Denis Makarov (info@binarythings.com)
 | 
						||
// Web Site:  http://www.binarythings.com
 | 
						||
  sinh : function(x)
 | 
						||
  {
 | 
						||
    var r= Math.exp(x);
 | 
						||
    r= (r-1.0/r)/2.0;
 | 
						||
    return r;
 | 
						||
  },
 | 
						||
 | 
						||
  cosh : function(x)
 | 
						||
  {
 | 
						||
    var r= Math.exp(x);
 | 
						||
    r= (r+1.0/r)/2.0;
 | 
						||
    return r;
 | 
						||
  },
 | 
						||
 | 
						||
  tanh : function(x)
 | 
						||
  {
 | 
						||
    var r= Math.exp(x);
 | 
						||
    r= (r-1.0/r)/(r+1.0/r);
 | 
						||
    return r;
 | 
						||
  },
 | 
						||
 | 
						||
  asinh : function(x)
 | 
						||
  {
 | 
						||
    var s= (x>= 0? 1.0:-1.0);
 | 
						||
    return s*(Math.log( Math.abs(x) + Math.sqrt(x*x+1.0) ));
 | 
						||
  },
 | 
						||
 | 
						||
  acosh : function(x)
 | 
						||
  {
 | 
						||
    return 2.0*Math.log(Math.sqrt((x+1.0)/2.0) + Math.sqrt((x-1.0)/2.0));
 | 
						||
  },
 | 
						||
 | 
						||
  atanh : function(x)
 | 
						||
  {
 | 
						||
    return Math.log((x-1.0)/(x+1.0))/2.0;
 | 
						||
  },
 | 
						||
 | 
						||
// Grande Normale
 | 
						||
  gN : function(a,e,sinphi)
 | 
						||
  {
 | 
						||
    var temp= e*sinphi;
 | 
						||
    return a/Math.sqrt(1.0 - temp*temp);
 | 
						||
  },
 | 
						||
  
 | 
						||
  //code from the PROJ.4 pj_mlfn.c file;  this may be useful for other projections
 | 
						||
  pj_enfn: function(es) {
 | 
						||
    var en = new Array();
 | 
						||
    en[0] = this.C00 - es * (this.C02 + es * (this.C04 + es * (this.C06 + es * this.C08)));
 | 
						||
    en[1] = es * (this.C22 - es * (this.C04 + es * (this.C06 + es * this.C08)));
 | 
						||
    var t = es * es;
 | 
						||
    en[2] = t * (this.C44 - es * (this.C46 + es * this.C48));
 | 
						||
    t *= es;
 | 
						||
    en[3] = t * (this.C66 - es * this.C68);
 | 
						||
    en[4] = t * es * this.C88;
 | 
						||
    return en;
 | 
						||
  },
 | 
						||
  
 | 
						||
  pj_mlfn: function(phi, sphi, cphi, en) {
 | 
						||
    cphi *= sphi;
 | 
						||
    sphi *= sphi;
 | 
						||
    return(en[0] * phi - cphi * (en[1] + sphi*(en[2]+ sphi*(en[3] + sphi*en[4]))));
 | 
						||
  },
 | 
						||
  
 | 
						||
  pj_inv_mlfn: function(arg, es, en) {
 | 
						||
    var k = 1./(1.-es);
 | 
						||
    var phi = arg;
 | 
						||
    for (var i = Proj4js.common.MAX_ITER; i ; --i) { /* rarely goes over 2 iterations */
 | 
						||
      var s = Math.sin(phi);
 | 
						||
      var t = 1. - es * s * s;
 | 
						||
      //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg;
 | 
						||
      //phi -= t * (t * Math.sqrt(t)) * k;
 | 
						||
      t = (this.pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k;
 | 
						||
      phi -= t;
 | 
						||
      if (Math.abs(t) < Proj4js.common.EPSLN)
 | 
						||
        return phi;
 | 
						||
    }
 | 
						||
    Proj4js.reportError("cass:pj_inv_mlfn: Convergence error");
 | 
						||
    return phi;
 | 
						||
  },
 | 
						||
 | 
						||
/* meridinal distance for ellipsoid and inverse
 | 
						||
**	8th degree - accurate to < 1e-5 meters when used in conjuction
 | 
						||
**		with typical major axis values.
 | 
						||
**	Inverse determines phi to EPS (1e-11) radians, about 1e-6 seconds.
 | 
						||
*/
 | 
						||
  C00: 1.0,
 | 
						||
  C02: .25,
 | 
						||
  C04: .046875,
 | 
						||
  C06: .01953125,
 | 
						||
  C08: .01068115234375,
 | 
						||
  C22: .75,
 | 
						||
  C44: .46875,
 | 
						||
  C46: .01302083333333333333,
 | 
						||
  C48: .00712076822916666666,
 | 
						||
  C66: .36458333333333333333,
 | 
						||
  C68: .00569661458333333333,
 | 
						||
  C88: .3076171875  
 | 
						||
 | 
						||
};
 | 
						||
 | 
						||
/** datum object
 | 
						||
*/
 | 
						||
Proj4js.datum = Proj4js.Class({
 | 
						||
 | 
						||
  initialize : function(proj) {
 | 
						||
    this.datum_type = Proj4js.common.PJD_WGS84;   //default setting
 | 
						||
    if (proj.datumCode && proj.datumCode == 'none') {
 | 
						||
      this.datum_type = Proj4js.common.PJD_NODATUM;
 | 
						||
    }
 | 
						||
    if (proj && proj.datum_params) {
 | 
						||
      for (var i=0; i<proj.datum_params.length; i++) {
 | 
						||
        proj.datum_params[i]=parseFloat(proj.datum_params[i]);
 | 
						||
      }
 | 
						||
      if (proj.datum_params[0] != 0 || proj.datum_params[1] != 0 || proj.datum_params[2] != 0 ) {
 | 
						||
        this.datum_type = Proj4js.common.PJD_3PARAM;
 | 
						||
      }
 | 
						||
      if (proj.datum_params.length > 3) {
 | 
						||
        if (proj.datum_params[3] != 0 || proj.datum_params[4] != 0 ||
 | 
						||
            proj.datum_params[5] != 0 || proj.datum_params[6] != 0 ) {
 | 
						||
          this.datum_type = Proj4js.common.PJD_7PARAM;
 | 
						||
          proj.datum_params[3] *= Proj4js.common.SEC_TO_RAD;
 | 
						||
          proj.datum_params[4] *= Proj4js.common.SEC_TO_RAD;
 | 
						||
          proj.datum_params[5] *= Proj4js.common.SEC_TO_RAD;
 | 
						||
          proj.datum_params[6] = (proj.datum_params[6]/1000000.0) + 1.0;
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
    if (proj) {
 | 
						||
      this.a = proj.a;    //datum object also uses these values
 | 
						||
      this.b = proj.b;
 | 
						||
      this.es = proj.es;
 | 
						||
      this.ep2 = proj.ep2;
 | 
						||
      this.datum_params = proj.datum_params;
 | 
						||
    }
 | 
						||
  },
 | 
						||
 | 
						||
  /****************************************************************/
 | 
						||
  // cs_compare_datums()
 | 
						||
  //   Returns TRUE if the two datums match, otherwise FALSE.
 | 
						||
  compare_datums : function( dest ) {
 | 
						||
    if( this.datum_type != dest.datum_type ) {
 | 
						||
      return false; // false, datums are not equal
 | 
						||
    } else if( this.a != dest.a || Math.abs(this.es-dest.es) > 0.000000000050 ) {
 | 
						||
      // the tolerence for es is to ensure that GRS80 and WGS84
 | 
						||
      // are considered identical
 | 
						||
      return false;
 | 
						||
    } else if( this.datum_type == Proj4js.common.PJD_3PARAM ) {
 | 
						||
      return (this.datum_params[0] == dest.datum_params[0]
 | 
						||
              && this.datum_params[1] == dest.datum_params[1]
 | 
						||
              && this.datum_params[2] == dest.datum_params[2]);
 | 
						||
    } else if( this.datum_type == Proj4js.common.PJD_7PARAM ) {
 | 
						||
      return (this.datum_params[0] == dest.datum_params[0]
 | 
						||
              && this.datum_params[1] == dest.datum_params[1]
 | 
						||
              && this.datum_params[2] == dest.datum_params[2]
 | 
						||
              && this.datum_params[3] == dest.datum_params[3]
 | 
						||
              && this.datum_params[4] == dest.datum_params[4]
 | 
						||
              && this.datum_params[5] == dest.datum_params[5]
 | 
						||
              && this.datum_params[6] == dest.datum_params[6]);
 | 
						||
    } else if ( this.datum_type == Proj4js.common.PJD_GRIDSHIFT ||
 | 
						||
                dest.datum_type == Proj4js.common.PJD_GRIDSHIFT ) {
 | 
						||
      alert("ERROR: Grid shift transformations are not implemented.");
 | 
						||
      return false
 | 
						||
    } else {
 | 
						||
      return true; // datums are equal
 | 
						||
    }
 | 
						||
  }, // cs_compare_datums()
 | 
						||
 | 
						||
  /*
 | 
						||
   * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
 | 
						||
   * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
 | 
						||
   * according to the current ellipsoid parameters.
 | 
						||
   *
 | 
						||
   *    Latitude  : Geodetic latitude in radians                     (input)
 | 
						||
   *    Longitude : Geodetic longitude in radians                    (input)
 | 
						||
   *    Height    : Geodetic height, in meters                       (input)
 | 
						||
   *    X         : Calculated Geocentric X coordinate, in meters    (output)
 | 
						||
   *    Y         : Calculated Geocentric Y coordinate, in meters    (output)
 | 
						||
   *    Z         : Calculated Geocentric Z coordinate, in meters    (output)
 | 
						||
   *
 | 
						||
   */
 | 
						||
  geodetic_to_geocentric : function(p) {
 | 
						||
    var Longitude = p.x;
 | 
						||
    var Latitude = p.y;
 | 
						||
    var Height = p.z ? p.z : 0;   //Z value not always supplied
 | 
						||
    var X;  // output
 | 
						||
    var Y;
 | 
						||
    var Z;
 | 
						||
 | 
						||
    var Error_Code=0;  //  GEOCENT_NO_ERROR;
 | 
						||
    var Rn;            /*  Earth radius at location  */
 | 
						||
    var Sin_Lat;       /*  Math.sin(Latitude)  */
 | 
						||
    var Sin2_Lat;      /*  Square of Math.sin(Latitude)  */
 | 
						||
    var Cos_Lat;       /*  Math.cos(Latitude)  */
 | 
						||
 | 
						||
    /*
 | 
						||
    ** Don't blow up if Latitude is just a little out of the value
 | 
						||
    ** range as it may just be a rounding issue.  Also removed longitude
 | 
						||
    ** test, it should be wrapped by Math.cos() and Math.sin().  NFW for PROJ.4, Sep/2001.
 | 
						||
    */
 | 
						||
    if( Latitude < -Proj4js.common.HALF_PI && Latitude > -1.001 * Proj4js.common.HALF_PI ) {
 | 
						||
        Latitude = -Proj4js.common.HALF_PI;
 | 
						||
    } else if( Latitude > Proj4js.common.HALF_PI && Latitude < 1.001 * Proj4js.common.HALF_PI ) {
 | 
						||
        Latitude = Proj4js.common.HALF_PI;
 | 
						||
    } else if ((Latitude < -Proj4js.common.HALF_PI) || (Latitude > Proj4js.common.HALF_PI)) {
 | 
						||
      /* Latitude out of range */
 | 
						||
      Proj4js.reportError('geocent:lat out of range:'+Latitude);
 | 
						||
      return null;
 | 
						||
    }
 | 
						||
 | 
						||
    if (Longitude > Proj4js.common.PI) Longitude -= (2*Proj4js.common.PI);
 | 
						||
    Sin_Lat = Math.sin(Latitude);
 | 
						||
    Cos_Lat = Math.cos(Latitude);
 | 
						||
    Sin2_Lat = Sin_Lat * Sin_Lat;
 | 
						||
    Rn = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat));
 | 
						||
    X = (Rn + Height) * Cos_Lat * Math.cos(Longitude);
 | 
						||
    Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude);
 | 
						||
    Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat;
 | 
						||
 | 
						||
    p.x = X;
 | 
						||
    p.y = Y;
 | 
						||
    p.z = Z;
 | 
						||
    return Error_Code;
 | 
						||
  }, // cs_geodetic_to_geocentric()
 | 
						||
 | 
						||
 | 
						||
  geocentric_to_geodetic : function (p) {
 | 
						||
/* local defintions and variables */
 | 
						||
/* end-criterium of loop, accuracy of sin(Latitude) */
 | 
						||
var genau = 1.E-12;
 | 
						||
var genau2 = (genau*genau);
 | 
						||
var maxiter = 30;
 | 
						||
 | 
						||
    var P;        /* distance between semi-minor axis and location */
 | 
						||
    var RR;       /* distance between center and location */
 | 
						||
    var CT;       /* sin of geocentric latitude */
 | 
						||
    var ST;       /* cos of geocentric latitude */
 | 
						||
    var RX;
 | 
						||
    var RK;
 | 
						||
    var RN;       /* Earth radius at location */
 | 
						||
    var CPHI0;    /* cos of start or old geodetic latitude in iterations */
 | 
						||
    var SPHI0;    /* sin of start or old geodetic latitude in iterations */
 | 
						||
    var CPHI;     /* cos of searched geodetic latitude */
 | 
						||
    var SPHI;     /* sin of searched geodetic latitude */
 | 
						||
    var SDPHI;    /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
 | 
						||
    var At_Pole;     /* indicates location is in polar region */
 | 
						||
    var iter;        /* # of continous iteration, max. 30 is always enough (s.a.) */
 | 
						||
 | 
						||
    var X = p.x;
 | 
						||
    var Y = p.y;
 | 
						||
    var Z = p.z ? p.z : 0.0;   //Z value not always supplied
 | 
						||
    var Longitude;
 | 
						||
    var Latitude;
 | 
						||
    var Height;
 | 
						||
 | 
						||
    At_Pole = false;
 | 
						||
    P = Math.sqrt(X*X+Y*Y);
 | 
						||
    RR = Math.sqrt(X*X+Y*Y+Z*Z);
 | 
						||
 | 
						||
/*      special cases for latitude and longitude */
 | 
						||
    if (P/this.a < genau) {
 | 
						||
 | 
						||
/*  special case, if P=0. (X=0., Y=0.) */
 | 
						||
        At_Pole = true;
 | 
						||
        Longitude = 0.0;
 | 
						||
 | 
						||
/*  if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
 | 
						||
 *  of ellipsoid (=center of mass), Latitude becomes PI/2 */
 | 
						||
        if (RR/this.a < genau) {
 | 
						||
            Latitude = Proj4js.common.HALF_PI;
 | 
						||
            Height   = -this.b;
 | 
						||
            return;
 | 
						||
        }
 | 
						||
    } else {
 | 
						||
/*  ellipsoidal (geodetic) longitude
 | 
						||
 *  interval: -PI < Longitude <= +PI */
 | 
						||
        Longitude=Math.atan2(Y,X);
 | 
						||
    }
 | 
						||
 | 
						||
/* --------------------------------------------------------------
 | 
						||
 * Following iterative algorithm was developped by
 | 
						||
 * "Institut f<>r Erdmessung", University of Hannover, July 1988.
 | 
						||
 * Internet: www.ife.uni-hannover.de
 | 
						||
 * Iterative computation of CPHI,SPHI and Height.
 | 
						||
 * Iteration of CPHI and SPHI to 10**-12 radian resp.
 | 
						||
 * 2*10**-7 arcsec.
 | 
						||
 * --------------------------------------------------------------
 | 
						||
 */
 | 
						||
    CT = Z/RR;
 | 
						||
    ST = P/RR;
 | 
						||
    RX = 1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST);
 | 
						||
    CPHI0 = ST*(1.0-this.es)*RX;
 | 
						||
    SPHI0 = CT*RX;
 | 
						||
    iter = 0;
 | 
						||
 | 
						||
/* loop to find sin(Latitude) resp. Latitude
 | 
						||
 * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
 | 
						||
    do
 | 
						||
    {
 | 
						||
        iter++;
 | 
						||
        RN = this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0);
 | 
						||
 | 
						||
/*  ellipsoidal (geodetic) height */
 | 
						||
        Height = P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0);
 | 
						||
 | 
						||
        RK = this.es*RN/(RN+Height);
 | 
						||
        RX = 1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST);
 | 
						||
        CPHI = ST*(1.0-RK)*RX;
 | 
						||
        SPHI = CT*RX;
 | 
						||
        SDPHI = SPHI*CPHI0-CPHI*SPHI0;
 | 
						||
        CPHI0 = CPHI;
 | 
						||
        SPHI0 = SPHI;
 | 
						||
    }
 | 
						||
    while (SDPHI*SDPHI > genau2 && iter < maxiter);
 | 
						||
 | 
						||
/*      ellipsoidal (geodetic) latitude */
 | 
						||
    Latitude=Math.atan(SPHI/Math.abs(CPHI));
 | 
						||
 | 
						||
    p.x = Longitude;
 | 
						||
    p.y = Latitude;
 | 
						||
    p.z = Height;
 | 
						||
    return p;
 | 
						||
  }, // cs_geocentric_to_geodetic()
 | 
						||
 | 
						||
  /** Convert_Geocentric_To_Geodetic
 | 
						||
   * The method used here is derived from 'An Improved Algorithm for
 | 
						||
   * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
 | 
						||
   */
 | 
						||
  geocentric_to_geodetic_noniter : function (p) {
 | 
						||
    var X = p.x;
 | 
						||
    var Y = p.y;
 | 
						||
    var Z = p.z ? p.z : 0;   //Z value not always supplied
 | 
						||
    var Longitude;
 | 
						||
    var Latitude;
 | 
						||
    var Height;
 | 
						||
 | 
						||
    var W;        /* distance from Z axis */
 | 
						||
    var W2;       /* square of distance from Z axis */
 | 
						||
    var T0;       /* initial estimate of vertical component */
 | 
						||
    var T1;       /* corrected estimate of vertical component */
 | 
						||
    var S0;       /* initial estimate of horizontal component */
 | 
						||
    var S1;       /* corrected estimate of horizontal component */
 | 
						||
    var Sin_B0;   /* Math.sin(B0), B0 is estimate of Bowring aux variable */
 | 
						||
    var Sin3_B0;  /* cube of Math.sin(B0) */
 | 
						||
    var Cos_B0;   /* Math.cos(B0) */
 | 
						||
    var Sin_p1;   /* Math.sin(phi1), phi1 is estimated latitude */
 | 
						||
    var Cos_p1;   /* Math.cos(phi1) */
 | 
						||
    var Rn;       /* Earth radius at location */
 | 
						||
    var Sum;      /* numerator of Math.cos(phi1) */
 | 
						||
    var At_Pole;  /* indicates location is in polar region */
 | 
						||
 | 
						||
    X = parseFloat(X);  // cast from string to float
 | 
						||
    Y = parseFloat(Y);
 | 
						||
    Z = parseFloat(Z);
 | 
						||
 | 
						||
    At_Pole = false;
 | 
						||
    if (X != 0.0)
 | 
						||
    {
 | 
						||
        Longitude = Math.atan2(Y,X);
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        if (Y > 0)
 | 
						||
        {
 | 
						||
            Longitude = Proj4js.common.HALF_PI;
 | 
						||
        }
 | 
						||
        else if (Y < 0)
 | 
						||
        {
 | 
						||
            Longitude = -Proj4js.common.HALF_PI;
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            At_Pole = true;
 | 
						||
            Longitude = 0.0;
 | 
						||
            if (Z > 0.0)
 | 
						||
            {  /* north pole */
 | 
						||
                Latitude = Proj4js.common.HALF_PI;
 | 
						||
            }
 | 
						||
            else if (Z < 0.0)
 | 
						||
            {  /* south pole */
 | 
						||
                Latitude = -Proj4js.common.HALF_PI;
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {  /* center of earth */
 | 
						||
                Latitude = Proj4js.common.HALF_PI;
 | 
						||
                Height = -this.b;
 | 
						||
                return;
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 | 
						||
    W2 = X*X + Y*Y;
 | 
						||
    W = Math.sqrt(W2);
 | 
						||
    T0 = Z * Proj4js.common.AD_C;
 | 
						||
    S0 = Math.sqrt(T0 * T0 + W2);
 | 
						||
    Sin_B0 = T0 / S0;
 | 
						||
    Cos_B0 = W / S0;
 | 
						||
    Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
 | 
						||
    T1 = Z + this.b * this.ep2 * Sin3_B0;
 | 
						||
    Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0;
 | 
						||
    S1 = Math.sqrt(T1*T1 + Sum * Sum);
 | 
						||
    Sin_p1 = T1 / S1;
 | 
						||
    Cos_p1 = Sum / S1;
 | 
						||
    Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1);
 | 
						||
    if (Cos_p1 >= Proj4js.common.COS_67P5)
 | 
						||
    {
 | 
						||
        Height = W / Cos_p1 - Rn;
 | 
						||
    }
 | 
						||
    else if (Cos_p1 <= -Proj4js.common.COS_67P5)
 | 
						||
    {
 | 
						||
        Height = W / -Cos_p1 - Rn;
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        Height = Z / Sin_p1 + Rn * (this.es - 1.0);
 | 
						||
    }
 | 
						||
    if (At_Pole == false)
 | 
						||
    {
 | 
						||
        Latitude = Math.atan(Sin_p1 / Cos_p1);
 | 
						||
    }
 | 
						||
 | 
						||
    p.x = Longitude;
 | 
						||
    p.y = Latitude;
 | 
						||
    p.z = Height;
 | 
						||
    return p;
 | 
						||
  }, // geocentric_to_geodetic_noniter()
 | 
						||
 | 
						||
  /****************************************************************/
 | 
						||
  // pj_geocentic_to_wgs84( p )
 | 
						||
  //  p = point to transform in geocentric coordinates (x,y,z)
 | 
						||
  geocentric_to_wgs84 : function ( p ) {
 | 
						||
 | 
						||
    if( this.datum_type == Proj4js.common.PJD_3PARAM )
 | 
						||
    {
 | 
						||
      // if( x[io] == HUGE_VAL )
 | 
						||
      //    continue;
 | 
						||
      p.x += this.datum_params[0];
 | 
						||
      p.y += this.datum_params[1];
 | 
						||
      p.z += this.datum_params[2];
 | 
						||
 | 
						||
    }
 | 
						||
    else if (this.datum_type == Proj4js.common.PJD_7PARAM)
 | 
						||
    {
 | 
						||
      var Dx_BF =this.datum_params[0];
 | 
						||
      var Dy_BF =this.datum_params[1];
 | 
						||
      var Dz_BF =this.datum_params[2];
 | 
						||
      var Rx_BF =this.datum_params[3];
 | 
						||
      var Ry_BF =this.datum_params[4];
 | 
						||
      var Rz_BF =this.datum_params[5];
 | 
						||
      var M_BF  =this.datum_params[6];
 | 
						||
      // if( x[io] == HUGE_VAL )
 | 
						||
      //    continue;
 | 
						||
      var x_out = M_BF*(       p.x - Rz_BF*p.y + Ry_BF*p.z) + Dx_BF;
 | 
						||
      var y_out = M_BF*( Rz_BF*p.x +       p.y - Rx_BF*p.z) + Dy_BF;
 | 
						||
      var z_out = M_BF*(-Ry_BF*p.x + Rx_BF*p.y +       p.z) + Dz_BF;
 | 
						||
      p.x = x_out;
 | 
						||
      p.y = y_out;
 | 
						||
      p.z = z_out;
 | 
						||
    }
 | 
						||
  }, // cs_geocentric_to_wgs84
 | 
						||
 | 
						||
  /****************************************************************/
 | 
						||
  // pj_geocentic_from_wgs84()
 | 
						||
  //  coordinate system definition,
 | 
						||
  //  point to transform in geocentric coordinates (x,y,z)
 | 
						||
  geocentric_from_wgs84 : function( p ) {
 | 
						||
 | 
						||
    if( this.datum_type == Proj4js.common.PJD_3PARAM )
 | 
						||
    {
 | 
						||
      //if( x[io] == HUGE_VAL )
 | 
						||
      //    continue;
 | 
						||
      p.x -= this.datum_params[0];
 | 
						||
      p.y -= this.datum_params[1];
 | 
						||
      p.z -= this.datum_params[2];
 | 
						||
 | 
						||
    }
 | 
						||
    else if (this.datum_type == Proj4js.common.PJD_7PARAM)
 | 
						||
    {
 | 
						||
      var Dx_BF =this.datum_params[0];
 | 
						||
      var Dy_BF =this.datum_params[1];
 | 
						||
      var Dz_BF =this.datum_params[2];
 | 
						||
      var Rx_BF =this.datum_params[3];
 | 
						||
      var Ry_BF =this.datum_params[4];
 | 
						||
      var Rz_BF =this.datum_params[5];
 | 
						||
      var M_BF  =this.datum_params[6];
 | 
						||
      var x_tmp = (p.x - Dx_BF) / M_BF;
 | 
						||
      var y_tmp = (p.y - Dy_BF) / M_BF;
 | 
						||
      var z_tmp = (p.z - Dz_BF) / M_BF;
 | 
						||
      //if( x[io] == HUGE_VAL )
 | 
						||
      //    continue;
 | 
						||
 | 
						||
      p.x =        x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp;
 | 
						||
      p.y = -Rz_BF*x_tmp +       y_tmp + Rx_BF*z_tmp;
 | 
						||
      p.z =  Ry_BF*x_tmp - Rx_BF*y_tmp +       z_tmp;
 | 
						||
    } //cs_geocentric_from_wgs84()
 | 
						||
  }
 | 
						||
});
 | 
						||
 | 
						||
/** point object, nothing fancy, just allows values to be
 | 
						||
    passed back and forth by reference rather than by value.
 | 
						||
    Other point classes may be used as long as they have
 | 
						||
    x and y properties, which will get modified in the transform method.
 | 
						||
*/
 | 
						||
Proj4js.Point = Proj4js.Class({
 | 
						||
 | 
						||
    /**
 | 
						||
     * Constructor: Proj4js.Point
 | 
						||
     *
 | 
						||
     * Parameters:
 | 
						||
     * - x {float} or {Array} either the first coordinates component or
 | 
						||
     *     the full coordinates
 | 
						||
     * - y {float} the second component
 | 
						||
     * - z {float} the third component, optional.
 | 
						||
     */
 | 
						||
    initialize : function(x,y,z) {
 | 
						||
      if (typeof x == 'object') {
 | 
						||
        this.x = x[0];
 | 
						||
        this.y = x[1];
 | 
						||
        this.z = x[2] || 0.0;
 | 
						||
      } else if (typeof x == 'string' && typeof y == 'undefined') {
 | 
						||
        var coords = x.split(',');
 | 
						||
        this.x = parseFloat(coords[0]);
 | 
						||
        this.y = parseFloat(coords[1]);
 | 
						||
        this.z = parseFloat(coords[2]) || 0.0;
 | 
						||
      } else {
 | 
						||
        this.x = x;
 | 
						||
        this.y = y;
 | 
						||
        this.z = z || 0.0;
 | 
						||
      }
 | 
						||
    },
 | 
						||
 | 
						||
    /**
 | 
						||
     * APIMethod: clone
 | 
						||
     * Build a copy of a Proj4js.Point object.
 | 
						||
     *
 | 
						||
     * Return:
 | 
						||
     * {Proj4js}.Point the cloned point.
 | 
						||
     */
 | 
						||
    clone : function() {
 | 
						||
      return new Proj4js.Point(this.x, this.y, this.z);
 | 
						||
    },
 | 
						||
 | 
						||
    /**
 | 
						||
     * APIMethod: toString
 | 
						||
     * Return a readable string version of the point
 | 
						||
     *
 | 
						||
     * Return:
 | 
						||
     * {String} String representation of Proj4js.Point object. 
 | 
						||
     *           (ex. <i>"x=5,y=42"</i>)
 | 
						||
     */
 | 
						||
    toString : function() {
 | 
						||
        return ("x=" + this.x + ",y=" + this.y);
 | 
						||
    },
 | 
						||
 | 
						||
    /** 
 | 
						||
     * APIMethod: toShortString
 | 
						||
     * Return a short string version of the point.
 | 
						||
     *
 | 
						||
     * Return:
 | 
						||
     * {String} Shortened String representation of Proj4js.Point object. 
 | 
						||
     *         (ex. <i>"5, 42"</i>)
 | 
						||
     */
 | 
						||
    toShortString : function() {
 | 
						||
        return (this.x + ", " + this.y);
 | 
						||
    }
 | 
						||
});
 | 
						||
 | 
						||
Proj4js.PrimeMeridian = {
 | 
						||
    "greenwich": 0.0,               //"0dE",
 | 
						||
    "lisbon":     -9.131906111111,   //"9d07'54.862\"W",
 | 
						||
    "paris":       2.337229166667,   //"2d20'14.025\"E",
 | 
						||
    "bogota":    -74.080916666667,  //"74d04'51.3\"W",
 | 
						||
    "madrid":     -3.687938888889,  //"3d41'16.58\"W",
 | 
						||
    "rome":       12.452333333333,  //"12d27'8.4\"E",
 | 
						||
    "bern":        7.439583333333,  //"7d26'22.5\"E",
 | 
						||
    "jakarta":   106.807719444444,  //"106d48'27.79\"E",
 | 
						||
    "ferro":     -17.666666666667,  //"17d40'W",
 | 
						||
    "brussels":    4.367975,        //"4d22'4.71\"E",
 | 
						||
    "stockholm":  18.058277777778,  //"18d3'29.8\"E",
 | 
						||
    "athens":     23.7163375,       //"23d42'58.815\"E",
 | 
						||
    "oslo":       10.722916666667   //"10d43'22.5\"E"
 | 
						||
};
 | 
						||
 | 
						||
Proj4js.Ellipsoid = {
 | 
						||
  "MERIT": {a:6378137.0, rf:298.257, ellipseName:"MERIT 1983"},
 | 
						||
  "SGS85": {a:6378136.0, rf:298.257, ellipseName:"Soviet Geodetic System 85"},
 | 
						||
  "GRS80": {a:6378137.0, rf:298.257222101, ellipseName:"GRS 1980(IUGG, 1980)"},
 | 
						||
  "IAU76": {a:6378140.0, rf:298.257, ellipseName:"IAU 1976"},
 | 
						||
  "airy": {a:6377563.396, b:6356256.910, ellipseName:"Airy 1830"},
 | 
						||
  "APL4.": {a:6378137, rf:298.25, ellipseName:"Appl. Physics. 1965"},
 | 
						||
  "NWL9D": {a:6378145.0, rf:298.25, ellipseName:"Naval Weapons Lab., 1965"},
 | 
						||
  "mod_airy": {a:6377340.189, b:6356034.446, ellipseName:"Modified Airy"},
 | 
						||
  "andrae": {a:6377104.43, rf:300.0, ellipseName:"Andrae 1876 (Den., Iclnd.)"},
 | 
						||
  "aust_SA": {a:6378160.0, rf:298.25, ellipseName:"Australian Natl & S. Amer. 1969"},
 | 
						||
  "GRS67": {a:6378160.0, rf:298.2471674270, ellipseName:"GRS 67(IUGG 1967)"},
 | 
						||
  "bessel": {a:6377397.155, rf:299.1528128, ellipseName:"Bessel 1841"},
 | 
						||
  "bess_nam": {a:6377483.865, rf:299.1528128, ellipseName:"Bessel 1841 (Namibia)"},
 | 
						||
  "clrk66": {a:6378206.4, b:6356583.8, ellipseName:"Clarke 1866"},
 | 
						||
  "clrk80": {a:6378249.145, rf:293.4663, ellipseName:"Clarke 1880 mod."},
 | 
						||
  "CPM": {a:6375738.7, rf:334.29, ellipseName:"Comm. des Poids et Mesures 1799"},
 | 
						||
  "delmbr": {a:6376428.0, rf:311.5, ellipseName:"Delambre 1810 (Belgium)"},
 | 
						||
  "engelis": {a:6378136.05, rf:298.2566, ellipseName:"Engelis 1985"},
 | 
						||
  "evrst30": {a:6377276.345, rf:300.8017, ellipseName:"Everest 1830"},
 | 
						||
  "evrst48": {a:6377304.063, rf:300.8017, ellipseName:"Everest 1948"},
 | 
						||
  "evrst56": {a:6377301.243, rf:300.8017, ellipseName:"Everest 1956"},
 | 
						||
  "evrst69": {a:6377295.664, rf:300.8017, ellipseName:"Everest 1969"},
 | 
						||
  "evrstSS": {a:6377298.556, rf:300.8017, ellipseName:"Everest (Sabah & Sarawak)"},
 | 
						||
  "fschr60": {a:6378166.0, rf:298.3, ellipseName:"Fischer (Mercury Datum) 1960"},
 | 
						||
  "fschr60m": {a:6378155.0, rf:298.3, ellipseName:"Fischer 1960"},
 | 
						||
  "fschr68": {a:6378150.0, rf:298.3, ellipseName:"Fischer 1968"},
 | 
						||
  "helmert": {a:6378200.0, rf:298.3, ellipseName:"Helmert 1906"},
 | 
						||
  "hough": {a:6378270.0, rf:297.0, ellipseName:"Hough"},
 | 
						||
  "intl": {a:6378388.0, rf:297.0, ellipseName:"International 1909 (Hayford)"},
 | 
						||
  "kaula": {a:6378163.0, rf:298.24, ellipseName:"Kaula 1961"},
 | 
						||
  "lerch": {a:6378139.0, rf:298.257, ellipseName:"Lerch 1979"},
 | 
						||
  "mprts": {a:6397300.0, rf:191.0, ellipseName:"Maupertius 1738"},
 | 
						||
  "new_intl": {a:6378157.5, b:6356772.2, ellipseName:"New International 1967"},
 | 
						||
  "plessis": {a:6376523.0, rf:6355863.0, ellipseName:"Plessis 1817 (France)"},
 | 
						||
  "krass": {a:6378245.0, rf:298.3, ellipseName:"Krassovsky, 1942"},
 | 
						||
  "SEasia": {a:6378155.0, b:6356773.3205, ellipseName:"Southeast Asia"},
 | 
						||
  "walbeck": {a:6376896.0, b:6355834.8467, ellipseName:"Walbeck"},
 | 
						||
  "WGS60": {a:6378165.0, rf:298.3, ellipseName:"WGS 60"},
 | 
						||
  "WGS66": {a:6378145.0, rf:298.25, ellipseName:"WGS 66"},
 | 
						||
  "WGS72": {a:6378135.0, rf:298.26, ellipseName:"WGS 72"},
 | 
						||
  "WGS84": {a:6378137.0, rf:298.257223563, ellipseName:"WGS 84"},
 | 
						||
  "sphere": {a:6370997.0, b:6370997.0, ellipseName:"Normal Sphere (r=6370997)"}
 | 
						||
};
 | 
						||
 | 
						||
Proj4js.Datum = {
 | 
						||
  "WGS84": {towgs84: "0,0,0", ellipse: "WGS84", datumName: "WGS84"},
 | 
						||
  "GGRS87": {towgs84: "-199.87,74.79,246.62", ellipse: "GRS80", datumName: "Greek_Geodetic_Reference_System_1987"},
 | 
						||
  "NAD83": {towgs84: "0,0,0", ellipse: "GRS80", datumName: "North_American_Datum_1983"},
 | 
						||
  "NAD27": {nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", ellipse: "clrk66", datumName: "North_American_Datum_1927"},
 | 
						||
  "potsdam": {towgs84: "606.0,23.0,413.0", ellipse: "bessel", datumName: "Potsdam Rauenberg 1950 DHDN"},
 | 
						||
  "carthage": {towgs84: "-263.0,6.0,431.0", ellipse: "clark80", datumName: "Carthage 1934 Tunisia"},
 | 
						||
  "hermannskogel": {towgs84: "653.0,-212.0,449.0", ellipse: "bessel", datumName: "Hermannskogel"},
 | 
						||
  "ire65": {towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", ellipse: "mod_airy", datumName: "Ireland 1965"},
 | 
						||
  "nzgd49": {towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993", ellipse: "intl", datumName: "New Zealand Geodetic Datum 1949"},
 | 
						||
  "OSGB36": {towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", ellipse: "airy", datumName: "Airy 1830"}
 | 
						||
};
 | 
						||
 | 
						||
Proj4js.WGS84 = new Proj4js.Proj('WGS84');
 | 
						||
Proj4js.Datum['OSB36'] = Proj4js.Datum['OSGB36']; //as returned from spatialreference.org
 | 
						||
 | 
						||
//lookup table to go from the projection name in WKT to the Proj4js projection name
 | 
						||
//build this out as required
 | 
						||
Proj4js.wktProjections = {
 | 
						||
  "Lambert Tangential Conformal Conic Projection": "lcc",
 | 
						||
  "Mercator": "merc",
 | 
						||
  "Popular Visualisation Pseudo Mercator": "merc",
 | 
						||
  "Mercator_1SP": "merc",
 | 
						||
  "Transverse_Mercator": "tmerc",
 | 
						||
  "Transverse Mercator": "tmerc",
 | 
						||
  "Lambert Azimuthal Equal Area": "laea",
 | 
						||
  "Universal Transverse Mercator System": "utm"
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
Proj4js.defs['EPSG:3857'] = Proj4js.defs['EPSG:3785']; |