@turf/clusters-dbscan 7.3.0 → 7.3.2
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/dist/cjs/index.cjs +15 -43
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +14 -42
- package/dist/esm/index.js.map +1 -1
- package/package.json +11 -12
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,57 +1,29 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// index.ts
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// index.ts
|
|
2
2
|
var _clone = require('@turf/clone');
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var _rbush = require('rbush'); var _rbush2 = _interopRequireDefault(_rbush);
|
|
3
|
+
var _kdbush = require('kdbush'); var _kdbush2 = _interopRequireDefault(_kdbush);
|
|
4
|
+
var _geokdbush = require('geokdbush'); var geokdbush = _interopRequireWildcard(_geokdbush);
|
|
6
5
|
function clustersDbscan(points, maxDistance, options = {}) {
|
|
7
6
|
if (options.mutate !== true) points = _clone.clone.call(void 0, points);
|
|
8
7
|
const minPoints = options.minPoints || 3;
|
|
9
|
-
const
|
|
10
|
-
|
|
8
|
+
const kdIndex = new (0, _kdbush2.default)(points.features.length);
|
|
9
|
+
for (const point of points.features) {
|
|
10
|
+
kdIndex.add(point.geometry.coordinates[0], point.geometry.coordinates[1]);
|
|
11
|
+
}
|
|
12
|
+
kdIndex.finish();
|
|
11
13
|
var visited = points.features.map((_) => false);
|
|
12
14
|
var assigned = points.features.map((_) => false);
|
|
13
15
|
var isnoise = points.features.map((_) => false);
|
|
14
16
|
var clusterIds = points.features.map((_) => -1);
|
|
15
|
-
tree.load(
|
|
16
|
-
points.features.map((point, index) => {
|
|
17
|
-
var [x, y] = point.geometry.coordinates;
|
|
18
|
-
return {
|
|
19
|
-
minX: x,
|
|
20
|
-
minY: y,
|
|
21
|
-
maxX: x,
|
|
22
|
-
maxY: y,
|
|
23
|
-
index
|
|
24
|
-
};
|
|
25
|
-
})
|
|
26
|
-
);
|
|
27
17
|
const regionQuery = (index) => {
|
|
28
18
|
const point = points.features[index];
|
|
29
19
|
const [x, y] = point.geometry.coordinates;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return latDistanceInDegrees / Math.cos(_helpers.degreesToRadians.call(void 0, maxY));
|
|
38
|
-
} else {
|
|
39
|
-
return latDistanceInDegrees / Math.cos(_helpers.degreesToRadians.call(void 0, minY));
|
|
40
|
-
}
|
|
41
|
-
}();
|
|
42
|
-
const minX = Math.max(x - lonDistanceInDegrees, -360);
|
|
43
|
-
const maxX = Math.min(x + lonDistanceInDegrees, 360);
|
|
44
|
-
const bbox = { minX, minY, maxX, maxY };
|
|
45
|
-
return tree.search(bbox).filter(
|
|
46
|
-
(neighbor) => {
|
|
47
|
-
const neighborIndex = neighbor.index;
|
|
48
|
-
const neighborPoint = points.features[neighborIndex];
|
|
49
|
-
const distanceInKm = _distance.distance.call(void 0, point, neighborPoint, {
|
|
50
|
-
units: "kilometers"
|
|
51
|
-
});
|
|
52
|
-
return distanceInKm <= maxDistance;
|
|
53
|
-
}
|
|
54
|
-
);
|
|
20
|
+
return geokdbush.around(kdIndex, x, y, void 0, maxDistance).map((id) => ({
|
|
21
|
+
minX: points.features[id].geometry.coordinates[0],
|
|
22
|
+
minY: points.features[id].geometry.coordinates[1],
|
|
23
|
+
maxX: points.features[id].geometry.coordinates[0],
|
|
24
|
+
maxY: points.features[id].geometry.coordinates[1],
|
|
25
|
+
index: id
|
|
26
|
+
}));
|
|
55
27
|
};
|
|
56
28
|
const expandCluster = (clusteredId, neighbors) => {
|
|
57
29
|
for (var i = 0; i < neighbors.length; i++) {
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/turf/turf/packages/turf-clusters-dbscan/dist/cjs/index.cjs","../../index.ts"],"names":[],"mappings":"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","file":"/home/runner/work/turf/turf/packages/turf-clusters-dbscan/dist/cjs/index.cjs","sourcesContent":[null,"import { GeoJsonProperties, FeatureCollection, Point } from \"geojson\";\nimport { clone } from \"@turf/clone\";\nimport { distance } from \"@turf/distance\";\nimport { degreesToRadians, lengthToDegrees, Units } from \"@turf/helpers\";\nimport RBush from \"rbush\";\n\n/**\n * Point classification within the cluster.\n *\n * @typedef {\"core\" | \"edge\" | \"noise\"} Dbscan\n */\ntype Dbscan = \"core\" | \"edge\" | \"noise\";\n\n/**\n * Properties assigned to each clustered point.\n *\n * @extends GeoJsonProperties\n * @typedef {object} DbscanProps\n * @property {Dbscan} [dbscan] type of point it has been classified as\n * @property {number} [cluster] associated clusterId\n */\ntype DbscanProps = GeoJsonProperties & {\n dbscan?: Dbscan;\n cluster?: number;\n};\n\n// Structure of a point in the spatial index\ntype IndexedPoint = {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n index: number;\n};\n\n/**\n * Takes a set of {@link Point|points} and partition them into clusters according to {@link https://en.wikipedia.org/wiki/DBSCAN|DBSCAN's} data clustering algorithm.\n *\n * @function\n * @param {FeatureCollection<Point>} points to be clustered\n * @param {number} maxDistance Maximum Distance between any point of the cluster to generate the clusters (kilometers by default, see options)\n * @param {Object} [options={}] Optional parameters\n * @param {Units} [options.units=\"kilometers\"] in which `maxDistance` is expressed, Supports all valid Turf {@link https://turfjs.org/docs/api/types/Units Units}\n * @param {boolean} [options.mutate=false] Allows GeoJSON input to be mutated\n * @param {number} [options.minPoints=3] Minimum number of points to generate a single cluster,\n * points which do not meet this requirement will be classified as an 'edge' or 'noise'.\n * @returns {FeatureCollection<Point, DbscanProps>} Clustered Points with an additional two properties associated to each Feature:\n * - {number} cluster - the associated clusterId\n * - {string} dbscan - type of point it has been classified as ('core'|'edge'|'noise')\n * @example\n * // create random points with random z-values in their properties\n * var points = turf.randomPoint(100, {bbox: [0, 30, 20, 50]});\n * var maxDistance = 100;\n * var clustered = turf.clustersDbscan(points, maxDistance);\n *\n * //addToMap\n * var addToMap = [clustered];\n */\nfunction clustersDbscan(\n points: FeatureCollection<Point>,\n maxDistance: number,\n options: {\n units?: Units;\n minPoints?: number;\n mutate?: boolean;\n } = {}\n): FeatureCollection<Point, DbscanProps> {\n // Input validation being handled by Typescript\n // collectionOf(points, 'Point', 'points must consist of a FeatureCollection of only Points');\n // if (maxDistance === null || maxDistance === undefined) throw new Error('maxDistance is required');\n // if (!(Math.sign(maxDistance) > 0)) throw new Error('maxDistance is invalid');\n // if (!(minPoints === undefined || minPoints === null || Math.sign(minPoints) > 0)) throw new Error('options.minPoints is invalid');\n\n // Clone points to prevent any mutations\n if (options.mutate !== true) points = clone(points);\n\n // Defaults\n const minPoints = options.minPoints || 3;\n\n // Calculate the distance in degrees for region queries\n const latDistanceInDegrees = lengthToDegrees(maxDistance, options.units);\n\n // Create a spatial index\n var tree = new RBush(points.features.length);\n\n // Keeps track of whether a point has been visited or not.\n var visited = points.features.map((_) => false);\n\n // Keeps track of whether a point is assigned to a cluster or not.\n var assigned = points.features.map((_) => false);\n\n // Keeps track of whether a point is noise|edge or not.\n var isnoise = points.features.map((_) => false);\n\n // Keeps track of the clusterId for each point\n var clusterIds: number[] = points.features.map((_) => -1);\n\n // Index each point for spatial queries\n tree.load(\n points.features.map((point, index) => {\n var [x, y] = point.geometry.coordinates;\n return {\n minX: x,\n minY: y,\n maxX: x,\n maxY: y,\n index: index,\n } as IndexedPoint;\n })\n );\n\n // Function to find neighbors of a point within a given distance\n const regionQuery = (index: number): IndexedPoint[] => {\n const point = points.features[index];\n const [x, y] = point.geometry.coordinates;\n\n const minY = Math.max(y - latDistanceInDegrees, -90.0);\n const maxY = Math.min(y + latDistanceInDegrees, 90.0);\n\n const lonDistanceInDegrees = (function () {\n // Handle the case where the bounding box crosses the poles\n if (minY < 0 && maxY > 0) {\n return latDistanceInDegrees;\n }\n if (Math.abs(minY) < Math.abs(maxY)) {\n return latDistanceInDegrees / Math.cos(degreesToRadians(maxY));\n } else {\n return latDistanceInDegrees / Math.cos(degreesToRadians(minY));\n }\n })();\n\n const minX = Math.max(x - lonDistanceInDegrees, -360.0);\n const maxX = Math.min(x + lonDistanceInDegrees, 360.0);\n\n // Calculate the bounding box for the region query\n const bbox = { minX, minY, maxX, maxY };\n return (tree.search(bbox) as ReadonlyArray<IndexedPoint>).filter(\n (neighbor) => {\n const neighborIndex = neighbor.index;\n const neighborPoint = points.features[neighborIndex];\n const distanceInKm = distance(point, neighborPoint, {\n units: \"kilometers\",\n });\n return distanceInKm <= maxDistance;\n }\n );\n };\n\n // Function to expand a cluster\n const expandCluster = (clusteredId: number, neighbors: IndexedPoint[]) => {\n for (var i = 0; i < neighbors.length; i++) {\n var neighbor = neighbors[i];\n const neighborIndex = neighbor.index;\n if (!visited[neighborIndex]) {\n visited[neighborIndex] = true;\n const nextNeighbors = regionQuery(neighborIndex);\n if (nextNeighbors.length >= minPoints) {\n neighbors.push(...nextNeighbors);\n }\n }\n if (!assigned[neighborIndex]) {\n assigned[neighborIndex] = true;\n clusterIds[neighborIndex] = clusteredId;\n }\n }\n };\n\n // Main DBSCAN clustering algorithm\n var nextClusteredId = 0;\n points.features.forEach((_, index) => {\n if (visited[index]) return;\n const neighbors = regionQuery(index);\n if (neighbors.length >= minPoints) {\n const clusteredId = nextClusteredId;\n nextClusteredId++;\n visited[index] = true;\n expandCluster(clusteredId, neighbors);\n } else {\n isnoise[index] = true;\n }\n });\n\n // Assign DBSCAN properties to each point\n points.features.forEach((_, index) => {\n var clusterPoint = points.features[index];\n if (!clusterPoint.properties) {\n clusterPoint.properties = {};\n }\n\n if (clusterIds[index] >= 0) {\n clusterPoint.properties.dbscan = isnoise[index] ? \"edge\" : \"core\";\n clusterPoint.properties.cluster = clusterIds[index];\n } else {\n clusterPoint.properties.dbscan = \"noise\";\n }\n });\n\n return points as FeatureCollection<Point, DbscanProps>;\n}\n\nexport { Dbscan, DbscanProps, clustersDbscan };\nexport default clustersDbscan;\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/turf/turf/packages/turf-clusters-dbscan/dist/cjs/index.cjs","../../index.ts"],"names":[],"mappings":"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","file":"/home/runner/work/turf/turf/packages/turf-clusters-dbscan/dist/cjs/index.cjs","sourcesContent":[null,"import { GeoJsonProperties, FeatureCollection, Point } from \"geojson\";\nimport { clone } from \"@turf/clone\";\nimport { Units } from \"@turf/helpers\";\nimport KDBush from \"kdbush\";\nimport * as geokdbush from \"geokdbush\";\n\n/**\n * Point classification within the cluster.\n *\n * @typedef {\"core\" | \"edge\" | \"noise\"} Dbscan\n */\ntype Dbscan = \"core\" | \"edge\" | \"noise\";\n\n/**\n * Properties assigned to each clustered point.\n *\n * @extends GeoJsonProperties\n * @typedef {object} DbscanProps\n * @property {Dbscan} [dbscan] type of point it has been classified as\n * @property {number} [cluster] associated clusterId\n */\ntype DbscanProps = GeoJsonProperties & {\n dbscan?: Dbscan;\n cluster?: number;\n};\n\n// Structure of a point in the spatial index\ntype IndexedPoint = {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n index: number;\n};\n\n/**\n * Takes a set of {@link Point|points} and partition them into clusters according to {@link https://en.wikipedia.org/wiki/DBSCAN|DBSCAN's} data clustering algorithm.\n *\n * @function\n * @param {FeatureCollection<Point>} points to be clustered\n * @param {number} maxDistance Maximum Distance between any point of the cluster to generate the clusters (kilometers by default, see options)\n * @param {Object} [options={}] Optional parameters\n * @param {Units} [options.units=\"kilometers\"] in which `maxDistance` is expressed, Supports all valid Turf {@link https://turfjs.org/docs/api/types/Units Units}\n * @param {boolean} [options.mutate=false] Allows GeoJSON input to be mutated\n * @param {number} [options.minPoints=3] Minimum number of points to generate a single cluster,\n * points which do not meet this requirement will be classified as an 'edge' or 'noise'.\n * @returns {FeatureCollection<Point, DbscanProps>} Clustered Points with an additional two properties associated to each Feature:\n * - {number} cluster - the associated clusterId\n * - {string} dbscan - type of point it has been classified as ('core'|'edge'|'noise')\n * @example\n * // create random points with random z-values in their properties\n * var points = turf.randomPoint(100, {bbox: [0, 30, 20, 50]});\n * var maxDistance = 100;\n * var clustered = turf.clustersDbscan(points, maxDistance);\n *\n * //addToMap\n * var addToMap = [clustered];\n */\nfunction clustersDbscan(\n points: FeatureCollection<Point>,\n maxDistance: number,\n options: {\n units?: Units;\n minPoints?: number;\n mutate?: boolean;\n } = {}\n): FeatureCollection<Point, DbscanProps> {\n // Input validation being handled by Typescript\n // TODO oops! No it isn't. Typescript doesn't do runtime checking. We should\n // re-enable these checks, though will have to wait for a major version bump\n // as more restrictive checks could break currently working code.\n // collectionOf(points, 'Point', 'points must consist of a FeatureCollection of only Points');\n // if (maxDistance === null || maxDistance === undefined) throw new Error('maxDistance is required');\n // if (!(Math.sign(maxDistance) > 0)) throw new Error('maxDistance is invalid');\n // if (!(minPoints === undefined || minPoints === null || Math.sign(minPoints) > 0)) throw new Error('options.minPoints is invalid');\n\n // Clone points to prevent any mutations\n if (options.mutate !== true) points = clone(points);\n\n // Defaults\n const minPoints = options.minPoints || 3;\n\n // Create a spatial index\n const kdIndex = new KDBush(points.features.length);\n // Index each point for spatial queries\n for (const point of points.features) {\n kdIndex.add(point.geometry.coordinates[0], point.geometry.coordinates[1]);\n }\n kdIndex.finish();\n\n // Keeps track of whether a point has been visited or not.\n var visited = points.features.map((_) => false);\n\n // Keeps track of whether a point is assigned to a cluster or not.\n var assigned = points.features.map((_) => false);\n\n // Keeps track of whether a point is noise|edge or not.\n var isnoise = points.features.map((_) => false);\n\n // Keeps track of the clusterId for each point\n var clusterIds: number[] = points.features.map((_) => -1);\n\n // Function to find neighbors of a point within a given distance\n const regionQuery = (index: number): IndexedPoint[] => {\n const point = points.features[index];\n const [x, y] = point.geometry.coordinates;\n\n return (\n geokdbush\n // @ts-expect-error 2345 until https://github.com/mourner/geokdbush/issues/20 is resolved\n .around<number>(kdIndex, x, y, undefined, maxDistance)\n .map((id) => ({\n minX: points.features[id].geometry.coordinates[0],\n minY: points.features[id].geometry.coordinates[1],\n maxX: points.features[id].geometry.coordinates[0],\n maxY: points.features[id].geometry.coordinates[1],\n index: id,\n }))\n );\n };\n\n // Function to expand a cluster\n const expandCluster = (clusteredId: number, neighbors: IndexedPoint[]) => {\n for (var i = 0; i < neighbors.length; i++) {\n var neighbor = neighbors[i];\n const neighborIndex = neighbor.index;\n if (!visited[neighborIndex]) {\n visited[neighborIndex] = true;\n const nextNeighbors = regionQuery(neighborIndex);\n if (nextNeighbors.length >= minPoints) {\n neighbors.push(...nextNeighbors);\n }\n }\n if (!assigned[neighborIndex]) {\n assigned[neighborIndex] = true;\n clusterIds[neighborIndex] = clusteredId;\n }\n }\n };\n\n // Main DBSCAN clustering algorithm\n var nextClusteredId = 0;\n points.features.forEach((_, index) => {\n if (visited[index]) return;\n const neighbors = regionQuery(index);\n if (neighbors.length >= minPoints) {\n const clusteredId = nextClusteredId;\n nextClusteredId++;\n visited[index] = true;\n expandCluster(clusteredId, neighbors);\n } else {\n isnoise[index] = true;\n }\n });\n\n // Assign DBSCAN properties to each point\n points.features.forEach((_, index) => {\n var clusterPoint = points.features[index];\n if (!clusterPoint.properties) {\n clusterPoint.properties = {};\n }\n\n if (clusterIds[index] >= 0) {\n clusterPoint.properties.dbscan = isnoise[index] ? \"edge\" : \"core\";\n clusterPoint.properties.cluster = clusterIds[index];\n } else {\n clusterPoint.properties.dbscan = \"noise\";\n }\n });\n\n return points as FeatureCollection<Point, DbscanProps>;\n}\n\nexport { Dbscan, DbscanProps, clustersDbscan };\nexport default clustersDbscan;\n"]}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,57 +1,29 @@
|
|
|
1
1
|
// index.ts
|
|
2
2
|
import { clone } from "@turf/clone";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import RBush from "rbush";
|
|
3
|
+
import KDBush from "kdbush";
|
|
4
|
+
import * as geokdbush from "geokdbush";
|
|
6
5
|
function clustersDbscan(points, maxDistance, options = {}) {
|
|
7
6
|
if (options.mutate !== true) points = clone(points);
|
|
8
7
|
const minPoints = options.minPoints || 3;
|
|
9
|
-
const
|
|
10
|
-
|
|
8
|
+
const kdIndex = new KDBush(points.features.length);
|
|
9
|
+
for (const point of points.features) {
|
|
10
|
+
kdIndex.add(point.geometry.coordinates[0], point.geometry.coordinates[1]);
|
|
11
|
+
}
|
|
12
|
+
kdIndex.finish();
|
|
11
13
|
var visited = points.features.map((_) => false);
|
|
12
14
|
var assigned = points.features.map((_) => false);
|
|
13
15
|
var isnoise = points.features.map((_) => false);
|
|
14
16
|
var clusterIds = points.features.map((_) => -1);
|
|
15
|
-
tree.load(
|
|
16
|
-
points.features.map((point, index) => {
|
|
17
|
-
var [x, y] = point.geometry.coordinates;
|
|
18
|
-
return {
|
|
19
|
-
minX: x,
|
|
20
|
-
minY: y,
|
|
21
|
-
maxX: x,
|
|
22
|
-
maxY: y,
|
|
23
|
-
index
|
|
24
|
-
};
|
|
25
|
-
})
|
|
26
|
-
);
|
|
27
17
|
const regionQuery = (index) => {
|
|
28
18
|
const point = points.features[index];
|
|
29
19
|
const [x, y] = point.geometry.coordinates;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return latDistanceInDegrees / Math.cos(degreesToRadians(maxY));
|
|
38
|
-
} else {
|
|
39
|
-
return latDistanceInDegrees / Math.cos(degreesToRadians(minY));
|
|
40
|
-
}
|
|
41
|
-
}();
|
|
42
|
-
const minX = Math.max(x - lonDistanceInDegrees, -360);
|
|
43
|
-
const maxX = Math.min(x + lonDistanceInDegrees, 360);
|
|
44
|
-
const bbox = { minX, minY, maxX, maxY };
|
|
45
|
-
return tree.search(bbox).filter(
|
|
46
|
-
(neighbor) => {
|
|
47
|
-
const neighborIndex = neighbor.index;
|
|
48
|
-
const neighborPoint = points.features[neighborIndex];
|
|
49
|
-
const distanceInKm = distance(point, neighborPoint, {
|
|
50
|
-
units: "kilometers"
|
|
51
|
-
});
|
|
52
|
-
return distanceInKm <= maxDistance;
|
|
53
|
-
}
|
|
54
|
-
);
|
|
20
|
+
return geokdbush.around(kdIndex, x, y, void 0, maxDistance).map((id) => ({
|
|
21
|
+
minX: points.features[id].geometry.coordinates[0],
|
|
22
|
+
minY: points.features[id].geometry.coordinates[1],
|
|
23
|
+
maxX: points.features[id].geometry.coordinates[0],
|
|
24
|
+
maxY: points.features[id].geometry.coordinates[1],
|
|
25
|
+
index: id
|
|
26
|
+
}));
|
|
55
27
|
};
|
|
56
28
|
const expandCluster = (clusteredId, neighbors) => {
|
|
57
29
|
for (var i = 0; i < neighbors.length; i++) {
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../index.ts"],"sourcesContent":["import { GeoJsonProperties, FeatureCollection, Point } from \"geojson\";\nimport { clone } from \"@turf/clone\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../index.ts"],"sourcesContent":["import { GeoJsonProperties, FeatureCollection, Point } from \"geojson\";\nimport { clone } from \"@turf/clone\";\nimport { Units } from \"@turf/helpers\";\nimport KDBush from \"kdbush\";\nimport * as geokdbush from \"geokdbush\";\n\n/**\n * Point classification within the cluster.\n *\n * @typedef {\"core\" | \"edge\" | \"noise\"} Dbscan\n */\ntype Dbscan = \"core\" | \"edge\" | \"noise\";\n\n/**\n * Properties assigned to each clustered point.\n *\n * @extends GeoJsonProperties\n * @typedef {object} DbscanProps\n * @property {Dbscan} [dbscan] type of point it has been classified as\n * @property {number} [cluster] associated clusterId\n */\ntype DbscanProps = GeoJsonProperties & {\n dbscan?: Dbscan;\n cluster?: number;\n};\n\n// Structure of a point in the spatial index\ntype IndexedPoint = {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n index: number;\n};\n\n/**\n * Takes a set of {@link Point|points} and partition them into clusters according to {@link https://en.wikipedia.org/wiki/DBSCAN|DBSCAN's} data clustering algorithm.\n *\n * @function\n * @param {FeatureCollection<Point>} points to be clustered\n * @param {number} maxDistance Maximum Distance between any point of the cluster to generate the clusters (kilometers by default, see options)\n * @param {Object} [options={}] Optional parameters\n * @param {Units} [options.units=\"kilometers\"] in which `maxDistance` is expressed, Supports all valid Turf {@link https://turfjs.org/docs/api/types/Units Units}\n * @param {boolean} [options.mutate=false] Allows GeoJSON input to be mutated\n * @param {number} [options.minPoints=3] Minimum number of points to generate a single cluster,\n * points which do not meet this requirement will be classified as an 'edge' or 'noise'.\n * @returns {FeatureCollection<Point, DbscanProps>} Clustered Points with an additional two properties associated to each Feature:\n * - {number} cluster - the associated clusterId\n * - {string} dbscan - type of point it has been classified as ('core'|'edge'|'noise')\n * @example\n * // create random points with random z-values in their properties\n * var points = turf.randomPoint(100, {bbox: [0, 30, 20, 50]});\n * var maxDistance = 100;\n * var clustered = turf.clustersDbscan(points, maxDistance);\n *\n * //addToMap\n * var addToMap = [clustered];\n */\nfunction clustersDbscan(\n points: FeatureCollection<Point>,\n maxDistance: number,\n options: {\n units?: Units;\n minPoints?: number;\n mutate?: boolean;\n } = {}\n): FeatureCollection<Point, DbscanProps> {\n // Input validation being handled by Typescript\n // TODO oops! No it isn't. Typescript doesn't do runtime checking. We should\n // re-enable these checks, though will have to wait for a major version bump\n // as more restrictive checks could break currently working code.\n // collectionOf(points, 'Point', 'points must consist of a FeatureCollection of only Points');\n // if (maxDistance === null || maxDistance === undefined) throw new Error('maxDistance is required');\n // if (!(Math.sign(maxDistance) > 0)) throw new Error('maxDistance is invalid');\n // if (!(minPoints === undefined || minPoints === null || Math.sign(minPoints) > 0)) throw new Error('options.minPoints is invalid');\n\n // Clone points to prevent any mutations\n if (options.mutate !== true) points = clone(points);\n\n // Defaults\n const minPoints = options.minPoints || 3;\n\n // Create a spatial index\n const kdIndex = new KDBush(points.features.length);\n // Index each point for spatial queries\n for (const point of points.features) {\n kdIndex.add(point.geometry.coordinates[0], point.geometry.coordinates[1]);\n }\n kdIndex.finish();\n\n // Keeps track of whether a point has been visited or not.\n var visited = points.features.map((_) => false);\n\n // Keeps track of whether a point is assigned to a cluster or not.\n var assigned = points.features.map((_) => false);\n\n // Keeps track of whether a point is noise|edge or not.\n var isnoise = points.features.map((_) => false);\n\n // Keeps track of the clusterId for each point\n var clusterIds: number[] = points.features.map((_) => -1);\n\n // Function to find neighbors of a point within a given distance\n const regionQuery = (index: number): IndexedPoint[] => {\n const point = points.features[index];\n const [x, y] = point.geometry.coordinates;\n\n return (\n geokdbush\n // @ts-expect-error 2345 until https://github.com/mourner/geokdbush/issues/20 is resolved\n .around<number>(kdIndex, x, y, undefined, maxDistance)\n .map((id) => ({\n minX: points.features[id].geometry.coordinates[0],\n minY: points.features[id].geometry.coordinates[1],\n maxX: points.features[id].geometry.coordinates[0],\n maxY: points.features[id].geometry.coordinates[1],\n index: id,\n }))\n );\n };\n\n // Function to expand a cluster\n const expandCluster = (clusteredId: number, neighbors: IndexedPoint[]) => {\n for (var i = 0; i < neighbors.length; i++) {\n var neighbor = neighbors[i];\n const neighborIndex = neighbor.index;\n if (!visited[neighborIndex]) {\n visited[neighborIndex] = true;\n const nextNeighbors = regionQuery(neighborIndex);\n if (nextNeighbors.length >= minPoints) {\n neighbors.push(...nextNeighbors);\n }\n }\n if (!assigned[neighborIndex]) {\n assigned[neighborIndex] = true;\n clusterIds[neighborIndex] = clusteredId;\n }\n }\n };\n\n // Main DBSCAN clustering algorithm\n var nextClusteredId = 0;\n points.features.forEach((_, index) => {\n if (visited[index]) return;\n const neighbors = regionQuery(index);\n if (neighbors.length >= minPoints) {\n const clusteredId = nextClusteredId;\n nextClusteredId++;\n visited[index] = true;\n expandCluster(clusteredId, neighbors);\n } else {\n isnoise[index] = true;\n }\n });\n\n // Assign DBSCAN properties to each point\n points.features.forEach((_, index) => {\n var clusterPoint = points.features[index];\n if (!clusterPoint.properties) {\n clusterPoint.properties = {};\n }\n\n if (clusterIds[index] >= 0) {\n clusterPoint.properties.dbscan = isnoise[index] ? \"edge\" : \"core\";\n clusterPoint.properties.cluster = clusterIds[index];\n } else {\n clusterPoint.properties.dbscan = \"noise\";\n }\n });\n\n return points as FeatureCollection<Point, DbscanProps>;\n}\n\nexport { Dbscan, DbscanProps, clustersDbscan };\nexport default clustersDbscan;\n"],"mappings":";AACA,SAAS,aAAa;AAEtB,OAAO,YAAY;AACnB,YAAY,eAAe;AAsD3B,SAAS,eACP,QACA,aACA,UAII,CAAC,GACkC;AAWvC,MAAI,QAAQ,WAAW,KAAM,UAAS,MAAM,MAAM;AAGlD,QAAM,YAAY,QAAQ,aAAa;AAGvC,QAAM,UAAU,IAAI,OAAO,OAAO,SAAS,MAAM;AAEjD,aAAW,SAAS,OAAO,UAAU;AACnC,YAAQ,IAAI,MAAM,SAAS,YAAY,CAAC,GAAG,MAAM,SAAS,YAAY,CAAC,CAAC;AAAA,EAC1E;AACA,UAAQ,OAAO;AAGf,MAAI,UAAU,OAAO,SAAS,IAAI,CAAC,MAAM,KAAK;AAG9C,MAAI,WAAW,OAAO,SAAS,IAAI,CAAC,MAAM,KAAK;AAG/C,MAAI,UAAU,OAAO,SAAS,IAAI,CAAC,MAAM,KAAK;AAG9C,MAAI,aAAuB,OAAO,SAAS,IAAI,CAAC,MAAM,EAAE;AAGxD,QAAM,cAAc,CAAC,UAAkC;AACrD,UAAM,QAAQ,OAAO,SAAS,KAAK;AACnC,UAAM,CAAC,GAAG,CAAC,IAAI,MAAM,SAAS;AAE9B,WAGK,iBAAe,SAAS,GAAG,GAAG,QAAW,WAAW,EACpD,IAAI,CAAC,QAAQ;AAAA,MACZ,MAAM,OAAO,SAAS,EAAE,EAAE,SAAS,YAAY,CAAC;AAAA,MAChD,MAAM,OAAO,SAAS,EAAE,EAAE,SAAS,YAAY,CAAC;AAAA,MAChD,MAAM,OAAO,SAAS,EAAE,EAAE,SAAS,YAAY,CAAC;AAAA,MAChD,MAAM,OAAO,SAAS,EAAE,EAAE,SAAS,YAAY,CAAC;AAAA,MAChD,OAAO;AAAA,IACT,EAAE;AAAA,EAER;AAGA,QAAM,gBAAgB,CAAC,aAAqB,cAA8B;AACxE,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAI,WAAW,UAAU,CAAC;AAC1B,YAAM,gBAAgB,SAAS;AAC/B,UAAI,CAAC,QAAQ,aAAa,GAAG;AAC3B,gBAAQ,aAAa,IAAI;AACzB,cAAM,gBAAgB,YAAY,aAAa;AAC/C,YAAI,cAAc,UAAU,WAAW;AACrC,oBAAU,KAAK,GAAG,aAAa;AAAA,QACjC;AAAA,MACF;AACA,UAAI,CAAC,SAAS,aAAa,GAAG;AAC5B,iBAAS,aAAa,IAAI;AAC1B,mBAAW,aAAa,IAAI;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAGA,MAAI,kBAAkB;AACtB,SAAO,SAAS,QAAQ,CAAC,GAAG,UAAU;AACpC,QAAI,QAAQ,KAAK,EAAG;AACpB,UAAM,YAAY,YAAY,KAAK;AACnC,QAAI,UAAU,UAAU,WAAW;AACjC,YAAM,cAAc;AACpB;AACA,cAAQ,KAAK,IAAI;AACjB,oBAAc,aAAa,SAAS;AAAA,IACtC,OAAO;AACL,cAAQ,KAAK,IAAI;AAAA,IACnB;AAAA,EACF,CAAC;AAGD,SAAO,SAAS,QAAQ,CAAC,GAAG,UAAU;AACpC,QAAI,eAAe,OAAO,SAAS,KAAK;AACxC,QAAI,CAAC,aAAa,YAAY;AAC5B,mBAAa,aAAa,CAAC;AAAA,IAC7B;AAEA,QAAI,WAAW,KAAK,KAAK,GAAG;AAC1B,mBAAa,WAAW,SAAS,QAAQ,KAAK,IAAI,SAAS;AAC3D,mBAAa,WAAW,UAAU,WAAW,KAAK;AAAA,IACpD,OAAO;AACL,mBAAa,WAAW,SAAS;AAAA,IACnC;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAGA,IAAO,gBAAQ;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@turf/clusters-dbscan",
|
|
3
|
-
"version": "7.3.
|
|
3
|
+
"version": "7.3.2",
|
|
4
4
|
"description": "Takes a set of points and partition them into clusters according to DBSCAN's data clustering algorithm.",
|
|
5
5
|
"author": "Turf Authors",
|
|
6
6
|
"contributors": [
|
|
@@ -55,21 +55,19 @@
|
|
|
55
55
|
"bench": "tsx bench.ts",
|
|
56
56
|
"build": "tsup --config ../../tsup.config.ts",
|
|
57
57
|
"docs": "tsx ../../scripts/generate-readmes.ts",
|
|
58
|
-
"test": "
|
|
58
|
+
"test": "pnpm run /test:.*/",
|
|
59
59
|
"test:tape": "tsx test.ts",
|
|
60
60
|
"test:types": "tsc --esModuleInterop --module node16 --moduleResolution node16 --noEmit --strict types.ts"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@turf/centroid": "7.3.
|
|
64
|
-
"@turf/clusters": "7.3.
|
|
63
|
+
"@turf/centroid": "7.3.2",
|
|
64
|
+
"@turf/clusters": "7.3.2",
|
|
65
65
|
"@types/benchmark": "^2.1.5",
|
|
66
|
-
"@types/rbush": "^3.0.4",
|
|
67
66
|
"@types/tape": "^5.8.1",
|
|
68
67
|
"benchmark": "^2.1.4",
|
|
69
68
|
"chromatism": "^3.0.0",
|
|
70
69
|
"concaveman": "^1.2.1",
|
|
71
70
|
"load-json-file": "^7.0.1",
|
|
72
|
-
"npm-run-all": "^4.1.5",
|
|
73
71
|
"tape": "^5.9.0",
|
|
74
72
|
"tsup": "^8.4.0",
|
|
75
73
|
"tsx": "^4.19.4",
|
|
@@ -77,13 +75,14 @@
|
|
|
77
75
|
"write-json-file": "^6.0.0"
|
|
78
76
|
},
|
|
79
77
|
"dependencies": {
|
|
80
|
-
"@turf/clone": "7.3.
|
|
81
|
-
"@turf/
|
|
82
|
-
"@turf/
|
|
83
|
-
"@turf/meta": "7.3.0",
|
|
78
|
+
"@turf/clone": "7.3.2",
|
|
79
|
+
"@turf/helpers": "7.3.2",
|
|
80
|
+
"@turf/meta": "7.3.2",
|
|
84
81
|
"@types/geojson": "^7946.0.10",
|
|
85
|
-
"
|
|
82
|
+
"@types/geokdbush": "^1.1.5",
|
|
83
|
+
"geokdbush": "^2.0.1",
|
|
84
|
+
"kdbush": "^4.0.2",
|
|
86
85
|
"tslib": "^2.8.1"
|
|
87
86
|
},
|
|
88
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "099d9915467bacf45d554be4533fa9998c4efc88"
|
|
89
88
|
}
|