Files
infinite_lazy_grid/lib/core/spatial_hashing.dart

82 lines
2.1 KiB
Dart

import 'dart:collection';
import 'dart:math';
import 'package:flutter/material.dart';
typedef _CellKey = Point<int>;
class PointData<T> {
final Point point;
final T data;
PointData(this.point, this.data);
}
/// Data structure for spatial hashing to get widgets to be built quickly
/// based on their position in a 2D grid.
class SpatialHashing<T> {
final Size cellSize;
final HashMap<Point, T> _pointData = HashMap<Point, T>();
final HashMap<_CellKey, List<Point>> _cellMap = HashMap<_CellKey, List<Point>>();
SpatialHashing({required this.cellSize});
_CellKey _cellKey(Point point) {
int x = (point.x / cellSize.width).floor();
int y = (point.y / cellSize.height).floor();
return Point(x, y);
}
void add(Point point, T data) {
_CellKey cellKey = _cellKey(point);
_pointData[point] = data;
if (!_cellMap.containsKey(cellKey)) {
_cellMap[cellKey] = [];
}
_cellMap[cellKey]!.add(point);
}
void remove(Point point) {
final key = _cellKey(point);
if (_pointData.containsKey(point)) {
_pointData.remove(point); // remove the data
// cell map must have key then
_cellMap[key]!.remove(point); // remove from spatial hash
if (_cellMap[key]!.isEmpty) {
_cellMap.remove(key);
}
}
}
List<PointData<T>> getPointsAround(Point point, Offset offset) {
_CellKey cellKey = _cellKey(point);
List<PointData<T>> results = [];
// Calculate the range of cells to check
int startX = cellKey.x - (offset.dx / cellSize.width).floor();
int startY = cellKey.y - (offset.dy / cellSize.height).floor();
int endX = cellKey.x + (offset.dx / cellSize.width).ceil();
int endY = cellKey.y + (offset.dy / cellSize.height).ceil();
for (int x = startX; x <= endX; x++) {
for (int y = startY; y <= endY; y++) {
Point currentCellKey = Point(x, y);
if (_cellMap.containsKey(currentCellKey)) {
for (Point p in _cellMap[currentCellKey]!) {
results.add(PointData(p, _pointData[p] as T));
}
}
}
}
return results;
}
void clear() {
_pointData.clear();
_cellMap.clear();
}
}