index.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import convex from "@turf/convex";
  2. import centroid from "@turf/centroid";
  3. import { point } from "@turf/helpers";
  4. import { getType, getCoord } from "@turf/invariant";
  5. import { coordEach } from "@turf/meta";
  6. /**
  7. * Takes any {@link Feature} or a {@link FeatureCollection} and returns its [center of mass](https://en.wikipedia.org/wiki/Center_of_mass) using this formula: [Centroid of Polygon](https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon).
  8. *
  9. * @name centerOfMass
  10. * @param {GeoJSON} geojson GeoJSON to be centered
  11. * @param {Object} [options={}] Optional Parameters
  12. * @param {Object} [options.properties={}] Translate Properties to Feature
  13. * @returns {Feature<Point>} the center of mass
  14. * @example
  15. * var polygon = turf.polygon([[[-81, 41], [-88, 36], [-84, 31], [-80, 33], [-77, 39], [-81, 41]]]);
  16. *
  17. * var center = turf.centerOfMass(polygon);
  18. *
  19. * //addToMap
  20. * var addToMap = [polygon, center]
  21. */
  22. function centerOfMass(geojson, options) {
  23. if (options === void 0) { options = {}; }
  24. switch (getType(geojson)) {
  25. case "Point":
  26. return point(getCoord(geojson), options.properties);
  27. case "Polygon":
  28. var coords = [];
  29. coordEach(geojson, function (coord) {
  30. coords.push(coord);
  31. });
  32. // First, we neutralize the feature (set it around coordinates [0,0]) to prevent rounding errors
  33. // We take any point to translate all the points around 0
  34. var centre = centroid(geojson, { properties: options.properties });
  35. var translation = centre.geometry.coordinates;
  36. var sx = 0;
  37. var sy = 0;
  38. var sArea = 0;
  39. var i, pi, pj, xi, xj, yi, yj, a;
  40. var neutralizedPoints = coords.map(function (point) {
  41. return [point[0] - translation[0], point[1] - translation[1]];
  42. });
  43. for (i = 0; i < coords.length - 1; i++) {
  44. // pi is the current point
  45. pi = neutralizedPoints[i];
  46. xi = pi[0];
  47. yi = pi[1];
  48. // pj is the next point (pi+1)
  49. pj = neutralizedPoints[i + 1];
  50. xj = pj[0];
  51. yj = pj[1];
  52. // a is the common factor to compute the signed area and the final coordinates
  53. a = xi * yj - xj * yi;
  54. // sArea is the sum used to compute the signed area
  55. sArea += a;
  56. // sx and sy are the sums used to compute the final coordinates
  57. sx += (xi + xj) * a;
  58. sy += (yi + yj) * a;
  59. }
  60. // Shape has no area: fallback on turf.centroid
  61. if (sArea === 0) {
  62. return centre;
  63. }
  64. else {
  65. // Compute the signed area, and factorize 1/6A
  66. var area = sArea * 0.5;
  67. var areaFactor = 1 / (6 * area);
  68. // Compute the final coordinates, adding back the values that have been neutralized
  69. return point([translation[0] + areaFactor * sx, translation[1] + areaFactor * sy], options.properties);
  70. }
  71. default:
  72. // Not a polygon: Compute the convex hull and work with that
  73. var hull = convex(geojson);
  74. if (hull)
  75. return centerOfMass(hull, { properties: options.properties });
  76. // Hull is empty: fallback on the centroid
  77. else
  78. return centroid(geojson, { properties: options.properties });
  79. }
  80. }
  81. export default centerOfMass;