// index.ts import { clone } from "@turf/clone"; import { distance } from "@turf/distance"; import { degreesToRadians, lengthToDegrees } from "@turf/helpers"; // lib/rbush-export.ts import lib from "rbush"; var rbush = lib; // index.ts function clustersDbscan(points, maxDistance, options = {}) { if (options.mutate !== true) points = clone(points); const minPoints = options.minPoints || 3; const latDistanceInDegrees = lengthToDegrees(maxDistance, options.units); var tree = new rbush(points.features.length); var visited = points.features.map((_) => false); var assigned = points.features.map((_) => false); var isnoise = points.features.map((_) => false); var clusterIds = points.features.map((_) => -1); tree.load( points.features.map((point, index) => { var [x, y] = point.geometry.coordinates; return { minX: x, minY: y, maxX: x, maxY: y, index }; }) ); const regionQuery = (index) => { const point = points.features[index]; const [x, y] = point.geometry.coordinates; const minY = Math.max(y - latDistanceInDegrees, -90); const maxY = Math.min(y + latDistanceInDegrees, 90); const lonDistanceInDegrees = function() { if (minY < 0 && maxY > 0) { return latDistanceInDegrees; } if (Math.abs(minY) < Math.abs(maxY)) { return latDistanceInDegrees / Math.cos(degreesToRadians(maxY)); } else { return latDistanceInDegrees / Math.cos(degreesToRadians(minY)); } }(); const minX = Math.max(x - lonDistanceInDegrees, -360); const maxX = Math.min(x + lonDistanceInDegrees, 360); const bbox = { minX, minY, maxX, maxY }; return tree.search(bbox).filter( (neighbor) => { const neighborIndex = neighbor.index; const neighborPoint = points.features[neighborIndex]; const distanceInKm = distance(point, neighborPoint, { units: "kilometers" }); return distanceInKm <= maxDistance; } ); }; const expandCluster = (clusteredId, neighbors) => { for (var i = 0; i < neighbors.length; i++) { var neighbor = neighbors[i]; const neighborIndex = neighbor.index; if (!visited[neighborIndex]) { visited[neighborIndex] = true; const nextNeighbors = regionQuery(neighborIndex); if (nextNeighbors.length >= minPoints) { neighbors.push(...nextNeighbors); } } if (!assigned[neighborIndex]) { assigned[neighborIndex] = true; clusterIds[neighborIndex] = clusteredId; } } }; var nextClusteredId = 0; points.features.forEach((_, index) => { if (visited[index]) return; const neighbors = regionQuery(index); if (neighbors.length >= minPoints) { const clusteredId = nextClusteredId; nextClusteredId++; visited[index] = true; expandCluster(clusteredId, neighbors); } else { isnoise[index] = true; } }); points.features.forEach((_, index) => { var clusterPoint = points.features[index]; if (!clusterPoint.properties) { clusterPoint.properties = {}; } if (clusterIds[index] >= 0) { clusterPoint.properties.dbscan = isnoise[index] ? "edge" : "core"; clusterPoint.properties.cluster = clusterIds[index]; } else { clusterPoint.properties.dbscan = "noise"; } }); return points; } var turf_clusters_dbscan_default = clustersDbscan; export { clustersDbscan, turf_clusters_dbscan_default as default }; //# sourceMappingURL=index.js.map