From 46abb12de5fba73100363bfbea0c8f19b9e3b2ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20S=C3=A1nchez?= Date: Mon, 22 Mar 2010 22:21:05 +0000 Subject: [PATCH] Handle GEDCOM 5.5.1 formats for latitude and longitude (bug #3743) svn: r14910 --- src/PlaceUtils.py | 60 ++++++++++++++++++++++++++++++ src/plugins/export/ExportGedcom.py | 3 ++ 2 files changed, 63 insertions(+) diff --git a/src/PlaceUtils.py b/src/PlaceUtils.py index 16ea89b64..040401ca9 100644 --- a/src/PlaceUtils.py +++ b/src/PlaceUtils.py @@ -241,6 +241,38 @@ def __convert_using_classic_repr(stringValue, typedeg): return __convert_structure_to_float(sign, degs, mins, secs) +def __convert_using_modgedcom_repr(val, typedeg): + """ helper function that tries to convert the string using the + modified GEDCOM representation where direction [NSEW] is appended + instead of prepended. This particular representation is the result + of value normalization done on values passed to this function + """ + if typedeg == 'lat': + pos = val.find('N') + if pos >= 0: + stringValue = val[:pos] + else: + pos = val.find('S') + if pos >= 0: + stringValue = '-' + val[:pos] + else: + return None + else: + pos = val.find('E') + if pos >= 0: + stringValue = val[:pos] + else: + pos = val.find('W') + if pos >= 0: + stringValue = '-' + val[:pos] + else: + return None + try : + v = float(stringValue) + return v + except ValueError : + return None; + def __convert_float_val(val, typedeg = "lat"): # function converting input to float, recognizing decimal input, or # degree notation input. Only english input @@ -270,6 +302,11 @@ def __convert_float_val(val, typedeg = "lat"): v = __convert_using_classic_repr(val, typedeg) if v is not None : return v + + # format XX.YYYY[NSWE] + v = __convert_using_modgedcom_repr(val, typedeg) + if v is not None : + return v # no format succeeded return None @@ -364,6 +401,24 @@ def conv_lat_lon(latitude, longitude, format="D.D4"): else: return ("%.8f" % lat_float , str_lon) + if format == "GEDCOM": + # The 5.5.1 spec is inconsistent. Length is supposedly 5 to 8 chars, + # but the sample values are longer, using up to 6 fraction digits. + # As a compromise, we will produce up to 6 fraction digits, but only + # if necessary + # correct possible roundoff error + if lon_float >= 0: + str_lon = "%.6f" % (lon_float) + if str_lon == "180.000000": + str_lon ="W180.000000" + else: + str_lon = "E" + str_lon + else: + str_lon = "W" + "%.6f" % (-lon_float) + str_lon = str_lon[:-5] + str_lon[-5:].rstrip("0") + str_lat = ("%s%.6f" % (("N", lat_float) if lat_float >= 0 else ("S", -lat_float))) + str_lat = str_lat[:-5] + str_lat[-5:].rstrip("0") + return (str_lat, str_lon) deg_lat = int(lat_float) deg_lon = int(lon_float) @@ -624,6 +679,7 @@ if __name__ == '__main__': format5 = "ISO-DM" format6 = "ISO-DMS" format7 = "RT90" + format8 = "GEDCOM" print "Testing conv_lat_lon function, "+text+':' res1, res2 = conv_lat_lon(lat1,lon1,format0) print lat1,lon1,"in format",format0, "is ",res1,res2 @@ -641,6 +697,8 @@ if __name__ == '__main__': print lat1,lon1,"in format",format6, "is",res res1, res2 = conv_lat_lon(lat1,lon1,format7) print lat1,lon1,"in format",format7, "is",res1,res2,"\n" + res1, res2 = conv_lat_lon(lat1,lon1,format8) + print lat1,lon1,"in format",format8, "is",res1,res2,"\n" def test_formats_fail(lat1,lon1,text=''): print "This test should make conv_lat_lon function fail, "+text+":" @@ -687,6 +745,8 @@ if __name__ == '__main__': # test precision lat, lon = u' 50°59.99"S', u' 2°59\'59.99"E' test_formats_success(lat,lon) + lat, lon = 'N50.849888888888', 'E2.885897222222' + test_formats_success(lat,lon) # to large value of lat lat, lon = '90.849888888888', '2.885897222222' test_formats_fail(lat,lon) diff --git a/src/plugins/export/ExportGedcom.py b/src/plugins/export/ExportGedcom.py index e6bb1621e..d0b16cfab 100644 --- a/src/plugins/export/ExportGedcom.py +++ b/src/plugins/export/ExportGedcom.py @@ -47,6 +47,7 @@ from gen.updatecallback import UpdateCallback from Utils import media_path_full import gen.proxy from QuestionDialog import ErrorDialog +from PlaceUtils import conv_lat_lon #------------------------------------------------------------------------- # @@ -1366,6 +1367,8 @@ class GedcomWriter(UpdateCallback): self.__writeln(level, "PLAC", place_name.replace('\r', ' ')) longitude = place.get_longitude() latitude = place.get_latitude() + if longitude and latitude: + (latitude, longitude) = conv_lat_lon(latitude, longitude, "GEDCOM") if longitude and latitude: self.__writeln(level+1, "MAP") self.__writeln(level+2, 'LATI', latitude)