fully restructure quad tree from one that holds overlapping items in parent nodes, into one that holds overlapping items in each quadrant instead
This commit is contained in:
@@ -71,12 +71,9 @@ struct
|
|||||||
, tree: QuadTreeType.t
|
, tree: QuadTreeType.t
|
||||||
) =
|
) =
|
||||||
case tree of
|
case tree of
|
||||||
NODE {topLeft, topRight, bottomLeft, bottomRight, elements} =>
|
NODE {topLeft, topRight, bottomLeft, bottomRight} =>
|
||||||
let
|
let
|
||||||
(* fold over intersecting elements in this vector first *)
|
(* fold over intersecting elements in this vector first *)
|
||||||
val state = foldVec
|
|
||||||
(itemX, itemY, itemW, itemH, 0, elements, state, env)
|
|
||||||
|
|
||||||
val halfW = quadW div 2
|
val halfW = quadW div 2
|
||||||
val halfH = quadH div 2
|
val halfH = quadH div 2
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,7 @@ sig
|
|||||||
type item = {itemID: int, startX: int, startY: int, width: int, height: int}
|
type item = {itemID: int, startX: int, startY: int, width: int, height: int}
|
||||||
|
|
||||||
datatype t =
|
datatype t =
|
||||||
NODE of
|
NODE of {topLeft: t, topRight: t, bottomLeft: t, bottomRight: t}
|
||||||
{ topLeft: t
|
|
||||||
, topRight: t
|
|
||||||
, bottomLeft: t
|
|
||||||
, bottomRight: t
|
|
||||||
, elements: item vector
|
|
||||||
}
|
|
||||||
| LEAF of item vector
|
| LEAF of item vector
|
||||||
|
|
||||||
datatype quadrant =
|
datatype quadrant =
|
||||||
@@ -25,13 +19,7 @@ struct
|
|||||||
type item = {itemID: int, startX: int, startY: int, width: int, height: int}
|
type item = {itemID: int, startX: int, startY: int, width: int, height: int}
|
||||||
|
|
||||||
datatype t =
|
datatype t =
|
||||||
NODE of
|
NODE of {topLeft: t, topRight: t, bottomLeft: t, bottomRight: t}
|
||||||
{ topLeft: t
|
|
||||||
, topRight: t
|
|
||||||
, bottomLeft: t
|
|
||||||
, bottomRight: t
|
|
||||||
, elements: item vector
|
|
||||||
}
|
|
||||||
| LEAF of item vector
|
| LEAF of item vector
|
||||||
|
|
||||||
datatype quadrant =
|
datatype quadrant =
|
||||||
|
|||||||
@@ -92,19 +92,19 @@ struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun itemToString {itemID, startX, startY, width, height} =
|
fun itemToString {itemID, startX, startY, width, height} =
|
||||||
String.concat [
|
String.concat
|
||||||
"{itemID = ",
|
[ "{itemID = "
|
||||||
Int.toString itemID,
|
, Int.toString itemID
|
||||||
", startX = ",
|
, ", startX = "
|
||||||
Int.toString startX,
|
, Int.toString startX
|
||||||
", startY = ",
|
, ", startY = "
|
||||||
Int.toString startY,
|
, Int.toString startY
|
||||||
", width = ",
|
, ", width = "
|
||||||
Int.toString width,
|
, Int.toString width
|
||||||
", height = ",
|
, ", height = "
|
||||||
Int.toString height,
|
, Int.toString height
|
||||||
"}"
|
, "}"
|
||||||
]
|
]
|
||||||
|
|
||||||
type t = QuadTreeType.t
|
type t = QuadTreeType.t
|
||||||
|
|
||||||
@@ -186,44 +186,40 @@ struct
|
|||||||
else PARENT_QUADRANT
|
else PARENT_QUADRANT
|
||||||
end
|
end
|
||||||
|
|
||||||
fun splitLeaf (qX, qY, qW, qH, tl, tr, bl, br, pe, elements, pos) =
|
fun splitLeaf (qX, qY, qW, qH, tl, tr, bl, br, elements, pos) =
|
||||||
if pos < 0 then
|
if pos < 0 then
|
||||||
let
|
let
|
||||||
val tl = Vector.fromList tl
|
val tl = Vector.fromList tl
|
||||||
val tr = Vector.fromList tr
|
val tr = Vector.fromList tr
|
||||||
val bl = Vector.fromList bl
|
val bl = Vector.fromList bl
|
||||||
val br = Vector.fromList br
|
val br = Vector.fromList br
|
||||||
val pe = Vector.fromList pe
|
|
||||||
in
|
in
|
||||||
NODE
|
NODE
|
||||||
{ topLeft = LEAF tl
|
{ topLeft = LEAF tl
|
||||||
, topRight = LEAF tr
|
, topRight = LEAF tr
|
||||||
, bottomLeft = LEAF bl
|
, bottomLeft = LEAF bl
|
||||||
, bottomRight = LEAF br
|
, bottomRight = LEAF br
|
||||||
, elements = pe
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
val item = Vector.sub (elements, pos)
|
val item = Vector.sub (elements, pos)
|
||||||
val {startX = iX, startY = iY, width = iW, height = iH, ...} = item
|
val {startX = iX, startY = iY, width = iW, height = iH, ...} = item
|
||||||
|
|
||||||
|
val vtl = visitTopLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
val vtr = visitTopRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
|
||||||
|
val tl = if vtl then item :: tl else tl
|
||||||
|
|
||||||
|
val tr = if vtr then item :: tr else tr
|
||||||
|
|
||||||
|
val bl = if vbl then item :: bl else bl
|
||||||
|
|
||||||
|
val br = if vbr then item :: br else br
|
||||||
in
|
in
|
||||||
case whichQuadrant (iX, iY, iW, iH, qX, qY, qW, qH) of
|
splitLeaf (qX, qY, qW, qH, tl, tr, bl, br, elements, pos - 1)
|
||||||
TOP_LEFT =>
|
|
||||||
splitLeaf
|
|
||||||
(qX, qY, qW, qH, item :: tl, tr, bl, br, pe, elements, pos - 1)
|
|
||||||
| TOP_RIGHT =>
|
|
||||||
splitLeaf
|
|
||||||
(qX, qY, qW, qH, tl, item :: tr, bl, br, pe, elements, pos - 1)
|
|
||||||
| BOTTOM_LEFT =>
|
|
||||||
splitLeaf
|
|
||||||
(qX, qY, qW, qH, tl, tr, item :: bl, br, pe, elements, pos - 1)
|
|
||||||
| BOTTOM_RIGHT =>
|
|
||||||
splitLeaf
|
|
||||||
(qX, qY, qW, qH, tl, tr, bl, item :: br, pe, elements, pos - 1)
|
|
||||||
| PARENT_QUADRANT =>
|
|
||||||
splitLeaf
|
|
||||||
(qX, qY, qW, qH, tl, tr, bl, br, item :: pe, elements, pos - 1)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
fun insert
|
fun insert
|
||||||
@@ -239,238 +235,110 @@ struct
|
|||||||
, tree: t
|
, tree: t
|
||||||
) =
|
) =
|
||||||
case tree of
|
case tree of
|
||||||
NODE {topLeft, topRight, bottomLeft, bottomRight, elements} =>
|
NODE {topLeft, topRight, bottomLeft, bottomRight} =>
|
||||||
(* check which quadrant item is in, if any.
|
let
|
||||||
* If in any child quadrants, recurse insertion into there.
|
val halfW = quadWidth div 2
|
||||||
* Else, add to elements vector in current node. *)
|
val halfH = quadHeight div 2
|
||||||
(case
|
|
||||||
whichQuadrant
|
|
||||||
( itemX
|
|
||||||
, itemY
|
|
||||||
, itemWidth
|
|
||||||
, itemHeight
|
|
||||||
, quadX
|
|
||||||
, quadY
|
|
||||||
, quadWidth
|
|
||||||
, quadHeight
|
|
||||||
)
|
|
||||||
of
|
|
||||||
TOP_LEFT =>
|
|
||||||
let
|
|
||||||
(* I know I am repeating myself by recalculating
|
|
||||||
* halfWidth/halfHeight in case branches but I prefer this
|
|
||||||
* over increating the indentation level further
|
|
||||||
* *)
|
|
||||||
val halfWidth = quadWidth div 2
|
|
||||||
val halfHeight = quadHeight div 2
|
|
||||||
|
|
||||||
val newTopLeft = insert
|
val midX = halfW + quadX
|
||||||
( itemX
|
val midY = halfH + quadY
|
||||||
, itemY
|
|
||||||
, itemWidth
|
|
||||||
, itemHeight
|
|
||||||
, quadX
|
|
||||||
, quadY
|
|
||||||
, halfWidth
|
|
||||||
, halfHeight
|
|
||||||
, itemID
|
|
||||||
, topLeft
|
|
||||||
)
|
|
||||||
in
|
|
||||||
NODE
|
|
||||||
{ topLeft = newTopLeft
|
|
||||||
, topRight = topRight
|
|
||||||
, bottomLeft = bottomLeft
|
|
||||||
, bottomRight = bottomRight
|
|
||||||
, elements = elements
|
|
||||||
}
|
|
||||||
end
|
|
||||||
| TOP_RIGHT =>
|
|
||||||
let
|
|
||||||
val halfWidth = quadWidth div 2
|
|
||||||
val halfHeight = quadHeight div 2
|
|
||||||
val middleX = quadX + halfWidth
|
|
||||||
|
|
||||||
val newTopRight = insert
|
val iX = itemX
|
||||||
( itemX
|
val iY = itemY
|
||||||
, itemY
|
val iW = itemWidth
|
||||||
, itemWidth
|
val iH = itemHeight
|
||||||
, itemHeight
|
|
||||||
, middleX
|
|
||||||
, quadY
|
|
||||||
, halfWidth
|
|
||||||
, halfHeight
|
|
||||||
, itemID
|
|
||||||
, topRight
|
|
||||||
)
|
|
||||||
in
|
|
||||||
NODE
|
|
||||||
{ topLeft = topLeft
|
|
||||||
, topRight = newTopRight
|
|
||||||
, bottomLeft = bottomLeft
|
|
||||||
, bottomRight = bottomRight
|
|
||||||
, elements = elements
|
|
||||||
}
|
|
||||||
end
|
|
||||||
| BOTTOM_LEFT =>
|
|
||||||
let
|
|
||||||
val halfWidth = quadWidth div 2
|
|
||||||
val halfHeight = quadHeight div 2
|
|
||||||
val middleY = quadY + halfHeight
|
|
||||||
|
|
||||||
val newBottomLeft = insert
|
val qX = quadX
|
||||||
( itemX
|
val qY = quadY
|
||||||
, itemY
|
val qW = quadWidth
|
||||||
, itemWidth
|
val qH = quadHeight
|
||||||
, itemHeight
|
|
||||||
, quadX
|
|
||||||
, middleY
|
|
||||||
, halfWidth
|
|
||||||
, halfHeight
|
|
||||||
, itemID
|
|
||||||
, bottomLeft
|
|
||||||
)
|
|
||||||
in
|
|
||||||
NODE
|
|
||||||
{ topLeft = topLeft
|
|
||||||
, topRight = topRight
|
|
||||||
, bottomLeft = newBottomLeft
|
|
||||||
, bottomRight = bottomRight
|
|
||||||
, elements = elements
|
|
||||||
}
|
|
||||||
end
|
|
||||||
| BOTTOM_RIGHT =>
|
|
||||||
let
|
|
||||||
val halfWidth = quadWidth div 2
|
|
||||||
val halfHeight = quadHeight div 2
|
|
||||||
val middleX = quadX + halfWidth
|
|
||||||
val middleY = quadY + halfHeight
|
|
||||||
|
|
||||||
val newBottomRight = insert
|
val vtl = visitTopLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
( itemX
|
val vtr = visitTopRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
, itemY
|
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
, itemWidth
|
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
, itemHeight
|
|
||||||
, middleX
|
val tl =
|
||||||
, middleY
|
if vtl then
|
||||||
, halfWidth
|
insert (iX, iY, iW, iH, qX, qY, halfW, halfH, itemID, topLeft)
|
||||||
, halfHeight
|
else
|
||||||
, itemID
|
topLeft
|
||||||
, bottomRight
|
|
||||||
)
|
val tr =
|
||||||
in
|
if vtr then
|
||||||
NODE
|
insert (iX, iY, iW, iH, midX, qY, halfW, halfH, itemID, topRight)
|
||||||
{ topLeft = topLeft
|
else
|
||||||
, topRight = topRight
|
topRight
|
||||||
, bottomLeft = bottomLeft
|
|
||||||
, bottomRight = newBottomRight
|
val bl =
|
||||||
, elements = elements
|
if vbl then
|
||||||
}
|
insert
|
||||||
end
|
(iX, iY, iW, iH, qX, midY, halfW, halfH, itemID, bottomLeft)
|
||||||
| PARENT_QUADRANT =>
|
else
|
||||||
(* Does not fit in any of the child quadrants
|
bottomLeft
|
||||||
* so we must add to the current parent quadrant. *)
|
|
||||||
let
|
val br =
|
||||||
val item = mkItem (itemID, itemX, itemY, itemWidth, itemHeight)
|
if vbr then
|
||||||
val elements = Vector.concat [elements, Vector.fromList [item]]
|
insert
|
||||||
in
|
(iX, iY, iW, iH, midX, midY, halfW, halfH, itemID, bottomRight)
|
||||||
NODE
|
else
|
||||||
{ topLeft = topLeft
|
bottomRight
|
||||||
, topRight = topRight
|
in
|
||||||
, bottomLeft = bottomLeft
|
NODE {topLeft = tl, topRight = tr, bottomLeft = bl, bottomRight = br}
|
||||||
, bottomRight = bottomRight
|
end
|
||||||
, elements = elements
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
| LEAF elements =>
|
| LEAF elements =>
|
||||||
if Vector.length elements + 1 > maxSize then
|
if Vector.length elements + 1 > maxSize then
|
||||||
(* have to calculate quadrants and split *)
|
(* have to calculate quadrants and split *)
|
||||||
let
|
let
|
||||||
val pos = Vector.length elements - 1
|
val pos = Vector.length elements - 1
|
||||||
val item = mkItem (itemID, itemX, itemY, itemWidth, itemHeight)
|
val item = mkItem (itemID, itemX, itemY, itemWidth, itemHeight)
|
||||||
|
|
||||||
|
val halfW = quadWidth div 2
|
||||||
|
val halfH = quadHeight div 2
|
||||||
|
|
||||||
|
val midX = halfW + quadX
|
||||||
|
val midY = halfH + quadY
|
||||||
|
|
||||||
|
val iX = itemX
|
||||||
|
val iY = itemY
|
||||||
|
val iW = itemWidth
|
||||||
|
val iH = itemHeight
|
||||||
|
|
||||||
|
val qX = quadX
|
||||||
|
val qY = quadY
|
||||||
|
val qW = quadWidth
|
||||||
|
val qH = quadHeight
|
||||||
|
|
||||||
|
val vtl = visitTopLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
val vtr = visitTopRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
|
||||||
|
val pos = Vector.length elements - 1
|
||||||
|
val item = mkItem (itemID, itemX, itemY, itemWidth, itemHeight)
|
||||||
|
|
||||||
|
val tl = if vtl then [item] else []
|
||||||
|
|
||||||
|
val tr = if vtr then [item] else []
|
||||||
|
|
||||||
|
val bl = if vbl then [item] else []
|
||||||
|
|
||||||
|
val br = if vbr then [item] else []
|
||||||
|
|
||||||
|
val pe = []
|
||||||
in
|
in
|
||||||
(case
|
splitLeaf
|
||||||
whichQuadrant
|
( quadX
|
||||||
( itemX
|
, quadY
|
||||||
, itemY
|
, quadWidth
|
||||||
, itemWidth
|
, quadHeight
|
||||||
, itemHeight
|
, tl
|
||||||
, quadX
|
, tr
|
||||||
, quadY
|
, bl
|
||||||
, quadWidth
|
, br
|
||||||
, quadHeight
|
, elements
|
||||||
)
|
, pos
|
||||||
of
|
)
|
||||||
TOP_LEFT =>
|
|
||||||
splitLeaf
|
|
||||||
( quadX
|
|
||||||
, quadY
|
|
||||||
, quadWidth
|
|
||||||
, quadHeight
|
|
||||||
, [item]
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, elements
|
|
||||||
, pos
|
|
||||||
)
|
|
||||||
| TOP_RIGHT =>
|
|
||||||
splitLeaf
|
|
||||||
( quadX
|
|
||||||
, quadY
|
|
||||||
, quadWidth
|
|
||||||
, quadHeight
|
|
||||||
, []
|
|
||||||
, [item]
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, elements
|
|
||||||
, pos
|
|
||||||
)
|
|
||||||
| BOTTOM_LEFT =>
|
|
||||||
splitLeaf
|
|
||||||
( quadX
|
|
||||||
, quadY
|
|
||||||
, quadWidth
|
|
||||||
, quadHeight
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, [item]
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, elements
|
|
||||||
, pos
|
|
||||||
)
|
|
||||||
| BOTTOM_RIGHT =>
|
|
||||||
splitLeaf
|
|
||||||
( quadX
|
|
||||||
, quadY
|
|
||||||
, quadWidth
|
|
||||||
, quadHeight
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, [item]
|
|
||||||
, []
|
|
||||||
, elements
|
|
||||||
, pos
|
|
||||||
)
|
|
||||||
| PARENT_QUADRANT =>
|
|
||||||
splitLeaf
|
|
||||||
( quadX
|
|
||||||
, quadY
|
|
||||||
, quadWidth
|
|
||||||
, quadHeight
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, []
|
|
||||||
, [item]
|
|
||||||
, elements
|
|
||||||
, pos
|
|
||||||
))
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
(* can insert itemID in elements vector *)
|
(* can insert itemID in elements vector *)
|
||||||
@@ -502,9 +370,8 @@ struct
|
|||||||
val endX = startX + width
|
val endX = startX + width
|
||||||
val endY = startY + height
|
val endY = startY + height
|
||||||
in
|
in
|
||||||
isBetween (iX, startX, itemEndX, endX) andalso
|
isBetween (iX, startX, itemEndX, endX)
|
||||||
isBetween (iY, startY, itemEndY, endY) andalso
|
andalso isBetween (iY, startY, itemEndY, endY) andalso itemID <> checkID
|
||||||
itemID <> checkID
|
|
||||||
end
|
end
|
||||||
|
|
||||||
fun getCollisionsVec (iX, iY, iW, iH, itemID, pos, elements, acc) =
|
fun getCollisionsVec (iX, iY, iW, iH, itemID, pos, elements, acc) =
|
||||||
@@ -522,9 +389,8 @@ struct
|
|||||||
|
|
||||||
fun getCollisionsAll (iX, iY, iW, iH, qW, qH, itemID, acc, tree) =
|
fun getCollisionsAll (iX, iY, iW, iH, qW, qH, itemID, acc, tree) =
|
||||||
case tree of
|
case tree of
|
||||||
NODE {topLeft, topRight, bottomLeft, bottomRight, elements} =>
|
NODE {topLeft, topRight, bottomLeft, bottomRight} =>
|
||||||
let
|
let
|
||||||
val acc = getCollisionsVec (iX, iY, iW, iH, itemID, 0, elements, acc)
|
|
||||||
val halfWidth = qW div 2
|
val halfWidth = qW div 2
|
||||||
val halfHeight = qH div 2
|
val halfHeight = qH div 2
|
||||||
|
|
||||||
@@ -557,12 +423,8 @@ struct
|
|||||||
, tree: t
|
, tree: t
|
||||||
) =
|
) =
|
||||||
case tree of
|
case tree of
|
||||||
NODE {topLeft, topRight, bottomLeft, bottomRight, elements} =>
|
NODE {topLeft, topRight, bottomLeft, bottomRight} =>
|
||||||
let
|
let
|
||||||
(* get colliding elements in this node first *)
|
|
||||||
val acc = getCollisionsVec
|
|
||||||
(itemX, itemY, itemWidth, itemHeight, itemID, 0, elements, acc)
|
|
||||||
|
|
||||||
val halfW = quadWidth div 2
|
val halfW = quadWidth div 2
|
||||||
val halfH = quadHeight div 2
|
val halfH = quadHeight div 2
|
||||||
|
|
||||||
@@ -584,29 +446,55 @@ struct
|
|||||||
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vtl then
|
if vtl then
|
||||||
helpGetCollisions
|
helpGetCollisions
|
||||||
(iX, iY, iW, iH, qX, qY, halfW, halfH, itemID, acc, topLeft)
|
(iX, iY, iW, iH, qX, qY, halfW, halfH, itemID, acc, topLeft)
|
||||||
else acc
|
else
|
||||||
|
acc
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vtr then
|
if vtr then
|
||||||
helpGetCollisions
|
helpGetCollisions
|
||||||
(iX, iY, iW, iH, midX, qY, halfW, halfH, itemID, acc, topRight)
|
(iX, iY, iW, iH, midX, qY, halfW, halfH, itemID, acc, topRight)
|
||||||
else acc
|
else
|
||||||
|
acc
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vbl then
|
if vbl then
|
||||||
helpGetCollisions
|
helpGetCollisions
|
||||||
(iX, iY, iW, iH, qX, midY, halfW, halfH, itemID, acc, bottomLeft)
|
( iX
|
||||||
else acc
|
, iY
|
||||||
|
, iW
|
||||||
|
, iH
|
||||||
|
, qX
|
||||||
|
, midY
|
||||||
|
, halfW
|
||||||
|
, halfH
|
||||||
|
, itemID
|
||||||
|
, acc
|
||||||
|
, bottomLeft
|
||||||
|
)
|
||||||
|
else
|
||||||
|
acc
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vbl then
|
if vbl then
|
||||||
helpGetCollisions
|
helpGetCollisions
|
||||||
(iX, iY, iW, iH, midX, midY, halfW, halfH, itemID, acc, bottomRight)
|
( iX
|
||||||
else acc
|
, iY
|
||||||
|
, iW
|
||||||
|
, iH
|
||||||
|
, midX
|
||||||
|
, midY
|
||||||
|
, halfW
|
||||||
|
, halfH
|
||||||
|
, itemID
|
||||||
|
, acc
|
||||||
|
, bottomRight
|
||||||
|
)
|
||||||
|
else
|
||||||
|
acc
|
||||||
in
|
in
|
||||||
acc
|
acc
|
||||||
end
|
end
|
||||||
@@ -710,10 +598,8 @@ struct
|
|||||||
|
|
||||||
fun getCollisionSidesAll (iX, iY, iW, iH, qW, qH, itemID, acc, tree) =
|
fun getCollisionSidesAll (iX, iY, iW, iH, qW, qH, itemID, acc, tree) =
|
||||||
case tree of
|
case tree of
|
||||||
NODE {topLeft, topRight, bottomLeft, bottomRight, elements} =>
|
NODE {topLeft, topRight, bottomLeft, bottomRight} =>
|
||||||
let
|
let
|
||||||
val acc = getCollisionSideVec
|
|
||||||
(iX, iY, iW, iH, itemID, 0, elements, acc)
|
|
||||||
val halfWidth = qW div 2
|
val halfWidth = qW div 2
|
||||||
val halfHeight = qH div 2
|
val halfHeight = qH div 2
|
||||||
|
|
||||||
@@ -746,12 +632,8 @@ struct
|
|||||||
, tree: t
|
, tree: t
|
||||||
) =
|
) =
|
||||||
case tree of
|
case tree of
|
||||||
NODE {topLeft, topRight, bottomLeft, bottomRight, elements} =>
|
NODE {topLeft, topRight, bottomLeft, bottomRight} =>
|
||||||
let
|
let
|
||||||
(* get colliding elements in this node first *)
|
|
||||||
val acc = getCollisionSideVec
|
|
||||||
(itemX, itemY, itemWidth, itemHeight, itemID, 0, elements, acc)
|
|
||||||
|
|
||||||
val halfW = quadWidth div 2
|
val halfW = quadWidth div 2
|
||||||
val halfH = quadHeight div 2
|
val halfH = quadHeight div 2
|
||||||
|
|
||||||
@@ -773,29 +655,55 @@ struct
|
|||||||
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vtl then
|
if vtl then
|
||||||
helpGetCollisionSides
|
helpGetCollisionSides
|
||||||
(iX, iY, iW, iH, qX, qY, halfW, halfH, itemID, acc, topLeft)
|
(iX, iY, iW, iH, qX, qY, halfW, halfH, itemID, acc, topLeft)
|
||||||
else acc
|
else
|
||||||
|
acc
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vtr then
|
if vtr then
|
||||||
helpGetCollisionSides
|
helpGetCollisionSides
|
||||||
(iX, iY, iW, iH, midX, qY, halfW, halfH, itemID, acc, topRight)
|
(iX, iY, iW, iH, midX, qY, halfW, halfH, itemID, acc, topRight)
|
||||||
else acc
|
else
|
||||||
|
acc
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vbl then
|
if vbl then
|
||||||
helpGetCollisionSides
|
helpGetCollisionSides
|
||||||
(iX, iY, iW, iH, qX, midY, halfW, halfH, itemID, acc, bottomLeft)
|
( iX
|
||||||
else acc
|
, iY
|
||||||
|
, iW
|
||||||
|
, iH
|
||||||
|
, qX
|
||||||
|
, midY
|
||||||
|
, halfW
|
||||||
|
, halfH
|
||||||
|
, itemID
|
||||||
|
, acc
|
||||||
|
, bottomLeft
|
||||||
|
)
|
||||||
|
else
|
||||||
|
acc
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vbl then
|
if vbl then
|
||||||
helpGetCollisionSides
|
helpGetCollisionSides
|
||||||
(iX, iY, iW, iH, midX, midY, halfW, halfH, itemID, acc, bottomRight)
|
( iX
|
||||||
else acc
|
, iY
|
||||||
|
, iW
|
||||||
|
, iH
|
||||||
|
, midX
|
||||||
|
, midY
|
||||||
|
, halfW
|
||||||
|
, halfH
|
||||||
|
, itemID
|
||||||
|
, acc
|
||||||
|
, bottomRight
|
||||||
|
)
|
||||||
|
else
|
||||||
|
acc
|
||||||
in
|
in
|
||||||
acc
|
acc
|
||||||
end
|
end
|
||||||
@@ -851,10 +759,8 @@ struct
|
|||||||
|
|
||||||
fun getCollisionsBelowAll (iX, iY, iW, iH, qW, qH, itemID, acc, tree) =
|
fun getCollisionsBelowAll (iX, iY, iW, iH, qW, qH, itemID, acc, tree) =
|
||||||
case tree of
|
case tree of
|
||||||
NODE {topLeft, topRight, bottomLeft, bottomRight, elements} =>
|
NODE {topLeft, topRight, bottomLeft, bottomRight} =>
|
||||||
let
|
let
|
||||||
val acc = getCollisionsBelowVec
|
|
||||||
(iX, iY, iW, iH, itemID, 0, elements, acc)
|
|
||||||
val halfWidth = qW div 2
|
val halfWidth = qW div 2
|
||||||
val halfHeight = qH div 2
|
val halfHeight = qH div 2
|
||||||
|
|
||||||
@@ -887,12 +793,8 @@ struct
|
|||||||
, tree: t
|
, tree: t
|
||||||
) =
|
) =
|
||||||
case tree of
|
case tree of
|
||||||
NODE {topLeft, topRight, bottomLeft, bottomRight, elements} =>
|
NODE {topLeft, topRight, bottomLeft, bottomRight} =>
|
||||||
let
|
let
|
||||||
(* get colliding elements in this node first *)
|
|
||||||
val acc = getCollisionsBelowVec
|
|
||||||
(itemX, itemY, itemWidth, itemHeight, itemID, 0, elements, acc)
|
|
||||||
|
|
||||||
val halfW = quadWidth div 2
|
val halfW = quadWidth div 2
|
||||||
val halfH = quadHeight div 2
|
val halfH = quadHeight div 2
|
||||||
|
|
||||||
@@ -914,29 +816,55 @@ struct
|
|||||||
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vtl then
|
if vtl then
|
||||||
helpGetCollisionsBelow
|
helpGetCollisionsBelow
|
||||||
(iX, iY, iW, iH, qX, qY, halfW, halfH, itemID, acc, topLeft)
|
(iX, iY, iW, iH, qX, qY, halfW, halfH, itemID, acc, topLeft)
|
||||||
else acc
|
else
|
||||||
|
acc
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vtr then
|
if vtr then
|
||||||
helpGetCollisionsBelow
|
helpGetCollisionsBelow
|
||||||
(iX, iY, iW, iH, midX, qY, halfW, halfH, itemID, acc, topRight)
|
(iX, iY, iW, iH, midX, qY, halfW, halfH, itemID, acc, topRight)
|
||||||
else acc
|
else
|
||||||
|
acc
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vbl then
|
if vbl then
|
||||||
helpGetCollisionsBelow
|
helpGetCollisionsBelow
|
||||||
(iX, iY, iW, iH, qX, midY, halfW, halfH, itemID, acc, bottomLeft)
|
( iX
|
||||||
else acc
|
, iY
|
||||||
|
, iW
|
||||||
|
, iH
|
||||||
|
, qX
|
||||||
|
, midY
|
||||||
|
, halfW
|
||||||
|
, halfH
|
||||||
|
, itemID
|
||||||
|
, acc
|
||||||
|
, bottomLeft
|
||||||
|
)
|
||||||
|
else
|
||||||
|
acc
|
||||||
|
|
||||||
val acc =
|
val acc =
|
||||||
if vbl then
|
if vbl then
|
||||||
helpGetCollisionsBelow
|
helpGetCollisionsBelow
|
||||||
(iX, iY, iW, iH, midX, midY, halfW, halfH, itemID, acc, bottomRight)
|
( iX
|
||||||
else acc
|
, iY
|
||||||
|
, iW
|
||||||
|
, iH
|
||||||
|
, midX
|
||||||
|
, midY
|
||||||
|
, halfW
|
||||||
|
, halfH
|
||||||
|
, itemID
|
||||||
|
, acc
|
||||||
|
, bottomRight
|
||||||
|
)
|
||||||
|
else
|
||||||
|
acc
|
||||||
in
|
in
|
||||||
acc
|
acc
|
||||||
end
|
end
|
||||||
@@ -977,16 +905,15 @@ struct
|
|||||||
let
|
let
|
||||||
val item = Vector.sub (elements, pos)
|
val item = Vector.sub (elements, pos)
|
||||||
in
|
in
|
||||||
if
|
if isColliding (iX, iY, iW, iH, itemID, item) then
|
||||||
isColliding (iX, iY, iW, iH, itemID, item)
|
let
|
||||||
then
|
val _ = print
|
||||||
let val _ = print ("quad-tree.sml: has collision: \n" ^ itemToString
|
("quad-tree.sml: has collision: \n" ^ itemToString item ^ "\n")
|
||||||
item ^ "\n")
|
|
||||||
in
|
in
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
hasCollisionAtVec (iX, iY, iW, iH, itemID, pos + 1, elements)
|
hasCollisionAtVec (iX, iY, iW, iH, itemID, pos + 1, elements)
|
||||||
end
|
end
|
||||||
|
|
||||||
fun hasCollisionAt
|
fun hasCollisionAt
|
||||||
@@ -1002,10 +929,7 @@ struct
|
|||||||
, tree
|
, tree
|
||||||
) =
|
) =
|
||||||
case tree of
|
case tree of
|
||||||
NODE {topLeft, topRight, bottomLeft, bottomRight, elements} =>
|
NODE {topLeft, topRight, bottomLeft, bottomRight} =>
|
||||||
hasCollisionAtVec
|
|
||||||
(itemX, itemY, itemWidth, itemHeight, itemID, 0, elements)
|
|
||||||
orelse
|
|
||||||
let
|
let
|
||||||
val halfW = quadWidth div 2
|
val halfW = quadWidth div 2
|
||||||
val halfH = quadHeight div 2
|
val halfH = quadHeight div 2
|
||||||
@@ -1028,29 +952,33 @@ struct
|
|||||||
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
|
||||||
val tl =
|
val tl =
|
||||||
if vtl then
|
if vtl then
|
||||||
hasCollisionAt
|
hasCollisionAt
|
||||||
(iX, iY, iW, iH, qX, qY, halfW, halfH, itemID, topLeft)
|
(iX, iY, iW, iH, qX, qY, halfW, halfH, itemID, topLeft)
|
||||||
else false
|
else
|
||||||
|
false
|
||||||
|
|
||||||
val tr =
|
val tr =
|
||||||
if vtr then
|
if vtr then
|
||||||
hasCollisionAt
|
hasCollisionAt
|
||||||
(iX, iY, iW, iH, midX, qY, halfW, halfH, itemID, topRight)
|
(iX, iY, iW, iH, midX, qY, halfW, halfH, itemID, topRight)
|
||||||
else false
|
else
|
||||||
|
false
|
||||||
|
|
||||||
val bl =
|
val bl =
|
||||||
if vbl then
|
if vbl then
|
||||||
hasCollisionAt
|
hasCollisionAt
|
||||||
(iX, iY, iW, iH, qX, midY, halfW, halfH, itemID, bottomLeft)
|
(iX, iY, iW, iH, qX, midY, halfW, halfH, itemID, bottomLeft)
|
||||||
else false
|
else
|
||||||
|
false
|
||||||
|
|
||||||
val br =
|
val br =
|
||||||
if vbl then
|
if vbl then
|
||||||
hasCollisionAt
|
hasCollisionAt
|
||||||
(iX, iY, iW, iH, midX, midY, halfW, halfH, itemID, bottomRight)
|
(iX, iY, iW, iH, midX, midY, halfW, halfH, itemID, bottomRight)
|
||||||
else false
|
else
|
||||||
|
false
|
||||||
in
|
in
|
||||||
tl orelse tr orelse bl orelse br
|
tl orelse tr orelse bl orelse br
|
||||||
end
|
end
|
||||||
@@ -1071,10 +999,8 @@ struct
|
|||||||
|
|
||||||
fun getItemID (itemX, itemY, itemW, itemH, quadX, quadY, quadW, quadH, tree) =
|
fun getItemID (itemX, itemY, itemW, itemH, quadX, quadY, quadW, quadH, tree) =
|
||||||
case tree of
|
case tree of
|
||||||
NODE {topLeft, topRight, bottomLeft, bottomRight, elements} =>
|
NODE {topLeft, topRight, bottomLeft, bottomRight} =>
|
||||||
let
|
let
|
||||||
val tryID = getItemIDVec (itemX, itemY, itemW, itemH, 0, elements)
|
|
||||||
|
|
||||||
val halfW = quadW div 2
|
val halfW = quadW div 2
|
||||||
val halfH = quadH div 2
|
val halfH = quadH div 2
|
||||||
|
|
||||||
@@ -1096,31 +1022,37 @@ struct
|
|||||||
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
val vbl = visitBottomLeft (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
val vbr = visitBottomRight (iX, iY, iW, iH, qX, qY, qW, qH)
|
||||||
|
|
||||||
val tryID =
|
val try1 =
|
||||||
if vtl andalso tryID = ~1 then
|
if vtl then
|
||||||
getItemID
|
getItemID (iX, iY, iW, iH, qX, qY, halfW, halfH, topLeft)
|
||||||
(iX, iY, iW, iH, qX, qY, halfW, halfH, topLeft)
|
else
|
||||||
else tryID
|
~1
|
||||||
|
|
||||||
val tryID =
|
val try2 =
|
||||||
if vtr andalso tryID = ~1 then
|
if vtr then
|
||||||
getItemID
|
getItemID (iX, iY, iW, iH, midX, qY, halfW, halfH, topRight)
|
||||||
(iX, iY, iW, iH, midX, qY, halfW, halfH, topRight)
|
else
|
||||||
else tryID
|
~1
|
||||||
|
|
||||||
val tryID =
|
val try3 =
|
||||||
if vbl andalso tryID = ~1 then
|
if vbl then
|
||||||
getItemID
|
getItemID (iX, iY, iW, iH, qX, midY, halfW, halfH, bottomLeft)
|
||||||
(iX, iY, iW, iH, qX, midY, halfW, halfH, bottomLeft)
|
else
|
||||||
else tryID
|
~1
|
||||||
|
|
||||||
val tryID =
|
val try4 =
|
||||||
if vbl andalso tryID <> ~1 then
|
if vbl then
|
||||||
getItemID
|
getItemID (iX, iY, iW, iH, midX, midY, halfW, halfH, bottomRight)
|
||||||
(iX, iY, iW, iH, midX, midY, halfW, halfH, bottomRight)
|
else
|
||||||
else tryID
|
~1
|
||||||
|
|
||||||
|
(* get max: we assume query was narrow enough
|
||||||
|
* that only one ID is valid *)
|
||||||
|
val a = Int.max (try1, try2)
|
||||||
|
val a = Int.max (a, try3)
|
||||||
|
val a = Int.max (a, try4)
|
||||||
in
|
in
|
||||||
tryID
|
a
|
||||||
end
|
end
|
||||||
| LEAF elements => getItemIDVec (itemX, itemY, itemW, itemH, 0, elements)
|
| LEAF elements => getItemIDVec (itemX, itemY, itemW, itemH, 0, elements)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user