diff --git a/lib/OpenLayers/Control/ScaleLine.js b/lib/OpenLayers/Control/ScaleLine.js index f9a8c7dcc0..b62dff90f0 100644 --- a/lib/OpenLayers/Control/ScaleLine.js +++ b/lib/OpenLayers/Control/ScaleLine.js @@ -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" }); diff --git a/tests/manual/geodesic.html b/tests/manual/geodesic.html new file mode 100644 index 0000000000..e642558957 --- /dev/null +++ b/tests/manual/geodesic.html @@ -0,0 +1,160 @@ + +
+ + + + + + ++ Tests geodesic measurement of distances and areas against a geodesic ScaleLine. +
+ +Zoom in so the ScaleLine shows units in the range of 10-100 km. Measure + the length of the ScaleLine. The result should be approximately the same + as the distance printed on the ScaleLine.
+Zoom out so the ScaleLine shows units in the range of 100-500 km. Drag + the map to the South or North and see how the ScaleLine length changes.
+ +