From ce4b0e7ead97252af7b3f7eaa6cc31247632dc1c Mon Sep 17 00:00:00 2001 From: James Leahy Date: Thu, 7 Dec 2023 12:20:33 +0100 Subject: [PATCH] feature: LatLng has a const constructor --- example/maps_toolkit_example.dart | 4 +- lib/src/latlng.dart | 2 +- test/maps_toolkit_test.dart | 98 ++++++++++++++++--------------- test/polygon_util_test.dart | 76 ++++++++++++------------ 4 files changed, 93 insertions(+), 87 deletions(-) diff --git a/example/maps_toolkit_example.dart b/example/maps_toolkit_example.dart index 59b7420..87fe9c0 100644 --- a/example/maps_toolkit_example.dart +++ b/example/maps_toolkit_example.dart @@ -1,8 +1,8 @@ import 'package:maps_toolkit/maps_toolkit.dart'; void main() { - final cityLondon = LatLng(51.5073509, -0.1277583); - final cityParis = LatLng(48.856614, 2.3522219); + const cityLondon = LatLng(51.5073509, -0.1277583); + const cityParis = LatLng(48.856614, 2.3522219); final distance = SphericalUtil.computeDistanceBetween(cityLondon, cityParis) / 1000.0; diff --git a/lib/src/latlng.dart b/lib/src/latlng.dart index b1eae7d..f1bfb48 100644 --- a/lib/src/latlng.dart +++ b/lib/src/latlng.dart @@ -2,7 +2,7 @@ class LatLng { final double latitude; final double longitude; - LatLng(this.latitude, this.longitude); + const LatLng(this.latitude, this.longitude); factory LatLng.fromMap(Map dataMap) => LatLng(dataMap['latitude']!, dataMap['longitude']!); diff --git a/test/maps_toolkit_test.dart b/test/maps_toolkit_test.dart index 1ca00a1..128e285 100644 --- a/test/maps_toolkit_test.dart +++ b/test/maps_toolkit_test.dart @@ -17,12 +17,12 @@ void expectLatLngApproxEquals(LatLng actual, LatLng expected) { void main() { // The vertices of an octahedron, for testing - final up = LatLng(90, 0); - final down = LatLng(-90, 0); - final front = LatLng(0, 0); - final right = LatLng(0, 90); - final back = LatLng(0, 180); - final left = LatLng(0, -90); + const up = LatLng(90, 0); + const down = LatLng(-90, 0); + const front = LatLng(0, 0); + const right = LatLng(0, 90); + const back = LatLng(0, 180); + const left = LatLng(0, -90); setUp(() {}); @@ -150,19 +150,19 @@ void main() { expectLatLngApproxEquals( front, SphericalUtil.computeOffsetOrigin( - LatLng(0, 45), pi * SphericalUtil.earthRadius / 4, 90)!); + const LatLng(0, 45), pi * SphericalUtil.earthRadius / 4, 90)!); expectLatLngApproxEquals( front, SphericalUtil.computeOffsetOrigin( - LatLng(0, -45), pi * SphericalUtil.earthRadius / 4, -90)!); + const LatLng(0, -45), pi * SphericalUtil.earthRadius / 4, -90)!); expectLatLngApproxEquals( front, SphericalUtil.computeOffsetOrigin( - LatLng(45, 0), pi * SphericalUtil.earthRadius / 4, 0)!); + const LatLng(45, 0), pi * SphericalUtil.earthRadius / 4, 0)!); expectLatLngApproxEquals( front, SphericalUtil.computeOffsetOrigin( - LatLng(-45, 0), pi * SphericalUtil.earthRadius / 4, 180)!); + const LatLng(-45, 0), pi * SphericalUtil.earthRadius / 4, 180)!); // Situations with no solution, should return null. @@ -170,16 +170,16 @@ void main() { expect( null, SphericalUtil.computeOffsetOrigin( - LatLng(80, 0), pi * SphericalUtil.earthRadius / 4, 180)); + const LatLng(80, 0), pi * SphericalUtil.earthRadius / 4, 180)); // Second a distance that doesn't fit on the earth. expect( null, SphericalUtil.computeOffsetOrigin( - LatLng(80, 0), pi * SphericalUtil.earthRadius / 4, 90)); + const LatLng(80, 0), pi * SphericalUtil.earthRadius / 4, 90)); }); test('testComputeOffsetAndBackToOrigin', () { - var start = LatLng(40, 40); + var start = const LatLng(40, 40); num distance = 1e5; num heading = 15; LatLng end; @@ -200,7 +200,7 @@ void main() { expectLatLngApproxEquals( start, SphericalUtil.computeOffsetOrigin(end, distance, heading)!); - start = LatLng(-21, -73); + start = const LatLng(-21, -73); end = SphericalUtil.computeOffset(start, distance, heading); expectLatLngApproxEquals( start, SphericalUtil.computeOffsetOrigin(end, distance, heading)!); @@ -211,18 +211,18 @@ void main() { // First, for this particular situation the latitude is completely // arbitrary. start = SphericalUtil.computeOffsetOrigin( - LatLng(0, 90), pi * SphericalUtil.earthRadius / 2, 90)!; + const LatLng(0, 90), pi * SphericalUtil.earthRadius / 2, 90)!; expectLatLngApproxEquals( - LatLng(0, 90), + const LatLng(0, 90), SphericalUtil.computeOffset( start, pi * SphericalUtil.earthRadius / 2, 90)); // Second, for this particular situation the longitude is completely // arbitrary. start = SphericalUtil.computeOffsetOrigin( - LatLng(90, 0), pi * SphericalUtil.earthRadius / 4, 0)!; + const LatLng(90, 0), pi * SphericalUtil.earthRadius / 4, 0)!; expectLatLngApproxEquals( - LatLng(90, 0), + const LatLng(90, 0), SphericalUtil.computeOffset( start, pi * SphericalUtil.earthRadius / 4, 0)); }); @@ -237,39 +237,43 @@ void main() { // Between front and up expectLatLngApproxEquals( - LatLng(1, 0), SphericalUtil.interpolate(front, up, 1 / 90.0)); + const LatLng(1, 0), SphericalUtil.interpolate(front, up, 1 / 90.0)); expectLatLngApproxEquals( - LatLng(1, 0), SphericalUtil.interpolate(up, front, 89 / 90.0)); + const LatLng(1, 0), SphericalUtil.interpolate(up, front, 89 / 90.0)); expectLatLngApproxEquals( - LatLng(89, 0), SphericalUtil.interpolate(front, up, 89 / 90.0)); + const LatLng(89, 0), SphericalUtil.interpolate(front, up, 89 / 90.0)); expectLatLngApproxEquals( - LatLng(89, 0), SphericalUtil.interpolate(up, front, 1 / 90.0)); + const LatLng(89, 0), SphericalUtil.interpolate(up, front, 1 / 90.0)); // Between front and down expectLatLngApproxEquals( - LatLng(-1, 0), SphericalUtil.interpolate(front, down, 1 / 90.0)); + const LatLng(-1, 0), SphericalUtil.interpolate(front, down, 1 / 90.0)); expectLatLngApproxEquals( - LatLng(-1, 0), SphericalUtil.interpolate(down, front, 89 / 90.0)); + const LatLng(-1, 0), SphericalUtil.interpolate(down, front, 89 / 90.0)); + expectLatLngApproxEquals(const LatLng(-89, 0), + SphericalUtil.interpolate(front, down, 89 / 90.0)); expectLatLngApproxEquals( - LatLng(-89, 0), SphericalUtil.interpolate(front, down, 89 / 90.0)); - expectLatLngApproxEquals( - LatLng(-89, 0), SphericalUtil.interpolate(down, front, 1 / 90.0)); + const LatLng(-89, 0), SphericalUtil.interpolate(down, front, 1 / 90.0)); // Between left and back expectLatLngApproxEquals( - LatLng(0, -91), SphericalUtil.interpolate(left, back, 1 / 90.0)); - expectLatLngApproxEquals( - LatLng(0, -91), SphericalUtil.interpolate(back, left, 89 / 90.0)); + const LatLng(0, -91), SphericalUtil.interpolate(left, back, 1 / 90.0)); expectLatLngApproxEquals( - LatLng(0, -179), SphericalUtil.interpolate(left, back, 89 / 90.0)); + const LatLng(0, -91), SphericalUtil.interpolate(back, left, 89 / 90.0)); + expectLatLngApproxEquals(const LatLng(0, -179), + SphericalUtil.interpolate(left, back, 89 / 90.0)); expectLatLngApproxEquals( - LatLng(0, -179), SphericalUtil.interpolate(back, left, 1 / 90.0)); + const LatLng(0, -179), SphericalUtil.interpolate(back, left, 1 / 90.0)); // geodesic crosses pole expectLatLngApproxEquals( - up, SphericalUtil.interpolate(LatLng(45, 0), LatLng(45, 180), 1 / 2.0)); - expectLatLngApproxEquals(down, - SphericalUtil.interpolate(LatLng(-45, 0), LatLng(-45, 180), 1 / 2.0)); + up, + SphericalUtil.interpolate( + const LatLng(45, 0), const LatLng(45, 180), 1 / 2.0)); + expectLatLngApproxEquals( + down, + SphericalUtil.interpolate( + const LatLng(-45, 0), const LatLng(-45, 180), 1 / 2.0)); // boundary values for fraction, between left and back expectLatLngApproxEquals(left, SphericalUtil.interpolate(left, back, 0)); @@ -278,24 +282,24 @@ void main() { // two nearby points, separated by ~4m, for which the Slerp algorithm is not // stable and we have to fall back to linear interpolation. expectLatLngApproxEquals( - LatLng(-37.756872, 175.325252), - SphericalUtil.interpolate(LatLng(-37.756891, 175.325262), - LatLng(-37.756853, 175.325242), 0.5)); + const LatLng(-37.756872, 175.325252), + SphericalUtil.interpolate(const LatLng(-37.756891, 175.325262), + const LatLng(-37.756853, 175.325242), 0.5)); }); test('testComputeLength', () { List latLngs; expect(SphericalUtil.computeLength([]), closeTo(0, 1e-6)); - expect(SphericalUtil.computeLength([LatLng(0, 0)]), closeTo(0, 1e-6)); + expect(SphericalUtil.computeLength([const LatLng(0, 0)]), closeTo(0, 1e-6)); - latLngs = [LatLng(0, 0), LatLng(0.1, 0.1)]; + latLngs = [const LatLng(0, 0), const LatLng(0.1, 0.1)]; expect( SphericalUtil.computeLength(latLngs), closeTo( MathUtil.toRadians(0.1) * sqrt(2) * SphericalUtil.earthRadius, 1)); - latLngs = [LatLng(0, 0), LatLng(90, 0), LatLng(0, 90)]; + latLngs = [const LatLng(0, 0), const LatLng(90, 0), const LatLng(0, 90)]; expect(SphericalUtil.computeLength(latLngs), closeTo(pi * SphericalUtil.earthRadius, 1e-6)); }); @@ -322,7 +326,7 @@ void main() { // computeArea returns area of zero on small polys final area = computeTriangleArea( - LatLng(0, 0), + const LatLng(0, 0), LatLng(0, MathUtil.toDegrees(1E-6).toDouble()), LatLng(MathUtil.toDegrees(1E-6).toDouble(), 0)); const expectedArea = @@ -334,7 +338,7 @@ void main() { test('testComputeSignedTriangleArea', () { expect( computeSignedTriangleArea( - LatLng(0, 0), LatLng(0, 0.1), LatLng(0.1, 0.1)), + const LatLng(0, 0), const LatLng(0, 0.1), const LatLng(0.1, 0.1)), closeTo( SphericalUtil.earthRadius * SphericalUtil.earthRadius * @@ -365,10 +369,10 @@ void main() { closeTo( pi * SphericalUtil.earthRadius * SphericalUtil.earthRadius, .4)); - final p1 = LatLng(45.153474463955796, 39.33852195739747); - final p2 = LatLng(45.153474463955796, 39.33972358703614); - final p3 = LatLng(45.15252112936569, 39.33972358703614); - final p4 = LatLng(45.1525022138355, 39.3385460972786); + const p1 = LatLng(45.153474463955796, 39.33852195739747); + const p2 = LatLng(45.153474463955796, 39.33972358703614); + const p3 = LatLng(45.15252112936569, 39.33972358703614); + const p4 = LatLng(45.1525022138355, 39.3385460972786); expect(SphericalUtil.computeArea([p1, p2, p3, p4, p1]), closeTo(9987, 1)); }); diff --git a/test/polygon_util_test.dart b/test/polygon_util_test.dart index 7f5734f..2dea654 100644 --- a/test/polygon_util_test.dart +++ b/test/polygon_util_test.dart @@ -94,11 +94,11 @@ void locationIndexCase(List poly, LatLng point, int idx) { void main() { // The vertices of an octahedron, for testing final polygon = [ - LatLng(10, 10), - LatLng(10, 20), - LatLng(20, 20), - LatLng(20, 10), - LatLng(10, 10) + const LatLng(10, 10), + const LatLng(10, 20), + const LatLng(20, 20), + const LatLng(20, 10), + const LatLng(10, 10) ]; const encodedPolyline = @@ -107,20 +107,20 @@ void main() { setUp(() {}); test('containsLocation for empty polygon', () { - expect( - PolygonUtil.containsLocation(LatLng(1, 1), [], false), equals(false)); + expect(PolygonUtil.containsLocation(const LatLng(1, 1), [], false), + equals(false)); }); test('containsLocation without point', () { - expect(PolygonUtil.containsLocation(LatLng(99, 99), polygon, true), + expect(PolygonUtil.containsLocation(const LatLng(99, 99), polygon, true), equals(false)); }); test('containsLocation with point', () { - expect(PolygonUtil.containsLocation(LatLng(10, 10), polygon, true), + expect(PolygonUtil.containsLocation(const LatLng(10, 10), polygon, true), equals(true)); - expect(PolygonUtil.containsLocation(LatLng(15, 15), polygon, true), + expect(PolygonUtil.containsLocation(const LatLng(15, 15), polygon, true), equals(true)); }); @@ -163,12 +163,12 @@ void main() { test('simplify polygon - triangle', () { final triangle = []; - triangle.add(LatLng(28.06025, -82.41030)); - triangle.add(LatLng(28.06129, -82.40945)); - triangle.add(LatLng(28.06206, -82.40917)); - triangle.add(LatLng(28.06125, -82.40850)); - triangle.add(LatLng(28.06035, -82.40834)); - triangle.add(LatLng(28.06038, -82.40924)); + triangle.add(const LatLng(28.06025, -82.41030)); + triangle.add(const LatLng(28.06129, -82.40945)); + triangle.add(const LatLng(28.06206, -82.40917)); + triangle.add(const LatLng(28.06125, -82.40850)); + triangle.add(const LatLng(28.06035, -82.40834)); + triangle.add(const LatLng(28.06038, -82.40924)); expect(PolygonUtil.isClosedPolygon(triangle), equals(false)); final simplifiedTriangle88 = PolygonUtil.simplify(triangle, 88); @@ -218,7 +218,7 @@ void main() { test('on edge', () { // Empty - onEdgeCase([], [], [LatLng(0, 0)]); + onEdgeCase([], [], [const LatLng(0, 0)]); const small = 5e-7; // About 5cm on equator, half the default tolerance. const big = 2e-6; // About 10cm on equator, double the default tolerance. @@ -312,24 +312,26 @@ void main() { }); test('location index', () { - locationIndexCase(makeList([]), LatLng(0, 0), -1); + locationIndexCase(makeList([]), const LatLng(0, 0), -1); // One point. - locationIndexCase(makeList([1, 2]), LatLng(1, 2), 0); - locationIndexCase(makeList([1, 2]), LatLng(3, 5), -1); + locationIndexCase(makeList([1, 2]), const LatLng(1, 2), 0); + locationIndexCase(makeList([1, 2]), const LatLng(3, 5), -1); // Two points. - locationIndexCase(makeList([1, 2, 3, 5]), LatLng(1, 2), 0); - locationIndexCase(makeList([1, 2, 3, 5]), LatLng(3, 5), 0); - locationIndexCase(makeList([1, 2, 3, 5]), LatLng(4, 6), -1); + locationIndexCase(makeList([1, 2, 3, 5]), const LatLng(1, 2), 0); + locationIndexCase(makeList([1, 2, 3, 5]), const LatLng(3, 5), 0); + locationIndexCase(makeList([1, 2, 3, 5]), const LatLng(4, 6), -1); // Three points. - locationIndexCase(makeList([0, 80, 0, 90, 0, 100]), LatLng(0, 80), 0); - locationIndexCase(makeList([0, 80, 0, 90, 0, 100]), LatLng(0, 85), 0); - locationIndexCase(makeList([0, 80, 0, 90, 0, 100]), LatLng(0, 90), 0); - locationIndexCase(makeList([0, 80, 0, 90, 0, 100]), LatLng(0, 95), 1); - locationIndexCase(makeList([0, 80, 0, 90, 0, 100]), LatLng(0, 100), 1); - locationIndexCase(makeList([0, 80, 0, 90, 0, 100]), LatLng(0, 110), -1); + locationIndexCase(makeList([0, 80, 0, 90, 0, 100]), const LatLng(0, 80), 0); + locationIndexCase(makeList([0, 80, 0, 90, 0, 100]), const LatLng(0, 85), 0); + locationIndexCase(makeList([0, 80, 0, 90, 0, 100]), const LatLng(0, 90), 0); + locationIndexCase(makeList([0, 80, 0, 90, 0, 100]), const LatLng(0, 95), 1); + locationIndexCase( + makeList([0, 80, 0, 90, 0, 100]), const LatLng(0, 100), 1); + locationIndexCase( + makeList([0, 80, 0, 90, 0, 100]), const LatLng(0, 110), -1); }); test('contains', () { @@ -464,22 +466,22 @@ void main() { expect( PolygonUtil.containsLocation( - LatLng(55.455251, 25.392898), polygon, true), + const LatLng(55.455251, 25.392898), polygon, true), equals(true)); expect( PolygonUtil.containsLocation( - LatLng(55.454473, 25.394104), polygon, true), + const LatLng(55.454473, 25.394104), polygon, true), equals(true)); expect( PolygonUtil.containsLocation( - LatLng(25.392898, 55.455251), polygon, true), + const LatLng(25.392898, 55.455251), polygon, true), equals(false)); expect( PolygonUtil.containsLocation( - LatLng(25.394104, 55.454473), polygon, true), + const LatLng(25.394104, 55.454473), polygon, true), equals(false)); }); @@ -587,22 +589,22 @@ void main() { expect( PolygonUtil.containsLocation( - LatLng(55.455251, 25.392898), polygon, true), + const LatLng(55.455251, 25.392898), polygon, true), equals(false)); expect( PolygonUtil.containsLocation( - LatLng(25.392898, 55.455251), polygon, true), + const LatLng(25.392898, 55.455251), polygon, true), equals(true)); expect( PolygonUtil.containsLocation( - LatLng(55.454473, 25.394104), polygon, true), + const LatLng(55.454473, 25.394104), polygon, true), equals(false)); expect( PolygonUtil.containsLocation( - LatLng(25.394104, 55.454473), polygon, true), + const LatLng(25.394104, 55.454473), polygon, true), equals(true)); }); }