@turf/clusters 7.0.0-alpha.2 → 7.1.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -9
- package/dist/cjs/index.cjs +117 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/{es/index.js → cjs/index.d.cts} +11 -105
- package/dist/{js → esm}/index.d.ts +11 -8
- package/dist/esm/index.js +117 -0
- package/dist/esm/index.js.map +1 -0
- package/package.json +31 -26
- package/dist/es/package.json +0 -1
- package/dist/js/index.js +0 -303
package/README.md
CHANGED
|
@@ -182,26 +182,21 @@ Returns **any** The value that results from the reduction.
|
|
|
182
182
|
|
|
183
183
|
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
|
184
184
|
|
|
185
|
-
<!-- This file is automatically generated. Please don't edit it directly
|
|
186
|
-
if you find an error, edit the source file (likely index.js), and re-run
|
|
187
|
-
./scripts/generate-readmes in the turf project. -->
|
|
185
|
+
<!-- This file is automatically generated. Please don't edit it directly. If you find an error, edit the source file of the module in question (likely index.js or index.ts), and re-run "yarn docs" from the root of the turf project. -->
|
|
188
186
|
|
|
189
187
|
---
|
|
190
188
|
|
|
191
|
-
This module is part of the [Turfjs project](
|
|
192
|
-
module collection dedicated to geographic algorithms. It is maintained in the
|
|
193
|
-
[Turfjs/turf](https://github.com/Turfjs/turf) repository, where you can create
|
|
194
|
-
PRs and issues.
|
|
189
|
+
This module is part of the [Turfjs project](https://turfjs.org/), an open source module collection dedicated to geographic algorithms. It is maintained in the [Turfjs/turf](https://github.com/Turfjs/turf) repository, where you can create PRs and issues.
|
|
195
190
|
|
|
196
191
|
### Installation
|
|
197
192
|
|
|
198
|
-
Install this module individually:
|
|
193
|
+
Install this single module individually:
|
|
199
194
|
|
|
200
195
|
```sh
|
|
201
196
|
$ npm install @turf/clusters
|
|
202
197
|
```
|
|
203
198
|
|
|
204
|
-
Or install the
|
|
199
|
+
Or install the all-encompassing @turf/turf module that includes all modules as functions:
|
|
205
200
|
|
|
206
201
|
```sh
|
|
207
202
|
$ npm install @turf/turf
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// index.ts
|
|
2
|
+
var _meta = require('@turf/meta');
|
|
3
|
+
var _helpers = require('@turf/helpers');
|
|
4
|
+
function getCluster(geojson, filter) {
|
|
5
|
+
if (!geojson)
|
|
6
|
+
throw new Error("geojson is required");
|
|
7
|
+
if (geojson.type !== "FeatureCollection")
|
|
8
|
+
throw new Error("geojson must be a FeatureCollection");
|
|
9
|
+
if (filter === void 0 || filter === null)
|
|
10
|
+
throw new Error("filter is required");
|
|
11
|
+
var features = [];
|
|
12
|
+
_meta.featureEach.call(void 0, geojson, function(feature) {
|
|
13
|
+
if (applyFilter(feature.properties, filter))
|
|
14
|
+
features.push(feature);
|
|
15
|
+
});
|
|
16
|
+
return _helpers.featureCollection.call(void 0, features);
|
|
17
|
+
}
|
|
18
|
+
function clusterEach(geojson, property, callback) {
|
|
19
|
+
if (!geojson)
|
|
20
|
+
throw new Error("geojson is required");
|
|
21
|
+
if (geojson.type !== "FeatureCollection")
|
|
22
|
+
throw new Error("geojson must be a FeatureCollection");
|
|
23
|
+
if (property === void 0 || property === null)
|
|
24
|
+
throw new Error("property is required");
|
|
25
|
+
var bins = createBins(geojson, property);
|
|
26
|
+
var values = Object.keys(bins);
|
|
27
|
+
for (var index = 0; index < values.length; index++) {
|
|
28
|
+
var value = values[index];
|
|
29
|
+
var bin = bins[value];
|
|
30
|
+
var features = [];
|
|
31
|
+
for (var i = 0; i < bin.length; i++) {
|
|
32
|
+
features.push(geojson.features[bin[i]]);
|
|
33
|
+
}
|
|
34
|
+
callback(_helpers.featureCollection.call(void 0, features), value, index);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function clusterReduce(geojson, property, callback, initialValue) {
|
|
38
|
+
var previousValue = initialValue;
|
|
39
|
+
clusterEach(
|
|
40
|
+
geojson,
|
|
41
|
+
property,
|
|
42
|
+
function(cluster, clusterValue, currentIndex) {
|
|
43
|
+
if (currentIndex === 0 && initialValue === void 0)
|
|
44
|
+
previousValue = cluster;
|
|
45
|
+
else
|
|
46
|
+
previousValue = callback(
|
|
47
|
+
previousValue,
|
|
48
|
+
cluster,
|
|
49
|
+
clusterValue,
|
|
50
|
+
currentIndex
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
return previousValue;
|
|
55
|
+
}
|
|
56
|
+
function createBins(geojson, property) {
|
|
57
|
+
var bins = {};
|
|
58
|
+
_meta.featureEach.call(void 0, geojson, function(feature, i) {
|
|
59
|
+
var properties = feature.properties || {};
|
|
60
|
+
if (Object.prototype.hasOwnProperty.call(properties, String(property))) {
|
|
61
|
+
var value = properties[property];
|
|
62
|
+
if (Object.prototype.hasOwnProperty.call(bins, value))
|
|
63
|
+
bins[value].push(i);
|
|
64
|
+
else
|
|
65
|
+
bins[value] = [i];
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return bins;
|
|
69
|
+
}
|
|
70
|
+
function applyFilter(properties, filter) {
|
|
71
|
+
if (properties === void 0)
|
|
72
|
+
return false;
|
|
73
|
+
var filterType = typeof filter;
|
|
74
|
+
if (filterType === "number" || filterType === "string")
|
|
75
|
+
return Object.prototype.hasOwnProperty.call(properties, filter);
|
|
76
|
+
else if (Array.isArray(filter)) {
|
|
77
|
+
for (var i = 0; i < filter.length; i++) {
|
|
78
|
+
if (!applyFilter(properties, filter[i]))
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
} else {
|
|
83
|
+
return propertiesContainsFilter(properties, filter);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function propertiesContainsFilter(properties, filter) {
|
|
87
|
+
var keys = Object.keys(filter);
|
|
88
|
+
for (var i = 0; i < keys.length; i++) {
|
|
89
|
+
var key = keys[i];
|
|
90
|
+
if (properties[key] !== filter[key])
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
function filterProperties(properties, keys) {
|
|
96
|
+
if (!keys)
|
|
97
|
+
return {};
|
|
98
|
+
if (!keys.length)
|
|
99
|
+
return {};
|
|
100
|
+
var newProperties = {};
|
|
101
|
+
for (var i = 0; i < keys.length; i++) {
|
|
102
|
+
var key = keys[i];
|
|
103
|
+
if (Object.prototype.hasOwnProperty.call(properties, key))
|
|
104
|
+
newProperties[key] = properties[key];
|
|
105
|
+
}
|
|
106
|
+
return newProperties;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
exports.applyFilter = applyFilter; exports.clusterEach = clusterEach; exports.clusterReduce = clusterReduce; exports.createBins = createBins; exports.filterProperties = filterProperties; exports.getCluster = getCluster; exports.propertiesContainsFilter = propertiesContainsFilter;
|
|
117
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Feature,\n FeatureCollection,\n GeoJsonProperties,\n GeometryObject,\n} from \"geojson\";\nimport { featureEach } from \"@turf/meta\";\nimport { featureCollection } from \"@turf/helpers\";\n\n/**\n * Get Cluster\n *\n * @name getCluster\n * @param {FeatureCollection} geojson GeoJSON Features\n * @param {*} filter Filter used on GeoJSON properties to get Cluster\n * @returns {FeatureCollection} Single Cluster filtered by GeoJSON Properties\n * @example\n * var geojson = turf.featureCollection([\n * turf.point([0, 0], {'marker-symbol': 'circle'}),\n * turf.point([2, 4], {'marker-symbol': 'star'}),\n * turf.point([3, 6], {'marker-symbol': 'star'}),\n * turf.point([5, 1], {'marker-symbol': 'square'}),\n * turf.point([4, 2], {'marker-symbol': 'circle'})\n * ]);\n *\n * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)\n * var clustered = turf.clustersKmeans(geojson);\n *\n * // Retrieve first cluster (0)\n * var cluster = turf.getCluster(clustered, {cluster: 0});\n * //= cluster\n *\n * // Retrieve cluster based on custom properties\n * turf.getCluster(clustered, {'marker-symbol': 'circle'}).length;\n * //= 2\n * turf.getCluster(clustered, {'marker-symbol': 'square'}).length;\n * //= 1\n */\nfunction getCluster<\n G extends GeometryObject,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(geojson: FeatureCollection<G, P>, filter: any): FeatureCollection<G, P> {\n // Validation\n if (!geojson) throw new Error(\"geojson is required\");\n if (geojson.type !== \"FeatureCollection\")\n throw new Error(\"geojson must be a FeatureCollection\");\n if (filter === undefined || filter === null)\n throw new Error(\"filter is required\");\n\n // Filter Features\n var features: Feature<G, P>[] = [];\n featureEach<G, P>(geojson, function (feature) {\n if (applyFilter(feature.properties, filter)) features.push(feature);\n });\n return featureCollection(features);\n}\n\n/**\n * Callback for clusterEach\n *\n * @callback clusterEachCallback\n * @param {FeatureCollection} [cluster] The current cluster being processed.\n * @param {*} [clusterValue] Value used to create cluster being processed.\n * @param {number} [currentIndex] The index of the current element being processed in the array.Starts at index 0\n * @returns {void}\n */\n\n/**\n * clusterEach\n *\n * @name clusterEach\n * @param {FeatureCollection} geojson GeoJSON Features\n * @param {string|number} property GeoJSON property key/value used to create clusters\n * @param {Function} callback a method that takes (cluster, clusterValue, currentIndex)\n * @returns {void}\n * @example\n * var geojson = turf.featureCollection([\n * turf.point([0, 0]),\n * turf.point([2, 4]),\n * turf.point([3, 6]),\n * turf.point([5, 1]),\n * turf.point([4, 2])\n * ]);\n *\n * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)\n * var clustered = turf.clustersKmeans(geojson);\n *\n * // Iterate over each cluster\n * turf.clusterEach(clustered, 'cluster', function (cluster, clusterValue, currentIndex) {\n * //= cluster\n * //= clusterValue\n * //= currentIndex\n * })\n *\n * // Calculate the total number of clusters\n * var total = 0\n * turf.clusterEach(clustered, 'cluster', function () {\n * total++;\n * });\n *\n * // Create an Array of all the values retrieved from the 'cluster' property\n * var values = []\n * turf.clusterEach(clustered, 'cluster', function (cluster, clusterValue) {\n * values.push(clusterValue);\n * });\n */\nfunction clusterEach<\n G extends GeometryObject,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n geojson: FeatureCollection<G, P>,\n property: number | string,\n callback: (\n cluster: FeatureCollection<G, P>,\n clusterValue?: any,\n currentIndex?: number\n ) => void\n): void {\n // Validation\n if (!geojson) throw new Error(\"geojson is required\");\n if (geojson.type !== \"FeatureCollection\")\n throw new Error(\"geojson must be a FeatureCollection\");\n if (property === undefined || property === null)\n throw new Error(\"property is required\");\n\n // Create clusters based on property values\n var bins = createBins(geojson, property);\n var values = Object.keys(bins);\n for (var index = 0; index < values.length; index++) {\n var value = values[index];\n var bin = bins[value];\n var features = [];\n for (var i = 0; i < bin.length; i++) {\n features.push(geojson.features[bin[i]]);\n }\n callback(featureCollection(features), value, index);\n }\n}\n\n/**\n * Callback for clusterReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback clusterReduceCallback\n * @param {*} [previousValue] The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {FeatureCollection} [cluster] The current cluster being processed.\n * @param {*} [clusterValue] Value used to create cluster being processed.\n * @param {number} [currentIndex] The index of the current element being processed in the\n * array. Starts at index 0, if an initialValue is provided, and at index 1 otherwise.\n */\n\n/**\n * Reduce clusters in GeoJSON Features, similar to Array.reduce()\n *\n * @name clusterReduce\n * @param {FeatureCollection} geojson GeoJSON Features\n * @param {string|number} property GeoJSON property key/value used to create clusters\n * @param {Function} callback a method that takes (previousValue, cluster, clusterValue, currentIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var geojson = turf.featureCollection([\n * turf.point([0, 0]),\n * turf.point([2, 4]),\n * turf.point([3, 6]),\n * turf.point([5, 1]),\n * turf.point([4, 2])\n * ]);\n *\n * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)\n * var clustered = turf.clustersKmeans(geojson);\n *\n * // Iterate over each cluster and perform a calculation\n * var initialValue = 0\n * turf.clusterReduce(clustered, 'cluster', function (previousValue, cluster, clusterValue, currentIndex) {\n * //=previousValue\n * //=cluster\n * //=clusterValue\n * //=currentIndex\n * return previousValue++;\n * }, initialValue);\n *\n * // Calculate the total number of clusters\n * var total = turf.clusterReduce(clustered, 'cluster', function (previousValue) {\n * return previousValue++;\n * }, 0);\n *\n * // Create an Array of all the values retrieved from the 'cluster' property\n * var values = turf.clusterReduce(clustered, 'cluster', function (previousValue, cluster, clusterValue) {\n * return previousValue.concat(clusterValue);\n * }, []);\n */\nfunction clusterReduce<\n G extends GeometryObject,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n geojson: FeatureCollection<G, P>,\n property: number | string,\n callback: (\n previousValue: any | undefined,\n cluster: FeatureCollection<G, P>,\n clusterValue?: any,\n currentIndex?: number\n ) => void,\n initialValue?: any\n): void {\n var previousValue = initialValue;\n clusterEach(\n geojson,\n property,\n function (cluster, clusterValue, currentIndex) {\n if (currentIndex === 0 && initialValue === undefined)\n previousValue = cluster;\n else\n previousValue = callback(\n previousValue,\n cluster,\n clusterValue,\n currentIndex\n );\n }\n );\n return previousValue;\n}\n\n/**\n * Create Bins\n *\n * @private\n * @param {FeatureCollection} geojson GeoJSON Features\n * @param {string|number} property Property values are used to create bins\n * @returns {Object} bins with Feature IDs\n * @example\n * var geojson = turf.featureCollection([\n * turf.point([0, 0], {cluster: 0, foo: 'null'}),\n * turf.point([2, 4], {cluster: 1, foo: 'bar'}),\n * turf.point([5, 1], {0: 'foo'}),\n * turf.point([3, 6], {cluster: 1}),\n * ]);\n * createBins(geojson, 'cluster');\n * //= { '0': [ 0 ], '1': [ 1, 3 ] }\n */\nfunction createBins(\n geojson: FeatureCollection<any>,\n property: string | number\n) {\n var bins: Record<string, number[]> = {};\n\n featureEach(geojson, function (feature, i) {\n var properties = feature.properties || {};\n if (Object.prototype.hasOwnProperty.call(properties, String(property))) {\n var value = properties[property];\n if (Object.prototype.hasOwnProperty.call(bins, value))\n bins[value].push(i);\n else bins[value] = [i];\n }\n });\n return bins;\n}\n\n/**\n * Apply Filter\n *\n * @private\n * @param {*} properties Properties\n * @param {*} filter Filter\n * @returns {boolean} applied Filter to properties\n */\nfunction applyFilter(properties: any, filter: any) {\n if (properties === undefined) return false;\n var filterType = typeof filter;\n\n // String & Number\n if (filterType === \"number\" || filterType === \"string\")\n return Object.prototype.hasOwnProperty.call(properties, filter);\n // Array\n else if (Array.isArray(filter)) {\n for (var i = 0; i < filter.length; i++) {\n if (!applyFilter(properties, filter[i])) return false;\n }\n return true;\n // Object\n } else {\n return propertiesContainsFilter(properties, filter);\n }\n}\n\n/**\n * Properties contains filter (does not apply deepEqual operations)\n *\n * @private\n * @param {*} properties Properties\n * @param {Object} filter Filter\n * @returns {boolean} does filter equal Properties\n * @example\n * propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 0})\n * //= true\n * propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 1})\n * //= false\n */\nfunction propertiesContainsFilter(properties: any, filter: any): boolean {\n var keys = Object.keys(filter);\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n if (properties[key] !== filter[key]) return false;\n }\n return true;\n}\n\n/**\n * Filter Properties\n *\n * @private\n * @param {*} properties Properties\n * @param {Array<string>} keys Used to filter Properties\n * @returns {*} filtered Properties\n * @example\n * filterProperties({foo: 'bar', cluster: 0}, ['cluster'])\n * //= {cluster: 0}\n */\nfunction filterProperties(\n properties: Record<string, any>,\n keys: string[]\n): any {\n if (!keys) return {};\n if (!keys.length) return {};\n\n var newProperties: Record<string, any> = {};\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n if (Object.prototype.hasOwnProperty.call(properties, key))\n newProperties[key] = properties[key];\n }\n return newProperties;\n}\n\nexport {\n getCluster,\n clusterEach,\n clusterReduce,\n createBins,\n applyFilter,\n propertiesContainsFilter,\n filterProperties,\n};\n// No default export!\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { GeometryObject, GeoJsonProperties, FeatureCollection } from 'geojson';
|
|
2
|
+
|
|
3
3
|
/**
|
|
4
4
|
* Get Cluster
|
|
5
5
|
*
|
|
@@ -29,22 +29,7 @@ import { featureCollection } from "@turf/helpers";
|
|
|
29
29
|
* turf.getCluster(clustered, {'marker-symbol': 'square'}).length;
|
|
30
30
|
* //= 1
|
|
31
31
|
*/
|
|
32
|
-
|
|
33
|
-
// Validation
|
|
34
|
-
if (!geojson)
|
|
35
|
-
throw new Error("geojson is required");
|
|
36
|
-
if (geojson.type !== "FeatureCollection")
|
|
37
|
-
throw new Error("geojson must be a FeatureCollection");
|
|
38
|
-
if (filter === undefined || filter === null)
|
|
39
|
-
throw new Error("filter is required");
|
|
40
|
-
// Filter Features
|
|
41
|
-
var features = [];
|
|
42
|
-
featureEach(geojson, function (feature) {
|
|
43
|
-
if (applyFilter(feature.properties, filter))
|
|
44
|
-
features.push(feature);
|
|
45
|
-
});
|
|
46
|
-
return featureCollection(features);
|
|
47
|
-
}
|
|
32
|
+
declare function getCluster<G extends GeometryObject, P extends GeoJsonProperties = GeoJsonProperties>(geojson: FeatureCollection<G, P>, filter: any): FeatureCollection<G, P>;
|
|
48
33
|
/**
|
|
49
34
|
* Callback for clusterEach
|
|
50
35
|
*
|
|
@@ -93,27 +78,7 @@ export function getCluster(geojson, filter) {
|
|
|
93
78
|
* values.push(clusterValue);
|
|
94
79
|
* });
|
|
95
80
|
*/
|
|
96
|
-
|
|
97
|
-
// Validation
|
|
98
|
-
if (!geojson)
|
|
99
|
-
throw new Error("geojson is required");
|
|
100
|
-
if (geojson.type !== "FeatureCollection")
|
|
101
|
-
throw new Error("geojson must be a FeatureCollection");
|
|
102
|
-
if (property === undefined || property === null)
|
|
103
|
-
throw new Error("property is required");
|
|
104
|
-
// Create clusters based on property values
|
|
105
|
-
var bins = createBins(geojson, property);
|
|
106
|
-
var values = Object.keys(bins);
|
|
107
|
-
for (var index = 0; index < values.length; index++) {
|
|
108
|
-
var value = values[index];
|
|
109
|
-
var bin = bins[value];
|
|
110
|
-
var features = [];
|
|
111
|
-
for (var i = 0; i < bin.length; i++) {
|
|
112
|
-
features.push(geojson.features[bin[i]]);
|
|
113
|
-
}
|
|
114
|
-
callback(featureCollection(features), value, index);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
81
|
+
declare function clusterEach<G extends GeometryObject, P extends GeoJsonProperties = GeoJsonProperties>(geojson: FeatureCollection<G, P>, property: number | string, callback: (cluster: FeatureCollection<G, P>, clusterValue?: any, currentIndex?: number) => void): void;
|
|
117
82
|
/**
|
|
118
83
|
* Callback for clusterReduce
|
|
119
84
|
*
|
|
@@ -177,16 +142,7 @@ export function clusterEach(geojson, property, callback) {
|
|
|
177
142
|
* return previousValue.concat(clusterValue);
|
|
178
143
|
* }, []);
|
|
179
144
|
*/
|
|
180
|
-
|
|
181
|
-
var previousValue = initialValue;
|
|
182
|
-
clusterEach(geojson, property, function (cluster, clusterValue, currentIndex) {
|
|
183
|
-
if (currentIndex === 0 && initialValue === undefined)
|
|
184
|
-
previousValue = cluster;
|
|
185
|
-
else
|
|
186
|
-
previousValue = callback(previousValue, cluster, clusterValue, currentIndex);
|
|
187
|
-
});
|
|
188
|
-
return previousValue;
|
|
189
|
-
}
|
|
145
|
+
declare function clusterReduce<G extends GeometryObject, P extends GeoJsonProperties = GeoJsonProperties>(geojson: FeatureCollection<G, P>, property: number | string, callback: (previousValue: any | undefined, cluster: FeatureCollection<G, P>, clusterValue?: any, currentIndex?: number) => void, initialValue?: any): void;
|
|
190
146
|
/**
|
|
191
147
|
* Create Bins
|
|
192
148
|
*
|
|
@@ -204,20 +160,7 @@ export function clusterReduce(geojson, property, callback, initialValue) {
|
|
|
204
160
|
* createBins(geojson, 'cluster');
|
|
205
161
|
* //= { '0': [ 0 ], '1': [ 1, 3 ] }
|
|
206
162
|
*/
|
|
207
|
-
|
|
208
|
-
var bins = {};
|
|
209
|
-
featureEach(geojson, function (feature, i) {
|
|
210
|
-
var properties = feature.properties || {};
|
|
211
|
-
if (Object.prototype.hasOwnProperty.call(properties, String(property))) {
|
|
212
|
-
var value = properties[property];
|
|
213
|
-
if (Object.prototype.hasOwnProperty.call(bins, value))
|
|
214
|
-
bins[value].push(i);
|
|
215
|
-
else
|
|
216
|
-
bins[value] = [i];
|
|
217
|
-
}
|
|
218
|
-
});
|
|
219
|
-
return bins;
|
|
220
|
-
}
|
|
163
|
+
declare function createBins(geojson: FeatureCollection<any>, property: string | number): Record<string, number[]>;
|
|
221
164
|
/**
|
|
222
165
|
* Apply Filter
|
|
223
166
|
*
|
|
@@ -226,26 +169,7 @@ export function createBins(geojson, property) {
|
|
|
226
169
|
* @param {*} filter Filter
|
|
227
170
|
* @returns {boolean} applied Filter to properties
|
|
228
171
|
*/
|
|
229
|
-
|
|
230
|
-
if (properties === undefined)
|
|
231
|
-
return false;
|
|
232
|
-
var filterType = typeof filter;
|
|
233
|
-
// String & Number
|
|
234
|
-
if (filterType === "number" || filterType === "string")
|
|
235
|
-
return Object.prototype.hasOwnProperty.call(properties, filter);
|
|
236
|
-
// Array
|
|
237
|
-
else if (Array.isArray(filter)) {
|
|
238
|
-
for (var i = 0; i < filter.length; i++) {
|
|
239
|
-
if (!applyFilter(properties, filter[i]))
|
|
240
|
-
return false;
|
|
241
|
-
}
|
|
242
|
-
return true;
|
|
243
|
-
// Object
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
return propertiesContainsFilter(properties, filter);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
172
|
+
declare function applyFilter(properties: any, filter: any): boolean;
|
|
249
173
|
/**
|
|
250
174
|
* Properties contains filter (does not apply deepEqual operations)
|
|
251
175
|
*
|
|
@@ -259,15 +183,7 @@ export function applyFilter(properties, filter) {
|
|
|
259
183
|
* propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 1})
|
|
260
184
|
* //= false
|
|
261
185
|
*/
|
|
262
|
-
|
|
263
|
-
var keys = Object.keys(filter);
|
|
264
|
-
for (var i = 0; i < keys.length; i++) {
|
|
265
|
-
var key = keys[i];
|
|
266
|
-
if (properties[key] !== filter[key])
|
|
267
|
-
return false;
|
|
268
|
-
}
|
|
269
|
-
return true;
|
|
270
|
-
}
|
|
186
|
+
declare function propertiesContainsFilter(properties: any, filter: any): boolean;
|
|
271
187
|
/**
|
|
272
188
|
* Filter Properties
|
|
273
189
|
*
|
|
@@ -279,16 +195,6 @@ export function propertiesContainsFilter(properties, filter) {
|
|
|
279
195
|
* filterProperties({foo: 'bar', cluster: 0}, ['cluster'])
|
|
280
196
|
* //= {cluster: 0}
|
|
281
197
|
*/
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (!keys.length)
|
|
286
|
-
return {};
|
|
287
|
-
var newProperties = {};
|
|
288
|
-
for (var i = 0; i < keys.length; i++) {
|
|
289
|
-
var key = keys[i];
|
|
290
|
-
if (Object.prototype.hasOwnProperty.call(properties, key))
|
|
291
|
-
newProperties[key] = properties[key];
|
|
292
|
-
}
|
|
293
|
-
return newProperties;
|
|
294
|
-
}
|
|
198
|
+
declare function filterProperties(properties: Record<string, any>, keys: string[]): any;
|
|
199
|
+
|
|
200
|
+
export { applyFilter, clusterEach, clusterReduce, createBins, filterProperties, getCluster, propertiesContainsFilter };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GeometryObject, GeoJsonProperties, FeatureCollection } from 'geojson';
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
4
|
* Get Cluster
|
|
4
5
|
*
|
|
@@ -28,7 +29,7 @@ import { FeatureCollection, GeometryObject } from "geojson";
|
|
|
28
29
|
* turf.getCluster(clustered, {'marker-symbol': 'square'}).length;
|
|
29
30
|
* //= 1
|
|
30
31
|
*/
|
|
31
|
-
|
|
32
|
+
declare function getCluster<G extends GeometryObject, P extends GeoJsonProperties = GeoJsonProperties>(geojson: FeatureCollection<G, P>, filter: any): FeatureCollection<G, P>;
|
|
32
33
|
/**
|
|
33
34
|
* Callback for clusterEach
|
|
34
35
|
*
|
|
@@ -77,7 +78,7 @@ export declare function getCluster<G extends GeometryObject, P = any>(geojson: F
|
|
|
77
78
|
* values.push(clusterValue);
|
|
78
79
|
* });
|
|
79
80
|
*/
|
|
80
|
-
|
|
81
|
+
declare function clusterEach<G extends GeometryObject, P extends GeoJsonProperties = GeoJsonProperties>(geojson: FeatureCollection<G, P>, property: number | string, callback: (cluster: FeatureCollection<G, P>, clusterValue?: any, currentIndex?: number) => void): void;
|
|
81
82
|
/**
|
|
82
83
|
* Callback for clusterReduce
|
|
83
84
|
*
|
|
@@ -141,7 +142,7 @@ export declare function clusterEach<G extends GeometryObject, P = any>(geojson:
|
|
|
141
142
|
* return previousValue.concat(clusterValue);
|
|
142
143
|
* }, []);
|
|
143
144
|
*/
|
|
144
|
-
|
|
145
|
+
declare function clusterReduce<G extends GeometryObject, P extends GeoJsonProperties = GeoJsonProperties>(geojson: FeatureCollection<G, P>, property: number | string, callback: (previousValue: any | undefined, cluster: FeatureCollection<G, P>, clusterValue?: any, currentIndex?: number) => void, initialValue?: any): void;
|
|
145
146
|
/**
|
|
146
147
|
* Create Bins
|
|
147
148
|
*
|
|
@@ -159,7 +160,7 @@ export declare function clusterReduce<G extends GeometryObject, P = any>(geojson
|
|
|
159
160
|
* createBins(geojson, 'cluster');
|
|
160
161
|
* //= { '0': [ 0 ], '1': [ 1, 3 ] }
|
|
161
162
|
*/
|
|
162
|
-
|
|
163
|
+
declare function createBins(geojson: FeatureCollection<any>, property: string | number): Record<string, number[]>;
|
|
163
164
|
/**
|
|
164
165
|
* Apply Filter
|
|
165
166
|
*
|
|
@@ -168,7 +169,7 @@ export declare function createBins(geojson: FeatureCollection<any>, property: st
|
|
|
168
169
|
* @param {*} filter Filter
|
|
169
170
|
* @returns {boolean} applied Filter to properties
|
|
170
171
|
*/
|
|
171
|
-
|
|
172
|
+
declare function applyFilter(properties: any, filter: any): boolean;
|
|
172
173
|
/**
|
|
173
174
|
* Properties contains filter (does not apply deepEqual operations)
|
|
174
175
|
*
|
|
@@ -182,7 +183,7 @@ export declare function applyFilter(properties: any, filter: any): boolean;
|
|
|
182
183
|
* propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 1})
|
|
183
184
|
* //= false
|
|
184
185
|
*/
|
|
185
|
-
|
|
186
|
+
declare function propertiesContainsFilter(properties: any, filter: any): boolean;
|
|
186
187
|
/**
|
|
187
188
|
* Filter Properties
|
|
188
189
|
*
|
|
@@ -194,4 +195,6 @@ export declare function propertiesContainsFilter(properties: any, filter: any):
|
|
|
194
195
|
* filterProperties({foo: 'bar', cluster: 0}, ['cluster'])
|
|
195
196
|
* //= {cluster: 0}
|
|
196
197
|
*/
|
|
197
|
-
|
|
198
|
+
declare function filterProperties(properties: Record<string, any>, keys: string[]): any;
|
|
199
|
+
|
|
200
|
+
export { applyFilter, clusterEach, clusterReduce, createBins, filterProperties, getCluster, propertiesContainsFilter };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// index.ts
|
|
2
|
+
import { featureEach } from "@turf/meta";
|
|
3
|
+
import { featureCollection } from "@turf/helpers";
|
|
4
|
+
function getCluster(geojson, filter) {
|
|
5
|
+
if (!geojson)
|
|
6
|
+
throw new Error("geojson is required");
|
|
7
|
+
if (geojson.type !== "FeatureCollection")
|
|
8
|
+
throw new Error("geojson must be a FeatureCollection");
|
|
9
|
+
if (filter === void 0 || filter === null)
|
|
10
|
+
throw new Error("filter is required");
|
|
11
|
+
var features = [];
|
|
12
|
+
featureEach(geojson, function(feature) {
|
|
13
|
+
if (applyFilter(feature.properties, filter))
|
|
14
|
+
features.push(feature);
|
|
15
|
+
});
|
|
16
|
+
return featureCollection(features);
|
|
17
|
+
}
|
|
18
|
+
function clusterEach(geojson, property, callback) {
|
|
19
|
+
if (!geojson)
|
|
20
|
+
throw new Error("geojson is required");
|
|
21
|
+
if (geojson.type !== "FeatureCollection")
|
|
22
|
+
throw new Error("geojson must be a FeatureCollection");
|
|
23
|
+
if (property === void 0 || property === null)
|
|
24
|
+
throw new Error("property is required");
|
|
25
|
+
var bins = createBins(geojson, property);
|
|
26
|
+
var values = Object.keys(bins);
|
|
27
|
+
for (var index = 0; index < values.length; index++) {
|
|
28
|
+
var value = values[index];
|
|
29
|
+
var bin = bins[value];
|
|
30
|
+
var features = [];
|
|
31
|
+
for (var i = 0; i < bin.length; i++) {
|
|
32
|
+
features.push(geojson.features[bin[i]]);
|
|
33
|
+
}
|
|
34
|
+
callback(featureCollection(features), value, index);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function clusterReduce(geojson, property, callback, initialValue) {
|
|
38
|
+
var previousValue = initialValue;
|
|
39
|
+
clusterEach(
|
|
40
|
+
geojson,
|
|
41
|
+
property,
|
|
42
|
+
function(cluster, clusterValue, currentIndex) {
|
|
43
|
+
if (currentIndex === 0 && initialValue === void 0)
|
|
44
|
+
previousValue = cluster;
|
|
45
|
+
else
|
|
46
|
+
previousValue = callback(
|
|
47
|
+
previousValue,
|
|
48
|
+
cluster,
|
|
49
|
+
clusterValue,
|
|
50
|
+
currentIndex
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
return previousValue;
|
|
55
|
+
}
|
|
56
|
+
function createBins(geojson, property) {
|
|
57
|
+
var bins = {};
|
|
58
|
+
featureEach(geojson, function(feature, i) {
|
|
59
|
+
var properties = feature.properties || {};
|
|
60
|
+
if (Object.prototype.hasOwnProperty.call(properties, String(property))) {
|
|
61
|
+
var value = properties[property];
|
|
62
|
+
if (Object.prototype.hasOwnProperty.call(bins, value))
|
|
63
|
+
bins[value].push(i);
|
|
64
|
+
else
|
|
65
|
+
bins[value] = [i];
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return bins;
|
|
69
|
+
}
|
|
70
|
+
function applyFilter(properties, filter) {
|
|
71
|
+
if (properties === void 0)
|
|
72
|
+
return false;
|
|
73
|
+
var filterType = typeof filter;
|
|
74
|
+
if (filterType === "number" || filterType === "string")
|
|
75
|
+
return Object.prototype.hasOwnProperty.call(properties, filter);
|
|
76
|
+
else if (Array.isArray(filter)) {
|
|
77
|
+
for (var i = 0; i < filter.length; i++) {
|
|
78
|
+
if (!applyFilter(properties, filter[i]))
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
} else {
|
|
83
|
+
return propertiesContainsFilter(properties, filter);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function propertiesContainsFilter(properties, filter) {
|
|
87
|
+
var keys = Object.keys(filter);
|
|
88
|
+
for (var i = 0; i < keys.length; i++) {
|
|
89
|
+
var key = keys[i];
|
|
90
|
+
if (properties[key] !== filter[key])
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
function filterProperties(properties, keys) {
|
|
96
|
+
if (!keys)
|
|
97
|
+
return {};
|
|
98
|
+
if (!keys.length)
|
|
99
|
+
return {};
|
|
100
|
+
var newProperties = {};
|
|
101
|
+
for (var i = 0; i < keys.length; i++) {
|
|
102
|
+
var key = keys[i];
|
|
103
|
+
if (Object.prototype.hasOwnProperty.call(properties, key))
|
|
104
|
+
newProperties[key] = properties[key];
|
|
105
|
+
}
|
|
106
|
+
return newProperties;
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
applyFilter,
|
|
110
|
+
clusterEach,
|
|
111
|
+
clusterReduce,
|
|
112
|
+
createBins,
|
|
113
|
+
filterProperties,
|
|
114
|
+
getCluster,
|
|
115
|
+
propertiesContainsFilter
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../index.ts"],"sourcesContent":["import {\n Feature,\n FeatureCollection,\n GeoJsonProperties,\n GeometryObject,\n} from \"geojson\";\nimport { featureEach } from \"@turf/meta\";\nimport { featureCollection } from \"@turf/helpers\";\n\n/**\n * Get Cluster\n *\n * @name getCluster\n * @param {FeatureCollection} geojson GeoJSON Features\n * @param {*} filter Filter used on GeoJSON properties to get Cluster\n * @returns {FeatureCollection} Single Cluster filtered by GeoJSON Properties\n * @example\n * var geojson = turf.featureCollection([\n * turf.point([0, 0], {'marker-symbol': 'circle'}),\n * turf.point([2, 4], {'marker-symbol': 'star'}),\n * turf.point([3, 6], {'marker-symbol': 'star'}),\n * turf.point([5, 1], {'marker-symbol': 'square'}),\n * turf.point([4, 2], {'marker-symbol': 'circle'})\n * ]);\n *\n * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)\n * var clustered = turf.clustersKmeans(geojson);\n *\n * // Retrieve first cluster (0)\n * var cluster = turf.getCluster(clustered, {cluster: 0});\n * //= cluster\n *\n * // Retrieve cluster based on custom properties\n * turf.getCluster(clustered, {'marker-symbol': 'circle'}).length;\n * //= 2\n * turf.getCluster(clustered, {'marker-symbol': 'square'}).length;\n * //= 1\n */\nfunction getCluster<\n G extends GeometryObject,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(geojson: FeatureCollection<G, P>, filter: any): FeatureCollection<G, P> {\n // Validation\n if (!geojson) throw new Error(\"geojson is required\");\n if (geojson.type !== \"FeatureCollection\")\n throw new Error(\"geojson must be a FeatureCollection\");\n if (filter === undefined || filter === null)\n throw new Error(\"filter is required\");\n\n // Filter Features\n var features: Feature<G, P>[] = [];\n featureEach<G, P>(geojson, function (feature) {\n if (applyFilter(feature.properties, filter)) features.push(feature);\n });\n return featureCollection(features);\n}\n\n/**\n * Callback for clusterEach\n *\n * @callback clusterEachCallback\n * @param {FeatureCollection} [cluster] The current cluster being processed.\n * @param {*} [clusterValue] Value used to create cluster being processed.\n * @param {number} [currentIndex] The index of the current element being processed in the array.Starts at index 0\n * @returns {void}\n */\n\n/**\n * clusterEach\n *\n * @name clusterEach\n * @param {FeatureCollection} geojson GeoJSON Features\n * @param {string|number} property GeoJSON property key/value used to create clusters\n * @param {Function} callback a method that takes (cluster, clusterValue, currentIndex)\n * @returns {void}\n * @example\n * var geojson = turf.featureCollection([\n * turf.point([0, 0]),\n * turf.point([2, 4]),\n * turf.point([3, 6]),\n * turf.point([5, 1]),\n * turf.point([4, 2])\n * ]);\n *\n * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)\n * var clustered = turf.clustersKmeans(geojson);\n *\n * // Iterate over each cluster\n * turf.clusterEach(clustered, 'cluster', function (cluster, clusterValue, currentIndex) {\n * //= cluster\n * //= clusterValue\n * //= currentIndex\n * })\n *\n * // Calculate the total number of clusters\n * var total = 0\n * turf.clusterEach(clustered, 'cluster', function () {\n * total++;\n * });\n *\n * // Create an Array of all the values retrieved from the 'cluster' property\n * var values = []\n * turf.clusterEach(clustered, 'cluster', function (cluster, clusterValue) {\n * values.push(clusterValue);\n * });\n */\nfunction clusterEach<\n G extends GeometryObject,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n geojson: FeatureCollection<G, P>,\n property: number | string,\n callback: (\n cluster: FeatureCollection<G, P>,\n clusterValue?: any,\n currentIndex?: number\n ) => void\n): void {\n // Validation\n if (!geojson) throw new Error(\"geojson is required\");\n if (geojson.type !== \"FeatureCollection\")\n throw new Error(\"geojson must be a FeatureCollection\");\n if (property === undefined || property === null)\n throw new Error(\"property is required\");\n\n // Create clusters based on property values\n var bins = createBins(geojson, property);\n var values = Object.keys(bins);\n for (var index = 0; index < values.length; index++) {\n var value = values[index];\n var bin = bins[value];\n var features = [];\n for (var i = 0; i < bin.length; i++) {\n features.push(geojson.features[bin[i]]);\n }\n callback(featureCollection(features), value, index);\n }\n}\n\n/**\n * Callback for clusterReduce\n *\n * The first time the callback function is called, the values provided as arguments depend\n * on whether the reduce method has an initialValue argument.\n *\n * If an initialValue is provided to the reduce method:\n * - The previousValue argument is initialValue.\n * - The currentValue argument is the value of the first element present in the array.\n *\n * If an initialValue is not provided:\n * - The previousValue argument is the value of the first element present in the array.\n * - The currentValue argument is the value of the second element present in the array.\n *\n * @callback clusterReduceCallback\n * @param {*} [previousValue] The accumulated value previously returned in the last invocation\n * of the callback, or initialValue, if supplied.\n * @param {FeatureCollection} [cluster] The current cluster being processed.\n * @param {*} [clusterValue] Value used to create cluster being processed.\n * @param {number} [currentIndex] The index of the current element being processed in the\n * array. Starts at index 0, if an initialValue is provided, and at index 1 otherwise.\n */\n\n/**\n * Reduce clusters in GeoJSON Features, similar to Array.reduce()\n *\n * @name clusterReduce\n * @param {FeatureCollection} geojson GeoJSON Features\n * @param {string|number} property GeoJSON property key/value used to create clusters\n * @param {Function} callback a method that takes (previousValue, cluster, clusterValue, currentIndex)\n * @param {*} [initialValue] Value to use as the first argument to the first call of the callback.\n * @returns {*} The value that results from the reduction.\n * @example\n * var geojson = turf.featureCollection([\n * turf.point([0, 0]),\n * turf.point([2, 4]),\n * turf.point([3, 6]),\n * turf.point([5, 1]),\n * turf.point([4, 2])\n * ]);\n *\n * // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)\n * var clustered = turf.clustersKmeans(geojson);\n *\n * // Iterate over each cluster and perform a calculation\n * var initialValue = 0\n * turf.clusterReduce(clustered, 'cluster', function (previousValue, cluster, clusterValue, currentIndex) {\n * //=previousValue\n * //=cluster\n * //=clusterValue\n * //=currentIndex\n * return previousValue++;\n * }, initialValue);\n *\n * // Calculate the total number of clusters\n * var total = turf.clusterReduce(clustered, 'cluster', function (previousValue) {\n * return previousValue++;\n * }, 0);\n *\n * // Create an Array of all the values retrieved from the 'cluster' property\n * var values = turf.clusterReduce(clustered, 'cluster', function (previousValue, cluster, clusterValue) {\n * return previousValue.concat(clusterValue);\n * }, []);\n */\nfunction clusterReduce<\n G extends GeometryObject,\n P extends GeoJsonProperties = GeoJsonProperties,\n>(\n geojson: FeatureCollection<G, P>,\n property: number | string,\n callback: (\n previousValue: any | undefined,\n cluster: FeatureCollection<G, P>,\n clusterValue?: any,\n currentIndex?: number\n ) => void,\n initialValue?: any\n): void {\n var previousValue = initialValue;\n clusterEach(\n geojson,\n property,\n function (cluster, clusterValue, currentIndex) {\n if (currentIndex === 0 && initialValue === undefined)\n previousValue = cluster;\n else\n previousValue = callback(\n previousValue,\n cluster,\n clusterValue,\n currentIndex\n );\n }\n );\n return previousValue;\n}\n\n/**\n * Create Bins\n *\n * @private\n * @param {FeatureCollection} geojson GeoJSON Features\n * @param {string|number} property Property values are used to create bins\n * @returns {Object} bins with Feature IDs\n * @example\n * var geojson = turf.featureCollection([\n * turf.point([0, 0], {cluster: 0, foo: 'null'}),\n * turf.point([2, 4], {cluster: 1, foo: 'bar'}),\n * turf.point([5, 1], {0: 'foo'}),\n * turf.point([3, 6], {cluster: 1}),\n * ]);\n * createBins(geojson, 'cluster');\n * //= { '0': [ 0 ], '1': [ 1, 3 ] }\n */\nfunction createBins(\n geojson: FeatureCollection<any>,\n property: string | number\n) {\n var bins: Record<string, number[]> = {};\n\n featureEach(geojson, function (feature, i) {\n var properties = feature.properties || {};\n if (Object.prototype.hasOwnProperty.call(properties, String(property))) {\n var value = properties[property];\n if (Object.prototype.hasOwnProperty.call(bins, value))\n bins[value].push(i);\n else bins[value] = [i];\n }\n });\n return bins;\n}\n\n/**\n * Apply Filter\n *\n * @private\n * @param {*} properties Properties\n * @param {*} filter Filter\n * @returns {boolean} applied Filter to properties\n */\nfunction applyFilter(properties: any, filter: any) {\n if (properties === undefined) return false;\n var filterType = typeof filter;\n\n // String & Number\n if (filterType === \"number\" || filterType === \"string\")\n return Object.prototype.hasOwnProperty.call(properties, filter);\n // Array\n else if (Array.isArray(filter)) {\n for (var i = 0; i < filter.length; i++) {\n if (!applyFilter(properties, filter[i])) return false;\n }\n return true;\n // Object\n } else {\n return propertiesContainsFilter(properties, filter);\n }\n}\n\n/**\n * Properties contains filter (does not apply deepEqual operations)\n *\n * @private\n * @param {*} properties Properties\n * @param {Object} filter Filter\n * @returns {boolean} does filter equal Properties\n * @example\n * propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 0})\n * //= true\n * propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 1})\n * //= false\n */\nfunction propertiesContainsFilter(properties: any, filter: any): boolean {\n var keys = Object.keys(filter);\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n if (properties[key] !== filter[key]) return false;\n }\n return true;\n}\n\n/**\n * Filter Properties\n *\n * @private\n * @param {*} properties Properties\n * @param {Array<string>} keys Used to filter Properties\n * @returns {*} filtered Properties\n * @example\n * filterProperties({foo: 'bar', cluster: 0}, ['cluster'])\n * //= {cluster: 0}\n */\nfunction filterProperties(\n properties: Record<string, any>,\n keys: string[]\n): any {\n if (!keys) return {};\n if (!keys.length) return {};\n\n var newProperties: Record<string, any> = {};\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n if (Object.prototype.hasOwnProperty.call(properties, key))\n newProperties[key] = properties[key];\n }\n return newProperties;\n}\n\nexport {\n getCluster,\n clusterEach,\n clusterReduce,\n createBins,\n applyFilter,\n propertiesContainsFilter,\n filterProperties,\n};\n// No default export!\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@turf/clusters",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.0-alpha.7+0ce6ecca0",
|
|
4
4
|
"description": "turf clusters module",
|
|
5
5
|
"author": "Turf Authors",
|
|
6
6
|
"contributors": [
|
|
@@ -26,44 +26,49 @@
|
|
|
26
26
|
"clusters",
|
|
27
27
|
"clustering"
|
|
28
28
|
],
|
|
29
|
-
"
|
|
30
|
-
"
|
|
29
|
+
"type": "module",
|
|
30
|
+
"main": "dist/cjs/index.cjs",
|
|
31
|
+
"module": "dist/esm/index.js",
|
|
32
|
+
"types": "dist/esm/index.d.ts",
|
|
31
33
|
"exports": {
|
|
32
34
|
"./package.json": "./package.json",
|
|
33
35
|
".": {
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
"import": {
|
|
37
|
+
"types": "./dist/esm/index.d.ts",
|
|
38
|
+
"default": "./dist/esm/index.js"
|
|
39
|
+
},
|
|
40
|
+
"require": {
|
|
41
|
+
"types": "./dist/cjs/index.d.cts",
|
|
42
|
+
"default": "./dist/cjs/index.cjs"
|
|
43
|
+
}
|
|
37
44
|
}
|
|
38
45
|
},
|
|
39
|
-
"types": "dist/js/index.d.ts",
|
|
40
46
|
"sideEffects": false,
|
|
41
47
|
"files": [
|
|
42
48
|
"dist"
|
|
43
49
|
],
|
|
44
50
|
"scripts": {
|
|
45
|
-
"bench": "tsx bench.
|
|
46
|
-
"build": "
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"test": "
|
|
51
|
-
"test:tape": "tsx test.js",
|
|
52
|
-
"test:types": "tsc --esModuleInterop --noEmit --strict types.ts"
|
|
51
|
+
"bench": "tsx bench.ts",
|
|
52
|
+
"build": "tsup --config ../../tsup.config.ts",
|
|
53
|
+
"docs": "tsx ../../scripts/generate-readmes.ts",
|
|
54
|
+
"test": "npm-run-all --npm-path npm test:*",
|
|
55
|
+
"test:tape": "tsx test.ts",
|
|
56
|
+
"test:types": "tsc --esModuleInterop --module node16 --moduleResolution node16 --noEmit --strict types.ts"
|
|
53
57
|
},
|
|
54
58
|
"devDependencies": {
|
|
55
|
-
"@types/
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
59
|
+
"@types/benchmark": "^2.1.5",
|
|
60
|
+
"@types/tape": "^4.2.32",
|
|
61
|
+
"benchmark": "^2.1.4",
|
|
62
|
+
"npm-run-all": "^4.1.5",
|
|
63
|
+
"tape": "^5.7.2",
|
|
64
|
+
"tsup": "^8.0.1",
|
|
65
|
+
"tsx": "^4.6.2",
|
|
66
|
+
"typescript": "^5.2.2"
|
|
62
67
|
},
|
|
63
68
|
"dependencies": {
|
|
64
|
-
"@turf/helpers": "^7.
|
|
65
|
-
"@turf/meta": "^7.
|
|
66
|
-
"tslib": "^2.
|
|
69
|
+
"@turf/helpers": "^7.1.0-alpha.7+0ce6ecca0",
|
|
70
|
+
"@turf/meta": "^7.1.0-alpha.7+0ce6ecca0",
|
|
71
|
+
"tslib": "^2.6.2"
|
|
67
72
|
},
|
|
68
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "0ce6ecca05829690270fec6d6bed2003495fe0ea"
|
|
69
74
|
}
|
package/dist/es/package.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"type":"module"}
|
package/dist/js/index.js
DELETED
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const meta_1 = require("@turf/meta");
|
|
4
|
-
const helpers_1 = require("@turf/helpers");
|
|
5
|
-
/**
|
|
6
|
-
* Get Cluster
|
|
7
|
-
*
|
|
8
|
-
* @name getCluster
|
|
9
|
-
* @param {FeatureCollection} geojson GeoJSON Features
|
|
10
|
-
* @param {*} filter Filter used on GeoJSON properties to get Cluster
|
|
11
|
-
* @returns {FeatureCollection} Single Cluster filtered by GeoJSON Properties
|
|
12
|
-
* @example
|
|
13
|
-
* var geojson = turf.featureCollection([
|
|
14
|
-
* turf.point([0, 0], {'marker-symbol': 'circle'}),
|
|
15
|
-
* turf.point([2, 4], {'marker-symbol': 'star'}),
|
|
16
|
-
* turf.point([3, 6], {'marker-symbol': 'star'}),
|
|
17
|
-
* turf.point([5, 1], {'marker-symbol': 'square'}),
|
|
18
|
-
* turf.point([4, 2], {'marker-symbol': 'circle'})
|
|
19
|
-
* ]);
|
|
20
|
-
*
|
|
21
|
-
* // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)
|
|
22
|
-
* var clustered = turf.clustersKmeans(geojson);
|
|
23
|
-
*
|
|
24
|
-
* // Retrieve first cluster (0)
|
|
25
|
-
* var cluster = turf.getCluster(clustered, {cluster: 0});
|
|
26
|
-
* //= cluster
|
|
27
|
-
*
|
|
28
|
-
* // Retrieve cluster based on custom properties
|
|
29
|
-
* turf.getCluster(clustered, {'marker-symbol': 'circle'}).length;
|
|
30
|
-
* //= 2
|
|
31
|
-
* turf.getCluster(clustered, {'marker-symbol': 'square'}).length;
|
|
32
|
-
* //= 1
|
|
33
|
-
*/
|
|
34
|
-
function getCluster(geojson, filter) {
|
|
35
|
-
// Validation
|
|
36
|
-
if (!geojson)
|
|
37
|
-
throw new Error("geojson is required");
|
|
38
|
-
if (geojson.type !== "FeatureCollection")
|
|
39
|
-
throw new Error("geojson must be a FeatureCollection");
|
|
40
|
-
if (filter === undefined || filter === null)
|
|
41
|
-
throw new Error("filter is required");
|
|
42
|
-
// Filter Features
|
|
43
|
-
var features = [];
|
|
44
|
-
meta_1.featureEach(geojson, function (feature) {
|
|
45
|
-
if (applyFilter(feature.properties, filter))
|
|
46
|
-
features.push(feature);
|
|
47
|
-
});
|
|
48
|
-
return helpers_1.featureCollection(features);
|
|
49
|
-
}
|
|
50
|
-
exports.getCluster = getCluster;
|
|
51
|
-
/**
|
|
52
|
-
* Callback for clusterEach
|
|
53
|
-
*
|
|
54
|
-
* @callback clusterEachCallback
|
|
55
|
-
* @param {FeatureCollection} [cluster] The current cluster being processed.
|
|
56
|
-
* @param {*} [clusterValue] Value used to create cluster being processed.
|
|
57
|
-
* @param {number} [currentIndex] The index of the current element being processed in the array.Starts at index 0
|
|
58
|
-
* @returns {void}
|
|
59
|
-
*/
|
|
60
|
-
/**
|
|
61
|
-
* clusterEach
|
|
62
|
-
*
|
|
63
|
-
* @name clusterEach
|
|
64
|
-
* @param {FeatureCollection} geojson GeoJSON Features
|
|
65
|
-
* @param {string|number} property GeoJSON property key/value used to create clusters
|
|
66
|
-
* @param {Function} callback a method that takes (cluster, clusterValue, currentIndex)
|
|
67
|
-
* @returns {void}
|
|
68
|
-
* @example
|
|
69
|
-
* var geojson = turf.featureCollection([
|
|
70
|
-
* turf.point([0, 0]),
|
|
71
|
-
* turf.point([2, 4]),
|
|
72
|
-
* turf.point([3, 6]),
|
|
73
|
-
* turf.point([5, 1]),
|
|
74
|
-
* turf.point([4, 2])
|
|
75
|
-
* ]);
|
|
76
|
-
*
|
|
77
|
-
* // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)
|
|
78
|
-
* var clustered = turf.clustersKmeans(geojson);
|
|
79
|
-
*
|
|
80
|
-
* // Iterate over each cluster
|
|
81
|
-
* turf.clusterEach(clustered, 'cluster', function (cluster, clusterValue, currentIndex) {
|
|
82
|
-
* //= cluster
|
|
83
|
-
* //= clusterValue
|
|
84
|
-
* //= currentIndex
|
|
85
|
-
* })
|
|
86
|
-
*
|
|
87
|
-
* // Calculate the total number of clusters
|
|
88
|
-
* var total = 0
|
|
89
|
-
* turf.clusterEach(clustered, 'cluster', function () {
|
|
90
|
-
* total++;
|
|
91
|
-
* });
|
|
92
|
-
*
|
|
93
|
-
* // Create an Array of all the values retrieved from the 'cluster' property
|
|
94
|
-
* var values = []
|
|
95
|
-
* turf.clusterEach(clustered, 'cluster', function (cluster, clusterValue) {
|
|
96
|
-
* values.push(clusterValue);
|
|
97
|
-
* });
|
|
98
|
-
*/
|
|
99
|
-
function clusterEach(geojson, property, callback) {
|
|
100
|
-
// Validation
|
|
101
|
-
if (!geojson)
|
|
102
|
-
throw new Error("geojson is required");
|
|
103
|
-
if (geojson.type !== "FeatureCollection")
|
|
104
|
-
throw new Error("geojson must be a FeatureCollection");
|
|
105
|
-
if (property === undefined || property === null)
|
|
106
|
-
throw new Error("property is required");
|
|
107
|
-
// Create clusters based on property values
|
|
108
|
-
var bins = createBins(geojson, property);
|
|
109
|
-
var values = Object.keys(bins);
|
|
110
|
-
for (var index = 0; index < values.length; index++) {
|
|
111
|
-
var value = values[index];
|
|
112
|
-
var bin = bins[value];
|
|
113
|
-
var features = [];
|
|
114
|
-
for (var i = 0; i < bin.length; i++) {
|
|
115
|
-
features.push(geojson.features[bin[i]]);
|
|
116
|
-
}
|
|
117
|
-
callback(helpers_1.featureCollection(features), value, index);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
exports.clusterEach = clusterEach;
|
|
121
|
-
/**
|
|
122
|
-
* Callback for clusterReduce
|
|
123
|
-
*
|
|
124
|
-
* The first time the callback function is called, the values provided as arguments depend
|
|
125
|
-
* on whether the reduce method has an initialValue argument.
|
|
126
|
-
*
|
|
127
|
-
* If an initialValue is provided to the reduce method:
|
|
128
|
-
* - The previousValue argument is initialValue.
|
|
129
|
-
* - The currentValue argument is the value of the first element present in the array.
|
|
130
|
-
*
|
|
131
|
-
* If an initialValue is not provided:
|
|
132
|
-
* - The previousValue argument is the value of the first element present in the array.
|
|
133
|
-
* - The currentValue argument is the value of the second element present in the array.
|
|
134
|
-
*
|
|
135
|
-
* @callback clusterReduceCallback
|
|
136
|
-
* @param {*} [previousValue] The accumulated value previously returned in the last invocation
|
|
137
|
-
* of the callback, or initialValue, if supplied.
|
|
138
|
-
* @param {FeatureCollection} [cluster] The current cluster being processed.
|
|
139
|
-
* @param {*} [clusterValue] Value used to create cluster being processed.
|
|
140
|
-
* @param {number} [currentIndex] The index of the current element being processed in the
|
|
141
|
-
* array. Starts at index 0, if an initialValue is provided, and at index 1 otherwise.
|
|
142
|
-
*/
|
|
143
|
-
/**
|
|
144
|
-
* Reduce clusters in GeoJSON Features, similar to Array.reduce()
|
|
145
|
-
*
|
|
146
|
-
* @name clusterReduce
|
|
147
|
-
* @param {FeatureCollection} geojson GeoJSON Features
|
|
148
|
-
* @param {string|number} property GeoJSON property key/value used to create clusters
|
|
149
|
-
* @param {Function} callback a method that takes (previousValue, cluster, clusterValue, currentIndex)
|
|
150
|
-
* @param {*} [initialValue] Value to use as the first argument to the first call of the callback.
|
|
151
|
-
* @returns {*} The value that results from the reduction.
|
|
152
|
-
* @example
|
|
153
|
-
* var geojson = turf.featureCollection([
|
|
154
|
-
* turf.point([0, 0]),
|
|
155
|
-
* turf.point([2, 4]),
|
|
156
|
-
* turf.point([3, 6]),
|
|
157
|
-
* turf.point([5, 1]),
|
|
158
|
-
* turf.point([4, 2])
|
|
159
|
-
* ]);
|
|
160
|
-
*
|
|
161
|
-
* // Create a cluster using K-Means (adds `cluster` to GeoJSON properties)
|
|
162
|
-
* var clustered = turf.clustersKmeans(geojson);
|
|
163
|
-
*
|
|
164
|
-
* // Iterate over each cluster and perform a calculation
|
|
165
|
-
* var initialValue = 0
|
|
166
|
-
* turf.clusterReduce(clustered, 'cluster', function (previousValue, cluster, clusterValue, currentIndex) {
|
|
167
|
-
* //=previousValue
|
|
168
|
-
* //=cluster
|
|
169
|
-
* //=clusterValue
|
|
170
|
-
* //=currentIndex
|
|
171
|
-
* return previousValue++;
|
|
172
|
-
* }, initialValue);
|
|
173
|
-
*
|
|
174
|
-
* // Calculate the total number of clusters
|
|
175
|
-
* var total = turf.clusterReduce(clustered, 'cluster', function (previousValue) {
|
|
176
|
-
* return previousValue++;
|
|
177
|
-
* }, 0);
|
|
178
|
-
*
|
|
179
|
-
* // Create an Array of all the values retrieved from the 'cluster' property
|
|
180
|
-
* var values = turf.clusterReduce(clustered, 'cluster', function (previousValue, cluster, clusterValue) {
|
|
181
|
-
* return previousValue.concat(clusterValue);
|
|
182
|
-
* }, []);
|
|
183
|
-
*/
|
|
184
|
-
function clusterReduce(geojson, property, callback, initialValue) {
|
|
185
|
-
var previousValue = initialValue;
|
|
186
|
-
clusterEach(geojson, property, function (cluster, clusterValue, currentIndex) {
|
|
187
|
-
if (currentIndex === 0 && initialValue === undefined)
|
|
188
|
-
previousValue = cluster;
|
|
189
|
-
else
|
|
190
|
-
previousValue = callback(previousValue, cluster, clusterValue, currentIndex);
|
|
191
|
-
});
|
|
192
|
-
return previousValue;
|
|
193
|
-
}
|
|
194
|
-
exports.clusterReduce = clusterReduce;
|
|
195
|
-
/**
|
|
196
|
-
* Create Bins
|
|
197
|
-
*
|
|
198
|
-
* @private
|
|
199
|
-
* @param {FeatureCollection} geojson GeoJSON Features
|
|
200
|
-
* @param {string|number} property Property values are used to create bins
|
|
201
|
-
* @returns {Object} bins with Feature IDs
|
|
202
|
-
* @example
|
|
203
|
-
* var geojson = turf.featureCollection([
|
|
204
|
-
* turf.point([0, 0], {cluster: 0, foo: 'null'}),
|
|
205
|
-
* turf.point([2, 4], {cluster: 1, foo: 'bar'}),
|
|
206
|
-
* turf.point([5, 1], {0: 'foo'}),
|
|
207
|
-
* turf.point([3, 6], {cluster: 1}),
|
|
208
|
-
* ]);
|
|
209
|
-
* createBins(geojson, 'cluster');
|
|
210
|
-
* //= { '0': [ 0 ], '1': [ 1, 3 ] }
|
|
211
|
-
*/
|
|
212
|
-
function createBins(geojson, property) {
|
|
213
|
-
var bins = {};
|
|
214
|
-
meta_1.featureEach(geojson, function (feature, i) {
|
|
215
|
-
var properties = feature.properties || {};
|
|
216
|
-
if (Object.prototype.hasOwnProperty.call(properties, String(property))) {
|
|
217
|
-
var value = properties[property];
|
|
218
|
-
if (Object.prototype.hasOwnProperty.call(bins, value))
|
|
219
|
-
bins[value].push(i);
|
|
220
|
-
else
|
|
221
|
-
bins[value] = [i];
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
return bins;
|
|
225
|
-
}
|
|
226
|
-
exports.createBins = createBins;
|
|
227
|
-
/**
|
|
228
|
-
* Apply Filter
|
|
229
|
-
*
|
|
230
|
-
* @private
|
|
231
|
-
* @param {*} properties Properties
|
|
232
|
-
* @param {*} filter Filter
|
|
233
|
-
* @returns {boolean} applied Filter to properties
|
|
234
|
-
*/
|
|
235
|
-
function applyFilter(properties, filter) {
|
|
236
|
-
if (properties === undefined)
|
|
237
|
-
return false;
|
|
238
|
-
var filterType = typeof filter;
|
|
239
|
-
// String & Number
|
|
240
|
-
if (filterType === "number" || filterType === "string")
|
|
241
|
-
return Object.prototype.hasOwnProperty.call(properties, filter);
|
|
242
|
-
// Array
|
|
243
|
-
else if (Array.isArray(filter)) {
|
|
244
|
-
for (var i = 0; i < filter.length; i++) {
|
|
245
|
-
if (!applyFilter(properties, filter[i]))
|
|
246
|
-
return false;
|
|
247
|
-
}
|
|
248
|
-
return true;
|
|
249
|
-
// Object
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
return propertiesContainsFilter(properties, filter);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
exports.applyFilter = applyFilter;
|
|
256
|
-
/**
|
|
257
|
-
* Properties contains filter (does not apply deepEqual operations)
|
|
258
|
-
*
|
|
259
|
-
* @private
|
|
260
|
-
* @param {*} properties Properties
|
|
261
|
-
* @param {Object} filter Filter
|
|
262
|
-
* @returns {boolean} does filter equal Properties
|
|
263
|
-
* @example
|
|
264
|
-
* propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 0})
|
|
265
|
-
* //= true
|
|
266
|
-
* propertiesContainsFilter({foo: 'bar', cluster: 0}, {cluster: 1})
|
|
267
|
-
* //= false
|
|
268
|
-
*/
|
|
269
|
-
function propertiesContainsFilter(properties, filter) {
|
|
270
|
-
var keys = Object.keys(filter);
|
|
271
|
-
for (var i = 0; i < keys.length; i++) {
|
|
272
|
-
var key = keys[i];
|
|
273
|
-
if (properties[key] !== filter[key])
|
|
274
|
-
return false;
|
|
275
|
-
}
|
|
276
|
-
return true;
|
|
277
|
-
}
|
|
278
|
-
exports.propertiesContainsFilter = propertiesContainsFilter;
|
|
279
|
-
/**
|
|
280
|
-
* Filter Properties
|
|
281
|
-
*
|
|
282
|
-
* @private
|
|
283
|
-
* @param {*} properties Properties
|
|
284
|
-
* @param {Array<string>} keys Used to filter Properties
|
|
285
|
-
* @returns {*} filtered Properties
|
|
286
|
-
* @example
|
|
287
|
-
* filterProperties({foo: 'bar', cluster: 0}, ['cluster'])
|
|
288
|
-
* //= {cluster: 0}
|
|
289
|
-
*/
|
|
290
|
-
function filterProperties(properties, keys) {
|
|
291
|
-
if (!keys)
|
|
292
|
-
return {};
|
|
293
|
-
if (!keys.length)
|
|
294
|
-
return {};
|
|
295
|
-
var newProperties = {};
|
|
296
|
-
for (var i = 0; i < keys.length; i++) {
|
|
297
|
-
var key = keys[i];
|
|
298
|
-
if (Object.prototype.hasOwnProperty.call(properties, key))
|
|
299
|
-
newProperties[key] = properties[key];
|
|
300
|
-
}
|
|
301
|
-
return newProperties;
|
|
302
|
-
}
|
|
303
|
-
exports.filterProperties = filterProperties;
|