From c923ef857c5fd13b1543ffa40013b1ca70d81dde Mon Sep 17 00:00:00 2001 From: Anton Borries Date: Thu, 21 Jan 2021 23:51:09 +0100 Subject: [PATCH] [google_maps_flutter_web] Reverse Hole winding when needed (#3440) The Web Version needs the holes in a polygon to be defined in the opposite direction to their parent polygon. This change automatically reverses the definition of a hole, when needed. In debug mode, it'll let the user know that the holes need to be wound differently. Co-authored-by: Anton Borries --- .../google_maps_flutter_web/CHANGELOG.md | 4 +++ .../lib/src/convert.dart | 30 ++++++++++++++++- .../google_maps_flutter_web/pubspec.yaml | 2 +- .../test/test_driver/shapes_integration.dart | 33 +++++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md index 940419a215fca..caa64ec730884 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.1 + +* Auto-reverse holes if they're the same direction as the polygon. [Issue](https://github.com/flutter/flutter/issues/74096). + ## 0.1.0+10 * Update `package:google_maps_flutter_platform_interface` to `^1.1.0`. diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart index c9fd1cd55d3bb..95f481a9bdc50 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart @@ -482,9 +482,23 @@ gmaps.PolygonOptions _polygonOptionsFromPolygon( polygon.points.forEach((point) { path.add(_latLngToGmLatLng(point)); }); + final polygonDirection = _isPolygonClockwise(path); List> paths = [path]; + int holeIndex = 0; polygon.holes?.forEach((hole) { - paths.add(hole.map((point) => _latLngToGmLatLng(point)).toList()); + List holePath = + hole.map((point) => _latLngToGmLatLng(point)).toList(); + if (_isPolygonClockwise(holePath) == polygonDirection) { + holePath = holePath.reversed.toList(); + if (kDebugMode) { + print( + 'Hole [$holeIndex] in Polygon [${polygon.polygonId.value}] has been reversed.' + ' Ensure holes in polygons are "wound in the opposite direction to the outer path."' + ' More info: https://github.com/flutter/flutter/issues/74096'); + } + } + paths.add(holePath); + holeIndex++; }); return gmaps.PolygonOptions() ..paths = paths @@ -498,6 +512,20 @@ gmaps.PolygonOptions _polygonOptionsFromPolygon( ..geodesic = polygon.geodesic; } +/// Calculates the direction of a given Polygon +/// based on: https://stackoverflow.com/a/1165943 +/// +/// returns [true] if clockwise [false] if counterclockwise +bool _isPolygonClockwise(List path) { + var direction = 0.0; + for (var i = 0; i < path.length; i++) { + direction = direction + + ((path[(i + 1) % path.length].lat - path[i].lat) * + (path[(i + 1) % path.length].lng + path[i].lng)); + } + return direction >= 0; +} + gmaps.PolylineOptions _polylineOptionsFromPolyline( gmaps.GMap googleMap, Polyline polyline) { List paths = []; diff --git a/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml index bd879553a06dc..099a1238be1ca 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml @@ -1,7 +1,7 @@ name: google_maps_flutter_web description: Web platform implementation of google_maps_flutter homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter -version: 0.1.0+10 +version: 0.1.1 flutter: plugin: diff --git a/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/shapes_integration.dart b/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/shapes_integration.dart index 4d5c2b17cc56c..26db542c60fe7 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/shapes_integration.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/shapes_integration.dart @@ -245,6 +245,39 @@ void main() { expect(geometry.poly.containsLocation(pointInHole, polygon), false); }); + + testWidgets('Hole Path gets reversed to display correctly', + (WidgetTester tester) async { + final polygons = { + Polygon( + polygonId: PolygonId('BermudaTriangle'), + points: [ + LatLng(25.774, -80.19), + LatLng(18.466, -66.118), + LatLng(32.321, -64.757), + ], + holes: [ + [ + LatLng(27.339, -66.668), + LatLng(29.57, -67.514), + LatLng(28.745, -70.579), + ], + ], + ), + }; + + controller.addPolygons(polygons); + + expect( + controller.polygons.values.first.polygon.paths.getAt(1).getAt(0).lat, + 28.745); + expect( + controller.polygons.values.first.polygon.paths.getAt(1).getAt(1).lat, + 29.57); + expect( + controller.polygons.values.first.polygon.paths.getAt(1).getAt(2).lat, + 27.339); + }); }); group('PolylinesController', () {