From fb2bc76c10fb09e69a123701fef76afe2b9a0ae2 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Mon, 7 Jul 2025 23:08:47 +0100 Subject: [PATCH] code search function to query quad tree --- dotscape | Bin 978656 -> 978656 bytes fcore/quad-tree.sml | 113 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/dotscape b/dotscape index bc874a5dd22f5918e66bf08d224719715b34e383..aa50f151463574ba7b1a7b5dedb47a199461d3b8 100755 GIT binary patch delta 9512 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 diff --git a/fcore/quad-tree.sml b/fcore/quad-tree.sml index fad93ec..48a98c7 100644 --- a/fcore/quad-tree.sml +++ b/fcore/quad-tree.sml @@ -244,4 +244,117 @@ struct Vector.concat vec end end + + (* building and querying quad tree, plus compression *) + datatype quad_tree = + LEAF of {x: int, y: int, ex: int, ey: int, data: int} + | NODE of {tl: quad_tree, tr: quad_tree, bl: quad_tree, br: quad_tree} + | EMPTY + + fun buildTree (x, y, size, grid) = + if x >= Vector.length grid orelse y >= Vector.length grid then + EMPTY + else if quadHasSameColour (x, y, x + size, y + size, grid) then + let + val yAxis = Vector.sub (grid, x) + val data = Vector.sub (yAxis, y) + in + if data = ignoreData then + EMPTY + else + let + val ex = x + size + val ey = y + size + in + LEAF {x = x, y = y, ex = ex, ey = ey, data = data} + end + end + else + (if size mod 2 = 0 orelse size = 1 then + let + val halfSize = size div 2 + val tl = buildTree (x, y, halfSize, grid) + val tr = buildTree (x + halfSize, y, halfSize, grid) + val bl = buildTree (x, y + halfSize, halfSize, grid) + val br = buildTree (x + halfSize, y + halfSize, halfSize, grid) + in + NODE {tl = tl, tr = tr, bl = bl, br = br} + end + else + (* handles odd-number divisions. + * For example, `7 div 2` is 3 because of integer division. + * We would not cover every pixel unless we handle odd numbers specially. *) + let + val halfSizeBefore = size div 2 + val halfSizeAfter = (size + 1) div 2 + val tl = buildTree (x, y, halfSizeAfter, grid) + val tr = buildTree (x + halfSizeBefore, y, halfSizeAfter, grid) + val bl = buildTree (x, y + halfSizeBefore, halfSizeAfter, grid) + val br = + buildTree + (x + halfSizeBefore, y + halfSizeBefore, halfSizeAfter, grid) + in + NODE {tl = tl, tr = tr, bl = bl, br = br} + end) + + fun getItemWithDataAt (x, y, qx, qy, size, tree, data) = + case tree of + EMPTY => NONE + | LEAF (item as {x = ix, y = iy, ex = iex, ey = iey, data = oldData}) => + if data = oldData then + (* data matches *) + if (x >= ix andalso x <= iex) andalso (y >= iy andalso y <= iey) then + (* search coordinates are in item *) + SOME item + else + NONE + else + NONE + | NODE {tl, tr, bl, br} => + if size mod 2 = 0 orelse size = 1 then + let + val halfSize = size div 2 + val qmx = x + halfSize + val qfx = x + size + val qmy = y + halfSize + val qfy = y + size + in + if y >= qy andalso y <= qmy then + (* top *) + if x >= qx andalso x <= qmx then + (* top left *) + getItemWithDataAt (x, y, qx, qy, halfSize, tl, data) + else + (* top right *) + getItemWithDataAt (x, y, qx + halfSize, qy, halfSize, tr, data) + else (* bottom *) if x >= qx andalso x <= qmx then + (* bottom left *) + getItemWithDataAt (x, y, qx, qy + halfSize, halfSize, bl, data) + else + (* bottom right *) + getItemWithDataAt + (x, y, qx + halfSize, qy + halfSize, halfSize, br, data) + end + else + let + val halfSizeBefore = size div 2 + val halfSizeAfter = (size + 1) div 2 + val qmx = x + halfSizeBefore + val qmy = y + halfSizeBefore + in + if y >= qy andalso y <= qmy then + (* top *) + if x >= qx andalso x <= qmx then + (* top left *) + getItemWithDataAt (x, y, qx, qy, halfSizeAfter, tl, data) + else + (* top right *) + getItemWithDataAt (x, y, qmx, qy, halfSizeAfter, tr, data) + else (* bottom *) if x >= qx andalso x <= qmx then + (* bottom left *) + getItemWithDataAt (x, y, qx, qmy, halfSizeAfter, bl, data) + else + (* bottom right *) + getItemWithDataAt (x, y, qmx, qmy, halfSizeAfter, br, data) + end end