diff --git a/lib/src/layer/polygon_layer/painter.dart b/lib/src/layer/polygon_layer/painter.dart index d2f36e27c..ce87ce4e4 100644 --- a/lib/src/layer/polygon_layer/painter.dart +++ b/lib/src/layer/polygon_layer/painter.dart @@ -32,6 +32,9 @@ base class _PolygonPainter /// This may improve performance: see [polygonLabels] for more information. final bool drawLabelsLast; + /// See [PolygonLayer.debugAltRenderer] + final bool debugAltRenderer; + /// Create a new [_PolygonPainter] instance. _PolygonPainter({ required this.polygons, @@ -39,6 +42,7 @@ base class _PolygonPainter required super.camera, required this.polygonLabels, required this.drawLabelsLast, + required this.debugAltRenderer, required super.hitNotifier, }) : bounds = camera.visibleBounds; @@ -125,6 +129,50 @@ base class _PolygonPainter } final vertices = Vertices.raw(VertexMode.triangles, points); canvas.drawVertices(vertices, BlendMode.src, paint); + + if (debugAltRenderer) { + for (int i = 0; i < trianglePoints.length; i += 3) { + canvas.drawCircle( + trianglePoints[i], + 5, + Paint()..color = const Color(0x7EFF0000), + ); + canvas.drawCircle( + trianglePoints[i + 1], + 5, + Paint()..color = const Color(0x7E00FF00), + ); + canvas.drawCircle( + trianglePoints[i + 2], + 5, + Paint()..color = const Color(0x7E0000FF), + ); + + final path = Path() + ..addPolygon( + [ + trianglePoints[i], + trianglePoints[i + 1], + trianglePoints[i + 2], + ], + true, + ); + + canvas.drawPath( + path, + Paint() + ..color = const Color(0x7EFFFFFF) + ..style = PaintingStyle.fill, + ); + + canvas.drawPath( + path, + Paint() + ..color = const Color(0xFF000000) + ..style = PaintingStyle.stroke, + ); + } + } } else { canvas.drawPath(filledPath, paint); } @@ -163,6 +211,25 @@ base class _PolygonPainter polygonTriangles != null ? projectedPolygon.holePoints : null, ); + if (debugAltRenderer) { + const offsetsLabelStyle = TextStyle( + color: Color(0xFF000000), + fontSize: 16, + ); + + for (int i = 0; i < fillOffsets.length; i++) { + TextPainter( + text: TextSpan( + text: i.toString(), + style: offsetsLabelStyle, + ), + textDirection: TextDirection.ltr, + ) + ..layout(maxWidth: 100) + ..paint(canvas, fillOffsets[i]); + } + } + // The hash is based on the polygons visual properties. If the hash from // the current and the previous polygon no longer match, we need to flush // the batch previous polygons. @@ -323,6 +390,7 @@ base class _PolygonPainter final isSolid = polygon.pattern == const StrokePattern.solid(); final isDashed = polygon.pattern.segments != null; final isDotted = polygon.pattern.spacingFactor != null; + if (isSolid) { final SolidPixelHiker hiker = SolidPixelHiker( offsets: offsets, diff --git a/lib/src/layer/polygon_layer/polygon_layer.dart b/lib/src/layer/polygon_layer/polygon_layer.dart index ac959ed10..db5fa4299 100644 --- a/lib/src/layer/polygon_layer/polygon_layer.dart +++ b/lib/src/layer/polygon_layer/polygon_layer.dart @@ -42,6 +42,10 @@ class PolygonLayer extends StatefulWidget { /// above before enabling. final bool useAltRendering; + /// Whether to overlay a debugging tool when [useAltRendering] is enabled to + /// display triangulation results + final bool debugAltRenderer; + /// Whether to cull polygons and polygon sections that are outside of the /// viewport /// @@ -76,6 +80,7 @@ class PolygonLayer extends StatefulWidget { super.key, required this.polygons, this.useAltRendering = false, + this.debugAltRenderer = false, this.polygonCulling = true, this.simplificationTolerance = 0.5, this.polygonLabels = true, @@ -175,10 +180,10 @@ class _PolygonLayerState extends State> { : points.elementAt(ii ~/ 2).y, growable: false, ), - // Not sure how just this works but it seems to :D holeIndices: culledPolygon.holePoints.isEmpty ? null - : [culledPolygon.points.length], + : _generateHolesIndices(culledPolygon) + .toList(growable: false), ); }, growable: false, @@ -192,6 +197,7 @@ class _PolygonLayerState extends State> { camera: camera, polygonLabels: widget.polygonLabels, drawLabelsLast: widget.drawLabelsLast, + debugAltRenderer: widget.debugAltRenderer, hitNotifier: widget.hitNotifier, ), size: Size(camera.size.x, camera.size.y), @@ -199,6 +205,15 @@ class _PolygonLayerState extends State> { ); } + Iterable _generateHolesIndices(_ProjectedPolygon polygon) sync* { + var prevValue = polygon.points.length; + yield prevValue; + + for (int i = 0; i < polygon.holePoints.length - 1; i++) { + yield prevValue += polygon.holePoints[i].length; + } + } + List<_ProjectedPolygon> _computeZoomLevelSimplification({ required MapCamera camera, required List<_ProjectedPolygon> polygons,