Handle GEDCOM 5.5.1 formats for latitude and longitude (bug #3743)
svn: r14912
This commit is contained in:
		| @@ -241,6 +241,38 @@ def __convert_using_classic_repr(stringValue, typedeg): | |||||||
|  |  | ||||||
|     return __convert_structure_to_float(sign, degs, mins, secs) |     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"): | def __convert_float_val(val, typedeg = "lat"): | ||||||
|     # function converting input to float, recognizing decimal input, or  |     # function converting input to float, recognizing decimal input, or  | ||||||
|     # degree notation input. Only english input |     # degree notation input. Only english input | ||||||
| @@ -270,6 +302,11 @@ def __convert_float_val(val, typedeg = "lat"): | |||||||
|     v = __convert_using_classic_repr(val, typedeg)  |     v = __convert_using_classic_repr(val, typedeg)  | ||||||
|     if v is not None :  |     if v is not None :  | ||||||
|         return v |         return v | ||||||
|  |  | ||||||
|  |     # format XX.YYYY[NSWE] | ||||||
|  |     v = __convert_using_modgedcom_repr(val, typedeg) | ||||||
|  |     if v is not None : | ||||||
|  |         return v | ||||||
|      |      | ||||||
|     # no format succeeded |     # no format succeeded | ||||||
|     return None |     return None | ||||||
| @@ -364,6 +401,24 @@ def conv_lat_lon(latitude, longitude, format="D.D4"): | |||||||
|         else: |         else: | ||||||
|             return ("%.8f" % lat_float , str_lon) |             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_lat = int(lat_float) | ||||||
|     deg_lon = int(lon_float) |     deg_lon = int(lon_float) | ||||||
| @@ -624,6 +679,7 @@ if __name__ == '__main__': | |||||||
|         format5 = "ISO-DM" |         format5 = "ISO-DM" | ||||||
|         format6 = "ISO-DMS" |         format6 = "ISO-DMS" | ||||||
|         format7 = "RT90" |         format7 = "RT90" | ||||||
|  |         format8 = "GEDCOM" | ||||||
|         print "Testing conv_lat_lon function, "+text+':' |         print "Testing conv_lat_lon function, "+text+':' | ||||||
|         res1, res2 = conv_lat_lon(lat1,lon1,format0) |         res1, res2 = conv_lat_lon(lat1,lon1,format0) | ||||||
|         print lat1,lon1,"in format",format0, "is   ",res1,res2 |         print lat1,lon1,"in format",format0, "is   ",res1,res2 | ||||||
| @@ -641,6 +697,8 @@ if __name__ == '__main__': | |||||||
|         print lat1,lon1,"in format",format6, "is",res |         print lat1,lon1,"in format",format6, "is",res | ||||||
|         res1, res2 = conv_lat_lon(lat1,lon1,format7) |         res1, res2 = conv_lat_lon(lat1,lon1,format7) | ||||||
|         print lat1,lon1,"in format",format7, "is",res1,res2,"\n" |         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=''): |     def test_formats_fail(lat1,lon1,text=''): | ||||||
|         print "This test should make conv_lat_lon function fail, "+text+":" |         print "This test should make conv_lat_lon function fail, "+text+":" | ||||||
| @@ -687,6 +745,8 @@ if __name__ == '__main__': | |||||||
|     # test precision |     # test precision | ||||||
|     lat, lon =  u' 50°59.99"S', u'  2°59\'59.99"E' |     lat, lon =  u' 50°59.99"S', u'  2°59\'59.99"E' | ||||||
|     test_formats_success(lat,lon) |     test_formats_success(lat,lon) | ||||||
|  |     lat, lon = 'N50.849888888888', 'E2.885897222222' | ||||||
|  |     test_formats_success(lat,lon) | ||||||
|     # to large value of lat |     # to large value of lat | ||||||
|     lat, lon =  '90.849888888888', '2.885897222222' |     lat, lon =  '90.849888888888', '2.885897222222' | ||||||
|     test_formats_fail(lat,lon) |     test_formats_fail(lat,lon) | ||||||
|   | |||||||
| @@ -47,6 +47,7 @@ from gen.updatecallback import UpdateCallback | |||||||
| from Utils import media_path_full | from Utils import media_path_full | ||||||
| import gen.proxy | import gen.proxy | ||||||
| from QuestionDialog import ErrorDialog | 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', ' ')) |         self.__writeln(level, "PLAC", place_name.replace('\r', ' ')) | ||||||
|         longitude = place.get_longitude() |         longitude = place.get_longitude() | ||||||
|         latitude = place.get_latitude() |         latitude = place.get_latitude() | ||||||
|  |         if longitude and latitude: | ||||||
|  |             (latitude, longitude) = conv_lat_lon(latitude, longitude, "GEDCOM") | ||||||
|         if longitude and latitude: |         if longitude and latitude: | ||||||
|             self.__writeln(level+1, "MAP") |             self.__writeln(level+1, "MAP") | ||||||
|             self.__writeln(level+2, 'LATI', latitude) |             self.__writeln(level+2, 'LATI', latitude) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user