# Distanz berechnen, wenn ich Longitude und Latidute habe?



## beta20 (20. Mrz 2020)

Hallo,

ich möchte gerne eine relative einfache Datenbankabfrage haben, die die Distanz berechnet.
Ich habe eine Entity, die Longitude und Latidute haben.
Die Werte habe ich bereits in meiner Datenbank.

Mittels eines Parameters möchte ich nun prüfen, ob zB Ort1 und Ort2 eine Distanz von 10km hat...
Die Frage ist nun, wie ich diese Distanz berechnen kann?

Also heißt sowas:
public List<Entity> findAddress(double distance, double longitudeAdress1, double latiduteAddress2).

*SELECT m FROM Address WHERE ??????*

Was schreibe ich hier genau in der WHERE Bedingung? 
Angabe soll in KM sein.. Version2 wäre dann auch die Ausgabe in Meilen...


----------



## Thallius (20. Mrz 2020)

Select Records which have distance of 5km or greater between them
					

I am working on a location app and i need to get all locations from my Mysql Location table which have a 5km distance between them.  For Ex location table have below entries:     id     Latitude   ...




					stackoverflow.com
				




Das sollte helfen


----------



## beta20 (20. Mrz 2020)

Ok, danke....
Dann hab ich nun aber eine weitere Frage...

Im Select gebe ich ja dann nicht mehr nur "SELECT m" aus (also das Objekt)
Das müsste dann eher dann "SELECT m, distance" sein...
Genauer gesagt:


```
List<EntityHelper> findAddress(double pDistance, double longitudeAdress1, double latiduteAddress2)

"SELECT m, 2 * 3961 * asin(sqrt( power((sin(radians((m.lat2 – longitudeAdress1) / 2))) , 2) + cos(radians(latiduteAddress2)) * cos(radians(m.lat2)) * power((sin(radians((m.lon2 – longitudeAdress1) / 2))) , 2) )) as distance"
FROM Address
HAVING distance > pDistance
```


Denn die Distanz möchte ich später auch in meiner Liste in der Web GUI anzeigen...

*Wie müsste ich das dann aufbauen?*

Wenn ich das richtig sehe, müsste dann ja auch die Entity anders sein?
List<*EntityHelper*> findAddress(double distance, double longitudeAdress1, double latiduteAddress2).

Dann erstelle ich eine Klasse EntityHelper mit den Properties:
private Address address;
private double distance;


----------



## fhoffmann (20. Mrz 2020)

Willst du wirklich die Datenbank die Distanz aller gespeicherten Punkte zu deinem gegebenen Punkt ausrechnen lassen?
Was ist, wenn in der Datenbank sehr viele Punkte gespeichert sind?

Ich würde zunächst (in Java) ein "Quadrat" (mit Seitenlänge 2 * pDistance) um den gegebene Punkt bestimmen 
und dann aus der Datenbank alle Punkte lesen, die innerhalb dieses Quadrates liegen. 
Im letzten Schritt kann dann wiederum Java alle Punkte wegschmeißen, die nicht im Kreis mit Radius pDistance um den gegebenen Punkt liegen.


----------



## beta20 (20. Mrz 2020)

Ich weiß nicht, ob wir das gleiche meinen.
Im Grunde will ich von einer Entity (die bereits Lat und Lon beinhaltet und gespeichert hat), nur diese Objekte zurückgeben, die in eine bestimmte Distanz haben. Nicht anderes, als wenn man bei Ebay Kleinanzeige bspw. eine Artikel sucht innerhalb zB 10 Kilometer....

Meinen wir das gleiche?


----------



## fhoffmann (20. Mrz 2020)

Ja, wir meinen das gleiche.

