Give the ScaleLine control a geodesic option. Setting this to true will provide an accurate scale bar in Spherical Mercator maps. r=bartvde (closes #1890)

git-svn-id: http://svn.openlayers.org/trunk/openlayers@10110 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
ahocevar
2010-03-18 13:26:02 +00:00
parent 1dd852ef09
commit e7b0857e31
2 changed files with 196 additions and 3 deletions

View File

@@ -61,6 +61,12 @@ OpenLayers.Control.ScaleLine = OpenLayers.Class(OpenLayers.Control, {
* {DOMElement}
*/
eBottom:null,
/**
* APIProperty: geodesic
* {Boolean} Use geodesic measurement. Default is false.
*/
geodesic: false,
/**
* Constructor: OpenLayers.Control.ScaleLine
@@ -156,7 +162,14 @@ OpenLayers.Control.ScaleLine = OpenLayers.Class(OpenLayers.Control, {
var inches = OpenLayers.INCHES_PER_UNIT;
// convert maxWidth to map units
var maxSizeData = this.maxWidth * res * inches[curMapUnits];
var maxSizeData = this.maxWidth * res * inches[curMapUnits];
var geodesicRatio = 1;
if(this.geodesic === true) {
var maxSizeGeodesic = this.getGeodesicLength(this.maxWidth);
var maxSizeKilometers = maxSizeData / inches["km"];
geodesicRatio = maxSizeGeodesic / maxSizeKilometers;
maxSizeData *= geodesicRatio;
}
// decide whether to use large or small scale units
var topUnits;
@@ -182,8 +195,8 @@ OpenLayers.Control.ScaleLine = OpenLayers.Class(OpenLayers.Control, {
bottomMax = bottomRounded / inches[curMapUnits] * inches[bottomUnits];
// and to pixel units
var topPx = topMax / res;
var bottomPx = bottomMax / res;
var topPx = topMax / res / geodesicRatio;
var bottomPx = bottomMax / res / geodesicRatio;
// now set the pixel widths
// and the values inside them
@@ -200,6 +213,26 @@ OpenLayers.Control.ScaleLine = OpenLayers.Class(OpenLayers.Control, {
},
/**
* Method: getGeodesicLength
*
* Parameters:
* pixels - {Number} the pixels to get the geodesic length in meters for.
*/
getGeodesicLength: function(pixels) {
var map = this.map;
var centerPx = map.getPixelFromLonLat(map.getCenter());
var bottom = map.getLonLatFromPixel(centerPx.add(0, -pixels / 2));
var top = map.getLonLatFromPixel(centerPx.add(0, pixels / 2));
var source = map.getProjectionObject();
var dest = new OpenLayers.Projection("EPSG:4326");
if(!source.equals(dest)) {
bottom.transform(source, dest);
top.transform(source, dest);
}
return OpenLayers.Util.distVincenty(bottom, top);
},
CLASS_NAME: "OpenLayers.Control.ScaleLine"
});