Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions lib/src/layer/polygon_layer/polygon_layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -228,19 +228,28 @@ class _PolygonLayerState<R extends Object> extends State<PolygonLayer<R>>
(i) {
final culledPolygon = culled[i];

final points = culledPolygon.holePoints.isEmpty
? culledPolygon.points
: culledPolygon.points
.followedBy(culledPolygon.holePoints.expand((e) => e));
// Flatten the points and hole points into the coordinate list
// directly, avoiding quadratic `elementAt` calls on a lazy
// concatenated iterable.
var totalLength = culledPolygon.points.length;
for (final hole in culledPolygon.holePoints) {
totalLength += hole.length;
}
final coords = Float64List(totalLength * 2);
var ii = 0;
for (final point in culledPolygon.points) {
coords[ii++] = point.dx;
coords[ii++] = point.dy;
}
for (final hole in culledPolygon.holePoints) {
for (final point in hole) {
coords[ii++] = point.dx;
coords[ii++] = point.dy;
}
}

return Earcut.triangulateRaw(
List.generate(
points.length * 2,
(ii) => ii.isEven
? points.elementAt(ii ~/ 2).dx
: points.elementAt(ii ~/ 2).dy,
growable: false,
),
coords,
holeIndices: culledPolygon.holePoints.isEmpty
? null
: _generateHolesIndices(culledPolygon)
Expand Down
29 changes: 23 additions & 6 deletions lib/src/misc/offsets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,26 @@ class OffsetHelper {
final crs = camera.crs;
final zoomScale = crs.scale(camera.zoom);

final realPoints = holePoints == null || holePoints.isEmpty
? points
: points.followedBy(holePoints.expand((e) => e));
// Flatten the points and hole points into a single list, so that the
// loops below can use constant-time indexing. Using a lazy concatenated
// iterable here makes `elementAt` walk from the start on every call,
// which is quadratic in the total number of points.
final List<Offset> realPoints;
if (holePoints == null || holePoints.isEmpty) {
realPoints = points;
} else {
var totalLength = points.length;
for (final hole in holePoints) {
totalLength += hole.length;
}
realPoints = List<Offset>.filled(totalLength, Offset.zero)
..setRange(0, points.length, points);
var start = points.length;
for (final hole in holePoints) {
realPoints.setRange(start, start + hole.length, hole);
start += hole.length;
}
}

final ox = -_origin.dx;
final oy = -_origin.dy;
Expand All @@ -92,7 +109,7 @@ class OffsetHelper {
-worldWidth,
];
final halfScreenWidth = camera.size.width / 2;
final p = realPoints.elementAt(0);
final p = realPoints[0];
late double result;
late double bestX;
for (int i = 0; i < addedWidths.length; i++) {
Expand All @@ -119,7 +136,7 @@ class OffsetHelper {
if (crs case final CrsWithStaticTransformation crs) {
final v = List<Offset>.filled(len, Offset.zero, growable: true);
for (int i = 0; i < len; ++i) {
final p = realPoints.elementAt(i);
final p = realPoints[i];
final (x, y) = crs.transform(p.dx + addedWorldWidth, p.dy, zoomScale);
v[i] = Offset(x + ox + shift, y + oy);
}
Expand All @@ -128,7 +145,7 @@ class OffsetHelper {

final v = List<Offset>.filled(len, Offset.zero, growable: true);
for (int i = 0; i < len; ++i) {
final p = realPoints.elementAt(i);
final p = realPoints[i];
final (x, y) = crs.transform(p.dx + addedWorldWidth, p.dy, zoomScale);
v[i] = Offset(x + ox + shift, y + oy);
}
Expand Down
Loading