index.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import clone from "@turf/clone";
  2. import { coordAll, featureEach } from "@turf/meta";
  3. import skmeans from "skmeans";
  4. /**
  5. * Takes a set of {@link Point|points} and partition them into clusters using the k-mean .
  6. * It uses the [k-means algorithm](https://en.wikipedia.org/wiki/K-means_clustering)
  7. *
  8. * @name clustersKmeans
  9. * @param {FeatureCollection<Point>} points to be clustered
  10. * @param {Object} [options={}] Optional parameters
  11. * @param {number} [options.numberOfClusters=Math.sqrt(numberOfPoints/2)] numberOfClusters that will be generated
  12. * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
  13. * @returns {FeatureCollection<Point>} Clustered Points with an additional two properties associated to each Feature:
  14. * - {number} cluster - the associated clusterId
  15. * - {[number, number]} centroid - Centroid of the cluster [Longitude, Latitude]
  16. * @example
  17. * // create random points with random z-values in their properties
  18. * var points = turf.randomPoint(100, {bbox: [0, 30, 20, 50]});
  19. * var options = {numberOfClusters: 7};
  20. * var clustered = turf.clustersKmeans(points, options);
  21. *
  22. * //addToMap
  23. * var addToMap = [clustered];
  24. */
  25. function clustersKmeans(points, options) {
  26. if (options === void 0) { options = {}; }
  27. // Default Params
  28. var count = points.features.length;
  29. options.numberOfClusters =
  30. options.numberOfClusters || Math.round(Math.sqrt(count / 2));
  31. // numberOfClusters can't be greater than the number of points
  32. // fallbacks to count
  33. if (options.numberOfClusters > count)
  34. options.numberOfClusters = count;
  35. // Clone points to prevent any mutations (enabled by default)
  36. if (options.mutate !== true)
  37. points = clone(points);
  38. // collect points coordinates
  39. var data = coordAll(points);
  40. // create seed to avoid skmeans to drift
  41. var initialCentroids = data.slice(0, options.numberOfClusters);
  42. // create skmeans clusters
  43. var skmeansResult = skmeans(data, options.numberOfClusters, initialCentroids);
  44. // store centroids {clusterId: [number, number]}
  45. var centroids = {};
  46. skmeansResult.centroids.forEach(function (coord, idx) {
  47. centroids[idx] = coord;
  48. });
  49. // add associated cluster number
  50. featureEach(points, function (point, index) {
  51. var clusterId = skmeansResult.idxs[index];
  52. point.properties.cluster = clusterId;
  53. point.properties.centroid = centroids[clusterId];
  54. });
  55. return points;
  56. }
  57. export default clustersKmeans;