Comments (5)
After some tweaks and modifications, this passes the same tests as used on your other geographical libraries - full repository here: https://github.com/cirlam/georbush
from rbush.
No problem! Glad you find it useful. I can't take credit for it though, the hard work done by @mourner on geokdbush and geoflatbush made it possible.
from rbush.
I'd like to do that but don't have a timeline for that. The two approaches (geoflatbush vs geokdbush) are roughly equivalent — I like the flatbush one slightly more because it seems simpler.
from rbush.
Thanks for the advice! I've quickly combined your rbush-knn with the geoflatbush library to give me the code below. I think it all seems sensible, but I've yet to test it - any criticism is welcome.
var Queue = require('tinyqueue');
const earthRadius = 6371;
const earthCircumference = 40007;
const rad = Math.PI / 180;
exports.around = function(tree, lng, lat,n = Infinity, maxDistance = Infinity, predicate) {
var node = tree.data,
result = [],
toBBox = tree.toBBox,
i, child, dist, candidate;
var queue = new Queue([],compareDist);
const cosLat = Math.cos(lat * rad);
const sinLat = Math.sin(lat * rad);
while (node) {
for (i = 0; i < node.children.length; i++) {
child = node.children[i];
childBBox = node.leaf ? toBBox(child) : child;
const minLng = childBBox.minX;
const minLat = childBBox.minY;
const maxLng = childBBox.maxX;
const maxLat = childBBox.maxY;
dist = boxDist(lng, lat, minLng, minLat, maxLng, maxLat, cosLat, sinLat);
if (!maxDistance || dist <= maxDistance) {
queue.push({
node: child,
isItem: node.leaf,
dist: dist
});
}
}
while (queue.length && queue.peek().isItem) {
candidate = queue.pop().node;
if (!predicate || predicate(candidate))
result.push(candidate);
if (n && result.length === n) return result;
}
node = queue.pop();
if (node) node = node.node;
}
return result;
}
function compareDist(a, b) {
return a.dist - b.dist;
}
// lower bound for distance from a location to points inside a bounding box
function boxDist(lng, lat, minLng, minLat, maxLng, maxLat, cosLat, sinLat) {
if (minLng === maxLng && minLat === maxLat) {
return greatCircleDist(lng, lat, minLng, minLat, cosLat, sinLat);
}
// query point is between minimum and maximum longitudes
if (lng >= minLng && lng <= maxLng) {
if (lat <= minLat) return earthCircumference * (minLat - lat) / 360; // south
if (lat >= maxLat) return earthCircumference * (lat - maxLat) / 360; // north
return 0; // inside the bbox
}
// query point is west or east of the bounding box;
// calculate the extremum for great circle distance from query point to the closest longitude
const closestLng = (minLng - lng + 360) % 360 <= (lng - maxLng + 360) % 360 ? minLng : maxLng;
const cosLngDelta = Math.cos((closestLng - lng) * rad);
const extremumLat = Math.atan(sinLat / (cosLat * cosLngDelta)) / rad;
// calculate distances to lower and higher bbox corners and extremum (if it's within this range);
// one of the three distances will be the lower bound of great circle distance to bbox
let d = Math.max(
greatCircleDistPart(minLat, cosLat, sinLat, cosLngDelta),
greatCircleDistPart(maxLat, cosLat, sinLat, cosLngDelta));
if (extremumLat > minLat && extremumLat < maxLat) {
d = Math.max(d, greatCircleDistPart(extremumLat, cosLat, sinLat, cosLngDelta));
}
return earthRadius * Math.acos(d);
}
// distance using spherical law of cosines; should be precise enough for our needs
function greatCircleDist(lng, lat, lng2, lat2, cosLat, sinLat) {
const cosLngDelta = Math.cos((lng2 - lng) * rad);
return earthRadius * Math.acos(greatCircleDistPart(lat2, cosLat, sinLat, cosLngDelta));
}
// partial greatCircleDist to reduce trigonometric calculations
function greatCircleDistPart(lat, cosLat, sinLat, cosLngDelta) {
const d = sinLat * Math.sin(lat * rad) + cosLat * Math.cos(lat * rad) * cosLngDelta;
return Math.min(d, 1);
}
exports.distance = function(lng, lat, lng2, lat2) {
return greatCircleDist(lng, lat, lng2, lat2, Math.cos(lat * rad), Math.sin(lat * rad));
}
from rbush.
@cirlam Thanks for implementing georbush. It works great!
from rbush.
Related Issues (20)
- Can you provide a browserify distribution? HOT 1
- How to limit the result count from the query? HOT 11
- how to search by id ? HOT 2
- tree.getById(id) how to get by id? HOT 2
- Why "RTree" is geographically even distribution while "RBush" is NOT? HOT 1
- About evenly geographic distribution when limit the result size HOT 2
- Invalid collision on maxX/Y (pixel-perfect collision false positive) HOT 3
- Does RBUSH supports to use Latitude and Longitude? HOT 5
- Hi i can't figure out how to use this library can anyone help? HOT 3
- Typescript attempts to use missing default constructor HOT 4
- How to search when usiong the extended class for points HOT 1
- is there any quick way to return the bounding box of tree itself? HOT 1
- Questions: Performance Remove + Moving item HOT 1
- Definition of "intersection" could be made more explicit in the readme HOT 2
- Returns all items when bounds provided to search contains center 0,0 HOT 3
- Support esm HOT 1
- search & collides support custom intersects & contains
- Balancing? HOT 1
- Unable to resolve dependency tree
- Performance benchmark vs other libraries HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rbush.