+++ /dev/null
-/* Copyright (c) 2006 MetaCarta, Inc., published under the BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/license.txt for the full
- * text of the license. */
-/**
-* @class
-*/
-OpenLayers.Util = new Object();
-
-
-
-
-/**
-* @class This class represents a screen coordinate, in x and y coordinates
-*/
-OpenLayers.Pixel = Class.create();
-OpenLayers.Pixel.prototype = {
-
- /** @type float */
- x: 0.0,
-
- /** @type float */
- y: 0.0,
-
- /**
- * @constructor
- *
- * @param {float} x
- * @param {float} y
- */
- initialize: function(x, y) {
- this.x = x;
- this.y = y;
- },
-
- /**
- * @return string representation of Pixel. ex: "x=200.4,y=242.2"
- * @type str
- */
- toString:function() {
- return ("x=" + this.x + ",y=" + this.y);
- },
-
- /**
- * @type OpenLayers.Pixel
- */
- copyOf:function() {
- return new OpenLayers.Pixel(this.x, this.y);
- },
-
- /**
- * @param {OpenLayers.Pixel} px
- *
- * @return whether or not the point passed in as parameter is equal to this
- * note that if px passed in is null, returns false
- * @type bool
- */
- equals:function(px) {
- var equals = false;
- if (px != null) {
- equals = ((this.x == px.x) && (this.y == px.y));
- }
- return equals;
- },
-
- /**
- * @param {int} x
- * @param {int} y
- *
- * @return a new Pixel with this pixel's x&y augmented by the
- * values passed in.
- * @type OpenLayers.Pixel
- */
- add:function(x, y) {
- return new OpenLayers.Pixel(this.x + x, this.y + y);
- },
-
- /**
- * @param {OpenLayers.Pixel} px
- *
- * @return a new Pixel with this pixel's x&y augmented by the
- * x&y values of the pixel passed in.
- * @type OpenLayers.Pixel
- */
- offset:function(px) {
- return this.add(px.x, px.y);
- },
-
- /** @final @type str */
- CLASS_NAME: "OpenLayers.Pixel"
-};
-
-
-/**
-* @class This class represents a width and height pair
-*/
-OpenLayers.Size = Class.create();
-OpenLayers.Size.prototype = {
-
- /** @type float */
- w: 0.0,
-
- /** @type float */
- h: 0.0,
-
-
- /**
- * @constructor
- *
- * @param {float} w
- * @param {float} h
- */
- initialize: function(w, h) {
- this.w = w;
- this.h = h;
- },
-
- /**
- * @return String representation of OpenLayers.Size object.
- * (ex. <i>"w=55,h=66"</i>)
- * @type String
- */
- toString:function() {
- return ("w=" + this.w + ",h=" + this.h);
- },
-
- /**
- * @return New OpenLayers.Size object with the same w and h values
- * @type OpenLayers.Size
- */
- copyOf:function() {
- return new OpenLayers.Size(this.w, this.h);
- },
-
- /**
- * @param {OpenLayers.Size} sz
- * @returns Boolean value indicating whether the passed-in OpenLayers.Size
- * object has the same w and h components as this
- * note that if sz passed in is null, returns false
- *
- * @type bool
- */
- equals:function(sz) {
- var equals = false;
- if (sz != null) {
- equals = ((this.w == sz.w) && (this.h == sz.h));
- }
- return equals;
- },
-
- /** @final @type String */
- CLASS_NAME: "OpenLayers.Size"
-};
-
-/**
-* @class This class represents a longitude and latitude pair
-*/
-OpenLayers.LonLat = Class.create();
-OpenLayers.LonLat.prototype = {
-
- /** @type float */
- lon: 0.0,
-
- /** @type float */
- lat: 0.0,
-
- /**
- * @constructor
- *
- * @param {float} lon
- * @param {float} lat
- */
- initialize: function(lon, lat) {
- this.lon = lon;
- this.lat = lat;
- },
-
- /**
- * @return String representation of OpenLayers.LonLat object.
- * (ex. <i>"lon=5,lat=42"</i>)
- * @type String
- */
- toString:function() {
- return ("lon=" + this.lon + ",lat=" + this.lat);
- },
-
- /**
- * @return Shortened String representation of OpenLayers.LonLat object.
- * (ex. <i>"5, 42"</i>)
- * @type String
- */
- toShortString:function() {
- return (this.lon + ", " + this.lat);
- },
-
- /**
- * @return New OpenLayers.LonLat object with the same lon and lat values
- * @type OpenLayers.LonLat
- */
- copyOf:function() {
- return new OpenLayers.LonLat(this.lon, this.lat);
- },
-
- /**
- * @param {float} lon
- * @param {float} lat
- *
- * @return A new OpenLayers.LonLat object with the lon and lat passed-in
- * added to this's.
- * @type OpenLayers.LonLat
- */
- add:function(lon, lat) {
- return new OpenLayers.LonLat(this.lon + lon, this.lat + lat);
- },
-
- /**
- * @param {OpenLayers.LonLat} ll
- * @returns Boolean value indicating whether the passed-in OpenLayers.LonLat
- * object has the same lon and lat components as this
- * note that if ll passed in is null, returns false
- *
- * @type bool
- */
- equals:function(ll) {
- var equals = false;
- if (ll != null) {
- equals = ((this.lon == ll.lon) && (this.lat == ll.lat));
- }
- return equals;
- },
-
- /** @final @type String */
- CLASS_NAME: "OpenLayers.LonLat"
-};
-
-/** Alternative constructor that builds a new OpenLayers.LonLat from a
-* parameter string
-*
-* @constructor
-*
-* @param {String} str Comma-separated Lon,Lat coordinate string.
-* (ex. <i>"5,40"</i>)
-*
-* @returns New OpenLayers.LonLat object built from the passed-in String.
-* @type OpenLayers.LonLat
-*/
-OpenLayers.LonLat.fromString = function(str) {
- var pair = str.split(",");
- return new OpenLayers.LonLat(parseFloat(pair[0]),
- parseFloat(pair[1]));
-};
-
-
-
-
-/**
-* @class This class represents a bounding box.
-* Data stored as left, bottom, right, top floats
-*/
-OpenLayers.Bounds = Class.create();
-OpenLayers.Bounds.prototype = {
-
- /** @type float */
- left: 0.0,
-
- /** @type float */
- bottom: 0.0,
-
- /** @type float */
- right: 0.0,
-
- /** @type float */
- top: 0.0,
-
- /**
- * @constructor
- *
- * @param {float} left
- * @param {float} bottom
- * @param {float} right
- * @param {float} top
- *
- */
- initialize: function(left, bottom, right, top) {
- this.left = left;
- this.bottom = bottom;
- this.right = right;
- this.top = top;
- },
-
- /**
- * @returns A fresh copy of the bounds
- * @type OpenLayers.Bounds
- */
- copyOf:function() {
- return new OpenLayers.Bounds(this.left, this.bottom,
- this.right, this.top);
- },
-
- /**
- * @param {OpenLayers.Bounds} bounds
- * @returns Boolean value indicating whether the passed-in OpenLayers.Bounds
- * object has the same left, right, top, bottom components as this
- * note that if bounds passed in is null, returns false
- *
- * @type bool
- */
- equals:function(bounds) {
- var equals = false;
- if (bounds != null) {
- equals = ((this.left == bounds.left) &&
- (this.right == bounds.right) &&
- (this.top == bounds.top) &&
- (this.bottom == bounds.bottom));
- }
- return equals;
- },
-
- /**
- * @return String representation of OpenLayers.Bounds object.
- * (ex.<i>"left-bottom=(5,42) right-top=(10,45)"</i>)
- * @type String
- */
- toString:function(){
- return ( "left-bottom=(" + this.left + "," + this.bottom + ")"
- + " right-top=(" + this.right + "," + this.top + ")" );
- },
-
- /**
- * @return Simple String representation of OpenLayers.Bounds object.
- * (ex. <i>"5,42,10,45"</i>)
- * @type String
- */
- toBBOX:function() {
- return (this.left + "," + this.bottom + ","
- + this.right + "," + this.top);
- },
-
- /**
- * @returns The width of the bounds
- * @type float
- */
- getWidth:function() {
- return (this.right - this.left);
- },
-
- /**
- * @returns The height of the bounds
- * @type float
- */
- getHeight:function() {
- return (this.top - this.bottom);
- },
-
- /**
- * @returns An OpenLayers.Size which represents the size of the box
- * @type OpenLayers.Size
- */
- getSize:function() {
- return new OpenLayers.Size(this.getWidth(), this.getHeight());
- },
-
- /**
- * @returns An OpenLayers.Pixel which represents the center of the bounds
- * @type OpenLayers.Pixel
- */
- getCenterPixel:function() {
- return new OpenLayers.Pixel( (this.left + this.right) / 2,
- (this.bottom + this.top) / 2);
- },
-
- /**
- * @returns An OpenLayers.LonLat which represents the center of the bounds
- * @type OpenLayers.LonLat
- */
- getCenterLonLat:function() {
- return new OpenLayers.LonLat( (this.left + this.right) / 2,
- (this.bottom + this.top) / 2);
- },
-
- /**
- * @param {float} x
- * @param {float} y
- *
- * @returns A new OpenLayers.Bounds whose coordinates are the same as this,
- * but shifted by the passed-in x and y values
- * @type OpenLayers.Bounds
- */
- add:function(x, y){
- return new OpenLayers.Box(this.left + x, this.bottom + y,
- this.right + x, this.top + y);
- },
-
- /**
- * @param {float} x
- * @param {float} y
- * @param {Boolean} inclusive Whether or not to include the border.
- * Default is true
- *
- * @return Whether or not the passed-in coordinates are within this bounds
- * @type Boolean
- */
- contains:function(x, y, inclusive) {
-
- //set default
- if (inclusive == null) {
- inclusive = true;
- }
-
- var contains = false;
- if (inclusive) {
- contains = ((x >= this.left) && (x <= this.right) &&
- (y >= this.bottom) && (y <= this.top));
- } else {
- contains = ((x > this.left) && (x < this.right) &&
- (y > this.bottom) && (y < this.top));
- }
- return contains;
- },
-
- /**
- * @param {OpenLayers.Bounds} bounds
- * @param {Boolean} partial If true, only part of passed-in
- * OpenLayers.Bounds needs be within this bounds.
- * If false, the entire passed-in bounds must be
- * within. Default is false
- * @param {Boolean} inclusive Whether or not to include the border.
- * Default is true
- *
- * @return Whether or not the passed-in OpenLayers.Bounds object is
- * contained within this bounds.
- * @type Boolean
- */
- containsBounds:function(bounds, partial, inclusive) {
-
- //set defaults
- if (partial == null) {
- partial = false;
- }
- if (inclusive == null) {
- inclusive = true;
- }
-
- var inLeft;
- var inTop;
- var inRight;
- var inBottom;
-
- if (inclusive) {
- inLeft = (bounds.left >= this.left) && (bounds.left <= this.right);
- inTop = (bounds.top >= this.bottom) && (bounds.top <= this.top);
- inRight= (bounds.right >= this.left) && (bounds.right <= this.right);
- inBottom = (bounds.bottom >= this.bottom) && (bounds.bottom <= this.top);
- } else {
- inLeft = (bounds.left > this.left) && (bounds.left < this.right);
- inTop = (bounds.top > this.bottom) && (bounds.top < this.top);
- inRight= (bounds.right > this.left) && (bounds.right < this.right);
- inBottom = (bounds.bottom > this.bottom) && (bounds.bottom < this.top);
- }
-
- return (partial) ? (inTop || inBottom) && (inLeft || inRight )
- : (inTop && inLeft && inBottom && inRight);
- },
-
- /**
- * @param {OpenLayers.LonLat} lonlat
- *
- * @returns The quadrant ("br" "tr" "tl" "bl") of the bounds in which
- * the coordinate lies.
- * @type String
- */
- determineQuadrant: function(lonlat) {
-
- var quadrant = "";
- var center = this.getCenterLonLat();
-
- quadrant += (lonlat.lat < center.lat) ? "b" : "t";
- quadrant += (lonlat.lon < center.lon) ? "l" : "r";
-
- return quadrant;
- },
-
- /** @final @type String */
- CLASS_NAME: "OpenLayers.Bounds"
-};
-
-/** Alternative constructor that builds a new OpenLayers.Bounds from a
-* parameter string
-*
-* @constructor
-*
-* @param {String} str Comma-separated bounds string. (ex. <i>"5,42,10,45"</i>)
-*
-* @returns New OpenLayers.Bounds object built from the passed-in String.
-* @type OpenLayers.Bounds
-*/
-OpenLayers.Bounds.fromString = function(str) {
- var bounds = str.split(",");
- return OpenLayers.Bounds.fromArray(bounds);
-};
-
-/** Alternative constructor that builds a new OpenLayers.Bounds
-* from an array
-*
-* @constructor
-*
-* @param {Array} bbox Array of bounds values (ex. <i>[5,42,10,45]</i>)
-*
-* @returns New OpenLayers.Bounds object built from the passed-in Array.
-* @type OpenLayers.Bounds
-*/
-OpenLayers.Bounds.fromArray = function(bbox) {
- return new OpenLayers.Bounds(parseFloat(bbox[0]),
- parseFloat(bbox[1]),
- parseFloat(bbox[2]),
- parseFloat(bbox[3]));
-};
-
-/** Alternative constructor that builds a new OpenLayers.Bounds
-* from an OpenLayers.Size
-*
-* @constructor
-*
-* @param {OpenLayers.Size} size
-*
-* @returns New OpenLayers.Bounds object built with top and left set to 0 and
-* bottom right taken from the passed-in OpenLayers.Size.
-* @type OpenLayers.Bounds
-*/
-OpenLayers.Bounds.fromSize = function(size) {
- return new OpenLayers.Bounds(0,
- size.h,
- size.w,
- 0);
-};
-/**
- * @param {String} quadrant
- *
- * @returns The opposing quadrant ("br" "tr" "tl" "bl"). For Example, if
- * you pass in "bl" it returns "tr", if you pass in "br" it
- * returns "tl", etc.
- * @type String
- */
-OpenLayers.Bounds.oppositeQuadrant = function(quadrant) {
- var opp = "";
-
- opp += (quadrant.charAt(0) == 't') ? 'b' : 't';
- opp += (quadrant.charAt(1) == 'l') ? 'r' : 'l';
-
- return opp;
-};
-
-// Some other helpful things
-
-/**
-* @param {String} sStart
-*
-* @returns Whether or not this string starts with the string passed in.
-* @type Boolean
-*/
-String.prototype.startsWith = function(sStart){
- return (this.substr(0,sStart.length) == sStart);
-};
-
-/**
-* @returns A trimmed version of the string - all leading and
-* trailing spaces removed
-* @type String
-*/
-String.prototype.trim = function() {
-
- var b = 0;
- while(this.substr(b,1) == " ") {
- b++;
- }
-
- var e = this.length - 1;
- while(this.substr(e,1) == " ") {
- e--;
- }
-
- return this.substring(b, e+1);
-};
-
-/** Remove an object from an array. Iterates through the array
-* to find the item, then removes it.
-*
-* @param {Object} item
-*
-* @returns A reference to the array
-* @type Array
-*/
-Array.prototype.remove = function(item) {
- for(var i=0; i < this.length; i++) {
- if(this[i] == item) {
- this.splice(i,1);
- //break;more than once??
- }
- }
- return this;
-}
-
-/**
-* @returns A fresh copy of the array
-* @type Array
-*/
-Array.prototype.copyOf = function() {
- var copy = new Array();
- for (var i = 0; i < this.length; i++) {
- copy[i] = this[i];
- }
- return copy;
-};
-
-/**
-* @param {Object} item
-*/
-Array.prototype.prepend = function(item) {
- this.splice(0, 0, item);
-};
-
-/**
-* @param {Object} item
-*/
-Array.prototype.append = function(item){
- this[this.length] = item;
-};
-
-/**
-*/
-Array.prototype.clear = function() {
- this.length = 0;
-};
-
-/**
-* @param {Object} element
-*
-* @returns The first index of the element in the array if found. Else returns -1
-* @type int
-*/
-Array.prototype.indexOf = function(element) {
- var index = -1;
- for(var i=0; i < this.length; i++) {
- if (this[i] == element) {
- index = i;
- break;
- }
- }
- return index;
-}
-
-/**
- * @param {String} id
- * @param {OpenLayers.Pixel} px
- * @param {OpenLayers.Size} sz
- * @param {String} position
- * @param {String} border
- * @param {String} overflow
- */
-OpenLayers.Util.modifyDOMElement = function(element, id, px, sz, position,
- border, overflow) {
-
- if (id) {
- element.id = id;
- }
- if (px) {
- element.style.left = px.x + "px";
- element.style.top = px.y + "px";
- }
- if (sz) {
- element.style.width = sz.w + "px";
- element.style.height = sz.h + "px";
- }
- if (position) {
- element.style.position = position;
- }
- if (border) {
- element.style.border = border;
- }
- if (overflow) {
- element.style.overflow = overflow;
- }
-};
-
-/**
-* zIndex is NOT set
-*
-* @param {String} id
-* @param {OpenLayers.Pixel} px
-* @param {OpenLayers.Size} sz
-* @param {String} imgURL
-* @param {String} position
-* @param {String} border
-* @param {String} overflow
-*
-* @returns A DOM Div created with the specified attributes.
-* @type DOMElement
-*/
-OpenLayers.Util.createDiv = function(id, px, sz, imgURL, position,
- border, overflow) {
-
- var dom = document.createElement('div');
-
- //set specific properties
- dom.style.padding = "0";
- dom.style.margin = "0";
- if (imgURL) {
- dom.style.backgroundImage = 'url(' + imgURL + ')';
- }
-
- //set generic properties
- if (!id) {
- id = "OpenLayersDiv" + (Math.random() * 10000 % 10000);
- }
- if (!position) {
- position = "absolute";
- }
- OpenLayers.Util.modifyDOMElement(dom, id, px, sz,
- position, border, overflow);
-
- return dom;
-};
-
-/**
-* @param {String} id
-* @param {OpenLayers.Pixel} px
-* @param {OpenLayers.Size} sz
-* @param {String} imgURL
-* @param {String} position
-* @param {String} border
-*
-* @returns A DOM Image created with the specified attributes.
-* @type DOMElement
-*/
-OpenLayers.Util.createImage = function(id, px, sz, imgURL, position, border) {
-
- image = document.createElement("img");
-
- //set special properties
- image.style.alt = id;
- image.galleryImg = "no";
- if (imgURL) {
- image.src = imgURL;
- }
-
- //set generic properties
- if (!id) {
- id = "OpenLayersDiv" + (Math.random() * 10000 % 10000);
- }
- if (!position) {
- position = "relative";
- }
- OpenLayers.Util.modifyDOMElement(image, id, px, sz, position, border);
-
- return image;
-};
-
-OpenLayers.Util.alphaHack = function() {
- var arVersion = navigator.appVersion.split("MSIE");
- var version = parseFloat(arVersion[1]);
-
- return ( (document.body.filters) &&
- (version >= 5.5) && (version < 7) );
-}
-
-/**
-* @param {DOMElement} div Div containing Alpha-adjusted Image
-* @param {String} id
-* @param {OpenLayers.Pixel} px
-* @param {OpenLayers.Size} sz
-* @param {String} imgURL
-* @param {String} position
-* @param {String} border
-* @param {String} sizing 'crop', 'scale', or 'image'. Default is "scale"
-*/
-OpenLayers.Util.modifyAlphaImageDiv = function(div, id, px, sz, imgURL,
- position, border, sizing) {
-
- OpenLayers.Util.modifyDOMElement(div, id, px, sz);
-
- var img = div.childNodes[0];
-
- if (imgURL) {
- img.src = imgURL;
- }
- OpenLayers.Util.modifyDOMElement(img, div.id + "_innerImage", null, sz,
- "relative", border);
-
- if (OpenLayers.Util.alphaHack()) {
- div.style.display = "inline-block";
- if (sizing == null) {
- sizing = "scale";
- }
- div.style.filter = "progid:DXImageTransform.Microsoft" +
- ".AlphaImageLoader(src='" + img.src + "', " +
- "sizingMethod='" + sizing + "')";
- img.style.filter = "progid:DXImageTransform.Microsoft" +
- ".Alpha(opacity=0)";
- }
-};
-
-/**
-* @param {String} id
-* @param {OpenLayers.Pixel} px
-* @param {OpenLayers.Size} sz
-* @param {String} imgURL
-* @param {String} position
-* @param {String} border
-* @param {String} sizing 'crop', 'scale', or 'image'. Default is "scale"
-*
-* @returns A DOM Div created with a DOM Image inside it. If the hack is
-* needed for transparency in IE, it is added.
-* @type DOMElement
-*/
-OpenLayers.Util.createAlphaImageDiv = function(id, px, sz, imgURL,
- position, border, sizing) {
-
- var div = OpenLayers.Util.createDiv();
- var img = OpenLayers.Util.createImage();
- div.appendChild(img);
-
- OpenLayers.Util.modifyAlphaImageDiv(div, id, px, sz, imgURL,
- position, border, sizing);
-
- return div;
-};
-
-
-/** Creates a new hash and copies over all the keys from the
-* passed-in object, but storing them under an uppercased
-* version of the key at which they were stored.
-*
-* @param {Object} object
-*
-* @returns A new Object with all the same keys but uppercased
-* @type Object
-*/
-OpenLayers.Util.upperCaseObject = function (object) {
- var uObject = new Object();
- for (var key in object) {
- uObject[key.toUpperCase()] = object[key];
- }
- return uObject;
-};
-
-/** Takes a hash and copies any keys that don't exist from
-* another hash, by analogy with Object.extend() from
-* Prototype.js.
-*
-* @param {Object} to
-* @param {Object} from
-*
-* @type Object
-*/
-OpenLayers.Util.applyDefaults = function (to, from) {
- for (var key in from) {
- if (to[key] == null) {
- to[key] = from[key];
- }
- }
- return to;
-};
-
-/**
-* @param {Object} params
-*
-* @returns a concatenation of the properties of an object in
-* http parameter notation.
-* (ex. <i>"key1=value1&key2=value2&key3=value3"</i>)
-* @type String
-*/
-OpenLayers.Util.getParameterString = function(params) {
- paramsArray = new Array();
-
- for (var key in params) {
- var value = params[key];
- //skip functions
- if (typeof value == 'function') continue;
-
- paramsArray.push(key + "=" + value);
- }
-
- return paramsArray.join("&");
-};
-
-/**
-* @returns The fully formatted image location string
-* @type String
-*/
-OpenLayers.Util.getImagesLocation = function() {
- return OpenLayers._getScriptLocation() + "img/";
-};
-
-
-
-/** These could/should be made namespace aware?
-*
-* @param {} p
-* @param {str} tagName
-*
-* @return {Array}
-*/
-OpenLayers.Util.getNodes=function(p, tagName) {
- var nodes = Try.these(
- function () {
- return OpenLayers.Util._getNodes(p.documentElement.childNodes,
- tagName);
- },
- function () {
- return OpenLayers.Util._getNodes(p.childNodes, tagName);
- }
- );
- return nodes;
-};
-
-/**
-* @param {Array} nodes
-* @param {str} tagName
-*
-* @return {Array}
-*/
-OpenLayers.Util._getNodes=function(nodes, tagName) {
- var retArray = new Array();
- for (var i=0;i<nodes.length;i++) {
- if (nodes[i].nodeName==tagName) {
- retArray.push(nodes[i]);
- }
- }
-
- return retArray;
-};
-
-
-
-/**
-* @param {} parent
-* @param {str} item
-* @param {int} index
-*
-* @return {str}
-*/
-OpenLayers.Util.getTagText = function (parent, item, index) {
- var result = OpenLayers.Util.getNodes(parent, item);
- if (result && (result.length > 0))
- {
- if (!index) {
- index=0;
- }
- if (result[index].childNodes.length > 1) {
- return result.childNodes[1].nodeValue;
- }
- else if (result[index].childNodes.length == 1) {
- return result[index].firstChild.nodeValue;
- }
- } else {
- return "";
- }
-};
-
-/**
-* @param {Event} evt
-* @param {HTMLDivElement} div
-*
-* @return {boolean}
-*/
-OpenLayers.Util.mouseLeft = function (evt, div) {
- // start with the element to which the mouse has moved
- var target = (evt.relatedTarget) ? evt.relatedTarget : evt.toElement;
- // walk up the DOM tree.
- while (target != div && target != null) {
- target = target.parentNode;
- }
- // if the target we stop at isn't the div, then we've left the div.
- return (target != div);
-};
-
-OpenLayers.Util.rad = function(x) {return x*Math.PI/180;};
-OpenLayers.Util.distVincenty=function(p1, p2) {
- var a = 6378137, b = 6356752.3142, f = 1/298.257223563;
- var L = OpenLayers.Util.rad(p2.lon - p1.lon);
- var U1 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p1.lat)));
- var U2 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p2.lat)));
- var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
- var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
- var lambda = L, lambdaP = 2*Math.PI;
- var iterLimit = 20;
- while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) {
- var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
- var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
- (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
- if (sinSigma==0) return 0; // co-incident points
- var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
- var sigma = Math.atan2(sinSigma, cosSigma);
- var alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma);
- var cosSqAlpha = Math.cos(alpha) * Math.cos(alpha);
- var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
- var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
- lambdaP = lambda;
- lambda = L + (1-C) * f * Math.sin(alpha) *
- (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
- }
- if (iterLimit==0) return NaN // formula failed to converge
- var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
- var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
- var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
- var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
- B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
- var s = b*A*(sigma-deltaSigma);
- var d = s.toFixed(3)/1000; // round to 1mm precision
- return d;
-};