@@ -108,7 +108,7 @@ bool _matchesPattern(String string, Pattern pattern) =>
108
108
string.contains (pattern);
109
109
110
110
bool isValid (String code) {
111
- if (code == null || code .length == 1 ) {
111
+ if (code.length == 1 ) {
112
112
return false ;
113
113
}
114
114
@@ -254,33 +254,40 @@ bool isFull(String code) {
254
254
/// * [codeLength] : The number of significant digits in the output code, not
255
255
/// including any separator characters.
256
256
String encode (num latitude, num longitude, {int codeLength = pairCodeLength}) {
257
- if (codeLength < minDigitCount || (codeLength < pairCodeLength && codeLength.isOdd)) {
257
+ if (codeLength < minDigitCount ||
258
+ (codeLength < pairCodeLength && codeLength.isOdd)) {
258
259
throw ArgumentError ('Invalid Open Location Code length: $codeLength ' );
259
260
}
260
261
codeLength = min (maxDigitCount, codeLength);
261
- // Ensure that latitude and longitude are valid.
262
- latitude = clipLatitude (latitude);
263
- longitude = normalizeLongitude (longitude);
264
- // Latitude 90 needs to be adjusted to be just less, so the returned code
265
- // can also be decoded.
266
- if (latitude == 90 ) {
267
- latitude -= computeLatitudePrecision (codeLength).toDouble ();
268
- }
269
- var code = '' ;
270
262
271
- // Compute the code.
272
263
// This approach converts each value to an integer after multiplying it by
273
264
// the final precision. This allows us to use only integer operations, so
274
265
// avoiding any accumulation of floating point representation errors.
275
266
276
- // Multiply values by their precision and convert to positive.
277
- // Force to integers so the division operations will have integer results.
278
- // Note: Dart requires rounding before truncating to ensure precision!
279
- var latVal =
280
- ((latitude + latitudeMax) * finalLatPrecision * 1e6 ).round () ~ / 1e6 ;
281
- var lngVal =
282
- ((longitude + longitudeMax) * finalLngPrecision * 1e6 ).round () ~ / 1e6 ;
267
+ // Convert latitude into a positive integer clipped into the range 0-(just
268
+ // under 180*2.5e7). Latitude 90 needs to be adjusted to be just less, so the
269
+ // returned code can also be decoded.
270
+ var latVal = (latitude * finalLatPrecision).round ().toInt ();
271
+ latVal += latitudeMax * finalLatPrecision;
272
+ if (latVal < 0 ) {
273
+ latVal = 0 ;
274
+ } else if (latVal >= 2 * latitudeMax * finalLatPrecision) {
275
+ latVal = 2 * latitudeMax * finalLatPrecision - 1 ;
276
+ }
277
+ // Convert longitude into a positive integer and normalise it into the range
278
+ // 0-360*8.192e6.
279
+ var lngVal = (longitude * finalLngPrecision).round ().toInt ();
280
+ lngVal += longitudeMax * finalLngPrecision;
281
+ if (lngVal < 0 ) {
282
+ // Dart's % operator differs from other languages in that it returns the
283
+ // same sign as the divisor. This means we don't need to add the range to
284
+ // the result.
285
+ lngVal = (lngVal % (2 * longitudeMax * finalLngPrecision));
286
+ } else if (lngVal >= 2 * longitudeMax * finalLngPrecision) {
287
+ lngVal = lngVal % (2 * longitudeMax * finalLngPrecision);
288
+ }
283
289
290
+ var code = '' ;
284
291
// Compute the grid part of the code if necessary.
285
292
if (codeLength > pairCodeLength) {
286
293
for (var i = 0 ; i < maxDigitCount - pairCodeLength; i++ ) {
@@ -326,7 +333,8 @@ String encode(num latitude, num longitude, {int codeLength = pairCodeLength}) {
326
333
CodeArea decode (String code) {
327
334
if (! isFull (code)) {
328
335
throw ArgumentError (
329
- 'Passed Open Location Code is not a valid full code: $code ' );
336
+ 'Passed Open Location Code is not a valid full code: $code ' ,
337
+ );
330
338
}
331
339
// Strip out separator character (we've already established the code is
332
340
// valid so the maximum is one), padding characters and convert to upper
@@ -381,8 +389,13 @@ CodeArea decode(String code) {
381
389
var lat = normalLat / pairPrecision + gridLat / finalLatPrecision;
382
390
var lng = normalLng / pairPrecision + gridLng / finalLngPrecision;
383
391
// Return the code area.
384
- return CodeArea (lat, lng, lat + latPrecision, lng + lngPrecision,
385
- min (code.length, maxDigitCount));
392
+ return CodeArea (
393
+ lat,
394
+ lng,
395
+ lat + latPrecision,
396
+ lng + lngPrecision,
397
+ min (code.length, maxDigitCount),
398
+ );
386
399
}
387
400
388
401
/// Recover the nearest matching code to a specified location.
@@ -420,7 +433,10 @@ CodeArea decode(String code) {
420
433
/// passed code was not a valid short code, but was a valid full code, it is
421
434
/// returned unchanged.
422
435
String recoverNearest (
423
- String shortCode, num referenceLatitude, num referenceLongitude) {
436
+ String shortCode,
437
+ num referenceLatitude,
438
+ num referenceLongitude,
439
+ ) {
424
440
if (! isShort (shortCode)) {
425
441
if (isFull (shortCode)) {
426
442
return shortCode.toUpperCase ();
@@ -442,9 +458,10 @@ String recoverNearest(
442
458
var halfResolution = resolution / 2.0 ;
443
459
444
460
// Use the reference location to pad the supplied short code and decode it.
445
- var codeArea = decode (encode (referenceLatitude, referenceLongitude)
446
- .substring (0 , paddingLength) +
447
- shortCode);
461
+ var codeArea = decode (
462
+ encode (referenceLatitude, referenceLongitude).substring (0 , paddingLength) +
463
+ shortCode,
464
+ );
448
465
var centerLatitude = codeArea.center.latitude;
449
466
var centerLongitude = codeArea.center.longitude;
450
467
@@ -470,8 +487,11 @@ String recoverNearest(
470
487
centerLongitude += resolution;
471
488
}
472
489
473
- return encode (centerLatitude, centerLongitude,
474
- codeLength: codeArea.codeLength);
490
+ return encode (
491
+ centerLatitude,
492
+ centerLongitude,
493
+ codeLength: codeArea.codeLength,
494
+ );
475
495
}
476
496
477
497
/// Remove characters from the start of an OLC [code] .
@@ -506,8 +526,10 @@ String shorten(String code, num latitude, num longitude) {
506
526
latitude = clipLatitude (latitude);
507
527
longitude = normalizeLongitude (longitude);
508
528
// How close are the latitude and longitude to the code center.
509
- var range = max ((codeArea.center.latitude - latitude).abs (),
510
- (codeArea.center.longitude - longitude).abs ());
529
+ var range = max (
530
+ (codeArea.center.latitude - latitude).abs (),
531
+ (codeArea.center.longitude - longitude).abs (),
532
+ );
511
533
for (var i = pairResolutions.length - 2 ; i >= 1 ; i-- ) {
512
534
// Check if we're close enough to shorten. The range must be less than 1/2
513
535
// the resolution to shorten at all, and we want to allow some safety, so
0 commit comments