Geokoordinaten umrechnen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
World_of_Tanks
User
Beiträge: 14
Registriert: Donnerstag 25. April 2019, 14:44

Hallo zusammen!

Ich hoffe, ich bin hier in der richtigen Abteilung. Ich würde gerne Geokoordinaten ineinander umrechnen (etwa von "Dezimalgrad" in die Darstellung "Grad, Minute, Sekunde"). ich habe gehofft das Python vielleicht schon ein Modul o.ä. für so so etwas bereithält. So zum Bsp. sollte/könnte es aussehen.

Input: (52.59781, 13.401967)

Output: (52° 35´ 52,115‘‘; 13° 24‘ 7,0812‘‘)

Kennt da jemand was? Vielen Dank im Voraus!
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Ausgabe ist nicht korrekt, es muß 52° 35' 52.116'' heißen.

Sowas ist in einer Zeile schnell selbst programmiert, ich wüßte nicht, dass es dafür schon etwas fertiges gibt.
World_of_Tanks
User
Beiträge: 14
Registriert: Donnerstag 25. April 2019, 14:44

Da hat sich wohl der Fehlerteufel eingeschlichen. Wenn es nichts fertiges gibt, dann heißt es wohl doch selbst machen.

Aber bist du sicher, dass man das in einer Zeile programmieren kann? Wenn ja gib mir doch bitte mal nen Hinweis, zumal man bedenken muss, dass man auch mit negativen Zahlen arbeiten muss.
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Schreib es doch erstmal so, wie Du denkst, ans Optimieren kann man dann immer noch gehen.
World_of_Tanks
User
Beiträge: 14
Registriert: Donnerstag 25. April 2019, 14:44

Ok, ich hab jetzt das mal schnell zusammengeschustert. Wieso wird bei der Ausgabe eine Extra-Leerzeichen eingefügt?

Code: Alles auswählen

lon = 52.59781
grad = int(lon)
minuten = int((lon-int(lon))*60)
sekunden = (((lon-int(lon))*60)-int((lon-int(lon))*60))*60
print(grad, "° ", minuten, "´ ", round(sekunden,3), "´´")
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@World_of_Tanks: Du solltest Dir mal den Modulo-Operator anschauen.

Zu den Leerzeichen: Weil `print()` das halt so macht? Steht in der Dokumentation, das zwischen den einzelnen Werten das ausgegeben wird was als `sep`-Argument übergeben wird, und das der Defaultwert ein Leerzeichen ist. Bevor Du jetzt mit dem Gedanken spielst etwas anderes für `sep` zu übergeben: Verwende Zeichenkettenformatierung — auch um das `round()` weg zu bekommen.

Code: Alles auswählen

print(f"{grad}° {minuten}´ {sekunden:.3f}´´")
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
World_of_Tanks
User
Beiträge: 14
Registriert: Donnerstag 25. April 2019, 14:44

Vielen Dank! So eine Formatierung hab ich aber noch nie gesehen. Wo kann ich nachlesen was 'f' und ':.3f' bedeutet? Ich hab beim letzteren zwar eine Ahnung, würde mich trotzdem gern weiterbilden.
Und modulo geht doch nur für ganze Zahlen so weit ich weiß.
Zuletzt geändert von World_of_Tanks am Mittwoch 25. September 2019, 10:00, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie Du schon selbst geschrieben hast, muß man auf negative Zahlen achten.

Code: Alles auswählen

print(f"{int(lon)}° {int(abs(lon) % 1 * 60)}' {abs(lon * 60) % 1 * 60:.3f}''")
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Puh. So sehr ich f-Strings mag, ich wuerde in Produktions-Code niemals so viel Berechnungen in einen String stecken. Besser eine Funktion zu definieren, die drei Rueckgabewerte hat, und die dann benutzen. Das laesst sich testen, das Syntax-Highlighting unterstuetzt einen bei der Betrachtung, etc.
World_of_Tanks
User
Beiträge: 14
Registriert: Donnerstag 25. April 2019, 14:44

Danke Leute, hat mir sehr geholfen. Hab auch noch schnell N(ord) u. S(üd) eingefügt. Und das mit der Funktion überleg ich mir noch, denn so wäre ich eigentlich auch an die Sache rangegangen.
tmessers
User
Beiträge: 28
Registriert: Dienstag 30. Oktober 2018, 21:08

Ich bin über diesen Beitrag gestolpert.
Da ich gerade mit der selben Problematik beschäftigt bin, hier meine Lösung:

Code: Alles auswählen

#Dieses Programm rechnet Geokoordinaten im Dezimalgradfromat 
#in die Formate Grad Minuten Sekunden, Gradminuten und CH1903 um. 

#Ausgangskoordinaten als Grundlage der Berechnung
#Format Dezimalgrad
lon=float(input("Bitte Nordwert im Format XX.XXXXXX eingeben:\n")) #47.69055
int_lon=int(lon)

