Play with KDBush.

master
Sander Vocke 6 years ago
parent dc14e652f7
commit 5800a274f8
  1. 1
      package.json
  2. 84
      src/database.js
  3. 5
      yarn.lock

@ -21,6 +21,7 @@
"eslint": "^6.8.0",
"eslint-plugin-react-hooks": "^2.3.0",
"geojson-utils": "^1.1.0",
"kdbush": "^3.0.0",
"leaflet": "^1.6.0",
"lodash": "^4.17.15",
"object-hash": "^2.0.1",

@ -2,8 +2,9 @@ import React, { useEffect, useState, useContext } from 'react';
import NodeEnvironment from 'jest-environment-node';
import { add_geo_area_to_store, get_geo_area_from_store } from './geo_store.js';
import * as turf from '@turf/turf'
import pointsWithinPolygon from '@turf/points-within-polygon';
import KDBush from 'kdbush';
export async function sqljs_async_queries(sqljs_object, queries) {
//var t0 = performance.now();
@ -109,37 +110,96 @@ export async function add_full_tag_info(db) {
function polygons_benchmark(database) {
var img_query = "SELECT Images.id, ImagePositions.latitudeNumber, ImagePositions.longitudeNumber FROM Images "
+ "LEFT JOIN ImagePositions ON ImagePositions.imageid=Images.id GROUP BY Images.id;";
+ "LEFT JOIN ImagePositions ON ImagePositions.imageid=Images.id WHERE ImagePositions.latitudeNumber NOT NULL GROUP BY Images.id;";
sqljs_async_queries(database, [img_query]).then(res => {
fetch("https://nominatim.openstreetmap.org/search?polygon_geojson=1&polygon_threshold=0.001&format=json&limit=5&q=Australia")
fetch("https://nominatim.openstreetmap.org/search?polygon_geojson=1&polygon_threshold=0.001&format=json&limit=1&q=Australia")
.then(res => res.json())
.then(jsonres => {
var geojson;
var polies;
var points = [];
console.log("Nominatim geo answer:", jsonres);
if (Array.isArray(jsonres) && jsonres.length > 0) {
geojson = jsonres[0].geojson;
polies = jsonres[0].geojson;
}
if (res && Array.isArray(res) && res.length > 0) {
var cols = res[0].columns;
var data = res[0].values;
data.forEach(row => {
points.push([row[cols.indexOf("longitudeNumber")], row[cols.indexOf("latitudeNumber")]]);
points.push([parseFloat(row[cols.indexOf("longitudeNumber")]), parseFloat(row[cols.indexOf("latitudeNumber")])]);
});
}
console.log("Points: ", points);
console.log("GEOJSON: ", geojson);
console.time("points within polygon");
var found = pointsWithinPolygon(points, geojson);
console.timeEnd("points within polygon");
console.log("Nominatim GEOJSON: ", polies);
{
// Try Turf
const tpoints = turf.points(points);
console.time("Turf points within polygon");
var found = turf.pointsWithinPolygon(tpoints, polies);
console.timeEnd("Turf points within polygon");
console.log("Turf PointsWithinPolygon: ", found);
}
console.log("PointsWithinPolygon: ", found);
{
// Try KDBush
console.time("Build KDBush index");
const index = new KDBush(points, p => p[0], p => p[1], 16, Float64Array);
console.timeEnd("Build KDBush index");
// Get bounding boxes for all subpolygons
var boxes = [];
console.time("Build KDBush poly boxes");
for (let i = 0; i < polies.coordinates.length; i++) {
const outerPoly = polies.coordinates[i][0];
var minx = Number.POSITIVE_INFINITY;
var miny = Number.POSITIVE_INFINITY;
var maxx = Number.NEGATIVE_INFINITY;
var maxy = Number.NEGATIVE_INFINITY;
for (let j = 0; j < outerPoly.length; j++) {
minx = Math.min(minx, outerPoly[j][0]);
miny = Math.min(miny, outerPoly[j][1]);
maxx = Math.max(maxx, outerPoly[j][0]);
maxy = Math.max(maxy, outerPoly[j][1]);
}
boxes.push([minx, miny, maxx, maxy]);
}
console.timeEnd("Build KDBush poly boxes");
console.log("KDBush boxes: ", boxes);
// Test points in KD tree against each subpolygon bounding box
console.time("Find box points in KDBush");
let hits = new Set();
for (let i = 0; i < boxes.length; i++) {
const ids = index.range(boxes[i][0], boxes[i][1], boxes[i][2], boxes[i][3]);
ids.forEach(e => hits.add(e));
}
console.timeEnd("Find box points in KDBush");
console.log("Hits: ", hits);
// Test hit points exactly
console.time("Get exact hits after KDBush");
var realhits = [];
var hitcache = {};
hits.forEach(hit => {
const point = points[hit];
if(point in hitcache && hitcache[point]) {
realhits.push(hit);
return;
}
const is_real_hit = turf.booleanPointInPolygon(turf.point(points[hit]), polies);
hitcache[point] = is_real_hit;
if(is_real_hit){
realhits.push(hit);
}
});
console.log("Real: ", realhits);
console.timeEnd("Get exact hits after KDBush");
}
});
})
.catch(err => { throw err; });

@ -6505,6 +6505,11 @@ jsx-ast-utils@^2.2.1:
array-includes "^3.0.3"
object.assign "^4.1.0"
kdbush@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-3.0.0.tgz#f8484794d47004cc2d85ed3a79353dbe0abc2bf0"
integrity sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==
killable@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"

Loading…
Cancel
Save