index.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { geomReduce } from "@turf/meta";
  2. // Note: change RADIUS => earthRadius
  3. var RADIUS = 6378137;
  4. /**
  5. * Takes one or more features and returns their area in square meters.
  6. *
  7. * @name area
  8. * @param {GeoJSON} geojson input GeoJSON feature(s)
  9. * @returns {number} area in square meters
  10. * @example
  11. * var polygon = turf.polygon([[[125, -15], [113, -22], [154, -27], [144, -15], [125, -15]]]);
  12. *
  13. * var area = turf.area(polygon);
  14. *
  15. * //addToMap
  16. * var addToMap = [polygon]
  17. * polygon.properties.area = area
  18. */
  19. export default function area(geojson) {
  20. return geomReduce(geojson, function (value, geom) {
  21. return value + calculateArea(geom);
  22. }, 0);
  23. }
  24. /**
  25. * Calculate Area
  26. *
  27. * @private
  28. * @param {Geometry} geom GeoJSON Geometries
  29. * @returns {number} area
  30. */
  31. function calculateArea(geom) {
  32. var total = 0;
  33. var i;
  34. switch (geom.type) {
  35. case "Polygon":
  36. return polygonArea(geom.coordinates);
  37. case "MultiPolygon":
  38. for (i = 0; i < geom.coordinates.length; i++) {
  39. total += polygonArea(geom.coordinates[i]);
  40. }
  41. return total;
  42. case "Point":
  43. case "MultiPoint":
  44. case "LineString":
  45. case "MultiLineString":
  46. return 0;
  47. }
  48. return 0;
  49. }
  50. function polygonArea(coords) {
  51. var total = 0;
  52. if (coords && coords.length > 0) {
  53. total += Math.abs(ringArea(coords[0]));
  54. for (var i = 1; i < coords.length; i++) {
  55. total -= Math.abs(ringArea(coords[i]));
  56. }
  57. }
  58. return total;
  59. }
  60. /**
  61. * @private
  62. * Calculate the approximate area of the polygon were it projected onto the earth.
  63. * Note that this area will be positive if ring is oriented clockwise, otherwise it will be negative.
  64. *
  65. * Reference:
  66. * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for Polygons on a Sphere",
  67. * JPL Publication 07-03, Jet Propulsion
  68. * Laboratory, Pasadena, CA, June 2007 https://trs.jpl.nasa.gov/handle/2014/40409
  69. *
  70. * @param {Array<Array<number>>} coords Ring Coordinates
  71. * @returns {number} The approximate signed geodesic area of the polygon in square meters.
  72. */
  73. function ringArea(coords) {
  74. var p1;
  75. var p2;
  76. var p3;
  77. var lowerIndex;
  78. var middleIndex;
  79. var upperIndex;
  80. var i;
  81. var total = 0;
  82. var coordsLength = coords.length;
  83. if (coordsLength > 2) {
  84. for (i = 0; i < coordsLength; i++) {
  85. if (i === coordsLength - 2) {
  86. // i = N-2
  87. lowerIndex = coordsLength - 2;
  88. middleIndex = coordsLength - 1;
  89. upperIndex = 0;
  90. }
  91. else if (i === coordsLength - 1) {
  92. // i = N-1
  93. lowerIndex = coordsLength - 1;
  94. middleIndex = 0;
  95. upperIndex = 1;
  96. }
  97. else {
  98. // i = 0 to N-3
  99. lowerIndex = i;
  100. middleIndex = i + 1;
  101. upperIndex = i + 2;
  102. }
  103. p1 = coords[lowerIndex];
  104. p2 = coords[middleIndex];
  105. p3 = coords[upperIndex];
  106. total += (rad(p3[0]) - rad(p1[0])) * Math.sin(rad(p2[1]));
  107. }
  108. total = (total * RADIUS * RADIUS) / 2;
  109. }
  110. return total;
  111. }
  112. function rad(num) {
  113. return (num * Math.PI) / 180;
  114. }