if int_lon > 90:
   print("Der Nordwert darf 90 nicht übersteigen.")
   exit()

lat=float(input("Bitte Ostwert im Format XX.XXXXXX eingeben:\n"))#08.52695
int_lat=int(lat)
if int(lat) > 180:
   print("Der Ostwert darf 180 nicht übersteigen.")
   exit()

print('DG:  N %s° E %s°' %(lon,lat))

#Umrechung Dezimalgrad in Grad Minuten Sekunden
def koord_umr_dg_gms(lon):
 #print(lon)
 grad_lon=int(lon)
 #print(grad_lon)
 minuten_lon=int((lon-int(lon))*60)
 sekunden_lon=round((((lon-int(lon))*60)-int((lon-int(lon))*60))*60,2)
 grad_lat=int(lat)
 #print(grad_lon)
 minuten_lat=int((lat-int(lat))*60)
 sekunden_lat=round((((lat-int(lat))*60)-int((lat-int(lat))*60))*60,2)
 return grad_lon, minuten_lon, sekunden_lon, grad_lat, minuten_lat, sekunden_lat

erg_gms= koord_umr_dg_gms(lon)
print("GMS: N %s° %s' %s""" "E %s° %s' %s""" %(erg_gms[0],erg_gms[1],erg_gms[2],erg_gms[3],erg_gms[4],erg_gms[5]))

#Umrechnung Dezimalgrad in Gradminuten
def koord_umr_dg_gm(lon):
 grad_lon=int(lon)
 minuten_lon=(round(lon-grad_lon,6))*60

 grad_lat=int(lat)
 minuten_lat=(round(lat-grad_lat,6))*60    
 return grad_lon, minuten_lon, grad_lat, minuten_lat

erg_gm=koord_umr_dg_gm(lon)
print("DM:  N %s° %s' E %s° %s'" %(erg_gm[0],erg_gm[1], erg_gm[2],erg_gm[3]))

#Umrechnung Dezimalgrad in CH1903 (Schweizer Koordinaten)
def koord_umr_dg_ch1903(lon,lat):
 grad_lon=int(lon)
 minuten_lon1=(round(lon-grad_lon,6))*60
 minuten_lon2=round(minuten_lon1)
 minuten_lon3=minuten_lon1-minuten_lon2
 zwischen_lon_1=grad_lon*3600
 zwischen_lon_2=minuten_lon1*60
 zwischen_lon_3=int(minuten_lon2)/1000*60

 grad_lat=int(lat)
 minuten_lat1=(round(lat-grad_lat,6))*60
 minuten_lat2=round(minuten_lat1)
 minuten_lat3=minuten_lat1-minuten_lat2
 zwischen_lat_1=grad_lat*3600
 zwischen_lat_2=minuten_lat1*60
 zwischen_lat_3=int(minuten_lat2)/1000*60

 phi=(zwischen_lon_1+zwischen_lon_2+zwischen_lon_3)
 #print(phi)
 lam=(zwischen_lat_1+zwischen_lat_2+zwischen_lat_3)
 #print(lam)
 phi2 = (phi - 169028.66) / 10000
 #print(phi2)
 lam2 = (lam - 26782.5) / 10000
 #print(lam2)
 nordwert = int((200147.07 + 308807.95 * phi2 + 3745.25 * (lam2*lam2) + 76.63 * (phi2*phi2) + 119.79 * (phi2*phi2*phi2) - 194.56 * (lam2*lam2) * phi2))
 ostwert = int((600072.37 + 211455.93 * lam2 - 10938.51 * lam2 * phi2 - 0.36 * lam2 * (phi2*phi2)- 44.54 * (lam2*lam2*lam2)))
 return nordwert, ostwert

erg_ch1903=koord_umr_dg_ch1903(lon,lat)
print("CH:  N %s   E %s" %(int(erg_ch1903[0]),int(erg_ch1903[1])))
Was kann man besser machen?
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

@tmessers: Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht mal 1 und mal 3.
Die vielen Rundungen und Zwischenwerte machen den Code schwer lesbar. Gerundet wird immer erst bei der Ausgabe.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1205
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Wieso hat niemand divmod vorgeschlagen?

Code: Alles auswählen

def convert(coord):
    degrees, coord = divmod(coord * 60, 60)
    minutes, seconds = divmod(coord * 60, 60)
    return degrees, minutes, seconds
Die Formatierung sollte man außerhalb der Funktion irgendwo anders vornehmen.
Da es sich um Koordinaten-Paare handelt, könnte man entweder mit `map` arbeiten oder noch eine Zusatzfunktion erstellen, die die `convert` Funktion auf Längengrad und Breitengrad anwendet und beide Werte zurückliefert.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
tmessers
User
Beiträge: 28
Registriert: Dienstag 30. Oktober 2018, 21:08

Danke für Eure Tipps. Ich werde sei beherzigen.
Antworten