From 547b5bac9735e0146bf3434c1ad3ef54072eb674 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Fri, 31 Jan 2025 06:24:51 +0000 Subject: [PATCH] use an immutable vector (always of length 4) for representing quad tree's internal nodes --- fcore/quad-tree-fold.sml | 13 +++++--- fcore/quad-tree-type.sml | 20 +++++++----- fcore/quad-tree.sml | 68 ++++++++++++++++++++-------------------- 3 files changed, 54 insertions(+), 47 deletions(-) diff --git a/fcore/quad-tree-fold.sml b/fcore/quad-tree-fold.sml index 9947bfa..4a71fca 100644 --- a/fcore/quad-tree-fold.sml +++ b/fcore/quad-tree-fold.sml @@ -38,14 +38,17 @@ struct fun foldRegion (rx, ry, rw, rh, env, state, tree) = case tree of - NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => + NODE {nodes, x, y, w, h} => if isCollidingPlus (rx, ry, rw, rh, x, y, w, h) then let - val state = foldRegion (rx, ry, rw, rh, env, state, topLeft) - val state = foldRegion (rx, ry, rw, rh, env, state, topRight) - val state = foldRegion (rx, ry, rw, rh, env, state, bottomLeft) + val state = + foldRegion (rx, ry, rw, rh, env, state, Vector.sub (nodes, tlIdx)) + val state = + foldRegion (rx, ry, rw, rh, env, state, Vector.sub (nodes, trIdx)) + val state = + foldRegion (rx, ry, rw, rh, env, state, Vector.sub (nodes, blIdx)) in - foldRegion (rx, ry, rw, rh, env, state, bottomRight) + foldRegion (rx, ry, rw, rh, env, state, Vector.sub (nodes, brIdx)) end else state diff --git a/fcore/quad-tree-type.sml b/fcore/quad-tree-type.sml index fc8cca5..76f2c4a 100644 --- a/fcore/quad-tree-type.sml +++ b/fcore/quad-tree-type.sml @@ -4,10 +4,7 @@ sig datatype t = NODE of - { topLeft: t - , topRight: t - , bottomLeft: t - , bottomRight: t + { nodes: t vector , x: int , y: int , w: int @@ -15,6 +12,11 @@ sig } | LEAF of {items: item vector, x: int, y: int, w: int, h: int} + val tlIdx: int + val trIdx: int + val blIdx: int + val brIdx: int + val isColliding: int * int * int * int * int * int * int * int -> bool @@ -50,10 +52,7 @@ struct datatype t = NODE of - { topLeft: t - , topRight: t - , bottomLeft: t - , bottomRight: t + { nodes: t vector , x: int , y: int , w: int @@ -61,6 +60,11 @@ struct } | LEAF of {items: item vector, x: int, y: int, w: int, h: int} + val tlIdx = 0 + val trIdx = 1 + val blIdx = 2 + val brIdx = 3 + fun isColliding (ix, iy, ifx, ify, cx, cy, cfx, cfy) = ix < cfx andalso ifx > cx andalso iy < cfy andalso ify > cy diff --git a/fcore/quad-tree.sml b/fcore/quad-tree.sml index 8d12d71..caf7225 100644 --- a/fcore/quad-tree.sml +++ b/fcore/quad-tree.sml @@ -97,10 +97,7 @@ struct val br = mkBottomRight (x, y, w, h, br) in NODE - { topLeft = tl - , topRight = tr - , bottomLeft = bl - , bottomRight = br + { nodes = Vector.fromList [tl, tr, bl, br] , x = x , y = y , w = w @@ -130,22 +127,19 @@ struct fun insert (iX, iY, iW, iH, itemID, tree: t) = case tree of - NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => + NODE {nodes, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then let (* we are not necessarily inserting into all nodes. * If isCollidingPlus returns false recursively, * we return the same node back. *) - val tl = insert (iX, iY, iW, iH, itemID, topLeft) - val tr = insert (iX, iY, iW, iH, itemID, topRight) - val bl = insert (iX, iY, iW, iH, itemID, bottomLeft) - val br = insert (iX, iY, iW, iH, itemID, bottomRight) + val tl = insert (iX, iY, iW, iH, itemID, Vector.sub (nodes, tlIdx)) + val tr = insert (iX, iY, iW, iH, itemID, Vector.sub (nodes, trIdx)) + val bl = insert (iX, iY, iW, iH, itemID, Vector.sub (nodes, blIdx)) + val br = insert (iX, iY, iW, iH, itemID, Vector.sub (nodes, brIdx)) in NODE - { topLeft = tl - , topRight = tr - , bottomLeft = bl - , bottomRight = br + { nodes = Vector.fromList [tl, tr, bl, br] , x = x , y = y , w = w @@ -206,16 +200,19 @@ struct fun getCollisionsAll (iX, iY, iW, iH, itemID, acc, tree) = case tree of - NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => + NODE {nodes, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then let - val acc = getCollisionsAll (iX, iY, iW, iH, itemID, acc, topLeft) + val acc = + getCollisionsAll (iX, iY, iW, iH, itemID, acc, Vector.sub (nodes, tlIdx)) - val acc = getCollisionsAll (iX, iY, iW, iH, itemID, acc, topRight) + val acc = + getCollisionsAll (iX, iY, iW, iH, itemID, acc, Vector.sub (nodes, trIdx)) - val acc = getCollisionsAll (iX, iY, iW, iH, itemID, acc, bottomLeft) + val acc = + getCollisionsAll (iX, iY, iW, iH, itemID, acc, Vector.sub (nodes, blIdx)) in - getCollisionsAll (iX, iY, iW, iH, itemID, acc, bottomRight) + getCollisionsAll (iX, iY, iW, iH, itemID, acc, Vector.sub (nodes, brIdx)) end else acc @@ -227,17 +224,20 @@ struct fun helpGetCollisions (iX, iY, iW, iH, itemID, acc, tree: t) = case tree of - NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => + NODE {nodes, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then let - val acc = helpGetCollisions (iX, iY, iW, iH, itemID, acc, topLeft) + val acc = + helpGetCollisions (iX, iY, iW, iH, itemID, acc, Vector.sub (nodes, tlIdx)) - val acc = helpGetCollisions (iX, iY, iW, iH, itemID, acc, topRight) + val acc = + helpGetCollisions (iX, iY, iW, iH, itemID, acc, Vector.sub (nodes, trIdx)) - val acc = helpGetCollisions - (iX, iY, iW, iH, itemID, acc, bottomLeft) + val acc = + helpGetCollisions (iX, iY, iW, iH, itemID, acc, Vector.sub (nodes, blIdx)) in - helpGetCollisions (iX, iY, iW, iH, itemID, acc, bottomRight) + helpGetCollisions + (iX, iY, iW, iH, itemID, acc, Vector.sub (nodes, brIdx)) end else acc @@ -263,12 +263,12 @@ struct fun hasCollisionAt (iX, iY, iW, iH, itemID, tree) = case tree of - NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => + NODE {nodes, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then - hasCollisionAt (iX, iY, iW, iH, itemID, topLeft) - orelse hasCollisionAt (iX, iY, iW, iH, itemID, topRight) - orelse hasCollisionAt (iX, iY, iW, iH, itemID, bottomLeft) - orelse hasCollisionAt (iX, iY, iW, iH, itemID, bottomRight) + hasCollisionAt (iX, iY, iW, iH, itemID, Vector.sub (nodes, tlIdx)) + orelse hasCollisionAt (iX, iY, iW, iH, itemID, Vector.sub (nodes, trIdx)) + orelse hasCollisionAt (iX, iY, iW, iH, itemID, Vector.sub (nodes, blIdx)) + orelse hasCollisionAt (iX, iY, iW, iH, itemID, Vector.sub (nodes, brIdx)) else false | LEAF {items, x, y, w, h} => @@ -290,13 +290,13 @@ struct fun getItemID (iX, iY, iW, iH, tree) = case tree of - NODE {topLeft, topRight, bottomLeft, bottomRight, x, y, w, h} => + NODE {nodes, x, y, w, h} => if isCollidingPlus (iX, iY, iW, iH, x, y, w, h) then let - val try1 = getItemID (iX, iY, iW, iH, topLeft) - val try2 = getItemID (iX, iY, iW, iH, topRight) - val try3 = getItemID (iX, iY, iW, iH, bottomLeft) - val try4 = getItemID (iX, iY, iW, iH, bottomRight) + val try1 = getItemID (iX, iY, iW, iH, Vector.sub (nodes, tlIdx)) + val try2 = getItemID (iX, iY, iW, iH, Vector.sub (nodes, trIdx)) + val try3 = getItemID (iX, iY, iW, iH, Vector.sub (nodes, blIdx)) + val try4 = getItemID (iX, iY, iW, iH, Vector.sub (nodes, brIdx)) (* get max: we assume query was narrow enough * that only one ID is valid *)