Supercluster
This package contains two very fast point clustering algorithms:
Supercluster
: A port of MapBox's javascript supercluster library for fast marker clustering which is blazingly fast but doesn't allow addition/removal of points.SuperclusterMutable
: An adaptation of the same supercluster library but modified to use a mutable underlying index which means that points may be added/removed.
Usage
Note: For the sake of these examples the following class is used to represent points on the map:
class MapPoint {
String name;
final double lat;
final double lon;
MapPoint({
required this.name,
required this.lat,
required this.lon,
});
@override
String toString() => '"$name" ($lat, $lon)';
}
Supercluster example
void main() {
final points = [
MapPoint(name: 'first', lat: 46, lon: 1.5),
MapPoint(name: 'second', lat: 46.4, lon: 0.9),
MapPoint(name: 'third', lat: 45, lon: 19),
];
final supercluster = SuperclusterImmutable<MapPoint>(
getX: (p) => p.lon,
getY: (p) => p.lat,
)
..load(points);
final clustersAndPoints = supercluster.search(0, 40, 20, 50, 5).map(
(e) =>
e.map(
cluster: (cluster) => 'cluster (${cluster.numPoints} points)',
point: (point) => 'point ${point.originalPoint}',
),
);
print(clustersAndPoints.join(', '));
// prints: cluster (2 points), point "third" (45.0, 19.0)
}
SuperclusterMutable example
void main() {
final points = [
MapPoint(name: 'first', lat: 46, lon: 1.5),
MapPoint(name: 'second', lat: 46.4, lon: 0.9),
MapPoint(name: 'third', lat: 45, lon: 19),
];
final supercluster = SuperclusterMutable<MapPoint>(
getX: (p) => p.lon,
getY: (p) => p.lat,
extractClusterData: (customMapPoint) =>
ClusterNameData([customMapPoint.name]),
)
..load(points);
var clustersAndPoints = supercluster.search(0.0, 40, 20, 50, 5).map(
(e) =>
e.map(
cluster: (cluster) => 'cluster (${cluster.numPoints} points)',
point: (point) => 'point ${point.originalPoint}',
),
);
print(clustersAndPoints.join(', '));
// prints: cluster (2 points), point "third" (45.0, 19.0)
supercluster.add(MapPoint(name: 'fourth', lat: 45.1, lon: 18));
supercluster.remove(points[1]);
clustersAndPoints = supercluster.search(0.0, 40, 20, 50, 5).map(
(e) =>
e.map(
cluster: (cluster) => 'cluster (${cluster.numPoints} points)',
point: (point) => 'point ${point.originalPoint}'),
);
print(clustersAndPoints.join(', '));
// prints: point "third" (45.0, 19.0), point "fourth" (45.1, 18.0), point "first" (46.0, 1.5)
}