Ich suche eine Eisdiele, die höchstens einen Kilometer von meinem Standort entfernet ist. Du berechnest dazu mit sinus, cosinus, pow etc zunächst die Entfernung zu allen Eisdielen auf der Welt - das kann lange dauern.
Im Grunde suchst du die Eisdielen, die in einem Kreis mit Radius 1 km um den Standort liegen. Da kannst du doch zunächst alle Eisdielen suchen, die in einem Quadrat (das den Kreis umschließt) liegen. Da brauchst du gar nicht zu rechnen, sondern musst nur fragen, ob die longitude und latitude jeweils zwischen zwei Werten liegen. Und anschließend kannst du die Eisdielen aus dem Quadrat, die nicht im Kreis liegen, wieder löschen.


----------



## Thallius (20. Mrz 2020)

Dazu muss man anmerken, dass der Kreis ja nicht wirklich ein Kreis ist. Sonst wre die Berechnung ja einfach. Da geht noch die Erdkrümmung mit rein. Die ist aber je nachdem in welchen Größenordnungen du suchst und bei welchen Breitengraden fast zu vernachlässigen. Wenn du also nur eine Umkreissuche für Deutschland um die 50km machst, dann kannst du auch mit einem Kreis rechnen. Ansonsten must du es halt genau machen.
Im Zeifelsfall würde ich das Rechteck einfach 20% größer wählen als nötig und dann die genaue Berechnung für die verbleibenden ERgebnisse anwenden


----------



## beta20 (20. Mrz 2020)

oh... so ungefähr verstehe ich was du meinst... aber wie man hier nun die Formel erstellt, weiß ich nicht... Kannst du hier bitte helfen?

Ich gebe dir aber Recht, dass es nicht so viel Sinn macht und das Zeit kostet, wenn man im SQL für jede Adresse erstmal die Distanz ausrechnet...
Daher wäre es mir auch Recht, wenn ich einfach mit den longitude und latitude reche, ohne COS etc. anwenden zu müssen...

Also auf den Meter genau muss es nicht passen, wenn da eine Differenz von 500m - 1000m drin ist, kann ich damit auch leben...


----------



## Thallius (20. Mrz 2020)

Leis dir das mal durch. Da wird das ziemlich gut erkläre finde ich



			Entfernungsberechnung


----------



## beta20 (20. Mrz 2020)

danke....

Also wenn ich das richtig zusammenfasse:

Folgendes wäre die exakteste Lösung, die aber deutlich mehr Rechenaufwand / Laufzeit beansprucht.


> dist = 6378.388 * acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1))



Folgende Berechnung würde aber auch gehen, ist dann aber nicht mehr soo exakt. Lat1 und Lat2 habe ich ja bereits. Einmal aus der Datenbank und einmal als Parameter von meiner Java Methode...



> distance = sqrt(dx * dx + dy * dy)
> 
> mit distance: Entfernung in km
> dx = 111.3 * cos(lat) * (lon1 - lon2)
> ...




Was ich jedoch dann hier nicht verstehe ist:


> Als Wert für lat wird dabei ein Wert gewählt, der genau zwischen lat1 und lat2 liegt.



Wie wähle ich den?


Nichtsdestotrotz müsste ich mein Rückgabewert bzw. Rückgabe Liste als eine neue Entity zurückgeben, oder? (Wie bereits oben beschrieben)
Denn wie bekomme ich sonst die Info der Distanz in meiner Ausgabeliste in der GUI?


----------



## mihe7 (21. Mrz 2020)

beta20 hat gesagt.:


> Wie wähle ich den?


(lat1+lat2)/2 ?


----------



## beta20 (22. Mrz 2020)

Ok, ich habe es nun geschafft, dass ich mehrere Werte (Entities und Zahlen im Select habe, und diese dann in der Liste ausgebe...)

Dennoch hakts noch bei der Berechnung...



fhoffmann hat gesagt.:


> Im Grunde suchst du die Eisdielen, die in einem Kreis mit Radius 1 km um den Standort liegen. Da kannst du doch zunächst alle Eisdielen suchen, die in einem Quadrat (das den Kreis umschließt) liegen. Da brauchst du gar nicht zu rechnen, sondern musst nur fragen, ob die longitude und latitude jeweils zwischen zwei Werten liegen. Und anschließend kannst du die Eisdielen aus dem Quadrat, die nicht im Kreis liegen, wieder löschen.



1) Wie sieht diese Berechnung aus?

2) Brauche ich mehrere SQL Queries? 
a) Quadrat berechnen​b) Kreis berechnen​
3) Die Distanzformel verwende ich dann in der letzten Berechnung im SELECT?


----------



## mrBrown (22. Mrz 2020)

Wie genau muss die Berechnung aus fachlicher Sicht den überhaupt sein? 
Die Berechnungen sind immer Luftlinie, es kann also gut passieren, dass du bei einer maximalen Entfernung von zb 5km den Ort rausschmeißt, der per Straße 5,002km entfernt ist, aber den drin lässt, der per Straße 15km entfernt ist.
Außerdem sind die Koordinaten immer ein konkrete Punkt, bei Ort X liegt der uU hinten Rechts auf dem Grundstück, bei Ort Y vorne Links, was dann auch wieder ein paar hundert Meter auslegen kann.

Danach kannst du die Gedanken machen, welche Formel du nutzt. Reicht vielleicht generell ein Quadrat als Suchgebiet, oder ein sehr grober Kreis, oder muss es die genauste Berechnung sein?


----------



## beta20 (22. Mrz 2020)

Die genauste Berechnung muss es nicht sein... Mir reicht ein grober Kreis, wie es zB bei Ebay Kleinanzeigen etc. ist.
Mir ist aber dennoch nicht klar welche bzw. wie dann die Formel / SQL aussehen soll...


----------



## mrBrown (22. Mrz 2020)

Die Formel steht doch bereits in #10


----------



## Xyz1 (22. Mrz 2020)

Es gibt dafür zwei Ansätze

```
public class D {
	public static double airlineInMeters(double lat1, double lon1, double lat2, double lon2) {
		double d_ew = (lon2 - lon1) * Math.cos(lat1);
		double d_ns = (lat2 - lat1);
		return Math.sqrt(d_ew * d_ew + d_ns * d_ns) * 100000.0;
	}

	public static double haversineInMeters(double lat1, double lon1, double lat2, double lon2) {
		final double R = 6367444.5; // metres
		double r1 = Math.toRadians(lat1);
		double r2 = Math.toRadians(lat2);
		double r3 = Math.toRadians(lat2 - lat1);
		double r4 = Math.toRadians(lon2 - lon1);

		double a = Math.sin(r3 / 2) * Math.sin(r3 / 2)
				+ Math.cos(r1) * Math.cos(r2) * Math.sin(r4 / 2) * Math.sin(r4 / 2);
		double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

		return R * c;
	}

	public static double percent(double d1, double d2) {
		if (d1 < d2)
			return (d2 - d1) / d1 * 100;
		else
			return (d1 - d2) / d2 * 100;
	}

	public static void main(String[] args) {
		double lat1 = 50.6;
		double lon1 = 7.76;
		double lat2 = 52.8;
		double lon2 = 13.3;
		double a = airlineInMeters   (lat1, lon1, lat2, lon2);
		double b = haversineInMeters (lat1, lon1, lat2, lon2);
		double c = percent(a, b);
		System.out.println(a + " " + b + " " + c);
	}
}
```

Ich habe jetzt zwei zufällige Punkte genommen (das sollte man zwar nicht machen, ich weiß, aber darauf gesch...), einmal bei Frankfurt in der Nähe und einmal bei Berlin in einem Wald. Beide Ansätze sind nicht zu 100% genau und die Entfernung beträgt nach Maps ungefähr 450km.

hth


----------



## beta20 (22. Mrz 2020)

danke, werde es mir später anschauen


----------

