| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 | 
							- import { featureEach } from "@turf/meta";
 
- import { featureCollection } from "@turf/helpers";
 
- /**
 
-  * Get Cluster
 
-  *
 
-  * @name getCluster
 
-  * @param {FeatureCollection} geojson GeoJSON Features
 
-  * @param {*} filter Filter used on GeoJSON properties to get Cluster
 
-  * @returns {FeatureCollection} Single Cluster filtered by GeoJSON Properties
 
-  * @example
 
-  * var geojson = turf.featureCollection([
 
-  *     turf.point([0, 0], {'marker-symbol': 'circle'}),
 
-  *     turf.point([2, 4], {'marker-symbol': 'star'}),
 
-  *     turf.point([3, 6], {'marker-symbol': 'star'}),
 
-  *     turf.point([5, 1], {'marker-symbol': 'square'}),
 
-  *     turf.point([4, 2], {'marker-symbol': 'circle'})
 
-  * ]);
 
-  *
 
-  * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)
 
-  * var clustered = turf.clustersKmeans(geojson);
 
-  *
 
-  * // Retrieve first cluster (0)
 
-  * var cluster = turf.getCluster(clustered, {cluster: 0});
 
-  * //= cluster
 
-  *
 
-  * // Retrieve cluster based on custom properties
 
-  * turf.getCluster(clustered, {'marker-symbol': 'circle'}).length;
 
-  * //= 2
 
-  * turf.getCluster(clustered, {'marker-symbol': 'square'}).length;
 
-  * //= 1
 
-  */
 
- export function getCluster(geojson, filter) {
 
-     // Validation
 
-     if (!geojson)
 
-         throw new Error("geojson is required");
 
-     if (geojson.type !== "FeatureCollection")
 
-         throw new Error("geojson must be a FeatureCollection");
 
-     if (filter === undefined || filter === null)
 
-         throw new Error("filter is required");
 
-     // Filter Features
 
-     var features = [];
 
-     featureEach(geojson, function (feature) {
 
-         if (applyFilter(feature.properties, filter))
 
-             features.push(feature);
 
-     });
 
-     return featureCollection(features);
 
- }
 
- /**
 
-  * Callback for clusterEach
 
-  *
 
-  * @callback clusterEachCallback
 
-  * @param {FeatureCollection} [cluster] The current cluster being processed.
 
-  * @param {*} [clusterValue] Value used to create cluster being processed.
 
-  * @param {number} [currentIndex] The index of the current element being processed in the array.Starts at index 0
 
-  * @returns {void}
 
-  */
 
- /**
 
-  * clusterEach
 
-  *
 
-  * @name clusterEach
 
-  * @param {FeatureCollection} geojson GeoJSON Features
 
-  * @param {string|number} property GeoJSON property key/value used to create clusters
 
-  * @param {Function} callback a method that takes (cluster, clusterValue, currentIndex)
 
-  * @returns {void}
 
-  * @example
 
-  * var geojson = turf.featureCollection([
 
-  *     turf.point([0, 0]),
 
-  *     turf.point([2, 4]),
 
-  *     turf.point([3, 6]),
 
-  *     turf.point([5, 1]),
 
-  *     turf.point([4, 2])
 
-  * ]);
 
-  *
 
-  * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)
 
-  * var clustered = turf.clustersKmeans(geojson);
 
-  *
 
-  * // Iterate over each cluster
 
-  * turf.clusterEach(clustered, 'cluster', function (cluster, clusterValue, currentIndex) {
 
-  *     //= cluster
 
-  *     //= clusterValue
 
-  *     //= currentIndex
 
-  * })
 
-  *
 
-  * // Calculate the total number of clusters
 
-  * var total = 0
 
-  * turf.clusterEach(clustered, 'cluster', function () {
 
-  *     total++;
 
-  * });
 
-  *
 
-  * // Create an Array of all the values retrieved from the 'cluster' property
 
-  * var values = []
 
-  * turf.clusterEach(clustered, 'cluster', function (cluster, clusterValue) {
 
-  *     values.push(clusterValue);
 
-  * });
 
-  */
 
