Mehr

Finden Sie N nächstgelegene Punkte mit JTS?


Ich versuche, eine mobile App zu erstellen und die x-Anzahl der Punkte zu finden, die einem Benutzerstandort am nächsten sind und bestimmte Bedingungen erfüllen, die der Benutzer im Frontend auswählt.

Meine aktuelle Lösung besteht darin, inkrementell einen kleinen Bereich um den Benutzer herum zu durchsuchen und den Suchbereich mit einem JTS-QuadTree zu erweitern, bis die x-Elemente gefunden oder die maximalen Grenzen erreicht sind.

öffentliches statisches Set searchQuadTree(Quadtree quadTree, final MyBoundary, data_bounds, final ArrayList Typen) {// verwendet, um QuadTree Doppelshell zu suchen = SHELL; letztes Doppel EXPAND_SHELL = 5000; letztes Doppel MAX_SHELL_SIZE = 70000; letztes int MAX_SEARCH_ITEMS = 20; einstellen resultSet = neues HashSet(); // Polygon erstellen, um nach Punkten zu suchen, die sich damit schneiden Polygon polygon = data_bounds.searchAreaPoly(shell, 0); Aufführen items = quadTree.query(polygon.getEnvelopeInternal()); if(items != null) { GeometryFactory factory = new GeometryFactory(); // suche, bis die minimalen Suchkriterien gefunden wurden while ((resultSet.size() < MAX_SEARCH_ITEMS) && (shell < MAX_SHELL_SIZE)) { Iterator { iterator = items.iterator(); while (iterator.hasNext()) { MyQuadNode item = iterator.next(); Punktpunkt = factory.createPoint(getWGSCoord(item.getLongitude(), item.getLatitude())); if (types.contains(item.getType()) && polygon.contains(point) && resultSet.size() < MAX_SEARCH_ITEMS) { resultSet.add(item.getImageUrl()); } } } if(resultSet.size() < MAX_SEARCH_ITEMS) { //Shell zuerst langsam erweitern; if (Shell <1000) {Shell *= 5; aufrechtzuerhalten. Sonst if (Shell < 5000) {Shell *= 2; } else { Shell += EXPAND_SHELL; } //Suche ein größeres Flächenpolygon = data_bounds.searchAreaPoly(Shell, 0); Aufführen allItems = quadTree.query(polygon.getEnvelopeInternal()); // Vermeiden Sie das zweimalige Filtern derselben Elemente allItems.removeAll(items); items = allItems; } } } Ergebnismenge zurückgeben; }

Dies funktioniert gut (obwohl es nicht wirklich die nächsten Nachbarn findet) für einen kleinen Datensatz. Wenn der Datensatz groß wird, scheint dies jedoch ineffizient zu sein. Ich schätze die Effizienz liegt bei etwa x(nlogn + n + n), wobei x = MAX_SEARCH_ITEMS.

Wurde dieses Problem schon einmal gelöst?


Ich bin kein Java-Entwickler und kenne keine vorhandenen Java-Implementierungen dafür, aber die Verwendung des k-Nearest Neighbors-Algorithmus mit einem k-d-Baum wird wahrscheinlich eine viel bessere Leistung erzielen.

Wenn jedoch Genauigkeit wichtig ist, müssen Sie die Haversine (sphärisch) oder Vincenty (ellipsoide) Distanzformeln für die Distanzmetrik implementieren, da die euklidische Distanz bei Breiten-Längen-Koordinaten abhängig von der Entfernung der einzelnen Punkte voneinander sehr ungenau ist und vom Äquator.

Je nachdem, wie viele Daten Sie haben und Ihre spezielle Konfiguration, möchten Sie vielleicht eine räumliche Datenbank wie PostGIS verwenden, wie in diesem Beispiel: Eine generische Lösung für PostGIS nächster Nachbar