Skip to content
Open
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
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export {
QuadTree,
Rectangle
};

32 changes: 16 additions & 16 deletions src/quad-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ export class QuadTree<T extends Rectangle> {
*/
public retrieve(from: Rectangle | Point, logging: boolean = false): Array<T> {
if (from instanceof Point) {
if (!this.rect.contains(from)) {
if (!Rectangle.contains(this.rect, from)) {
return [];
}
}

if (from instanceof Rectangle) {
if (!this.rect.intersects(from)) {
if (!Rectangle.intersects(this.rect, from)) {
return [];
}
}
Expand Down Expand Up @@ -108,11 +108,11 @@ export class QuadTree<T extends Rectangle> {

const intersectingNodes = this.nodes.filter((node) => {
if (from instanceof Point) {
return node.contains(from);
return Rectangle.contains(node, from);
}

if (from instanceof Rectangle) {
return node.intersects(from);
return Rectangle.intersects(node, from);
}

return false;
Expand Down Expand Up @@ -148,33 +148,34 @@ export class QuadTree<T extends Rectangle> {
* Since this function performs an operation on the tree, it will also notify all subscribers that a delete operation has occured
* and will provide the value passed to this function.
*/
public delete(at: Rectangle | Point) {
public delete(at: Rectangle | Point, shouldEmitEvent: boolean = true) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are still passing a rectangle, so this doesn't accomplish anything other than no longer creating an extra function on the rectangle when it is made. This seems like a premature optimization to me. In addition, every change should trigger events, it is up to subscribers to determine whether the event is relevant. Think of it like a proxy, the caller of this function should not be aware that there are any subscribers in my opinion - the same as any other store that has a subscriber. If you want to avoid an infinite loop of events.

this._delete(at);
if (!shouldEmitEvent) return;
for (const subscriber of this.subscriptions) {
subscriber({ type: "delete", node: at });
}
}

private _delete(at: Rectangle | Point): void {
if (at instanceof Point) {
if (!this.rect.contains(at)) {
if (!Rectangle.contains(this.rect, at)) {
return;
}
}

if (at instanceof Rectangle) {
if (!this.rect.intersects(at)) {
if (!Rectangle.intersects(this.rect, at)) {
return;
}
}

this.nodes = this.nodes.filter((node) => {
if (at instanceof Point) {
return !node.contains(at);
return !Rectangle.contains(node, at);
}

if (at instanceof Rectangle) {
return !node.intersects(at);
return !Rectangle.intersects(node, at);
}

return true;
Expand All @@ -197,7 +198,7 @@ export class QuadTree<T extends Rectangle> {
return;
}

if (!this.rect.intersects(node)) {
if (!Rectangle.intersects(this.rect,node)) {
if (!this.isRoot)
return QUAD_CODES.NODE_NOT_WITHIN_BOUNDS;

Expand Down Expand Up @@ -292,12 +293,11 @@ export class QuadTree<T extends Rectangle> {
* Returns the number of children that the current node intersects with.
*/
private childIntersections(node: T) {
const intersections = [
this.topLeft!.rect.intersects(node),
this.topRight!.rect.intersects(node),
this.bottomLeft!.rect.intersects(node),
this.bottomRight!.rect.intersects(node)
]
const intersections: boolean[] = []
if (this.topLeft) intersections.push(Rectangle.intersects(this.topLeft.rect, node))
if (this.topRight) intersections.push(Rectangle.intersects(this.topRight.rect, node))
if (this.bottomLeft) intersections.push(Rectangle.intersects(this.bottomLeft.rect, node))
if (this.bottomRight) intersections.push(Rectangle.intersects(this.bottomRight.rect, node))

return intersections.filter(Boolean).length;
}
Expand Down
20 changes: 10 additions & 10 deletions src/rectangle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@ export class Rectangle {
public height: number
) {}

public contains(point: Point): boolean {
static contains(thisRect: Rectangle, point: Point): boolean {
return (
point.x >= this.x - this.width / 2 &&
point.x <= this.x + this.width / 2 &&
point.y >= this.y - this.height / 2 &&
point.y <= this.y + this.height / 2
point.x >= thisRect.x - thisRect.width / 2 &&
point.x <= thisRect.x + thisRect.width / 2 &&
point.y >= thisRect.y - thisRect.height / 2 &&
point.y <= thisRect.y + thisRect.height / 2
)
}

public intersects(rect: Rectangle): boolean {
static intersects(thisRect:Rectangle, rect: Rectangle): boolean {
return !(
rect.x - (rect.width / 2) > this.x + (this.width / 2) ||
rect.x + (rect.width / 2) < this.x - (this.width / 2) ||
rect.y - (rect.height / 2) > this.y + (this.height / 2) ||
rect.y + (rect.height / 2) < this.y - (this.height / 2)
rect.x - (rect.width / 2) > thisRect.x + (thisRect.width / 2) ||
rect.x + (rect.width / 2) < thisRect.x - (thisRect.width / 2) ||
rect.y - (rect.height / 2) > thisRect.y + (thisRect.height / 2) ||
rect.y + (rect.height / 2) < thisRect.y - (thisRect.height / 2)
)
}

Expand Down