Function for getting spherical area
This commit is contained in:
@@ -437,11 +437,12 @@ olx.MapOptions.prototype.view;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object literal with options for the {@link ol.Sphere.getLength}.
|
* Object literal with options for the {@link ol.Sphere.getLength} or
|
||||||
|
* {@link ol.Sphere.getArea} functions.
|
||||||
* @typedef {{projection: (ol.ProjectionLike|undefined),
|
* @typedef {{projection: (ol.ProjectionLike|undefined),
|
||||||
* radius: (number|undefined)}}
|
* radius: (number|undefined)}}
|
||||||
*/
|
*/
|
||||||
olx.SphereLengthOptions;
|
olx.SphereMetricOptions;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -450,7 +451,7 @@ olx.SphereLengthOptions;
|
|||||||
* @type {(ol.ProjectionLike|undefined)}
|
* @type {(ol.ProjectionLike|undefined)}
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
olx.SphereLengthOptions.prototype.projection;
|
olx.SphereMetricOptions.prototype.projection;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -459,7 +460,7 @@ olx.SphereLengthOptions.prototype.projection;
|
|||||||
* @type {(number|undefined)}
|
* @type {(number|undefined)}
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
olx.SphereLengthOptions.prototype.radius;
|
olx.SphereMetricOptions.prototype.radius;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
104
src/ol/sphere.js
104
src/ol/sphere.js
@@ -52,18 +52,7 @@ ol.Sphere = function(radius) {
|
|||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
ol.Sphere.prototype.geodesicArea = function(coordinates) {
|
ol.Sphere.prototype.geodesicArea = function(coordinates) {
|
||||||
var area = 0, len = coordinates.length;
|
return ol.Sphere.getArea_(coordinates, this.radius);
|
||||||
var x1 = coordinates[len - 1][0];
|
|
||||||
var y1 = coordinates[len - 1][1];
|
|
||||||
for (var i = 0; i < len; i++) {
|
|
||||||
var x2 = coordinates[i][0], y2 = coordinates[i][1];
|
|
||||||
area += ol.math.toRadians(x2 - x1) *
|
|
||||||
(2 + Math.sin(ol.math.toRadians(y1)) +
|
|
||||||
Math.sin(ol.math.toRadians(y2)));
|
|
||||||
x1 = x2;
|
|
||||||
y1 = y2;
|
|
||||||
}
|
|
||||||
return area * this.radius * this.radius / 2.0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -117,7 +106,7 @@ ol.Sphere.DEFAULT_RADIUS = 6371008.8;
|
|||||||
* the sum of all rings. For points, the length is zero. For multi-part
|
* the sum of all rings. For points, the length is zero. For multi-part
|
||||||
* geometries, the length is the sum of the length of each part.
|
* geometries, the length is the sum of the length of each part.
|
||||||
* @param {ol.geom.Geometry} geometry A geometry.
|
* @param {ol.geom.Geometry} geometry A geometry.
|
||||||
* @param {olx.SphereLengthOptions} opt_options Options for the length
|
* @param {olx.SphereMetricOptions} opt_options Options for the length
|
||||||
* calculation. By default, geometries are assumed to be in 'EPSG:3857'.
|
* calculation. By default, geometries are assumed to be in 'EPSG:3857'.
|
||||||
* You can change this by providing a `projection` option.
|
* You can change this by providing a `projection` option.
|
||||||
* @return {number} The spherical length (in meters).
|
* @return {number} The spherical length (in meters).
|
||||||
@@ -206,3 +195,92 @@ ol.Sphere.getDistance_ = function(c1, c2, radius) {
|
|||||||
Math.cos(lat1) * Math.cos(lat2);
|
Math.cos(lat1) * Math.cos(lat2);
|
||||||
return 2 * radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
return 2 * radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the spherical area of a geometry. This is the area (in meters) assuming
|
||||||
|
* that polygon edges are segments of great circles on a sphere.
|
||||||
|
* @param {ol.geom.Geometry} geometry A geometry.
|
||||||
|
* @param {olx.SphereMetricOptions} opt_options Options for the area
|
||||||
|
* calculation. By default, geometries are assumed to be in 'EPSG:3857'.
|
||||||
|
* You can change this by providing a `projection` option.
|
||||||
|
* @return {number} The spherical area (in meters).
|
||||||
|
*/
|
||||||
|
ol.Sphere.getArea = function(geometry, opt_options) {
|
||||||
|
var options = opt_options || {};
|
||||||
|
var radius = options.radius || ol.Sphere.DEFAULT_RADIUS;
|
||||||
|
var projection = options.projection || 'EPSG:3857';
|
||||||
|
geometry = geometry.clone().transform(projection, 'EPSG:4326');
|
||||||
|
var type = geometry.getType();
|
||||||
|
var area = 0;
|
||||||
|
var coordinates, coords, i, ii, j, jj;
|
||||||
|
switch (type) {
|
||||||
|
case ol.geom.GeometryType.POINT:
|
||||||
|
case ol.geom.GeometryType.MULTI_POINT:
|
||||||
|
case ol.geom.GeometryType.LINE_STRING:
|
||||||
|
case ol.geom.GeometryType.MULTI_LINE_STRING:
|
||||||
|
case ol.geom.GeometryType.LINEAR_RING: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ol.geom.GeometryType.POLYGON: {
|
||||||
|
coordinates = /** @type {ol.geom.Polygon} */ (geometry).getCoordinates();
|
||||||
|
area = Math.abs(ol.Sphere.getArea_(coordinates[0], radius));
|
||||||
|
for (i = 1, ii = coordinates.length; i < ii; ++i) {
|
||||||
|
area -= Math.abs(ol.Sphere.getArea_(coordinates[i], radius));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ol.geom.GeometryType.MULTI_POLYGON: {
|
||||||
|
coordinates = /** @type {ol.geom.SimpleGeometry} */ (geometry).getCoordinates();
|
||||||
|
for (i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||||
|
coords = coordinates[i];
|
||||||
|
area += Math.abs(ol.Sphere.getArea_(coords[0], radius));
|
||||||
|
for (j = 1, jj = coords.length; j < jj; ++j) {
|
||||||
|
area -= Math.abs(ol.Sphere.getArea_(coords[j], radius));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ol.geom.GeometryType.GEOMETRY_COLLECTION: {
|
||||||
|
var geometries = /** @type {ol.geom.GeometryCollection} */ (geometry).getGeometries();
|
||||||
|
for (i = 0, ii = geometries.length; i < ii; ++i) {
|
||||||
|
area += ol.Sphere.getArea(geometries[i], opt_options);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new Error('Unsupported geometry type: ' + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return area;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the spherical area for a list of coordinates.
|
||||||
|
*
|
||||||
|
* [Reference](https://trs-new.jpl.nasa.gov/handle/2014/40409)
|
||||||
|
* Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
|
||||||
|
* Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
|
||||||
|
* Laboratory, Pasadena, CA, June 2007
|
||||||
|
*
|
||||||
|
* @param {Array.<ol.Coordinate>} coordinates List of coordinates of a linear
|
||||||
|
* ring. If the ring is oriented clockwise, the area will be positive,
|
||||||
|
* otherwise it will be negative.
|
||||||
|
* @param {number} radius The sphere radius.
|
||||||
|
* @return {number} Area (in meters).
|
||||||
|
*/
|
||||||
|
ol.Sphere.getArea_ = function(coordinates, radius) {
|
||||||
|
var area = 0, len = coordinates.length;
|
||||||
|
var x1 = coordinates[len - 1][0];
|
||||||
|
var y1 = coordinates[len - 1][1];
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
var x2 = coordinates[i][0], y2 = coordinates[i][1];
|
||||||
|
area += ol.math.toRadians(x2 - x1) *
|
||||||
|
(2 + Math.sin(ol.math.toRadians(y1)) +
|
||||||
|
Math.sin(ol.math.toRadians(y2)));
|
||||||
|
x1 = x2;
|
||||||
|
y1 = y2;
|
||||||
|
}
|
||||||
|
return area * radius * radius / 2.0;
|
||||||
|
};
|
||||||
|
|||||||
@@ -177,3 +177,23 @@ describe('ol.Sphere.getLength()', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('ol.Sphere.getArea()', function() {
|
||||||
|
var geometry;
|
||||||
|
before(function(done) {
|
||||||
|
afterLoadText('spec/ol/format/wkt/illinois.wkt', function(wkt) {
|
||||||
|
try {
|
||||||
|
var format = new ol.format.WKT();
|
||||||
|
geometry = format.readGeometry(wkt);
|
||||||
|
} catch (e) {
|
||||||
|
done(e);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calculates the area of Ilinois', function() {
|
||||||
|
var area = ol.Sphere.getArea(geometry, {projection: 'EPSG:4326'});
|
||||||
|
expect(area).to.equal(145652224192.4434);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user