- export function clusterEach(geojson, property, callback) {
 
-     // Validation
 
-     if (!geojson)
 
-         throw new Error("geojson is required");
 
-     if (geojson.type !== "FeatureCollection")
 
-         throw new Error("geojson must be a FeatureCollection");
 
-     if (property === undefined || property === null)
 
-         throw new Error("property is required");
 
-     // Create clusters based on property values
 
-     var bins = createBins(geojson, property);
 
-     var values = Object.keys(bins);
 
-     for (var index = 0; index < values.length; index++) {
 
-         var value = values[index];
 
-         var bin = bins[value];
 
-         var features = [];
 
-         for (var i = 0; i < bin.length; i++) {
 
-             features.push(geojson.features[bin[i]]);
 
-         }
 
-         callback(featureCollection(features), value, index);
 
-     }
 
- }
 
- /**
 
-  * Callback for clusterReduce
 
-  *
 
-  * The first time the callback function is called, the values provided as arguments depend
 
-  * on whether the reduce method has an initialValue argument.
 
-  *
 
-  * If an initialValue is provided to the reduce method:
 
-  *  - The previousValue argument is initialValue.
 
-  *  - The currentValue argument is the value of the first element present in the array.
 
-  *
 
-  * If an initialValue is not provided:
 
-  *  - The previousValue argument is the value of the first element present in the array.
 
-  *  - The currentValue argument is the value of the second element present in the array.
 
-  *
 
-  * @callback clusterReduceCallback
 
-  * @param {*} [previousValue] The accumulated value previously returned in the last invocation
 
-  * of the callback, or initialValue, if supplied.
 
-  * @param {FeatureCollection} [cluster] The current cluster being processed.
 
-  * @param {*} [clusterValue] Value used to create cluster being processed.
 
-  * @param {number} [currentIndex] The index of the current element being processed in the
 
-  * array. Starts at index 0, if an initialValue is provided, and at index 1 otherwise.
 
-  */
 
- /**
 
-  * Reduce clusters in GeoJSON Features, similar to Array.reduce()
 
-  *
 
-  * @name clusterReduce
 
-  * @param {FeatureCollection} geojson GeoJSON Features
 
-  * @param {string|number} property GeoJSON property key/value used to create clusters
 
-  * @param {Function} callback a method that takes (previousValue, cluster, clusterValue, currentIndex)
 
-  * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
 
-  * @returns {*} The value that results from the reduction.
 
-  * @example
 
-  * var geojson = turf.featureCollection([
 
-  *     turf.point([0, 0]),
 
-  *     turf.point([2, 4]),
 
-  *     turf.point([3, 6]),
 
-  *     turf.point([5, 1]),
 
-  *     turf.point([4, 2])
 
-  * ]);
 
-  *
 
-  * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)
 
-  * var clustered = turf.clustersKmeans(geojson);
 
-  *
 
-  * // Iterate over each cluster and perform a calculation
 
-  * var initialValue = 0
 
-  * turf.clusterReduce(clustered, 'cluster', function (previousValue, cluster, clusterValue, currentIndex) {
 
-  *     //=previousValue
 
-  *     //=cluster
 
-  *     //=clusterValue
 
-  *     //=currentIndex
 
-  *     return previousValue++;
 
-  * }, initialValue);
 
-  *
 
-  * // Calculate the total number of clusters
 
-  * var total = turf.clusterReduce(clustered, 'cluster', function (previousValue) {
 
-  *     return previousValue++;
 
-  * }, 0);
 
-  *
 
-  * // Create an Array of all the values retrieved from the 'cluster' property
 
-  * var values = turf.clusterReduce(clustered, 'cluster', function (previousValue, cluster, clusterValue) {
 
-  *     return previousValue.concat(clusterValue);
 
-  * }, []);
 
-  */
 
