[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 <anton.borries@2denker.de>
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 940419a..caa64ec 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 c9fd1cd..95f481a 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 @@
polygon.points.forEach((point) {
path.add(_latLngToGmLatLng(point));
});
+ final polygonDirection = _isPolygonClockwise(path);
List<List<gmaps.LatLng>> paths = [path];
+ int holeIndex = 0;
polygon.holes?.forEach((hole) {
- paths.add(hole.map((point) => _latLngToGmLatLng(point)).toList());
+ List<gmaps.LatLng> 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 @@
..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<gmaps.LatLng> 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<gmaps.LatLng> 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 bd87955..099a123 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 4d5c2b1..26db542 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 @@
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', () {