49 lines
1.1 KiB
TypeScript
49 lines
1.1 KiB
TypeScript
import RBush from 'rbush';
|
|
import type { BoundingBox, CADElement } from '../types/cad.types';
|
|
|
|
interface IndexedItem extends BoundingBox {
|
|
element: CADElement;
|
|
}
|
|
|
|
export class SpatialIndex {
|
|
private tree: RBush<IndexedItem>;
|
|
|
|
constructor() {
|
|
this.tree = new RBush<IndexedItem>();
|
|
}
|
|
|
|
insert(element: CADElement): void {
|
|
const bbox = this.elementBBox(element);
|
|
this.tree.insert({ ...bbox, element });
|
|
}
|
|
|
|
bulkInsert(elements: CADElement[]): void {
|
|
const items = elements.map(el => ({ ...this.elementBBox(el), element: el }));
|
|
this.tree.load(items);
|
|
}
|
|
|
|
search(viewport: BoundingBox): CADElement[] {
|
|
return this.tree.search(viewport).map(item => item.element);
|
|
}
|
|
|
|
remove(element: CADElement): void {
|
|
const bbox = this.elementBBox(element);
|
|
this.tree.remove({ ...bbox, element }, (a, b) => a.element.id === b.element.id);
|
|
}
|
|
|
|
clear(): void {
|
|
this.tree.clear();
|
|
}
|
|
|
|
private elementBBox(el: CADElement): BoundingBox {
|
|
const halfW = el.width / 2;
|
|
const halfH = el.height / 2;
|
|
return {
|
|
minX: el.x - halfW,
|
|
minY: el.y - halfH,
|
|
maxX: el.x + halfW,
|
|
maxY: el.y + halfH,
|
|
};
|
|
}
|
|
}
|