node-red-contrib-tak-registration
Version:
A Node-RED node to register to TAK and to help wrap files as datapackages to send to TAK
110 lines (108 loc) • 3.56 kB
JavaScript
// 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