@@ -16,7 +16,6 @@ package olc
1616
1717import (
1818 "errors"
19- "math"
2019 "strings"
2120)
2221
4241func Encode (lat , lng float64 , codeLen int ) string {
4342 // This approach converts each value to an integer after multiplying it by the final precision.
4443 // This allows us to use only integer operations, so avoiding any accumulation of floating point representation errors.
45-
46- // Convert latitude into a positive integer clipped into the range 0-(just under 180*2.5e7).
47- // Latitude 90 needs to be adjusted to be just less, so the returned code can also be decoded.
48- latVal := int64 (math .Round (lat * finalLatPrecision ))
49- latVal += latMax * finalLatPrecision
50- if latVal < 0 {
51- latVal = 0
52- } else if latVal >= 2 * latMax * finalLatPrecision {
53- latVal = 2 * latMax * finalLatPrecision - 1
54- }
55- // Convert longitude into a positive integer and normalise it into the range 0-360*8.192e6.
56- lngVal := int64 (math .Round (lng * finalLngPrecision ))
57- lngVal += lngMax * finalLngPrecision
58- if lngVal <= 0 {
59- lngVal = lngVal % (2 * lngMax * finalLngPrecision ) + 2 * lngMax * finalLngPrecision
60- } else if lngVal >= 2 * lngMax * finalLngPrecision {
61- lngVal = lngVal % (2 * lngMax * finalLngPrecision )
62- }
44+ latVal := latitudeAsInteger (lat )
45+ lngVal := longitudeAsInteger (lng )
6346
6447 // Clip the code length to legal values.
6548 codeLen = clipCodeLen (codeLen )
@@ -69,39 +52,27 @@ func Encode(lat, lng float64, codeLen int) string {
6952
7053 // Compute the grid part of the code if necessary.
7154 if codeLen > pairCodeLen {
72- code [sepPos + 7 ], latVal , lngVal = latLngGridStep (latVal , lngVal )
73- code [sepPos + 6 ], latVal , lngVal = latLngGridStep (latVal , lngVal )
74- code [sepPos + 5 ], latVal , lngVal = latLngGridStep (latVal , lngVal )
75- code [sepPos + 4 ], latVal , lngVal = latLngGridStep (latVal , lngVal )
76- code [sepPos + 3 ], latVal , lngVal = latLngGridStep (latVal , lngVal )
55+ for i := maxCodeLen - pairCodeLen ; i >= 1 ; i -- {
56+ code [sepPos + 2 + i ], latVal , lngVal = latLngGridStep (latVal , lngVal )
57+ }
7758 } else {
7859 latVal /= gridLatFullValue
7960 lngVal /= gridLngFullValue
8061 }
8162
8263 // Add the pair after the separator.
83- latNdx := latVal % int64 (encBase )
84- lngNdx := lngVal % int64 (encBase )
85- code [sepPos + 2 ] = Alphabet [lngNdx ]
86- code [sepPos + 1 ] = Alphabet [latNdx ]
64+ code [sepPos + 2 ], lngVal = pairIndexStep (lngVal )
65+ code [sepPos + 1 ], latVal = pairIndexStep (latVal )
8766
8867 // Avoid the need for string concatenation by filling in the Separator manually.
8968 code [sepPos ] = Separator
9069
9170 // Compute the pair section of the code.
9271 // Even indices contain latitude and odd contain longitude.
93- code [7 ], lngVal = pairIndexStep (lngVal )
94- code [6 ], latVal = pairIndexStep (latVal )
95-
96- code [5 ], lngVal = pairIndexStep (lngVal )
97- code [4 ], latVal = pairIndexStep (latVal )
98-
99- code [3 ], lngVal = pairIndexStep (lngVal )
100- code [2 ], latVal = pairIndexStep (latVal )
101-
102- code [1 ], _ = pairIndexStep (lngVal )
103- code [0 ], _ = pairIndexStep (latVal )
104-
72+ for pairStart := (pairCodeLen / 2 + 1 ); pairStart >= 0 ; pairStart = pairStart - 2 {
73+ code [pairStart + 1 ], lngVal = pairIndexStep (lngVal )
74+ code [pairStart ], latVal = pairIndexStep (latVal )
75+ }
10576 // If we don't need to pad the code, return the requested section.
10677 if codeLen >= sepPos {
10778 return string (code [:codeLen + 1 ])
@@ -139,7 +110,7 @@ func latLngGridStep(latVal, lngVal int64) (byte, int64, int64) {
139110// pairIndexStep computes the next smallest pair code in sequence,
140111// followed by the remaining integer not yet converted to a pair code.
141112func pairIndexStep (coordinate int64 ) (byte , int64 ) {
142- coordinate /= int64 (encBase )
143113 latNdx := coordinate % int64 (encBase )
114+ coordinate /= int64 (encBase )
144115 return Alphabet [latNdx ], coordinate
145116}
0 commit comments