@@ -47,6 +47,78 @@ const int64_t kLongitudeMaxDegrees = 180;
4747const int kPositionLUT [' X' - ' C' + 1 ] = {8 , -1 , -1 , 9 , 10 , 11 , -1 , 12 ,
4848 -1 , -1 , 13 , -1 , -1 , 14 , 15 , 16 ,
4949 -1 , -1 , -1 , 17 , 18 , 19 };
50+
51+ int64_t latitudeToInteger (double latitude) {
52+ int64_t lat = round (latitude * kGridLatPrecisionInverse );
53+ lat += kLatitudeMaxDegrees * kGridLatPrecisionInverse ;
54+ if (lat < 0 ) {
55+ lat = 0 ;
56+ } else if (lat >= 2 * kLatitudeMaxDegrees * kGridLatPrecisionInverse ) {
57+ lat = 2 * kLatitudeMaxDegrees * kGridLatPrecisionInverse - 1 ;
58+ }
59+ return lat;
60+ }
61+
62+ int64_t longitudeToInteger (double longitude) {
63+ int64_t lng = round (longitude * kGridLngPrecisionInverse );
64+ lng += kLongitudeMaxDegrees * kGridLngPrecisionInverse ;
65+ if (lng <= 0 ) {
66+ lng = lng % (2 * kLongitudeMaxDegrees * kGridLngPrecisionInverse ) +
67+ 2 * kLongitudeMaxDegrees * kGridLngPrecisionInverse ;
68+ } else if (lng >= 2 * kLongitudeMaxDegrees * kGridLngPrecisionInverse ) {
69+ lng = lng % (2 * kLongitudeMaxDegrees * kGridLngPrecisionInverse );
70+ }
71+ return lng;
72+ }
73+
74+ std::string encodeIntegers (int64_t lat_val, int64_t lng_val,
75+ size_t code_length) {
76+ // Reserve characters for the code digits and the separator.
77+ std::string code = " 1234567890abcdef" ;
78+ // Add the separator character.
79+ code[internal::kSeparatorPosition ] = internal::kSeparator ;
80+
81+ // Compute the grid part of the code if necessary.
82+ if (code_length > internal::kPairCodeLength ) {
83+ for (size_t i = internal::kGridCodeLength ; i >= 1 ; i--) {
84+ int lat_digit = lat_val % internal::kGridRows ;
85+ int lng_digit = lng_val % internal::kGridColumns ;
86+ code[internal::kSeparatorPosition + 2 + i] =
87+ internal::kAlphabet [lat_digit * internal::kGridColumns + lng_digit];
88+ lat_val /= internal::kGridRows ;
89+ lng_val /= internal::kGridColumns ;
90+ }
91+ } else {
92+ lat_val /= pow (internal::kGridRows , internal::kGridCodeLength );
93+ lng_val /= pow (internal::kGridColumns , internal::kGridCodeLength );
94+ }
95+
96+ // Add the pair after the separator.
97+ code[internal::kSeparatorPosition + 1 ] =
98+ internal::kAlphabet [lat_val % internal::kEncodingBase ];
99+ code[internal::kSeparatorPosition + 2 ] =
100+ internal::kAlphabet [lng_val % internal::kEncodingBase ];
101+ lat_val /= internal::kEncodingBase ;
102+ lng_val /= internal::kEncodingBase ;
103+
104+ // Compute the pair section before the separator in reverse order.
105+ // Even indices contain latitude and odd contain longitude.
106+ for (int i = (internal::kPairCodeLength / 2 + 1 ); i >= 0 ; i -= 2 ) {
107+ code[i] = internal::kAlphabet [lat_val % internal::kEncodingBase ];
108+ code[i + 1 ] = internal::kAlphabet [lng_val % internal::kEncodingBase ];
109+ lat_val /= internal::kEncodingBase ;
110+ lng_val /= internal::kEncodingBase ;
111+ }
112+ // Replace digits with padding if necessary.
113+ if (code_length < internal::kSeparatorPosition ) {
114+ for (size_t i = code_length; i < internal::kSeparatorPosition ; i++) {
115+ code[i] = internal::kPaddingCharacter ;
116+ }
117+ code_length = internal::kSeparatorPosition ;
118+ }
119+ // Return the code up to and including the separator.
120+ return code.substr (0 , code_length + 1 );
121+ }
50122} // namespace internal
51123
52124namespace {
@@ -129,78 +201,9 @@ std::string Encode(const LatLng &location, size_t code_length) {
129201 code_length = code_length + 1 ;
130202 }
131203 // Convert latitude and longitude into integer values.
132- int64_t lat_val =
133- round (location.latitude * internal::kGridLatPrecisionInverse );
134- int64_t lng_val =
135- round (location.longitude * internal::kGridLngPrecisionInverse );
136-
137- // Adjust latitude and longitude so that they are normalized/clipped.
138- lat_val += internal::kLatitudeMaxDegrees * internal::kGridLatPrecisionInverse ;
139- if (lat_val < 0 ) {
140- lat_val = 0 ;
141- } else if (lat_val >= 2 * internal::kLatitudeMaxDegrees *
142- internal::kGridLatPrecisionInverse ) {
143- lat_val =
144- 2 * internal::kLatitudeMaxDegrees * internal::kGridLatPrecisionInverse -
145- 1 ;
146- }
147- lng_val +=
148- internal::kLongitudeMaxDegrees * internal::kGridLngPrecisionInverse ;
149- if (lng_val <= 0 ) {
150- lng_val =
151- lng_val % (2 * internal::kLongitudeMaxDegrees *
152- internal::kGridLngPrecisionInverse ) +
153- 2 * internal::kLongitudeMaxDegrees * internal::kGridLngPrecisionInverse ;
154- } else if (lng_val >= 2 * internal::kLongitudeMaxDegrees *
155- internal::kGridLngPrecisionInverse ) {
156- lng_val = lng_val % (2 * internal::kLongitudeMaxDegrees *
157- internal::kGridLngPrecisionInverse );
158- }
159- // Reserve characters for the code digits and the separator.
160- std::string code = " 1234567890abcdef" ;
161- // Add the separator character.
162- code[internal::kSeparatorPosition ] = internal::kSeparator ;
163-
164- // Compute the grid part of the code if necessary.
165- if (code_length > internal::kPairCodeLength ) {
166- for (size_t i = internal::kGridCodeLength ; i >= 1 ; i--) {
167- int lat_digit = lat_val % internal::kGridRows ;
168- int lng_digit = lng_val % internal::kGridColumns ;
169- code[internal::kSeparatorPosition + 2 + i] =
170- internal::kAlphabet [lat_digit * internal::kGridColumns + lng_digit];
171- lat_val /= internal::kGridRows ;
172- lng_val /= internal::kGridColumns ;
173- }
174- } else {
175- lat_val /= pow (internal::kGridRows , internal::kGridCodeLength );
176- lng_val /= pow (internal::kGridColumns , internal::kGridCodeLength );
177- }
178-
179- // Add the pair after the separator.
180- code[internal::kSeparatorPosition + 1 ] =
181- internal::kAlphabet [lat_val % internal::kEncodingBase ];
182- code[internal::kSeparatorPosition + 2 ] =
183- internal::kAlphabet [lng_val % internal::kEncodingBase ];
184- lat_val /= internal::kEncodingBase ;
185- lng_val /= internal::kEncodingBase ;
186-
187- // Compute the pair section before the separator in reverse order.
188- // Even indices contain latitude and odd contain longitude.
189- for (int i = (internal::kPairCodeLength / 2 + 1 ); i >= 0 ; i -= 2 ) {
190- code[i] = internal::kAlphabet [lat_val % internal::kEncodingBase ];
191- code[i + 1 ] = internal::kAlphabet [lng_val % internal::kEncodingBase ];
192- lat_val /= internal::kEncodingBase ;
193- lng_val /= internal::kEncodingBase ;
194- }
195- // Replace digits with padding if necessary.
196- if (code_length < internal::kSeparatorPosition ) {
197- for (size_t i = code_length; i < internal::kSeparatorPosition ; i++) {
198- code[i] = internal::kPaddingCharacter ;
199- }
200- code_length = internal::kSeparatorPosition ;
201- }
202- // Return the code up to and including the separator.
203- return code.substr (0 , code_length + 1 );
204+ int64_t lat_val = internal::latitudeToInteger (location.latitude );
205+ int64_t lng_val = internal::longitudeToInteger (location.longitude );
206+ return internal::encodeIntegers (lat_val, lng_val, code_length);
204207}
205208
206209std::string Encode (const LatLng &location) {
0 commit comments