From 628fd3ff23f574d2de386acf4bae7fde4bf03840 Mon Sep 17 00:00:00 2001 From: Doug Rinckes Date: Fri, 10 Jan 2025 06:49:56 +0000 Subject: [PATCH 1/9] split encode function --- c/src/olc.c | 56 ++++++++++++++++++++++++++------------------- c/src/olc.h | 12 ++++++++++ c/src/olc_private.h | 4 ++-- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/c/src/olc.c b/c/src/olc.c index 8cdc83cb..624fc92b 100644 --- a/c/src/olc.c +++ b/c/src/olc.c @@ -84,6 +84,13 @@ int OLC_IsFull(const char* code, size_t size) { int OLC_Encode(const OLC_LatLon* location, size_t length, char* code, int maxlen) { + // Convert to integers. Clipping and normalisation will be done in the integer encoding function. + long long int lat = location->lat * kGridLatPrecisionInverse; + long long int lon = location->lon * kGridLonPrecisionInverse; + return OLC_EncodeIntegers(lat, lon, length, code, maxlen); +} + +int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, char* code, int maxlen) { // Limit the maximum number of digits in the code. if (length > kMaximumDigitCount) { length = kMaximumDigitCount; @@ -94,51 +101,52 @@ int OLC_Encode(const OLC_LatLon* location, size_t length, char* code, if (length < kPairCodeLength && length % 2 == 1) { length = length + 1; } - // Adjust latitude and longitude so they fall into positive ranges. - double latitude = adjust_latitude(location->lat, length); - double longitude = normalize_longitude(location->lon); + // Convert latitude to positive range and clip. + lat += OLC_kLatMaxDegrees * kGridLatPrecisionInverse; + if (lat < 0) { + lat = 0; + } else if (lat >= 2 * OLC_kLatMaxDegrees * kGridLatPrecisionInverse) { + lat = 2 * OLC_kLatMaxDegrees * kGridLatPrecisionInverse - 1; + } + // Convert longitude to positive range and normalise. + lon += OLC_kLonMaxDegrees *kGridLonPrecisionInverse; + while (lon < 0) { + lon += 2 * OLC_kLonMaxDegrees *kGridLonPrecisionInverse; + } + while (lon >= 2 * OLC_kLonMaxDegrees *kGridLonPrecisionInverse) { + lon -= 2 * OLC_kLonMaxDegrees *kGridLonPrecisionInverse; + } // Build up the code here, then copy it to the passed pointer. char fullcode[] = "12345678901234567"; // Compute the code. - // This approach converts each value to an integer after multiplying it by - // the final precision. This allows us to use only integer operations, so - // avoiding any accumulation of floating point representation errors. - - // Multiply values by their precision and convert to positive without any - // floating point operations. - long long int lat_val = kLatMaxDegrees * 2.5e7; - long long int lng_val = kLonMaxDegrees * 8.192e6; - lat_val += latitude * 2.5e7; - lng_val += longitude * 8.192e6; - size_t pos = kMaximumDigitCount; // Compute the grid part of the code if necessary. if (length > kPairCodeLength) { for (size_t i = 0; i < kGridCodeLength; i++) { - int lat_digit = lat_val % kGridRows; - int lng_digit = lng_val % kGridCols; + int lat_digit = lat % kGridRows; + int lng_digit = lon % kGridCols; int ndx = lat_digit * kGridCols + lng_digit; fullcode[pos--] = kAlphabet[ndx]; // Note! Integer division. - lat_val /= kGridRows; - lng_val /= kGridCols; + lat /= kGridRows; + lon /= kGridCols; } } else { - lat_val /= pow(kGridRows, kGridCodeLength); - lng_val /= pow(kGridCols, kGridCodeLength); + lat /= pow(kGridRows, kGridCodeLength); + lon /= pow(kGridCols, kGridCodeLength); } pos = kPairCodeLength; // Compute the pair section of the code. for (size_t i = 0; i < kPairCodeLength / 2; i++) { - int lat_ndx = lat_val % kEncodingBase; - int lng_ndx = lng_val % kEncodingBase; + int lat_ndx = lat % kEncodingBase; + int lng_ndx = lon % kEncodingBase; fullcode[pos--] = kAlphabet[lng_ndx]; fullcode[pos--] = kAlphabet[lat_ndx]; // Note! Integer division. - lat_val /= kEncodingBase; - lng_val /= kEncodingBase; + lat /= kEncodingBase; + lon /= kEncodingBase; if (i == 0) { fullcode[pos--] = kSeparator; } diff --git a/c/src/olc.h b/c/src/olc.h index 4b5def16..11afb685 100644 --- a/c/src/olc.h +++ b/c/src/olc.h @@ -72,4 +72,16 @@ int OLC_Shorten(const char* code, size_t size, const OLC_LatLon* reference, int OLC_RecoverNearest(const char* short_code, size_t size, const OLC_LatLon* reference, char* code, int maxlen); +#ifdef __cplusplus +extern "C" { #endif + +// Encode location using integer coordinates. This function is exposed for +// testing purposes only. +int OLC_EncodeIntegers(long long int lat, long long int lon, size_t code_length, + char* code, int maxlen); +#ifdef __cplusplus +} +#endif + +#endif // OLC_OPENLOCATIONCODE_H diff --git a/c/src/olc_private.h b/c/src/olc_private.h index 981fd5b8..ea35c465 100644 --- a/c/src/olc_private.h +++ b/c/src/olc_private.h @@ -40,9 +40,9 @@ static const size_t kSeparatorPosition = 8; static const size_t kPairPrecisionInverse = 8000; // Inverse (1/) of the precision of the final grid digits in degrees. // Latitude is kEncodingBase^3 * kGridRows^kGridCodeLength -static const size_t kGridLatPrecisionInverse = 2.5e7; +static const long long int kGridLatPrecisionInverse = 2.5e7; // Longitude is kEncodingBase^3 * kGridColumns^kGridCodeLength -static const size_t kGridLonPrecisionInverse = 8.192e6; +static const long long int kGridLonPrecisionInverse = 8.192e6; // Latitude bounds are -kLatMaxDegrees degrees and +kLatMaxDegrees degrees // which we transpose to 0 and 180 degrees. static const double kLatMaxDegrees = OLC_kLatMaxDegrees; From 5323a2d65777dba5148a9d9b29d569543e7af90f Mon Sep 17 00:00:00 2001 From: Doug Rinckes Date: Fri, 10 Jan 2025 07:00:58 +0000 Subject: [PATCH 2/9] debugging --- c/src/olc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/c/src/olc.c b/c/src/olc.c index 624fc92b..caad8745 100644 --- a/c/src/olc.c +++ b/c/src/olc.c @@ -87,6 +87,8 @@ int OLC_Encode(const OLC_LatLon* location, size_t length, char* code, // Convert to integers. Clipping and normalisation will be done in the integer encoding function. long long int lat = location->lat * kGridLatPrecisionInverse; long long int lon = location->lon * kGridLonPrecisionInverse; + printf("encoding latitude %0.8f and longitude %0.8f\n", location->lat, location->lon); + printf(" initial integers: lat %lld lon %lld\n", lat, lon); return OLC_EncodeIntegers(lat, lon, length, code, maxlen); } @@ -106,7 +108,7 @@ int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, char if (lat < 0) { lat = 0; } else if (lat >= 2 * OLC_kLatMaxDegrees * kGridLatPrecisionInverse) { - lat = 2 * OLC_kLatMaxDegrees * kGridLatPrecisionInverse - 1; + lat = 2 * OLC_kLatMaxDegrees * kGridLatPrecisionInverse; } // Convert longitude to positive range and normalise. lon += OLC_kLonMaxDegrees *kGridLonPrecisionInverse; @@ -116,6 +118,7 @@ int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, char while (lon >= 2 * OLC_kLonMaxDegrees *kGridLonPrecisionInverse) { lon -= 2 * OLC_kLonMaxDegrees *kGridLonPrecisionInverse; } + printf(" final integers: lat %lld lon %lld\n", lat, lon); // Build up the code here, then copy it to the passed pointer. char fullcode[] = "12345678901234567"; From e58f7f4c597b3fdc1b5b188fd6b2b80a62192245 Mon Sep 17 00:00:00 2001 From: Doug Rinckes Date: Fri, 10 Jan 2025 09:41:21 +0000 Subject: [PATCH 3/9] correct double to integer rounding --- c/src/olc.c | 27 ++++++++++++++------------- c/src/olc.h | 12 ------------ 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/c/src/olc.c b/c/src/olc.c index caad8745..1a105f56 100644 --- a/c/src/olc.c +++ b/c/src/olc.c @@ -83,16 +83,17 @@ int OLC_IsFull(const char* code, size_t size) { } int OLC_Encode(const OLC_LatLon* location, size_t length, char* code, - int maxlen) { - // Convert to integers. Clipping and normalisation will be done in the integer encoding function. - long long int lat = location->lat * kGridLatPrecisionInverse; - long long int lon = location->lon * kGridLonPrecisionInverse; - printf("encoding latitude %0.8f and longitude %0.8f\n", location->lat, location->lon); - printf(" initial integers: lat %lld lon %lld\n", lat, lon); + int maxlen) { + // Multiply degrees by precision. Use lround to explicitly round rather than + // truncate, which causes issues when using values like 0.1 that do not have + // precise floating point representations. + long long int lat = lround(location->lat * kGridLatPrecisionInverse); + long long int lon = lround(location->lon * kGridLonPrecisionInverse); return OLC_EncodeIntegers(lat, lon, length, code, maxlen); } -int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, char* code, int maxlen) { +int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, + char* code, int maxlen) { // Limit the maximum number of digits in the code. if (length > kMaximumDigitCount) { length = kMaximumDigitCount; @@ -108,17 +109,17 @@ int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, char if (lat < 0) { lat = 0; } else if (lat >= 2 * OLC_kLatMaxDegrees * kGridLatPrecisionInverse) { - lat = 2 * OLC_kLatMaxDegrees * kGridLatPrecisionInverse; + // Subtract one to bring it just inside 90 degrees lat. + lat = 2 * OLC_kLatMaxDegrees * kGridLatPrecisionInverse - 1; } // Convert longitude to positive range and normalise. - lon += OLC_kLonMaxDegrees *kGridLonPrecisionInverse; + lon += OLC_kLonMaxDegrees * kGridLonPrecisionInverse; while (lon < 0) { - lon += 2 * OLC_kLonMaxDegrees *kGridLonPrecisionInverse; + lon += 2 * OLC_kLonMaxDegrees * kGridLonPrecisionInverse; } - while (lon >= 2 * OLC_kLonMaxDegrees *kGridLonPrecisionInverse) { - lon -= 2 * OLC_kLonMaxDegrees *kGridLonPrecisionInverse; + while (lon >= 2 * OLC_kLonMaxDegrees * kGridLonPrecisionInverse) { + lon -= 2 * OLC_kLonMaxDegrees * kGridLonPrecisionInverse; } - printf(" final integers: lat %lld lon %lld\n", lat, lon); // Build up the code here, then copy it to the passed pointer. char fullcode[] = "12345678901234567"; diff --git a/c/src/olc.h b/c/src/olc.h index 11afb685..b86cf9b3 100644 --- a/c/src/olc.h +++ b/c/src/olc.h @@ -72,16 +72,4 @@ int OLC_Shorten(const char* code, size_t size, const OLC_LatLon* reference, int OLC_RecoverNearest(const char* short_code, size_t size, const OLC_LatLon* reference, char* code, int maxlen); -#ifdef __cplusplus -extern "C" { -#endif - -// Encode location using integer coordinates. This function is exposed for -// testing purposes only. -int OLC_EncodeIntegers(long long int lat, long long int lon, size_t code_length, - char* code, int maxlen); -#ifdef __cplusplus -} -#endif - #endif // OLC_OPENLOCATIONCODE_H From 2020f7432fc56b2c16b4683f2635892d1e1a268d Mon Sep 17 00:00:00 2001 From: Doug Rinckes Date: Fri, 10 Jan 2025 09:59:54 +0000 Subject: [PATCH 4/9] correct tests for C rounding, correct function order --- c/src/olc.c | 20 ++++++++++---------- test_data/encoding.csv | 18 +++++++++--------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/c/src/olc.c b/c/src/olc.c index 1a105f56..bd74b86d 100644 --- a/c/src/olc.c +++ b/c/src/olc.c @@ -82,16 +82,6 @@ int OLC_IsFull(const char* code, size_t size) { return is_full(&info); } -int OLC_Encode(const OLC_LatLon* location, size_t length, char* code, - int maxlen) { - // Multiply degrees by precision. Use lround to explicitly round rather than - // truncate, which causes issues when using values like 0.1 that do not have - // precise floating point representations. - long long int lat = lround(location->lat * kGridLatPrecisionInverse); - long long int lon = lround(location->lon * kGridLonPrecisionInverse); - return OLC_EncodeIntegers(lat, lon, length, code, maxlen); -} - int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, char* code, int maxlen) { // Limit the maximum number of digits in the code. @@ -177,6 +167,16 @@ int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, return char_count; } +int OLC_Encode(const OLC_LatLon* location, size_t length, char* code, + int maxlen) { + // Multiply degrees by precision. Use lround to explicitly round rather than + // truncate, which causes issues when using values like 0.1 that do not have + // precise floating point representations. + long long int lat = lround(location->lat * kGridLatPrecisionInverse); + long long int lon = lround(location->lon * kGridLonPrecisionInverse); + return OLC_EncodeIntegers(lat, lon, length, code, maxlen); +} + int OLC_EncodeDefault(const OLC_LatLon* location, char* code, int maxlen) { return OLC_Encode(location, kPairCodeLength, code, maxlen); } diff --git a/test_data/encoding.csv b/test_data/encoding.csv index af7d2b19..c147065c 100644 --- a/test_data/encoding.csv +++ b/test_data/encoding.csv @@ -53,9 +53,9 @@ # return a 15-digit code # ################################################################################ -37.539669125,-122.375069724,15,849VGJQF+VX7QR3J -37.539669125,-122.375069724,16,849VGJQF+VX7QR3J -37.539669125,-122.375069724,100,849VGJQF+VX7QR3J +37.539669125,-122.375069724,15,849VGJQF+VX7QR3M +37.539669125,-122.375069724,16,849VGJQF+VX7QR3M +37.539669125,-122.375069724,100,849VGJQF+VX7QR3M ################################################################################ # # Test floating point representation/rounding errors. @@ -134,18 +134,18 @@ # ################################################################################ 80.0100000001,58.57,15,CHGW2H6C+2222222 -80.0099999999,58.57,15,CHGW2H5C+X2RRRRR +80.0099999999,58.57,15,CHGW2H6C+2222222 -80.0099999999,58.57,15,2HFWXHRC+2222222 --80.0100000001,58.57,15,2HFWXHQC+X2RRRRR +-80.0100000001,58.57,15,2HFWXHRC+2222222 ################################################################################ # # Add a few other examples. # ################################################################################ -47.000000080000000,8.00022229,15,8FVC2222+235235C -68.3500147997595,113.625636875353,15,9PWM9J2G+272FWJV -38.1176000887231,165.441989844555,15,8VC74C9R+2QX445C --28.1217794010122,-154.066811473758,15,5337VWHM+77PR2GR +47.000000080000000,8.00022229,15,8FVC2222+235235F +68.3500147997595,113.625636875353,15,9PWM9J2G+272FWR3 +38.1176000887231,165.441989844555,15,8VC74C9R+2QX445F +-28.1217794010122,-154.066811473758,15,5337VWHM+77PR2P2 ################################################################################ # # Test short length. From d3adb43cb5b532d677b26df6c1a8a525d7dd4692 Mon Sep 17 00:00:00 2001 From: Doug Rinckes Date: Fri, 10 Jan 2025 10:01:57 +0000 Subject: [PATCH 5/9] clang formatting --- c/src/olc.c | 2 +- c/src/olc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/c/src/olc.c b/c/src/olc.c index bd74b86d..d06af41a 100644 --- a/c/src/olc.c +++ b/c/src/olc.c @@ -168,7 +168,7 @@ int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, } int OLC_Encode(const OLC_LatLon* location, size_t length, char* code, - int maxlen) { + int maxlen) { // Multiply degrees by precision. Use lround to explicitly round rather than // truncate, which causes issues when using values like 0.1 that do not have // precise floating point representations. diff --git a/c/src/olc.h b/c/src/olc.h index b86cf9b3..5a0ac9d1 100644 --- a/c/src/olc.h +++ b/c/src/olc.h @@ -72,4 +72,4 @@ int OLC_Shorten(const char* code, size_t size, const OLC_LatLon* reference, int OLC_RecoverNearest(const char* short_code, size_t size, const OLC_LatLon* reference, char* code, int maxlen); -#endif // OLC_OPENLOCATIONCODE_H +#endif // OLC_OPENLOCATIONCODE_H From c42d2b08c02a4690f8a52293cb133e0cf75033a8 Mon Sep 17 00:00:00 2001 From: Doug Rinckes Date: Fri, 10 Jan 2025 10:05:52 +0000 Subject: [PATCH 6/9] switch from lng to lon for longitude --- c/src/olc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/c/src/olc.c b/c/src/olc.c index d06af41a..c51a93df 100644 --- a/c/src/olc.c +++ b/c/src/olc.c @@ -120,8 +120,8 @@ int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, if (length > kPairCodeLength) { for (size_t i = 0; i < kGridCodeLength; i++) { int lat_digit = lat % kGridRows; - int lng_digit = lon % kGridCols; - int ndx = lat_digit * kGridCols + lng_digit; + int lon_digit = lon % kGridCols; + int ndx = lat_digit * kGridCols + lon_digit; fullcode[pos--] = kAlphabet[ndx]; // Note! Integer division. lat /= kGridRows; @@ -135,8 +135,8 @@ int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, // Compute the pair section of the code. for (size_t i = 0; i < kPairCodeLength / 2; i++) { int lat_ndx = lat % kEncodingBase; - int lng_ndx = lon % kEncodingBase; - fullcode[pos--] = kAlphabet[lng_ndx]; + int lon_ndx = lon % kEncodingBase; + fullcode[pos--] = kAlphabet[lon_ndx]; fullcode[pos--] = kAlphabet[lat_ndx]; // Note! Integer division. lat /= kEncodingBase; @@ -507,9 +507,9 @@ static int decode(CodeInfo* info, OLC_CodeArea* decoded) { // convert them to floats at the end. Using doubles all the way results in // multiplying small rounding errors until they become significant. int normal_lat = -kLatMaxDegrees * kPairPrecisionInverse; - int normal_lng = -kLonMaxDegrees * kPairPrecisionInverse; + int normal_lon = -kLonMaxDegrees * kPairPrecisionInverse; int extra_lat = 0; - int extra_lng = 0; + int extra_lon = 0; // How many digits do we have to process? size_t digits = strlen(clean_code) < kPairCodeLength ? strlen(clean_code) @@ -519,11 +519,11 @@ static int decode(CodeInfo* info, OLC_CodeArea* decoded) { for (size_t i = 0; i < digits - 1; i += 2) { pv /= kEncodingBase; normal_lat += get_alphabet_position(clean_code[i]) * pv; - normal_lng += get_alphabet_position(clean_code[i + 1]) * pv; + normal_lon += get_alphabet_position(clean_code[i + 1]) * pv; } // Convert the place value to a float in degrees. double lat_precision = (double)pv / kPairPrecisionInverse; - double lng_precision = (double)pv / kPairPrecisionInverse; + double lon_precision = (double)pv / kPairPrecisionInverse; // Process any extra precision digits. if (strlen(clean_code) > kPairCodeLength) { // How many digits do we have to process? @@ -539,22 +539,22 @@ static int decode(CodeInfo* info, OLC_CodeArea* decoded) { int row = dval / kGridCols; int col = dval % kGridCols; extra_lat += row * row_pv; - extra_lng += col * col_pv; + extra_lon += col * col_pv; } // Adjust the precisions from the integer values to degrees. lat_precision = (double)row_pv / kGridLatPrecisionInverse; - lng_precision = (double)col_pv / kGridLonPrecisionInverse; + lon_precision = (double)col_pv / kGridLonPrecisionInverse; } // Merge the values from the normal and extra precision parts of the code. // Everything is ints so they all need to be cast to floats. double lat = (double)normal_lat / kPairPrecisionInverse + (double)extra_lat / kGridLatPrecisionInverse; - double lng = (double)normal_lng / kPairPrecisionInverse + - (double)extra_lng / kGridLonPrecisionInverse; + double lon = (double)normal_lon / kPairPrecisionInverse + + (double)extra_lon / kGridLonPrecisionInverse; decoded->lo.lat = lat; - decoded->lo.lon = lng; + decoded->lo.lon = lon; decoded->hi.lat = lat + lat_precision; - decoded->hi.lon = lng + lng_precision; + decoded->hi.lon = lon + lon_precision; decoded->len = strlen(clean_code); return decoded->len; } From aedbb0d30359d6ed8dbd9031fed142c74ea9edda Mon Sep 17 00:00:00 2001 From: Doug Rinckes Date: Fri, 10 Jan 2025 10:13:00 +0000 Subject: [PATCH 7/9] correct 80.01 boundary test case latitudes --- test_data/encoding.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_data/encoding.csv b/test_data/encoding.csv index c147065c..75a004ec 100644 --- a/test_data/encoding.csv +++ b/test_data/encoding.csv @@ -134,9 +134,9 @@ # ################################################################################ 80.0100000001,58.57,15,CHGW2H6C+2222222 -80.0099999999,58.57,15,CHGW2H6C+2222222 +80.00999996,58.57,15,CHGW2H5C+X2RRRRR -80.0099999999,58.57,15,2HFWXHRC+2222222 --80.0100000001,58.57,15,2HFWXHRC+2222222 +-80.0100000399,58.57,15,2HFWXHQC+X2RRRRR ################################################################################ # # Add a few other examples. From b6abb5abdb8427e513b617f9f50beac380878db0 Mon Sep 17 00:00:00 2001 From: Doug Rinckes Date: Fri, 10 Jan 2025 10:20:00 +0000 Subject: [PATCH 8/9] undo some lng->lon --- c/src/olc.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/c/src/olc.c b/c/src/olc.c index c51a93df..aa043d4c 100644 --- a/c/src/olc.c +++ b/c/src/olc.c @@ -82,7 +82,7 @@ int OLC_IsFull(const char* code, size_t size) { return is_full(&info); } -int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, +int OLC_EncodeIntegers(long long int lat, long long int lng, size_t length, char* code, int maxlen) { // Limit the maximum number of digits in the code. if (length > kMaximumDigitCount) { @@ -103,12 +103,12 @@ int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, lat = 2 * OLC_kLatMaxDegrees * kGridLatPrecisionInverse - 1; } // Convert longitude to positive range and normalise. - lon += OLC_kLonMaxDegrees * kGridLonPrecisionInverse; - while (lon < 0) { - lon += 2 * OLC_kLonMaxDegrees * kGridLonPrecisionInverse; + lng += OLC_kLonMaxDegrees * kGridLonPrecisionInverse; + while (lng < 0) { + lng += 2 * OLC_kLonMaxDegrees * kGridLonPrecisionInverse; } - while (lon >= 2 * OLC_kLonMaxDegrees * kGridLonPrecisionInverse) { - lon -= 2 * OLC_kLonMaxDegrees * kGridLonPrecisionInverse; + while (lng >= 2 * OLC_kLonMaxDegrees * kGridLonPrecisionInverse) { + lng -= 2 * OLC_kLonMaxDegrees * kGridLonPrecisionInverse; } // Build up the code here, then copy it to the passed pointer. @@ -120,27 +120,27 @@ int OLC_EncodeIntegers(long long int lat, long long int lon, size_t length, if (length > kPairCodeLength) { for (size_t i = 0; i < kGridCodeLength; i++) { int lat_digit = lat % kGridRows; - int lon_digit = lon % kGridCols; + int lon_digit = lng % kGridCols; int ndx = lat_digit * kGridCols + lon_digit; fullcode[pos--] = kAlphabet[ndx]; // Note! Integer division. lat /= kGridRows; - lon /= kGridCols; + lng /= kGridCols; } } else { lat /= pow(kGridRows, kGridCodeLength); - lon /= pow(kGridCols, kGridCodeLength); + lng /= pow(kGridCols, kGridCodeLength); } pos = kPairCodeLength; // Compute the pair section of the code. for (size_t i = 0; i < kPairCodeLength / 2; i++) { int lat_ndx = lat % kEncodingBase; - int lon_ndx = lon % kEncodingBase; + int lon_ndx = lng % kEncodingBase; fullcode[pos--] = kAlphabet[lon_ndx]; fullcode[pos--] = kAlphabet[lat_ndx]; // Note! Integer division. lat /= kEncodingBase; - lon /= kEncodingBase; + lng /= kEncodingBase; if (i == 0) { fullcode[pos--] = kSeparator; } @@ -173,8 +173,8 @@ int OLC_Encode(const OLC_LatLon* location, size_t length, char* code, // truncate, which causes issues when using values like 0.1 that do not have // precise floating point representations. long long int lat = lround(location->lat * kGridLatPrecisionInverse); - long long int lon = lround(location->lon * kGridLonPrecisionInverse); - return OLC_EncodeIntegers(lat, lon, length, code, maxlen); + long long int lng = lround(location->lon * kGridLonPrecisionInverse); + return OLC_EncodeIntegers(lat, lng, length, code, maxlen); } int OLC_EncodeDefault(const OLC_LatLon* location, char* code, int maxlen) { @@ -507,9 +507,9 @@ static int decode(CodeInfo* info, OLC_CodeArea* decoded) { // convert them to floats at the end. Using doubles all the way results in // multiplying small rounding errors until they become significant. int normal_lat = -kLatMaxDegrees * kPairPrecisionInverse; - int normal_lon = -kLonMaxDegrees * kPairPrecisionInverse; + int normal_lng = -kLonMaxDegrees * kPairPrecisionInverse; int extra_lat = 0; - int extra_lon = 0; + int extra_lng = 0; // How many digits do we have to process? size_t digits = strlen(clean_code) < kPairCodeLength ? strlen(clean_code) @@ -519,7 +519,7 @@ static int decode(CodeInfo* info, OLC_CodeArea* decoded) { for (size_t i = 0; i < digits - 1; i += 2) { pv /= kEncodingBase; normal_lat += get_alphabet_position(clean_code[i]) * pv; - normal_lon += get_alphabet_position(clean_code[i + 1]) * pv; + normal_lng += get_alphabet_position(clean_code[i + 1]) * pv; } // Convert the place value to a float in degrees. double lat_precision = (double)pv / kPairPrecisionInverse; @@ -539,7 +539,7 @@ static int decode(CodeInfo* info, OLC_CodeArea* decoded) { int row = dval / kGridCols; int col = dval % kGridCols; extra_lat += row * row_pv; - extra_lon += col * col_pv; + extra_lng += col * col_pv; } // Adjust the precisions from the integer values to degrees. lat_precision = (double)row_pv / kGridLatPrecisionInverse; @@ -549,12 +549,12 @@ static int decode(CodeInfo* info, OLC_CodeArea* decoded) { // Everything is ints so they all need to be cast to floats. double lat = (double)normal_lat / kPairPrecisionInverse + (double)extra_lat / kGridLatPrecisionInverse; - double lon = (double)normal_lon / kPairPrecisionInverse + - (double)extra_lon / kGridLonPrecisionInverse; + double lng = (double)normal_lng / kPairPrecisionInverse + + (double)extra_lng / kGridLonPrecisionInverse; decoded->lo.lat = lat; - decoded->lo.lon = lon; + decoded->lo.lon = lng; decoded->hi.lat = lat + lat_precision; - decoded->hi.lon = lon + lon_precision; + decoded->hi.lon = lng + lon_precision; decoded->len = strlen(clean_code); return decoded->len; } From 22a49d2f576e52dfbb3ae66f145c84243ecb502f Mon Sep 17 00:00:00 2001 From: Doug Rinckes Date: Fri, 10 Jan 2025 10:22:25 +0000 Subject: [PATCH 9/9] more lng->lon undoing --- c/src/olc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/c/src/olc.c b/c/src/olc.c index aa043d4c..9ef5bde6 100644 --- a/c/src/olc.c +++ b/c/src/olc.c @@ -120,8 +120,8 @@ int OLC_EncodeIntegers(long long int lat, long long int lng, size_t length, if (length > kPairCodeLength) { for (size_t i = 0; i < kGridCodeLength; i++) { int lat_digit = lat % kGridRows; - int lon_digit = lng % kGridCols; - int ndx = lat_digit * kGridCols + lon_digit; + int lng_digit = lng % kGridCols; + int ndx = lat_digit * kGridCols + lng_digit; fullcode[pos--] = kAlphabet[ndx]; // Note! Integer division. lat /= kGridRows; @@ -135,8 +135,8 @@ int OLC_EncodeIntegers(long long int lat, long long int lng, size_t length, // Compute the pair section of the code. for (size_t i = 0; i < kPairCodeLength / 2; i++) { int lat_ndx = lat % kEncodingBase; - int lon_ndx = lng % kEncodingBase; - fullcode[pos--] = kAlphabet[lon_ndx]; + int lng_ndx = lng % kEncodingBase; + fullcode[pos--] = kAlphabet[lng_ndx]; fullcode[pos--] = kAlphabet[lat_ndx]; // Note! Integer division. lat /= kEncodingBase; @@ -523,7 +523,7 @@ static int decode(CodeInfo* info, OLC_CodeArea* decoded) { } // Convert the place value to a float in degrees. double lat_precision = (double)pv / kPairPrecisionInverse; - double lon_precision = (double)pv / kPairPrecisionInverse; + double lng_precision = (double)pv / kPairPrecisionInverse; // Process any extra precision digits. if (strlen(clean_code) > kPairCodeLength) { // How many digits do we have to process? @@ -543,7 +543,7 @@ static int decode(CodeInfo* info, OLC_CodeArea* decoded) { } // Adjust the precisions from the integer values to degrees. lat_precision = (double)row_pv / kGridLatPrecisionInverse; - lon_precision = (double)col_pv / kGridLonPrecisionInverse; + lng_precision = (double)col_pv / kGridLonPrecisionInverse; } // Merge the values from the normal and extra precision parts of the code. // Everything is ints so they all need to be cast to floats. @@ -554,7 +554,7 @@ static int decode(CodeInfo* info, OLC_CodeArea* decoded) { decoded->lo.lat = lat; decoded->lo.lon = lng; decoded->hi.lat = lat + lat_precision; - decoded->hi.lon = lng + lon_precision; + decoded->hi.lon = lng + lng_precision; decoded->len = strlen(clean_code); return decoded->len; }