- export function clusterReduce(geojson, property, callback, initialValue) {
 
-     var previousValue = initialValue;
 
-     clusterEach(geojson, property, function (cluster, clusterValue, currentIndex) {
 
-         if (currentIndex === 0 && initialValue === undefined)
 
-             previousValue = cluster;
 
-         else
 
-             previousValue = callback(previousValue, cluster, clusterValue, currentIndex);
 
-     });
 
-     return previousValue;
 
- }
 
- /**
 
-  * Create Bins
 
-  *
 
-  * @private
 
-  * @param {FeatureCollection} geojson GeoJSON Features
 
-  * @param {string|number} property Property values are used to create bins
 
-  * @returns {Object} bins with Feature IDs
 
-  * @example
 
-  * var geojson = turf.featureCollection([
 
-  *     turf.point([0, 0], {cluster: 0, foo: 'null'}),
 
-  *     turf.point([2, 4], {cluster: 1, foo: 'bar'}),
 
-  *     turf.point([5, 1], {0: 'foo'}),
 
-  *     turf.point([3, 6], {cluster: 1}),
 
-  * ]);
 
-  * createBins(geojson, 'cluster');
 
-  * //= { '0': [ 0 ], '1': [ 1, 3 ] }
 
-  */
 
- export function createBins(geojson, property) {
 
-     var bins = {};
 
-     featureEach(geojson, function (feature, i) {
 
-         var properties = feature.properties || {};
 
-         if (Object.prototype.hasOwnProperty.call(properties, String(property))) {
 
-             var value = properties[property];
 
-             if (Object.prototype.hasOwnProperty.call(bins, value))
 
-                 bins[value].push(i);
 
-             else
 
-                 bins[value] = [i];
 
-         }
 
-     });
 
-     return bins;
 
- }
 
- /**
 
-  * Apply Filter
 
-  *
 
-  * @private
 
-  * @param {*} properties Properties
 
-  * @param {*} filter Filter
 
-  * @returns {boolean} applied Filter to properties
 
-  */
 
- export function applyFilter(properties, filter) {
 
-     if (properties === undefined)
 
-         return false;
 
-     var filterType = typeof filter;
 
-     // String & Number
 
-     if (filterType === "number" || filterType === "string")
 
-         return Object.prototype.hasOwnProperty.call(properties, filter);
 
-     // Array
 
-     else if (Array.isArray(filter)) {
 
-         for (var i = 0; i < filter.length; i++) {
 
-             if (!applyFilter(properties, filter[i]))
 
-                 return false;
 
-         }
 
-         return true;
 
-         // Object
 
-     }
 
-     else {
 
-         return propertiesContainsFilter(properties, filter);
 
-     }
 
- }
 
- /**
 
-  * Properties contains filter (does not apply deepEqual operations)
 
-  *
 
-  * @private
 
-  * @param {*} properties Properties
 
-  * @param {Object} filter Filter
 
-  * @returns {boolean} does filter equal Properties
 
-  * @example
 
-  * propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 0})
 
-  * //= true
 
-  * propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 1})
 
-  * //= false
 
-  */
 
- export function propertiesContainsFilter(properties, filter) {
 
-     var keys = Object.keys(filter);
 
-     for (var i = 0; i < keys.length; i++) {
 
-         var key = keys[i];
 
-         if (properties[key] !== filter[key])
 
-             return false;
 
-     }
 
-     return true;
 
- }
 
- /**
 
-  * Filter Properties
 
-  *
 
-  * @private
 
-  * @param {*} properties Properties
 
-  * @param {Array<string>} keys Used to filter Properties
 
-  * @returns {*} filtered Properties
 
-  * @example
 
-  * filterProperties({foo: 'bar', cluster: 0}, ['cluster'])
 
-  * //= {cluster: 0}
 
-  */
 
- export function filterProperties(properties, keys) {
 
-     if (!keys)
 
-         return {};
 
-     if (!keys.length)
 
-         return {};
 
-     var newProperties = {};
 
-     for (var i = 0; i < keys.length; i++) {
 
-         var key = keys[i];
 
-         if (Object.prototype.hasOwnProperty.call(properties, key))
 
-             newProperties[key] = properties[key];
 
-     }
 
-     return newProperties;
 
- }
 
 
  |