From 18fcec76d68c1b05c55672b6767682ce4103ded6 Mon Sep 17 00:00:00 2001 From: Julien Elbaz Date: Sat, 29 Apr 2017 10:10:12 +0900 Subject: [PATCH] [Feature] Allow negative quadtree coordinates. --- build/js/quadtree.js | 7 +++++-- build/js/quadtree.js.map | 2 +- build/js/quadtree.min.js | 2 +- build/js/quadtree.min.js.map | 2 +- docs/demo/quadtree.min.js | 2 +- docs/demo/quadtree.min.js.map | 2 +- docs/index.html | 3 ++- docs/quadtree.html | 3 ++- src/quadtree.coffee | 3 ++- test/test.coffee | 5 ++--- 10 files changed, 18 insertions(+), 13 deletions(-) diff --git a/build/js/quadtree.js b/build/js/quadtree.js index bff7e04..efa45f4 100644 --- a/build/js/quadtree.js +++ b/build/js/quadtree.js @@ -29,8 +29,11 @@ this.contents = []; this.oversized = []; this.size = 0; - if (this.x < 0 || this.y < 0 || this.width < 1 || this.height < 1) { - throw new Error("Dimensions and coordinates must be positive integers."); + if (this.width < 1 || this.height < 1) { + throw new Error("Dimensions must be positive integers."); + } + if (!Number.isInteger(this.x) || !Number.isInteger(this.y)) { + throw new Error("Coordinates must be integers"); } if (this.maxElements < 1) { throw new Error("The maximum number of elements before a split must be a positive integer."); diff --git a/build/js/quadtree.js.map b/build/js/quadtree.js.map index 01491f8..c2caa4a 100644 --- a/build/js/quadtree.js.map +++ b/build/js/quadtree.js.map @@ -1 +1 @@ -{"version":3,"file":"quadtree.js","sources":["quadtree.coffee"],"names":[],"mappings":"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","sourcesContent":["# quadtree-lib\n# ============\n#\n# **Quadtree-lib** is an easy to use, developer friendly quadtree library\n# which contains many helper methods to add, remove, iterate, filter, simulate\n# collisions over 2d elements and more.\n\n# #### UMD bundling related code\n((root, factory) ->\n if typeof define is 'function' and define.amd\n define [], factory\n else if typeof exports is 'object' and module.exports\n module.exports = factory()\n else\n root[\"Quadtree\"] = factory()\n) @, (-> class Quadtree\n # The Quadtree class\n # -------------------\n\n # ### Constructor\n\n # The quadtree constructor accepts a single parameter object containing the following properties :\n # - width / length : dimensions of the quadtree. [ *mandatory* ]\n # - maxElements : the maximum number of elements before the leaf 'splits' into subtrees. [ *defaults to 1* ]\n # - x / y : these coordinates are used internally by the library to position subtrees. [ *internal use only* ]\n constructor: ({@x, @y, @width, @height, @maxElements}) ->\n\n # An error is thrown when the width & length are not passed as constructor arguments.\n throw new Error \"Missing quadtree dimensions.\" if not @width? or not @height?\n @x ?= 0\n @y ?= 0\n @maxElements ?= 1\n @contents = []\n @oversized = []\n @size = 0\n\n # Dimension & coordinates are checked, an error is thrown in case of bad input.\n throw new Error \"Dimensions and coordinates must be positive integers.\" if @x < 0 or @y < 0 or @width < 1 or @height < 1\n throw new Error \"The maximum number of elements before a split must be a positive integer.\" if @maxElements < 1\n\n that = @\n\n # The subtrees list, by position.\n @children = {\n # Northwest tree.\n \"NW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Northeast tree.\n \"NE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y\n width: Math.ceil that.width / 2\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Southwest tree.\n \"SW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n # Southeast tree.\n \"SE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.ceil that.width / 2\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n }\n # Adding a getter which lazily creates the tree.\n for child of @children\n @children[child].get = ->\n if @tree? then @tree else @tree = @create(); @tree\n\n # ### Internal methods & vars\n\n # Retrieves the center coordinates of a rectangle.\n getCenter = (item) ->\n x: Math.floor((item.width ? 1) / 2) + item.x\n y: Math.floor((item.height ? 1) / 2) + item.y\n\n # Bounding box collision algorithm.\n boundingBoxCollision = (elt1, elt2) ->\n not(elt1.x >= elt2.x + (elt2.width ? 1) or\n elt1.x + (elt1.width ? 1) <= elt2.x or\n elt1.y >= elt2.y + (elt2.height ? 1) or\n elt1.y + (elt1.height ? 1) <= elt2.y)\n\n # Determines which subtree an element belongs to.\n calculateDirection = (element, tree) ->\n quadCenter = getCenter tree\n\n if element.x < quadCenter.x\n if element.y < quadCenter.y then \"NW\"\n else \"SW\"\n else\n if element.y < quadCenter.y then \"NE\"\n else \"SE\"\n\n # Validates a potential element of the tree.\n validateElement = (element) ->\n if not (typeof element is \"object\")\n throw new Error \"Element must be an Object.\"\n if not element.x? or not element.y?\n throw new Error \"Coordinates properties are missing.\"\n if element?.width < 0 or element?.height < 0\n throw new Error \"Width and height must be positive integers.\"\n\n # Returns splitted coordinates and dimensions.\n splitTree = (tree) ->\n leftWidth = Math.max (Math.floor tree.width / 2), 1\n rightWidth = Math.ceil tree.width / 2\n topHeight = Math.max (Math.floor tree.height / 2), 1\n bottomHeight = Math.ceil tree.height / 2\n \"NW\":\n x: tree.x\n y: tree.y\n width: leftWidth\n height: topHeight\n \"NE\":\n x: tree.x + leftWidth\n y: tree.y\n width: rightWidth\n height: topHeight\n \"SW\":\n x: tree.x\n y: tree.y + topHeight\n width: leftWidth\n height: bottomHeight\n \"SE\":\n x: tree.x + leftWidth\n y: tree.y + topHeight\n width: rightWidth\n height: bottomHeight\n\n # Determines wether an element fits into subtrees.\n fitting = (element, tree) ->\n where = []\n for direction, coordinates of splitTree tree when boundingBoxCollision element, coordinates\n where.push direction\n where\n\n # Add getters and setters for coordinates and dimensions properties in order to automatically reorganize the elements on change.\n observe = (item, tree) ->\n writeAccessors = (propName) ->\n item[\"_#{propName}\"] = item[propName]\n Object.defineProperty item, propName, {\n set: (val) ->\n tree.remove @\n @[\"_#{propName}\"] = val\n tree.push @\n get: ->\n @[\"_#{propName}\"]\n configurable: true\n }\n writeAccessors \"x\"\n writeAccessors \"y\"\n writeAccessors \"width\"\n writeAccessors \"height\"\n\n # ### Exposed methods\n\n # Add an element to the quadtree.\n # Elements can be observed to reorganize them into the quadtree automatically whenever their coordinates or dimensions are set (for ex. obj.x = ...).\n push: (item, doObserve) ->\n @pushAll([item], doObserve)\n\n # Push an array of elements.\n pushAll : (items, doObserve) ->\n for item in items\n validateElement item\n observe item, @ if doObserve\n\n fifo = [tree: @, elements: items]\n\n while fifo.length > 0\n { tree, elements } = fifo.shift()\n\n fifoCandidates = { \"NW\": null, \"NE\": null, \"SW\": null, \"SE\": null }\n\n for element in elements\n tree.size++\n\n fits = fitting element, tree\n\n if fits.length isnt 1 or tree.width is 1 or tree.height is 1\n tree.oversized.push element\n\n else if (tree.size - tree.oversized.length) <= tree.maxElements\n tree.contents.push element\n\n else\n direction = fits[0]\n relatedChild = tree.children[direction]\n fifoCandidates[direction] ?= { tree: relatedChild.get(), elements: [] }\n fifoCandidates[direction].elements.push(element)\n\n for content in tree.contents\n contentDir = (fitting content, tree)[0]\n fifoCandidates[contentDir] ?= { tree: tree.children[contentDir].get(), elements: [] }\n fifoCandidates[contentDir].elements.push(content)\n\n tree.contents = []\n\n for direction, candidate of fifoCandidates\n if candidate? then fifo.push candidate\n\n @\n\n # Removes an element from the quadtree.\n remove: (item) ->\n validateElement item\n\n index = @oversized.indexOf item\n if index > - 1\n @oversized.splice index, 1\n @size--\n return true\n\n index = @contents.indexOf item\n if index > - 1\n @contents.splice index, 1\n @size--\n return true\n\n relatedChild = @children[calculateDirection item, @]\n\n if relatedChild.tree? and relatedChild.tree.remove item\n @size--\n relatedChild.tree = null if relatedChild.tree.size is 0\n return true\n\n false\n\n # Returns an array of elements which collides with the `item` argument.\n # `item` being an object having x, y, width & height properties.\n\n # The default collision function is a basic bounding box algorithm.\n # You can change it by providing a function as a second argument.\n #```javascript\n #colliding({x: 10, y: 20}, function(element1, element2){\n # return // Place predicate here //\n #})\n #```\n colliding: (item, collisionFunction) ->\n validateElement item\n\n collisionFunction ?= boundingBoxCollision\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized when elt isnt item and collisionFunction item, elt then items.push elt\n for elt in top.contents when elt isnt item and collisionFunction item, elt then items.push elt\n\n fits = fitting item, top\n\n # Special case for elements located outside of the quadtree on the right / bottom side\n if fits.length is 0\n fits = []\n if item.x >= top.x + top.width\n fits.push \"NE\"\n if item.y >= top.y + top.height\n fits.push \"SW\"\n if fits.length > 0\n if fits.length is 1 then fits.push \"SE\" else fits = [\"SE\"]\n\n for child in fits when top.children[child].tree?\n fifo.push top.children[child].tree\n\n items\n\n # Alias of `where`.\n get: (query) ->\n @where query\n # Returns an array of elements that match the `query` argument.\n where: (query) ->\n # Naïve parsing (missing coordinates)\n if typeof query is \"object\" and (not query.x? or not query.y?)\n return @find (elt) ->\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n check\n\n # Optimised parsing\n validateElement query\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n for elt in top.contents\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n\n relatedChild = top.children[calculateDirection query, top]\n\n if relatedChild.tree?\n fifo.push relatedChild.tree\n\n items\n\n # For each element of the quadtree, performs the `action` function.\n #```javascript\n #quad.each(function(item){ console.log(item) })\n #```\n each: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized then action?(i)\n for i in top.contents then action?(i)\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n @\n\n # Returns an array of elements which validates the predicate.\n find: (predicate) ->\n fifo = [@]\n items = []\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized when predicate?(i) then items.push i\n for i in top.contents when predicate?(i) then items.push i\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n items\n\n # Returns a **cloned** `Quadtree` object which contains only the elements that validate the predicate.\n filter: (predicate) ->\n deepclone = (target) ->\n copycat = new Quadtree x: target.x, y: target.y, width: target.width, height: target.height, maxElements: target.maxElements\n copycat.size = 0\n for child of target.children when target.children[child].tree?\n copycat.children[child].tree = deepclone target.children[child].tree\n copycat.size += copycat.children[child].tree?.size ? 0\n\n for item in target.oversized when not predicate? or predicate?(item)\n copycat.oversized.push item\n for item in target.contents when not predicate? or predicate?(item)\n copycat.contents.push item\n\n copycat.size += copycat.oversized.length + copycat.contents.length\n if copycat.size is 0 then null else copycat\n\n deepclone @\n\n # Opposite of filter.\n reject: (predicate) ->\n @filter (i) ->\n not predicate?(i)\n\n # Visits each tree & subtree contained in the `Quadtree` object.\n # For each node, performs the `action` function, inside which `this` is bound to the node tree object.\n visit: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n that = fifo.shift()\n action.bind(that)()\n\n for child of that.children when that.children[child].tree?\n fifo.push that.children[child].tree\n @\n\n # Pretty printing function.\n pretty: ->\n str = \"\"\n\n indent = (level) ->\n res = \"\"\n res += \" \" for times in [level...0]\n res\n\n fifo = [{ label: \"ROOT\", tree: @, level: 0 }]\n while fifo.length > 0\n top = fifo.shift()\n indentation = indent(top.level)\n str += \"\"\"\n #{indentation}| #{top.label}\n #{indentation}| ------------\\n\n \"\"\"\n\n if top.tree.oversized.length > 0\n str += \"\"\"\n #{indentation}| * Oversized elements *\n #{indentation}| #{top.tree.oversized}\\n\n \"\"\"\n\n if top.tree.contents.length > 0\n str += \"\"\"\n #{indentation}| * Leaf content *\n #{indentation}| #{top.tree.contents}\\n\n \"\"\"\n\n isParent = false\n for child of top.tree.children when top.tree.children[child].tree?\n isParent = true\n fifo.unshift { label: child, tree: top.tree.children[child].tree, level: top.level + 1 }\n\n if isParent then str += \"#{indentation}└──┐\\n\"\n\n str\n)\n"]} \ No newline at end of file +{"version":3,"file":"quadtree.js","sources":["quadtree.coffee"],"names":[],"mappings":"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","sourcesContent":["# quadtree-lib\n# ============\n#\n# **Quadtree-lib** is an easy to use, developer friendly quadtree library\n# which contains many helper methods to add, remove, iterate, filter, simulate\n# collisions over 2d elements and more.\n\n# #### UMD bundling related code\n((root, factory) ->\n if typeof define is 'function' and define.amd\n define [], factory\n else if typeof exports is 'object' and module.exports\n module.exports = factory()\n else\n root[\"Quadtree\"] = factory()\n) @, (-> class Quadtree\n # The Quadtree class\n # -------------------\n\n # ### Constructor\n\n # The quadtree constructor accepts a single parameter object containing the following properties :\n # - width / length : dimensions of the quadtree. [ *mandatory* ]\n # - maxElements : the maximum number of elements before the leaf 'splits' into subtrees. [ *defaults to 1* ]\n # - x / y : these coordinates are used internally by the library to position subtrees. [ *internal use only* ]\n constructor: ({@x, @y, @width, @height, @maxElements}) ->\n\n # An error is thrown when the width & length are not passed as constructor arguments.\n throw new Error \"Missing quadtree dimensions.\" if not @width? or not @height?\n @x ?= 0\n @y ?= 0\n @maxElements ?= 1\n @contents = []\n @oversized = []\n @size = 0\n\n # Dimension & coordinates are checked, an error is thrown in case of bad input.\n throw new Error \"Dimensions must be positive integers.\" if @width < 1 or @height < 1\n throw new Error \"Coordinates must be integers\" if not Number.isInteger(@x) or not Number.isInteger(@y)\n throw new Error \"The maximum number of elements before a split must be a positive integer.\" if @maxElements < 1\n\n that = @\n\n # The subtrees list, by position.\n @children = {\n # Northwest tree.\n \"NW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Northeast tree.\n \"NE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y\n width: Math.ceil that.width / 2\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Southwest tree.\n \"SW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n # Southeast tree.\n \"SE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.ceil that.width / 2\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n }\n # Adding a getter which lazily creates the tree.\n for child of @children\n @children[child].get = ->\n if @tree? then @tree else @tree = @create(); @tree\n\n # ### Internal methods & vars\n\n # Retrieves the center coordinates of a rectangle.\n getCenter = (item) ->\n x: Math.floor((item.width ? 1) / 2) + item.x\n y: Math.floor((item.height ? 1) / 2) + item.y\n\n # Bounding box collision algorithm.\n boundingBoxCollision = (elt1, elt2) ->\n not(elt1.x >= elt2.x + (elt2.width ? 1) or\n elt1.x + (elt1.width ? 1) <= elt2.x or\n elt1.y >= elt2.y + (elt2.height ? 1) or\n elt1.y + (elt1.height ? 1) <= elt2.y)\n\n # Determines which subtree an element belongs to.\n calculateDirection = (element, tree) ->\n quadCenter = getCenter tree\n\n if element.x < quadCenter.x\n if element.y < quadCenter.y then \"NW\"\n else \"SW\"\n else\n if element.y < quadCenter.y then \"NE\"\n else \"SE\"\n\n # Validates a potential element of the tree.\n validateElement = (element) ->\n if not (typeof element is \"object\")\n throw new Error \"Element must be an Object.\"\n if not element.x? or not element.y?\n throw new Error \"Coordinates properties are missing.\"\n if element?.width < 0 or element?.height < 0\n throw new Error \"Width and height must be positive integers.\"\n\n # Returns splitted coordinates and dimensions.\n splitTree = (tree) ->\n leftWidth = Math.max (Math.floor tree.width / 2), 1\n rightWidth = Math.ceil tree.width / 2\n topHeight = Math.max (Math.floor tree.height / 2), 1\n bottomHeight = Math.ceil tree.height / 2\n \"NW\":\n x: tree.x\n y: tree.y\n width: leftWidth\n height: topHeight\n \"NE\":\n x: tree.x + leftWidth\n y: tree.y\n width: rightWidth\n height: topHeight\n \"SW\":\n x: tree.x\n y: tree.y + topHeight\n width: leftWidth\n height: bottomHeight\n \"SE\":\n x: tree.x + leftWidth\n y: tree.y + topHeight\n width: rightWidth\n height: bottomHeight\n\n # Determines wether an element fits into subtrees.\n fitting = (element, tree) ->\n where = []\n for direction, coordinates of splitTree tree when boundingBoxCollision element, coordinates\n where.push direction\n where\n\n # Add getters and setters for coordinates and dimensions properties in order to automatically reorganize the elements on change.\n observe = (item, tree) ->\n writeAccessors = (propName) ->\n item[\"_#{propName}\"] = item[propName]\n Object.defineProperty item, propName, {\n set: (val) ->\n tree.remove @\n @[\"_#{propName}\"] = val\n tree.push @\n get: ->\n @[\"_#{propName}\"]\n configurable: true\n }\n writeAccessors \"x\"\n writeAccessors \"y\"\n writeAccessors \"width\"\n writeAccessors \"height\"\n\n # ### Exposed methods\n\n # Add an element to the quadtree.\n # Elements can be observed to reorganize them into the quadtree automatically whenever their coordinates or dimensions are set (for ex. obj.x = ...).\n push: (item, doObserve) ->\n @pushAll([item], doObserve)\n\n # Push an array of elements.\n pushAll : (items, doObserve) ->\n for item in items\n validateElement item\n observe item, @ if doObserve\n\n fifo = [tree: @, elements: items]\n\n while fifo.length > 0\n { tree, elements } = fifo.shift()\n\n fifoCandidates = { \"NW\": null, \"NE\": null, \"SW\": null, \"SE\": null }\n\n for element in elements\n tree.size++\n\n fits = fitting element, tree\n\n if fits.length isnt 1 or tree.width is 1 or tree.height is 1\n tree.oversized.push element\n\n else if (tree.size - tree.oversized.length) <= tree.maxElements\n tree.contents.push element\n\n else\n direction = fits[0]\n relatedChild = tree.children[direction]\n fifoCandidates[direction] ?= { tree: relatedChild.get(), elements: [] }\n fifoCandidates[direction].elements.push(element)\n\n for content in tree.contents\n contentDir = (fitting content, tree)[0]\n fifoCandidates[contentDir] ?= { tree: tree.children[contentDir].get(), elements: [] }\n fifoCandidates[contentDir].elements.push(content)\n\n tree.contents = []\n\n for direction, candidate of fifoCandidates\n if candidate? then fifo.push candidate\n\n @\n\n # Removes an element from the quadtree.\n remove: (item) ->\n validateElement item\n\n index = @oversized.indexOf item\n if index > - 1\n @oversized.splice index, 1\n @size--\n return true\n\n index = @contents.indexOf item\n if index > - 1\n @contents.splice index, 1\n @size--\n return true\n\n relatedChild = @children[calculateDirection item, @]\n\n if relatedChild.tree? and relatedChild.tree.remove item\n @size--\n relatedChild.tree = null if relatedChild.tree.size is 0\n return true\n\n false\n\n # Returns an array of elements which collides with the `item` argument.\n # `item` being an object having x, y, width & height properties.\n\n # The default collision function is a basic bounding box algorithm.\n # You can change it by providing a function as a second argument.\n #```javascript\n #colliding({x: 10, y: 20}, function(element1, element2){\n # return // Place predicate here //\n #})\n #```\n colliding: (item, collisionFunction) ->\n validateElement item\n\n collisionFunction ?= boundingBoxCollision\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized when elt isnt item and collisionFunction item, elt then items.push elt\n for elt in top.contents when elt isnt item and collisionFunction item, elt then items.push elt\n\n fits = fitting item, top\n\n # Special case for elements located outside of the quadtree on the right / bottom side\n if fits.length is 0\n fits = []\n if item.x >= top.x + top.width\n fits.push \"NE\"\n if item.y >= top.y + top.height\n fits.push \"SW\"\n if fits.length > 0\n if fits.length is 1 then fits.push \"SE\" else fits = [\"SE\"]\n\n for child in fits when top.children[child].tree?\n fifo.push top.children[child].tree\n\n items\n\n # Alias of `where`.\n get: (query) ->\n @where query\n # Returns an array of elements that match the `query` argument.\n where: (query) ->\n # Naïve parsing (missing coordinates)\n if typeof query is \"object\" and (not query.x? or not query.y?)\n return @find (elt) ->\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n check\n\n # Optimised parsing\n validateElement query\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n for elt in top.contents\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n\n relatedChild = top.children[calculateDirection query, top]\n\n if relatedChild.tree?\n fifo.push relatedChild.tree\n\n items\n\n # For each element of the quadtree, performs the `action` function.\n #```javascript\n #quad.each(function(item){ console.log(item) })\n #```\n each: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized then action?(i)\n for i in top.contents then action?(i)\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n @\n\n # Returns an array of elements which validates the predicate.\n find: (predicate) ->\n fifo = [@]\n items = []\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized when predicate?(i) then items.push i\n for i in top.contents when predicate?(i) then items.push i\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n items\n\n # Returns a **cloned** `Quadtree` object which contains only the elements that validate the predicate.\n filter: (predicate) ->\n deepclone = (target) ->\n copycat = new Quadtree x: target.x, y: target.y, width: target.width, height: target.height, maxElements: target.maxElements\n copycat.size = 0\n for child of target.children when target.children[child].tree?\n copycat.children[child].tree = deepclone target.children[child].tree\n copycat.size += copycat.children[child].tree?.size ? 0\n\n for item in target.oversized when not predicate? or predicate?(item)\n copycat.oversized.push item\n for item in target.contents when not predicate? or predicate?(item)\n copycat.contents.push item\n\n copycat.size += copycat.oversized.length + copycat.contents.length\n if copycat.size is 0 then null else copycat\n\n deepclone @\n\n # Opposite of filter.\n reject: (predicate) ->\n @filter (i) ->\n not predicate?(i)\n\n # Visits each tree & subtree contained in the `Quadtree` object.\n # For each node, performs the `action` function, inside which `this` is bound to the node tree object.\n visit: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n that = fifo.shift()\n action.bind(that)()\n\n for child of that.children when that.children[child].tree?\n fifo.push that.children[child].tree\n @\n\n # Pretty printing function.\n pretty: ->\n str = \"\"\n\n indent = (level) ->\n res = \"\"\n res += \" \" for times in [level...0]\n res\n\n fifo = [{ label: \"ROOT\", tree: @, level: 0 }]\n while fifo.length > 0\n top = fifo.shift()\n indentation = indent(top.level)\n str += \"\"\"\n #{indentation}| #{top.label}\n #{indentation}| ------------\\n\n \"\"\"\n\n if top.tree.oversized.length > 0\n str += \"\"\"\n #{indentation}| * Oversized elements *\n #{indentation}| #{top.tree.oversized}\\n\n \"\"\"\n\n if top.tree.contents.length > 0\n str += \"\"\"\n #{indentation}| * Leaf content *\n #{indentation}| #{top.tree.contents}\\n\n \"\"\"\n\n isParent = false\n for child of top.tree.children when top.tree.children[child].tree?\n isParent = true\n fifo.unshift { label: child, tree: top.tree.children[child].tree, level: top.level + 1 }\n\n if isParent then str += \"#{indentation}└──┐\\n\"\n\n str\n)\n"]} \ No newline at end of file diff --git a/build/js/quadtree.min.js b/build/js/quadtree.min.js index a112ec0..25be8b9 100644 --- a/build/js/quadtree.min.js +++ b/build/js/quadtree.min.js @@ -1,2 +1,2 @@ -!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports&&module.exports?module.exports=t():e.Quadtree=t()}(this,function(){return function(){function e(t){var n,i;if(this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height,this.maxElements=t.maxElements,null==this.width||null==this.height)throw new Error("Missing quadtree dimensions.");if(null==this.x&&(this.x=0),null==this.y&&(this.y=0),null==this.maxElements&&(this.maxElements=1),this.contents=[],this.oversized=[],this.size=0,this.x<0||this.y<0||this.width<1||this.height<1)throw new Error("Dimensions and coordinates must be positive integers.");if(this.maxElements<1)throw new Error("The maximum number of elements before a split must be a positive integer.");i=this,this.children={NW:{create:function(){return new e({x:i.x,y:i.y,width:Math.max(Math.floor(i.width/2),1),height:Math.max(Math.floor(i.height/2),1),maxElements:i.maxElements})},tree:null},NE:{create:function(){return new e({x:i.x+Math.max(Math.floor(i.width/2),1),y:i.y,width:Math.ceil(i.width/2),height:Math.max(Math.floor(i.height/2),1),maxElements:i.maxElements})},tree:null},SW:{create:function(){return new e({x:i.x,y:i.y+Math.max(Math.floor(i.height/2),1),width:Math.max(Math.floor(i.width/2),1),height:Math.ceil(i.height/2),maxElements:i.maxElements})},tree:null},SE:{create:function(){return new e({x:i.x+Math.max(Math.floor(i.width/2),1),y:i.y+Math.max(Math.floor(i.height/2),1),width:Math.ceil(i.width/2),height:Math.ceil(i.height/2),maxElements:i.maxElements})},tree:null}};for(n in this.children)this.children[n].get=function(){return null!=this.tree?this.tree:(this.tree=this.create(),this.tree)}}var t,n,i,r,h,l,o;return r=function(e){var t,n;return{x:Math.floor((null!=(t=e.width)?t:1)/2)+e.x,y:Math.floor((null!=(n=e.height)?n:1)/2)+e.y}},t=function(e,t){var n,i,r,h;return!(e.x>=t.x+(null!=(n=t.width)?n:1)||e.x+(null!=(i=e.width)?i:1)<=t.x||e.y>=t.y+(null!=(r=t.height)?r:1)||e.y+(null!=(h=e.height)?h:1)<=t.y)},n=function(e,t){var n;return n=r(t),e.x0;){for(E=c.shift(),b=E.tree,f=E.elements,d={NW:null,NE:null,SW:null,SE:null},m=0,v=f.length;m-1?(this.oversized.splice(t,1),this.size--,!0):(t=this.contents.indexOf(e))>-1?(this.contents.splice(t,1),this.size--,!0):(i=this.children[n(e,this)],!(null==i.tree||!i.tree.remove(e))&&(this.size--,0===i.tree.size&&(i.tree=null),!0))},e.prototype.colliding=function(e,n){var r,h,l,s,u,f,c,d,a,p,g,m,x,y;for(o(e),null==n&&(n=t),u=[],l=[this];l.length>0;){for(y=l.shift(),m=y.oversized,f=0,a=m.length;f=y.x+y.width&&s.push("NE"),e.y>=y.y+y.height&&s.push("SW"),s.length>0&&(1===s.length?s.push("SE"):s=["SE"])),d=0,g=s.length;d0;){for(g=r.shift(),d=g.oversized,l=0,f=d.length;l0;){for(f=n.shift(),s=f.oversized,r=0,l=s.length;r0;){for(c=n.shift(),u=c.oversized,h=0,o=u.length;h0;){i=n.shift(),e.bind(i)();for(t in i.children)null!=i.children[t].tree&&n.push(i.children[t].tree)}return this},e.prototype.pretty=function(){var e,t,n,i,r,h,l;for(h="",n=function(e){var t,n,i;for(i="",t=n=e;n<=0?t<0:t>0;n<=0?++t:--t)i+=" ";return i},t=[{label:"ROOT",tree:this,level:0}];t.length>0;){l=t.shift(),i=n(l.level),h+=i+"| "+l.label+"\n"+i+"| ------------\n",l.tree.oversized.length>0&&(h+=i+"| * Oversized elements *\n"+i+"| "+l.tree.oversized+"\n"),l.tree.contents.length>0&&(h+=i+"| * Leaf content *\n"+i+"| "+l.tree.contents+"\n"),r=!1;for(e in l.tree.children)null!=l.tree.children[e].tree&&(r=!0,t.unshift({label:e,tree:l.tree.children[e].tree,level:l.level+1}));r&&(h+=i+"└──┐\n")}return h},e}()}); +!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports&&module.exports?module.exports=t():e.Quadtree=t()}(this,function(){return function(){function e(t){var n,i;if(this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height,this.maxElements=t.maxElements,null==this.width||null==this.height)throw new Error("Missing quadtree dimensions.");if(null==this.x&&(this.x=0),null==this.y&&(this.y=0),null==this.maxElements&&(this.maxElements=1),this.contents=[],this.oversized=[],this.size=0,this.width<1||this.height<1)throw new Error("Dimensions must be positive integers.");if(!Number.isInteger(this.x)||!Number.isInteger(this.y))throw new Error("Coordinates must be integers");if(this.maxElements<1)throw new Error("The maximum number of elements before a split must be a positive integer.");i=this,this.children={NW:{create:function(){return new e({x:i.x,y:i.y,width:Math.max(Math.floor(i.width/2),1),height:Math.max(Math.floor(i.height/2),1),maxElements:i.maxElements})},tree:null},NE:{create:function(){return new e({x:i.x+Math.max(Math.floor(i.width/2),1),y:i.y,width:Math.ceil(i.width/2),height:Math.max(Math.floor(i.height/2),1),maxElements:i.maxElements})},tree:null},SW:{create:function(){return new e({x:i.x,y:i.y+Math.max(Math.floor(i.height/2),1),width:Math.max(Math.floor(i.width/2),1),height:Math.ceil(i.height/2),maxElements:i.maxElements})},tree:null},SE:{create:function(){return new e({x:i.x+Math.max(Math.floor(i.width/2),1),y:i.y+Math.max(Math.floor(i.height/2),1),width:Math.ceil(i.width/2),height:Math.ceil(i.height/2),maxElements:i.maxElements})},tree:null}};for(n in this.children)this.children[n].get=function(){return null!=this.tree?this.tree:(this.tree=this.create(),this.tree)}}var t,n,i,r,h,l,o;return r=function(e){var t,n;return{x:Math.floor((null!=(t=e.width)?t:1)/2)+e.x,y:Math.floor((null!=(n=e.height)?n:1)/2)+e.y}},t=function(e,t){var n,i,r,h;return!(e.x>=t.x+(null!=(n=t.width)?n:1)||e.x+(null!=(i=e.width)?i:1)<=t.x||e.y>=t.y+(null!=(r=t.height)?r:1)||e.y+(null!=(h=e.height)?h:1)<=t.y)},n=function(e,t){var n;return n=r(t),e.x0;){for(E=c.shift(),b=E.tree,f=E.elements,d={NW:null,NE:null,SW:null,SE:null},m=0,v=f.length;m-1?(this.oversized.splice(t,1),this.size--,!0):(t=this.contents.indexOf(e))>-1?(this.contents.splice(t,1),this.size--,!0):(i=this.children[n(e,this)],!(null==i.tree||!i.tree.remove(e))&&(this.size--,0===i.tree.size&&(i.tree=null),!0))},e.prototype.colliding=function(e,n){var r,h,l,s,u,f,c,d,a,g,p,m,x,y;for(o(e),null==n&&(n=t),u=[],l=[this];l.length>0;){for(y=l.shift(),m=y.oversized,f=0,a=m.length;f=y.x+y.width&&s.push("NE"),e.y>=y.y+y.height&&s.push("SW"),s.length>0&&(1===s.length?s.push("SE"):s=["SE"])),d=0,p=s.length;d0;){for(p=r.shift(),d=p.oversized,l=0,f=d.length;l0;){for(f=n.shift(),s=f.oversized,r=0,l=s.length;r0;){for(c=n.shift(),u=c.oversized,h=0,o=u.length;h0;){i=n.shift(),e.bind(i)();for(t in i.children)null!=i.children[t].tree&&n.push(i.children[t].tree)}return this},e.prototype.pretty=function(){var e,t,n,i,r,h,l;for(h="",n=function(e){var t,n,i;for(i="",t=n=e;n<=0?t<0:t>0;n<=0?++t:--t)i+=" ";return i},t=[{label:"ROOT",tree:this,level:0}];t.length>0;){l=t.shift(),i=n(l.level),h+=i+"| "+l.label+"\n"+i+"| ------------\n",l.tree.oversized.length>0&&(h+=i+"| * Oversized elements *\n"+i+"| "+l.tree.oversized+"\n"),l.tree.contents.length>0&&(h+=i+"| * Leaf content *\n"+i+"| "+l.tree.contents+"\n"),r=!1;for(e in l.tree.children)null!=l.tree.children[e].tree&&(r=!0,t.unshift({label:e,tree:l.tree.children[e].tree,level:l.level+1}));r&&(h+=i+"└──┐\n")}return h},e}()}); //# sourceMappingURL=quadtree.min.js.map diff --git a/build/js/quadtree.min.js.map b/build/js/quadtree.min.js.map index 9159962..d47ad6d 100644 --- a/build/js/quadtree.min.js.map +++ b/build/js/quadtree.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["quadtree.coffee"],"names":["root","factory","define","amd","exports","module","this","Quadtree","arg","child","that","x","y","width","height","maxElements","Error","contents","oversized","size","children","NW","create","Math","max","floor","tree","NE","ceil","SW","SE","get","boundingBoxCollision","calculateDirection","fitting","getCenter","observe","splitTree","validateElement","item","ref","ref1","elt1","elt2","ref2","ref3","element","quadCenter","bottomHeight","leftWidth","rightWidth","topHeight","coordinates","direction","where","push","writeAccessors","propName","Object","defineProperty","set","val","remove","configurable","doObserve","pushAll","items","candidate","content","contentDir","elements","fifo","fifoCandidates","fits","j","k","l","len","len1","len2","relatedChild","length","shift","index","indexOf","splice","colliding","collisionFunction","elt","top","query","check","key","find","each","action","i","predicate","filter","deepclone","target","copycat","reject","visit","bind","pretty","indent","indentation","isParent","str","level","res","label","unshift"],"mappings":"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","file":"quadtree.min.js","sourcesContent":["# quadtree-lib\n# ============\n#\n# **Quadtree-lib** is an easy to use, developer friendly quadtree library\n# which contains many helper methods to add, remove, iterate, filter, simulate\n# collisions over 2d elements and more.\n\n# #### UMD bundling related code\n((root, factory) ->\n if typeof define is 'function' and define.amd\n define [], factory\n else if typeof exports is 'object' and module.exports\n module.exports = factory()\n else\n root[\"Quadtree\"] = factory()\n) @, (-> class Quadtree\n # The Quadtree class\n # -------------------\n\n # ### Constructor\n\n # The quadtree constructor accepts a single parameter object containing the following properties :\n # - width / length : dimensions of the quadtree. [ *mandatory* ]\n # - maxElements : the maximum number of elements before the leaf 'splits' into subtrees. [ *defaults to 1* ]\n # - x / y : these coordinates are used internally by the library to position subtrees. [ *internal use only* ]\n constructor: ({@x, @y, @width, @height, @maxElements}) ->\n\n # An error is thrown when the width & length are not passed as constructor arguments.\n throw new Error \"Missing quadtree dimensions.\" if not @width? or not @height?\n @x ?= 0\n @y ?= 0\n @maxElements ?= 1\n @contents = []\n @oversized = []\n @size = 0\n\n # Dimension & coordinates are checked, an error is thrown in case of bad input.\n throw new Error \"Dimensions and coordinates must be positive integers.\" if @x < 0 or @y < 0 or @width < 1 or @height < 1\n throw new Error \"The maximum number of elements before a split must be a positive integer.\" if @maxElements < 1\n\n that = @\n\n # The subtrees list, by position.\n @children = {\n # Northwest tree.\n \"NW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Northeast tree.\n \"NE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y\n width: Math.ceil that.width / 2\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Southwest tree.\n \"SW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n # Southeast tree.\n \"SE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.ceil that.width / 2\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n }\n # Adding a getter which lazily creates the tree.\n for child of @children\n @children[child].get = ->\n if @tree? then @tree else @tree = @create(); @tree\n\n # ### Internal methods & vars\n\n # Retrieves the center coordinates of a rectangle.\n getCenter = (item) ->\n x: Math.floor((item.width ? 1) / 2) + item.x\n y: Math.floor((item.height ? 1) / 2) + item.y\n\n # Bounding box collision algorithm.\n boundingBoxCollision = (elt1, elt2) ->\n not(elt1.x >= elt2.x + (elt2.width ? 1) or\n elt1.x + (elt1.width ? 1) <= elt2.x or\n elt1.y >= elt2.y + (elt2.height ? 1) or\n elt1.y + (elt1.height ? 1) <= elt2.y)\n\n # Determines which subtree an element belongs to.\n calculateDirection = (element, tree) ->\n quadCenter = getCenter tree\n\n if element.x < quadCenter.x\n if element.y < quadCenter.y then \"NW\"\n else \"SW\"\n else\n if element.y < quadCenter.y then \"NE\"\n else \"SE\"\n\n # Validates a potential element of the tree.\n validateElement = (element) ->\n if not (typeof element is \"object\")\n throw new Error \"Element must be an Object.\"\n if not element.x? or not element.y?\n throw new Error \"Coordinates properties are missing.\"\n if element?.width < 0 or element?.height < 0\n throw new Error \"Width and height must be positive integers.\"\n\n # Returns splitted coordinates and dimensions.\n splitTree = (tree) ->\n leftWidth = Math.max (Math.floor tree.width / 2), 1\n rightWidth = Math.ceil tree.width / 2\n topHeight = Math.max (Math.floor tree.height / 2), 1\n bottomHeight = Math.ceil tree.height / 2\n \"NW\":\n x: tree.x\n y: tree.y\n width: leftWidth\n height: topHeight\n \"NE\":\n x: tree.x + leftWidth\n y: tree.y\n width: rightWidth\n height: topHeight\n \"SW\":\n x: tree.x\n y: tree.y + topHeight\n width: leftWidth\n height: bottomHeight\n \"SE\":\n x: tree.x + leftWidth\n y: tree.y + topHeight\n width: rightWidth\n height: bottomHeight\n\n # Determines wether an element fits into subtrees.\n fitting = (element, tree) ->\n where = []\n for direction, coordinates of splitTree tree when boundingBoxCollision element, coordinates\n where.push direction\n where\n\n # Add getters and setters for coordinates and dimensions properties in order to automatically reorganize the elements on change.\n observe = (item, tree) ->\n writeAccessors = (propName) ->\n item[\"_#{propName}\"] = item[propName]\n Object.defineProperty item, propName, {\n set: (val) ->\n tree.remove @\n @[\"_#{propName}\"] = val\n tree.push @\n get: ->\n @[\"_#{propName}\"]\n configurable: true\n }\n writeAccessors \"x\"\n writeAccessors \"y\"\n writeAccessors \"width\"\n writeAccessors \"height\"\n\n # ### Exposed methods\n\n # Add an element to the quadtree.\n # Elements can be observed to reorganize them into the quadtree automatically whenever their coordinates or dimensions are set (for ex. obj.x = ...).\n push: (item, doObserve) ->\n @pushAll([item], doObserve)\n\n # Push an array of elements.\n pushAll : (items, doObserve) ->\n for item in items\n validateElement item\n observe item, @ if doObserve\n\n fifo = [tree: @, elements: items]\n\n while fifo.length > 0\n { tree, elements } = fifo.shift()\n\n fifoCandidates = { \"NW\": null, \"NE\": null, \"SW\": null, \"SE\": null }\n\n for element in elements\n tree.size++\n\n fits = fitting element, tree\n\n if fits.length isnt 1 or tree.width is 1 or tree.height is 1\n tree.oversized.push element\n\n else if (tree.size - tree.oversized.length) <= tree.maxElements\n tree.contents.push element\n\n else\n direction = fits[0]\n relatedChild = tree.children[direction]\n fifoCandidates[direction] ?= { tree: relatedChild.get(), elements: [] }\n fifoCandidates[direction].elements.push(element)\n\n for content in tree.contents\n contentDir = (fitting content, tree)[0]\n fifoCandidates[contentDir] ?= { tree: tree.children[contentDir].get(), elements: [] }\n fifoCandidates[contentDir].elements.push(content)\n\n tree.contents = []\n\n for direction, candidate of fifoCandidates\n if candidate? then fifo.push candidate\n\n @\n\n # Removes an element from the quadtree.\n remove: (item) ->\n validateElement item\n\n index = @oversized.indexOf item\n if index > - 1\n @oversized.splice index, 1\n @size--\n return true\n\n index = @contents.indexOf item\n if index > - 1\n @contents.splice index, 1\n @size--\n return true\n\n relatedChild = @children[calculateDirection item, @]\n\n if relatedChild.tree? and relatedChild.tree.remove item\n @size--\n relatedChild.tree = null if relatedChild.tree.size is 0\n return true\n\n false\n\n # Returns an array of elements which collides with the `item` argument.\n # `item` being an object having x, y, width & height properties.\n\n # The default collision function is a basic bounding box algorithm.\n # You can change it by providing a function as a second argument.\n #```javascript\n #colliding({x: 10, y: 20}, function(element1, element2){\n # return // Place predicate here //\n #})\n #```\n colliding: (item, collisionFunction) ->\n validateElement item\n\n collisionFunction ?= boundingBoxCollision\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized when elt isnt item and collisionFunction item, elt then items.push elt\n for elt in top.contents when elt isnt item and collisionFunction item, elt then items.push elt\n\n fits = fitting item, top\n\n # Special case for elements located outside of the quadtree on the right / bottom side\n if fits.length is 0\n fits = []\n if item.x >= top.x + top.width\n fits.push \"NE\"\n if item.y >= top.y + top.height\n fits.push \"SW\"\n if fits.length > 0\n if fits.length is 1 then fits.push \"SE\" else fits = [\"SE\"]\n\n for child in fits when top.children[child].tree?\n fifo.push top.children[child].tree\n\n items\n\n # Alias of `where`.\n get: (query) ->\n @where query\n # Returns an array of elements that match the `query` argument.\n where: (query) ->\n # Naïve parsing (missing coordinates)\n if typeof query is \"object\" and (not query.x? or not query.y?)\n return @find (elt) ->\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n check\n\n # Optimised parsing\n validateElement query\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n for elt in top.contents\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n\n relatedChild = top.children[calculateDirection query, top]\n\n if relatedChild.tree?\n fifo.push relatedChild.tree\n\n items\n\n # For each element of the quadtree, performs the `action` function.\n #```javascript\n #quad.each(function(item){ console.log(item) })\n #```\n each: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized then action?(i)\n for i in top.contents then action?(i)\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n @\n\n # Returns an array of elements which validates the predicate.\n find: (predicate) ->\n fifo = [@]\n items = []\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized when predicate?(i) then items.push i\n for i in top.contents when predicate?(i) then items.push i\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n items\n\n # Returns a **cloned** `Quadtree` object which contains only the elements that validate the predicate.\n filter: (predicate) ->\n deepclone = (target) ->\n copycat = new Quadtree x: target.x, y: target.y, width: target.width, height: target.height, maxElements: target.maxElements\n copycat.size = 0\n for child of target.children when target.children[child].tree?\n copycat.children[child].tree = deepclone target.children[child].tree\n copycat.size += copycat.children[child].tree?.size ? 0\n\n for item in target.oversized when not predicate? or predicate?(item)\n copycat.oversized.push item\n for item in target.contents when not predicate? or predicate?(item)\n copycat.contents.push item\n\n copycat.size += copycat.oversized.length + copycat.contents.length\n if copycat.size is 0 then null else copycat\n\n deepclone @\n\n # Opposite of filter.\n reject: (predicate) ->\n @filter (i) ->\n not predicate?(i)\n\n # Visits each tree & subtree contained in the `Quadtree` object.\n # For each node, performs the `action` function, inside which `this` is bound to the node tree object.\n visit: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n that = fifo.shift()\n action.bind(that)()\n\n for child of that.children when that.children[child].tree?\n fifo.push that.children[child].tree\n @\n\n # Pretty printing function.\n pretty: ->\n str = \"\"\n\n indent = (level) ->\n res = \"\"\n res += \" \" for times in [level...0]\n res\n\n fifo = [{ label: \"ROOT\", tree: @, level: 0 }]\n while fifo.length > 0\n top = fifo.shift()\n indentation = indent(top.level)\n str += \"\"\"\n #{indentation}| #{top.label}\n #{indentation}| ------------\\n\n \"\"\"\n\n if top.tree.oversized.length > 0\n str += \"\"\"\n #{indentation}| * Oversized elements *\n #{indentation}| #{top.tree.oversized}\\n\n \"\"\"\n\n if top.tree.contents.length > 0\n str += \"\"\"\n #{indentation}| * Leaf content *\n #{indentation}| #{top.tree.contents}\\n\n \"\"\"\n\n isParent = false\n for child of top.tree.children when top.tree.children[child].tree?\n isParent = true\n fifo.unshift { label: child, tree: top.tree.children[child].tree, level: top.level + 1 }\n\n if isParent then str += \"#{indentation}└──┐\\n\"\n\n str\n)\n"]} \ No newline at end of file +{"version":3,"sources":["quadtree.coffee"],"names":["root","factory","define","amd","exports","module","this","Quadtree","arg","child","that","x","y","width","height","maxElements","Error","contents","oversized","size","Number","isInteger","children","NW","create","Math","max","floor","tree","NE","ceil","SW","SE","get","boundingBoxCollision","calculateDirection","fitting","getCenter","observe","splitTree","validateElement","item","ref","ref1","elt1","elt2","ref2","ref3","element","quadCenter","bottomHeight","leftWidth","rightWidth","topHeight","coordinates","direction","where","push","writeAccessors","propName","Object","defineProperty","set","val","remove","configurable","doObserve","pushAll","items","candidate","content","contentDir","elements","fifo","fifoCandidates","fits","j","k","l","len","len1","len2","relatedChild","length","shift","index","indexOf","splice","colliding","collisionFunction","elt","top","query","check","key","find","each","action","i","predicate","filter","deepclone","target","copycat","reject","visit","bind","pretty","indent","indentation","isParent","str","level","res","label","unshift"],"mappings":"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","file":"quadtree.min.js","sourcesContent":["# quadtree-lib\n# ============\n#\n# **Quadtree-lib** is an easy to use, developer friendly quadtree library\n# which contains many helper methods to add, remove, iterate, filter, simulate\n# collisions over 2d elements and more.\n\n# #### UMD bundling related code\n((root, factory) ->\n if typeof define is 'function' and define.amd\n define [], factory\n else if typeof exports is 'object' and module.exports\n module.exports = factory()\n else\n root[\"Quadtree\"] = factory()\n) @, (-> class Quadtree\n # The Quadtree class\n # -------------------\n\n # ### Constructor\n\n # The quadtree constructor accepts a single parameter object containing the following properties :\n # - width / length : dimensions of the quadtree. [ *mandatory* ]\n # - maxElements : the maximum number of elements before the leaf 'splits' into subtrees. [ *defaults to 1* ]\n # - x / y : these coordinates are used internally by the library to position subtrees. [ *internal use only* ]\n constructor: ({@x, @y, @width, @height, @maxElements}) ->\n\n # An error is thrown when the width & length are not passed as constructor arguments.\n throw new Error \"Missing quadtree dimensions.\" if not @width? or not @height?\n @x ?= 0\n @y ?= 0\n @maxElements ?= 1\n @contents = []\n @oversized = []\n @size = 0\n\n # Dimension & coordinates are checked, an error is thrown in case of bad input.\n throw new Error \"Dimensions must be positive integers.\" if @width < 1 or @height < 1\n throw new Error \"Coordinates must be integers\" if not Number.isInteger(@x) or not Number.isInteger(@y)\n throw new Error \"The maximum number of elements before a split must be a positive integer.\" if @maxElements < 1\n\n that = @\n\n # The subtrees list, by position.\n @children = {\n # Northwest tree.\n \"NW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Northeast tree.\n \"NE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y\n width: Math.ceil that.width / 2\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Southwest tree.\n \"SW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n # Southeast tree.\n \"SE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.ceil that.width / 2\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n }\n # Adding a getter which lazily creates the tree.\n for child of @children\n @children[child].get = ->\n if @tree? then @tree else @tree = @create(); @tree\n\n # ### Internal methods & vars\n\n # Retrieves the center coordinates of a rectangle.\n getCenter = (item) ->\n x: Math.floor((item.width ? 1) / 2) + item.x\n y: Math.floor((item.height ? 1) / 2) + item.y\n\n # Bounding box collision algorithm.\n boundingBoxCollision = (elt1, elt2) ->\n not(elt1.x >= elt2.x + (elt2.width ? 1) or\n elt1.x + (elt1.width ? 1) <= elt2.x or\n elt1.y >= elt2.y + (elt2.height ? 1) or\n elt1.y + (elt1.height ? 1) <= elt2.y)\n\n # Determines which subtree an element belongs to.\n calculateDirection = (element, tree) ->\n quadCenter = getCenter tree\n\n if element.x < quadCenter.x\n if element.y < quadCenter.y then \"NW\"\n else \"SW\"\n else\n if element.y < quadCenter.y then \"NE\"\n else \"SE\"\n\n # Validates a potential element of the tree.\n validateElement = (element) ->\n if not (typeof element is \"object\")\n throw new Error \"Element must be an Object.\"\n if not element.x? or not element.y?\n throw new Error \"Coordinates properties are missing.\"\n if element?.width < 0 or element?.height < 0\n throw new Error \"Width and height must be positive integers.\"\n\n # Returns splitted coordinates and dimensions.\n splitTree = (tree) ->\n leftWidth = Math.max (Math.floor tree.width / 2), 1\n rightWidth = Math.ceil tree.width / 2\n topHeight = Math.max (Math.floor tree.height / 2), 1\n bottomHeight = Math.ceil tree.height / 2\n \"NW\":\n x: tree.x\n y: tree.y\n width: leftWidth\n height: topHeight\n \"NE\":\n x: tree.x + leftWidth\n y: tree.y\n width: rightWidth\n height: topHeight\n \"SW\":\n x: tree.x\n y: tree.y + topHeight\n width: leftWidth\n height: bottomHeight\n \"SE\":\n x: tree.x + leftWidth\n y: tree.y + topHeight\n width: rightWidth\n height: bottomHeight\n\n # Determines wether an element fits into subtrees.\n fitting = (element, tree) ->\n where = []\n for direction, coordinates of splitTree tree when boundingBoxCollision element, coordinates\n where.push direction\n where\n\n # Add getters and setters for coordinates and dimensions properties in order to automatically reorganize the elements on change.\n observe = (item, tree) ->\n writeAccessors = (propName) ->\n item[\"_#{propName}\"] = item[propName]\n Object.defineProperty item, propName, {\n set: (val) ->\n tree.remove @\n @[\"_#{propName}\"] = val\n tree.push @\n get: ->\n @[\"_#{propName}\"]\n configurable: true\n }\n writeAccessors \"x\"\n writeAccessors \"y\"\n writeAccessors \"width\"\n writeAccessors \"height\"\n\n # ### Exposed methods\n\n # Add an element to the quadtree.\n # Elements can be observed to reorganize them into the quadtree automatically whenever their coordinates or dimensions are set (for ex. obj.x = ...).\n push: (item, doObserve) ->\n @pushAll([item], doObserve)\n\n # Push an array of elements.\n pushAll : (items, doObserve) ->\n for item in items\n validateElement item\n observe item, @ if doObserve\n\n fifo = [tree: @, elements: items]\n\n while fifo.length > 0\n { tree, elements } = fifo.shift()\n\n fifoCandidates = { \"NW\": null, \"NE\": null, \"SW\": null, \"SE\": null }\n\n for element in elements\n tree.size++\n\n fits = fitting element, tree\n\n if fits.length isnt 1 or tree.width is 1 or tree.height is 1\n tree.oversized.push element\n\n else if (tree.size - tree.oversized.length) <= tree.maxElements\n tree.contents.push element\n\n else\n direction = fits[0]\n relatedChild = tree.children[direction]\n fifoCandidates[direction] ?= { tree: relatedChild.get(), elements: [] }\n fifoCandidates[direction].elements.push(element)\n\n for content in tree.contents\n contentDir = (fitting content, tree)[0]\n fifoCandidates[contentDir] ?= { tree: tree.children[contentDir].get(), elements: [] }\n fifoCandidates[contentDir].elements.push(content)\n\n tree.contents = []\n\n for direction, candidate of fifoCandidates\n if candidate? then fifo.push candidate\n\n @\n\n # Removes an element from the quadtree.\n remove: (item) ->\n validateElement item\n\n index = @oversized.indexOf item\n if index > - 1\n @oversized.splice index, 1\n @size--\n return true\n\n index = @contents.indexOf item\n if index > - 1\n @contents.splice index, 1\n @size--\n return true\n\n relatedChild = @children[calculateDirection item, @]\n\n if relatedChild.tree? and relatedChild.tree.remove item\n @size--\n relatedChild.tree = null if relatedChild.tree.size is 0\n return true\n\n false\n\n # Returns an array of elements which collides with the `item` argument.\n # `item` being an object having x, y, width & height properties.\n\n # The default collision function is a basic bounding box algorithm.\n # You can change it by providing a function as a second argument.\n #```javascript\n #colliding({x: 10, y: 20}, function(element1, element2){\n # return // Place predicate here //\n #})\n #```\n colliding: (item, collisionFunction) ->\n validateElement item\n\n collisionFunction ?= boundingBoxCollision\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized when elt isnt item and collisionFunction item, elt then items.push elt\n for elt in top.contents when elt isnt item and collisionFunction item, elt then items.push elt\n\n fits = fitting item, top\n\n # Special case for elements located outside of the quadtree on the right / bottom side\n if fits.length is 0\n fits = []\n if item.x >= top.x + top.width\n fits.push \"NE\"\n if item.y >= top.y + top.height\n fits.push \"SW\"\n if fits.length > 0\n if fits.length is 1 then fits.push \"SE\" else fits = [\"SE\"]\n\n for child in fits when top.children[child].tree?\n fifo.push top.children[child].tree\n\n items\n\n # Alias of `where`.\n get: (query) ->\n @where query\n # Returns an array of elements that match the `query` argument.\n where: (query) ->\n # Naïve parsing (missing coordinates)\n if typeof query is \"object\" and (not query.x? or not query.y?)\n return @find (elt) ->\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n check\n\n # Optimised parsing\n validateElement query\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n for elt in top.contents\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n\n relatedChild = top.children[calculateDirection query, top]\n\n if relatedChild.tree?\n fifo.push relatedChild.tree\n\n items\n\n # For each element of the quadtree, performs the `action` function.\n #```javascript\n #quad.each(function(item){ console.log(item) })\n #```\n each: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized then action?(i)\n for i in top.contents then action?(i)\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n @\n\n # Returns an array of elements which validates the predicate.\n find: (predicate) ->\n fifo = [@]\n items = []\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized when predicate?(i) then items.push i\n for i in top.contents when predicate?(i) then items.push i\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n items\n\n # Returns a **cloned** `Quadtree` object which contains only the elements that validate the predicate.\n filter: (predicate) ->\n deepclone = (target) ->\n copycat = new Quadtree x: target.x, y: target.y, width: target.width, height: target.height, maxElements: target.maxElements\n copycat.size = 0\n for child of target.children when target.children[child].tree?\n copycat.children[child].tree = deepclone target.children[child].tree\n copycat.size += copycat.children[child].tree?.size ? 0\n\n for item in target.oversized when not predicate? or predicate?(item)\n copycat.oversized.push item\n for item in target.contents when not predicate? or predicate?(item)\n copycat.contents.push item\n\n copycat.size += copycat.oversized.length + copycat.contents.length\n if copycat.size is 0 then null else copycat\n\n deepclone @\n\n # Opposite of filter.\n reject: (predicate) ->\n @filter (i) ->\n not predicate?(i)\n\n # Visits each tree & subtree contained in the `Quadtree` object.\n # For each node, performs the `action` function, inside which `this` is bound to the node tree object.\n visit: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n that = fifo.shift()\n action.bind(that)()\n\n for child of that.children when that.children[child].tree?\n fifo.push that.children[child].tree\n @\n\n # Pretty printing function.\n pretty: ->\n str = \"\"\n\n indent = (level) ->\n res = \"\"\n res += \" \" for times in [level...0]\n res\n\n fifo = [{ label: \"ROOT\", tree: @, level: 0 }]\n while fifo.length > 0\n top = fifo.shift()\n indentation = indent(top.level)\n str += \"\"\"\n #{indentation}| #{top.label}\n #{indentation}| ------------\\n\n \"\"\"\n\n if top.tree.oversized.length > 0\n str += \"\"\"\n #{indentation}| * Oversized elements *\n #{indentation}| #{top.tree.oversized}\\n\n \"\"\"\n\n if top.tree.contents.length > 0\n str += \"\"\"\n #{indentation}| * Leaf content *\n #{indentation}| #{top.tree.contents}\\n\n \"\"\"\n\n isParent = false\n for child of top.tree.children when top.tree.children[child].tree?\n isParent = true\n fifo.unshift { label: child, tree: top.tree.children[child].tree, level: top.level + 1 }\n\n if isParent then str += \"#{indentation}└──┐\\n\"\n\n str\n)\n"]} \ No newline at end of file diff --git a/docs/demo/quadtree.min.js b/docs/demo/quadtree.min.js index a112ec0..25be8b9 100644 --- a/docs/demo/quadtree.min.js +++ b/docs/demo/quadtree.min.js @@ -1,2 +1,2 @@ -!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports&&module.exports?module.exports=t():e.Quadtree=t()}(this,function(){return function(){function e(t){var n,i;if(this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height,this.maxElements=t.maxElements,null==this.width||null==this.height)throw new Error("Missing quadtree dimensions.");if(null==this.x&&(this.x=0),null==this.y&&(this.y=0),null==this.maxElements&&(this.maxElements=1),this.contents=[],this.oversized=[],this.size=0,this.x<0||this.y<0||this.width<1||this.height<1)throw new Error("Dimensions and coordinates must be positive integers.");if(this.maxElements<1)throw new Error("The maximum number of elements before a split must be a positive integer.");i=this,this.children={NW:{create:function(){return new e({x:i.x,y:i.y,width:Math.max(Math.floor(i.width/2),1),height:Math.max(Math.floor(i.height/2),1),maxElements:i.maxElements})},tree:null},NE:{create:function(){return new e({x:i.x+Math.max(Math.floor(i.width/2),1),y:i.y,width:Math.ceil(i.width/2),height:Math.max(Math.floor(i.height/2),1),maxElements:i.maxElements})},tree:null},SW:{create:function(){return new e({x:i.x,y:i.y+Math.max(Math.floor(i.height/2),1),width:Math.max(Math.floor(i.width/2),1),height:Math.ceil(i.height/2),maxElements:i.maxElements})},tree:null},SE:{create:function(){return new e({x:i.x+Math.max(Math.floor(i.width/2),1),y:i.y+Math.max(Math.floor(i.height/2),1),width:Math.ceil(i.width/2),height:Math.ceil(i.height/2),maxElements:i.maxElements})},tree:null}};for(n in this.children)this.children[n].get=function(){return null!=this.tree?this.tree:(this.tree=this.create(),this.tree)}}var t,n,i,r,h,l,o;return r=function(e){var t,n;return{x:Math.floor((null!=(t=e.width)?t:1)/2)+e.x,y:Math.floor((null!=(n=e.height)?n:1)/2)+e.y}},t=function(e,t){var n,i,r,h;return!(e.x>=t.x+(null!=(n=t.width)?n:1)||e.x+(null!=(i=e.width)?i:1)<=t.x||e.y>=t.y+(null!=(r=t.height)?r:1)||e.y+(null!=(h=e.height)?h:1)<=t.y)},n=function(e,t){var n;return n=r(t),e.x0;){for(E=c.shift(),b=E.tree,f=E.elements,d={NW:null,NE:null,SW:null,SE:null},m=0,v=f.length;m-1?(this.oversized.splice(t,1),this.size--,!0):(t=this.contents.indexOf(e))>-1?(this.contents.splice(t,1),this.size--,!0):(i=this.children[n(e,this)],!(null==i.tree||!i.tree.remove(e))&&(this.size--,0===i.tree.size&&(i.tree=null),!0))},e.prototype.colliding=function(e,n){var r,h,l,s,u,f,c,d,a,p,g,m,x,y;for(o(e),null==n&&(n=t),u=[],l=[this];l.length>0;){for(y=l.shift(),m=y.oversized,f=0,a=m.length;f=y.x+y.width&&s.push("NE"),e.y>=y.y+y.height&&s.push("SW"),s.length>0&&(1===s.length?s.push("SE"):s=["SE"])),d=0,g=s.length;d0;){for(g=r.shift(),d=g.oversized,l=0,f=d.length;l0;){for(f=n.shift(),s=f.oversized,r=0,l=s.length;r0;){for(c=n.shift(),u=c.oversized,h=0,o=u.length;h0;){i=n.shift(),e.bind(i)();for(t in i.children)null!=i.children[t].tree&&n.push(i.children[t].tree)}return this},e.prototype.pretty=function(){var e,t,n,i,r,h,l;for(h="",n=function(e){var t,n,i;for(i="",t=n=e;n<=0?t<0:t>0;n<=0?++t:--t)i+=" ";return i},t=[{label:"ROOT",tree:this,level:0}];t.length>0;){l=t.shift(),i=n(l.level),h+=i+"| "+l.label+"\n"+i+"| ------------\n",l.tree.oversized.length>0&&(h+=i+"| * Oversized elements *\n"+i+"| "+l.tree.oversized+"\n"),l.tree.contents.length>0&&(h+=i+"| * Leaf content *\n"+i+"| "+l.tree.contents+"\n"),r=!1;for(e in l.tree.children)null!=l.tree.children[e].tree&&(r=!0,t.unshift({label:e,tree:l.tree.children[e].tree,level:l.level+1}));r&&(h+=i+"└──┐\n")}return h},e}()}); +!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports&&module.exports?module.exports=t():e.Quadtree=t()}(this,function(){return function(){function e(t){var n,i;if(this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height,this.maxElements=t.maxElements,null==this.width||null==this.height)throw new Error("Missing quadtree dimensions.");if(null==this.x&&(this.x=0),null==this.y&&(this.y=0),null==this.maxElements&&(this.maxElements=1),this.contents=[],this.oversized=[],this.size=0,this.width<1||this.height<1)throw new Error("Dimensions must be positive integers.");if(!Number.isInteger(this.x)||!Number.isInteger(this.y))throw new Error("Coordinates must be integers");if(this.maxElements<1)throw new Error("The maximum number of elements before a split must be a positive integer.");i=this,this.children={NW:{create:function(){return new e({x:i.x,y:i.y,width:Math.max(Math.floor(i.width/2),1),height:Math.max(Math.floor(i.height/2),1),maxElements:i.maxElements})},tree:null},NE:{create:function(){return new e({x:i.x+Math.max(Math.floor(i.width/2),1),y:i.y,width:Math.ceil(i.width/2),height:Math.max(Math.floor(i.height/2),1),maxElements:i.maxElements})},tree:null},SW:{create:function(){return new e({x:i.x,y:i.y+Math.max(Math.floor(i.height/2),1),width:Math.max(Math.floor(i.width/2),1),height:Math.ceil(i.height/2),maxElements:i.maxElements})},tree:null},SE:{create:function(){return new e({x:i.x+Math.max(Math.floor(i.width/2),1),y:i.y+Math.max(Math.floor(i.height/2),1),width:Math.ceil(i.width/2),height:Math.ceil(i.height/2),maxElements:i.maxElements})},tree:null}};for(n in this.children)this.children[n].get=function(){return null!=this.tree?this.tree:(this.tree=this.create(),this.tree)}}var t,n,i,r,h,l,o;return r=function(e){var t,n;return{x:Math.floor((null!=(t=e.width)?t:1)/2)+e.x,y:Math.floor((null!=(n=e.height)?n:1)/2)+e.y}},t=function(e,t){var n,i,r,h;return!(e.x>=t.x+(null!=(n=t.width)?n:1)||e.x+(null!=(i=e.width)?i:1)<=t.x||e.y>=t.y+(null!=(r=t.height)?r:1)||e.y+(null!=(h=e.height)?h:1)<=t.y)},n=function(e,t){var n;return n=r(t),e.x0;){for(E=c.shift(),b=E.tree,f=E.elements,d={NW:null,NE:null,SW:null,SE:null},m=0,v=f.length;m-1?(this.oversized.splice(t,1),this.size--,!0):(t=this.contents.indexOf(e))>-1?(this.contents.splice(t,1),this.size--,!0):(i=this.children[n(e,this)],!(null==i.tree||!i.tree.remove(e))&&(this.size--,0===i.tree.size&&(i.tree=null),!0))},e.prototype.colliding=function(e,n){var r,h,l,s,u,f,c,d,a,g,p,m,x,y;for(o(e),null==n&&(n=t),u=[],l=[this];l.length>0;){for(y=l.shift(),m=y.oversized,f=0,a=m.length;f=y.x+y.width&&s.push("NE"),e.y>=y.y+y.height&&s.push("SW"),s.length>0&&(1===s.length?s.push("SE"):s=["SE"])),d=0,p=s.length;d0;){for(p=r.shift(),d=p.oversized,l=0,f=d.length;l0;){for(f=n.shift(),s=f.oversized,r=0,l=s.length;r0;){for(c=n.shift(),u=c.oversized,h=0,o=u.length;h0;){i=n.shift(),e.bind(i)();for(t in i.children)null!=i.children[t].tree&&n.push(i.children[t].tree)}return this},e.prototype.pretty=function(){var e,t,n,i,r,h,l;for(h="",n=function(e){var t,n,i;for(i="",t=n=e;n<=0?t<0:t>0;n<=0?++t:--t)i+=" ";return i},t=[{label:"ROOT",tree:this,level:0}];t.length>0;){l=t.shift(),i=n(l.level),h+=i+"| "+l.label+"\n"+i+"| ------------\n",l.tree.oversized.length>0&&(h+=i+"| * Oversized elements *\n"+i+"| "+l.tree.oversized+"\n"),l.tree.contents.length>0&&(h+=i+"| * Leaf content *\n"+i+"| "+l.tree.contents+"\n"),r=!1;for(e in l.tree.children)null!=l.tree.children[e].tree&&(r=!0,t.unshift({label:e,tree:l.tree.children[e].tree,level:l.level+1}));r&&(h+=i+"└──┐\n")}return h},e}()}); //# sourceMappingURL=quadtree.min.js.map diff --git a/docs/demo/quadtree.min.js.map b/docs/demo/quadtree.min.js.map index 9159962..d47ad6d 100644 --- a/docs/demo/quadtree.min.js.map +++ b/docs/demo/quadtree.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["quadtree.coffee"],"names":["root","factory","define","amd","exports","module","this","Quadtree","arg","child","that","x","y","width","height","maxElements","Error","contents","oversized","size","children","NW","create","Math","max","floor","tree","NE","ceil","SW","SE","get","boundingBoxCollision","calculateDirection","fitting","getCenter","observe","splitTree","validateElement","item","ref","ref1","elt1","elt2","ref2","ref3","element","quadCenter","bottomHeight","leftWidth","rightWidth","topHeight","coordinates","direction","where","push","writeAccessors","propName","Object","defineProperty","set","val","remove","configurable","doObserve","pushAll","items","candidate","content","contentDir","elements","fifo","fifoCandidates","fits","j","k","l","len","len1","len2","relatedChild","length","shift","index","indexOf","splice","colliding","collisionFunction","elt","top","query","check","key","find","each","action","i","predicate","filter","deepclone","target","copycat","reject","visit","bind","pretty","indent","indentation","isParent","str","level","res","label","unshift"],"mappings":"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","file":"quadtree.min.js","sourcesContent":["# quadtree-lib\n# ============\n#\n# **Quadtree-lib** is an easy to use, developer friendly quadtree library\n# which contains many helper methods to add, remove, iterate, filter, simulate\n# collisions over 2d elements and more.\n\n# #### UMD bundling related code\n((root, factory) ->\n if typeof define is 'function' and define.amd\n define [], factory\n else if typeof exports is 'object' and module.exports\n module.exports = factory()\n else\n root[\"Quadtree\"] = factory()\n) @, (-> class Quadtree\n # The Quadtree class\n # -------------------\n\n # ### Constructor\n\n # The quadtree constructor accepts a single parameter object containing the following properties :\n # - width / length : dimensions of the quadtree. [ *mandatory* ]\n # - maxElements : the maximum number of elements before the leaf 'splits' into subtrees. [ *defaults to 1* ]\n # - x / y : these coordinates are used internally by the library to position subtrees. [ *internal use only* ]\n constructor: ({@x, @y, @width, @height, @maxElements}) ->\n\n # An error is thrown when the width & length are not passed as constructor arguments.\n throw new Error \"Missing quadtree dimensions.\" if not @width? or not @height?\n @x ?= 0\n @y ?= 0\n @maxElements ?= 1\n @contents = []\n @oversized = []\n @size = 0\n\n # Dimension & coordinates are checked, an error is thrown in case of bad input.\n throw new Error \"Dimensions and coordinates must be positive integers.\" if @x < 0 or @y < 0 or @width < 1 or @height < 1\n throw new Error \"The maximum number of elements before a split must be a positive integer.\" if @maxElements < 1\n\n that = @\n\n # The subtrees list, by position.\n @children = {\n # Northwest tree.\n \"NW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Northeast tree.\n \"NE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y\n width: Math.ceil that.width / 2\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Southwest tree.\n \"SW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n # Southeast tree.\n \"SE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.ceil that.width / 2\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n }\n # Adding a getter which lazily creates the tree.\n for child of @children\n @children[child].get = ->\n if @tree? then @tree else @tree = @create(); @tree\n\n # ### Internal methods & vars\n\n # Retrieves the center coordinates of a rectangle.\n getCenter = (item) ->\n x: Math.floor((item.width ? 1) / 2) + item.x\n y: Math.floor((item.height ? 1) / 2) + item.y\n\n # Bounding box collision algorithm.\n boundingBoxCollision = (elt1, elt2) ->\n not(elt1.x >= elt2.x + (elt2.width ? 1) or\n elt1.x + (elt1.width ? 1) <= elt2.x or\n elt1.y >= elt2.y + (elt2.height ? 1) or\n elt1.y + (elt1.height ? 1) <= elt2.y)\n\n # Determines which subtree an element belongs to.\n calculateDirection = (element, tree) ->\n quadCenter = getCenter tree\n\n if element.x < quadCenter.x\n if element.y < quadCenter.y then \"NW\"\n else \"SW\"\n else\n if element.y < quadCenter.y then \"NE\"\n else \"SE\"\n\n # Validates a potential element of the tree.\n validateElement = (element) ->\n if not (typeof element is \"object\")\n throw new Error \"Element must be an Object.\"\n if not element.x? or not element.y?\n throw new Error \"Coordinates properties are missing.\"\n if element?.width < 0 or element?.height < 0\n throw new Error \"Width and height must be positive integers.\"\n\n # Returns splitted coordinates and dimensions.\n splitTree = (tree) ->\n leftWidth = Math.max (Math.floor tree.width / 2), 1\n rightWidth = Math.ceil tree.width / 2\n topHeight = Math.max (Math.floor tree.height / 2), 1\n bottomHeight = Math.ceil tree.height / 2\n \"NW\":\n x: tree.x\n y: tree.y\n width: leftWidth\n height: topHeight\n \"NE\":\n x: tree.x + leftWidth\n y: tree.y\n width: rightWidth\n height: topHeight\n \"SW\":\n x: tree.x\n y: tree.y + topHeight\n width: leftWidth\n height: bottomHeight\n \"SE\":\n x: tree.x + leftWidth\n y: tree.y + topHeight\n width: rightWidth\n height: bottomHeight\n\n # Determines wether an element fits into subtrees.\n fitting = (element, tree) ->\n where = []\n for direction, coordinates of splitTree tree when boundingBoxCollision element, coordinates\n where.push direction\n where\n\n # Add getters and setters for coordinates and dimensions properties in order to automatically reorganize the elements on change.\n observe = (item, tree) ->\n writeAccessors = (propName) ->\n item[\"_#{propName}\"] = item[propName]\n Object.defineProperty item, propName, {\n set: (val) ->\n tree.remove @\n @[\"_#{propName}\"] = val\n tree.push @\n get: ->\n @[\"_#{propName}\"]\n configurable: true\n }\n writeAccessors \"x\"\n writeAccessors \"y\"\n writeAccessors \"width\"\n writeAccessors \"height\"\n\n # ### Exposed methods\n\n # Add an element to the quadtree.\n # Elements can be observed to reorganize them into the quadtree automatically whenever their coordinates or dimensions are set (for ex. obj.x = ...).\n push: (item, doObserve) ->\n @pushAll([item], doObserve)\n\n # Push an array of elements.\n pushAll : (items, doObserve) ->\n for item in items\n validateElement item\n observe item, @ if doObserve\n\n fifo = [tree: @, elements: items]\n\n while fifo.length > 0\n { tree, elements } = fifo.shift()\n\n fifoCandidates = { \"NW\": null, \"NE\": null, \"SW\": null, \"SE\": null }\n\n for element in elements\n tree.size++\n\n fits = fitting element, tree\n\n if fits.length isnt 1 or tree.width is 1 or tree.height is 1\n tree.oversized.push element\n\n else if (tree.size - tree.oversized.length) <= tree.maxElements\n tree.contents.push element\n\n else\n direction = fits[0]\n relatedChild = tree.children[direction]\n fifoCandidates[direction] ?= { tree: relatedChild.get(), elements: [] }\n fifoCandidates[direction].elements.push(element)\n\n for content in tree.contents\n contentDir = (fitting content, tree)[0]\n fifoCandidates[contentDir] ?= { tree: tree.children[contentDir].get(), elements: [] }\n fifoCandidates[contentDir].elements.push(content)\n\n tree.contents = []\n\n for direction, candidate of fifoCandidates\n if candidate? then fifo.push candidate\n\n @\n\n # Removes an element from the quadtree.\n remove: (item) ->\n validateElement item\n\n index = @oversized.indexOf item\n if index > - 1\n @oversized.splice index, 1\n @size--\n return true\n\n index = @contents.indexOf item\n if index > - 1\n @contents.splice index, 1\n @size--\n return true\n\n relatedChild = @children[calculateDirection item, @]\n\n if relatedChild.tree? and relatedChild.tree.remove item\n @size--\n relatedChild.tree = null if relatedChild.tree.size is 0\n return true\n\n false\n\n # Returns an array of elements which collides with the `item` argument.\n # `item` being an object having x, y, width & height properties.\n\n # The default collision function is a basic bounding box algorithm.\n # You can change it by providing a function as a second argument.\n #```javascript\n #colliding({x: 10, y: 20}, function(element1, element2){\n # return // Place predicate here //\n #})\n #```\n colliding: (item, collisionFunction) ->\n validateElement item\n\n collisionFunction ?= boundingBoxCollision\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized when elt isnt item and collisionFunction item, elt then items.push elt\n for elt in top.contents when elt isnt item and collisionFunction item, elt then items.push elt\n\n fits = fitting item, top\n\n # Special case for elements located outside of the quadtree on the right / bottom side\n if fits.length is 0\n fits = []\n if item.x >= top.x + top.width\n fits.push \"NE\"\n if item.y >= top.y + top.height\n fits.push \"SW\"\n if fits.length > 0\n if fits.length is 1 then fits.push \"SE\" else fits = [\"SE\"]\n\n for child in fits when top.children[child].tree?\n fifo.push top.children[child].tree\n\n items\n\n # Alias of `where`.\n get: (query) ->\n @where query\n # Returns an array of elements that match the `query` argument.\n where: (query) ->\n # Naïve parsing (missing coordinates)\n if typeof query is \"object\" and (not query.x? or not query.y?)\n return @find (elt) ->\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n check\n\n # Optimised parsing\n validateElement query\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n for elt in top.contents\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n\n relatedChild = top.children[calculateDirection query, top]\n\n if relatedChild.tree?\n fifo.push relatedChild.tree\n\n items\n\n # For each element of the quadtree, performs the `action` function.\n #```javascript\n #quad.each(function(item){ console.log(item) })\n #```\n each: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized then action?(i)\n for i in top.contents then action?(i)\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n @\n\n # Returns an array of elements which validates the predicate.\n find: (predicate) ->\n fifo = [@]\n items = []\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized when predicate?(i) then items.push i\n for i in top.contents when predicate?(i) then items.push i\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n items\n\n # Returns a **cloned** `Quadtree` object which contains only the elements that validate the predicate.\n filter: (predicate) ->\n deepclone = (target) ->\n copycat = new Quadtree x: target.x, y: target.y, width: target.width, height: target.height, maxElements: target.maxElements\n copycat.size = 0\n for child of target.children when target.children[child].tree?\n copycat.children[child].tree = deepclone target.children[child].tree\n copycat.size += copycat.children[child].tree?.size ? 0\n\n for item in target.oversized when not predicate? or predicate?(item)\n copycat.oversized.push item\n for item in target.contents when not predicate? or predicate?(item)\n copycat.contents.push item\n\n copycat.size += copycat.oversized.length + copycat.contents.length\n if copycat.size is 0 then null else copycat\n\n deepclone @\n\n # Opposite of filter.\n reject: (predicate) ->\n @filter (i) ->\n not predicate?(i)\n\n # Visits each tree & subtree contained in the `Quadtree` object.\n # For each node, performs the `action` function, inside which `this` is bound to the node tree object.\n visit: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n that = fifo.shift()\n action.bind(that)()\n\n for child of that.children when that.children[child].tree?\n fifo.push that.children[child].tree\n @\n\n # Pretty printing function.\n pretty: ->\n str = \"\"\n\n indent = (level) ->\n res = \"\"\n res += \" \" for times in [level...0]\n res\n\n fifo = [{ label: \"ROOT\", tree: @, level: 0 }]\n while fifo.length > 0\n top = fifo.shift()\n indentation = indent(top.level)\n str += \"\"\"\n #{indentation}| #{top.label}\n #{indentation}| ------------\\n\n \"\"\"\n\n if top.tree.oversized.length > 0\n str += \"\"\"\n #{indentation}| * Oversized elements *\n #{indentation}| #{top.tree.oversized}\\n\n \"\"\"\n\n if top.tree.contents.length > 0\n str += \"\"\"\n #{indentation}| * Leaf content *\n #{indentation}| #{top.tree.contents}\\n\n \"\"\"\n\n isParent = false\n for child of top.tree.children when top.tree.children[child].tree?\n isParent = true\n fifo.unshift { label: child, tree: top.tree.children[child].tree, level: top.level + 1 }\n\n if isParent then str += \"#{indentation}└──┐\\n\"\n\n str\n)\n"]} \ No newline at end of file +{"version":3,"sources":["quadtree.coffee"],"names":["root","factory","define","amd","exports","module","this","Quadtree","arg","child","that","x","y","width","height","maxElements","Error","contents","oversized","size","Number","isInteger","children","NW","create","Math","max","floor","tree","NE","ceil","SW","SE","get","boundingBoxCollision","calculateDirection","fitting","getCenter","observe","splitTree","validateElement","item","ref","ref1","elt1","elt2","ref2","ref3","element","quadCenter","bottomHeight","leftWidth","rightWidth","topHeight","coordinates","direction","where","push","writeAccessors","propName","Object","defineProperty","set","val","remove","configurable","doObserve","pushAll","items","candidate","content","contentDir","elements","fifo","fifoCandidates","fits","j","k","l","len","len1","len2","relatedChild","length","shift","index","indexOf","splice","colliding","collisionFunction","elt","top","query","check","key","find","each","action","i","predicate","filter","deepclone","target","copycat","reject","visit","bind","pretty","indent","indentation","isParent","str","level","res","label","unshift"],"mappings":"CAQA,SAAEA,EAAMC,GACgB,kBAAVC,SAAyBA,OAAOC,IACtCD,UAAWD,GACW,gBAAXG,UAAwBC,OAAOD,QAC1CC,OAAOD,QAAUH,IAEjBD,EAAK,SAAcC,KACzBK,KAAG,iBAAU,YAUE,QAAAC,GAACC,GAGV,GAAAC,GAAAC,CAAA,IAHWJ,KAACK,EAAAH,EAAAG,EAAGL,KAACM,EAAAJ,EAAAI,EAAGN,KAACO,MAAAL,EAAAK,MAAOP,KAACQ,OAAAN,EAAAM,OAAQR,KAACS,YAAAP,EAAAO,YAGiB,MAAAT,KAAAO,OAAe,MAAAP,KAAAQ,OAArE,KAAM,IAAIE,OAAM,+BAShB,mBARAV,KAACK,EAAK,kBACNL,KAACM,EAAK,4BACNN,KAACS,YAAe,GAChBT,KAACW,YACDX,KAACY,aACDZ,KAACa,KAAO,EAGmDb,KAACO,MAAQ,GAAKP,KAACQ,OAAS,EAAnF,KAAM,IAAIE,OAAM,wCAChB,KAAsDI,OAAOC,UAAUf,KAACK,KAAUS,OAAOC,UAAUf,KAACM,GAApG,KAAM,IAAII,OAAM,+BAChB,IAA+FV,KAACS,YAAc,EAA9G,KAAM,IAAIC,OAAM,4EAEhBN,GAAOJ,KAGPA,KAACgB,UAEGC,IACIC,OAAQ,iBACJ,IAAIjB,IACAI,EAAGD,EAAKC,EACRC,EAAGF,EAAKE,EACRC,MAAOY,KAAKC,IAAKD,KAAKE,MAAMjB,EAAKG,MAAQ,GAAI,GAC7CC,OAAQW,KAAKC,IAAKD,KAAKE,MAAMjB,EAAKI,OAAS,GAAI,GAC/CC,YAAaL,EAAKK,eAE1Ba,KAAM,MAEVC,IACIL,OAAQ,iBACJ,IAAIjB,IACAI,EAAGD,EAAKC,EAAIc,KAAKC,IAAKD,KAAKE,MAAMjB,EAAKG,MAAQ,GAAI,GAClDD,EAAGF,EAAKE,EACRC,MAAOY,KAAKK,KAAKpB,EAAKG,MAAQ,GAC9BC,OAAQW,KAAKC,IAAKD,KAAKE,MAAMjB,EAAKI,OAAS,GAAI,GAC/CC,YAAaL,EAAKK,eAE1Ba,KAAM,MAEVG,IACIP,OAAQ,iBACJ,IAAIjB,IACAI,EAAGD,EAAKC,EACRC,EAAGF,EAAKE,EAAIa,KAAKC,IAAKD,KAAKE,MAAMjB,EAAKI,OAAS,GAAI,GACnDD,MAAOY,KAAKC,IAAKD,KAAKE,MAAMjB,EAAKG,MAAQ,GAAI,GAC7CC,OAAQW,KAAKK,KAAKpB,EAAKI,OAAS,GAChCC,YAAaL,EAAKK,eAE1Ba,KAAM,MAEVI,IACIR,OAAQ,iBACJ,IAAIjB,IACAI,EAAGD,EAAKC,EAAIc,KAAKC,IAAKD,KAAKE,MAAMjB,EAAKG,MAAQ,GAAI,GAClDD,EAAGF,EAAKE,EAAIa,KAAKC,IAAKD,KAAKE,MAAMjB,EAAKI,OAAS,GAAI,GACnDD,MAAOY,KAAKK,KAAKpB,EAAKG,MAAQ,GAC9BC,OAAQW,KAAKK,KAAKpB,EAAKI,OAAS,GAChCC,YAAaL,EAAKK,eAE1Ba,KAAM,MAGd,KAAAnB,IAAAH,MAAAgB,SACIhB,KAACgB,SAASb,GAAOwB,IAAM,WACnB,MAAG,OAAA3B,KAAAsB,KAAYtB,KAACsB,MAAUtB,KAACsB,KAAOtB,KAACkB,SAAUlB,KAACsB,OApE1D,GAAAM,GAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,QAyEAH,GAAY,SAACI,GACT,GAAAC,GAAAC,SAAAhC,EAAGc,KAAKE,OAAM,OAAAe,EAAAD,EAAA5B,OAAA6B,EAAe,GAAK,GAAKD,EAAK9B,EAC5CC,EAAGa,KAAKE,OAAM,OAAAgB,EAAAF,EAAA3B,QAAA6B,EAAe,GAAK,GAAKF,EAAK7B,IAGhDsB,EAAuB,SAACU,EAAMC,GAC1B,GAAAH,GAAAC,EAAAG,EAAAC,UAAIH,EAAKjC,GAAKkC,EAAKlC,GAAI,OAAA+B,EAAAG,EAAAhC,OAAA6B,EAAc,IACjCE,EAAKjC,GAAI,OAAAgC,EAAAC,EAAA/B,OAAA8B,EAAc,IAAME,EAAKlC,GAClCiC,EAAKhC,GAAKiC,EAAKjC,GAAI,OAAAkC,EAAAD,EAAA/B,QAAAgC,EAAe,IAClCF,EAAKhC,GAAI,OAAAmC,EAAAH,EAAA9B,QAAAiC,EAAe,IAAMF,EAAKjC,IAG3CuB,EAAqB,SAACa,EAASpB,GAC3B,GAAAqB,EAEA,OAFAA,GAAaZ,EAAUT,GAEpBoB,EAAQrC,EAAIsC,EAAWtC,EACnBqC,EAAQpC,EAAIqC,EAAWrC,EAAO,KAC5B,KAEFoC,EAAQpC,EAAIqC,EAAWrC,EAAO,KAC5B,MAGb4B,EAAkB,SAACQ,GACf,GAA0B,gBAAXA,GACX,KAAM,IAAIhC,OAAM,6BACpB,IAAO,MAAAgC,EAAArC,GAAkB,MAAAqC,EAAApC,EACrB,KAAM,IAAII,OAAM,sCACpB,KAAA,MAAAgC,EAAGA,EAASnC,MAAA,QAAQ,IAAjB,MAAAmC,EAAsBA,EAASlC,OAAA,QAAS,EACvC,KAAM,IAAIE,OAAM,gDAGxBuB,EAAY,SAACX,GACT,GAAAsB,GAAAC,EAAAC,EAAAC,QAAAF,GAAe1B,KAAKC,IAAKD,KAAKE,MAAMC,EAAKf,MAAQ,GAAI,GACrDuC,EAAe3B,KAAKK,KAAKF,EAAKf,MAAQ,GACtCwC,EAAe5B,KAAKC,IAAKD,KAAKE,MAAMC,EAAKd,OAAS,GAAI,GACtDoC,EAAezB,KAAKK,KAAKF,EAAKd,OAAS,IACvCS,IACIZ,EAAGiB,EAAKjB,EACRC,EAAGgB,EAAKhB,EACRC,MAAQsC,EACRrC,OAAQuC,GACZxB,IACIlB,EAAGiB,EAAKjB,EAAIwC,EACZvC,EAAGgB,EAAKhB,EACRC,MAAQuC,EACRtC,OAAQuC,GACZtB,IACIpB,EAAGiB,EAAKjB,EACRC,EAAGgB,EAAKhB,EAAIyC,EACZxC,MAAQsC,EACRrC,OAAQoC,GACZlB,IACIrB,EAAGiB,EAAKjB,EAAIwC,EACZvC,EAAGgB,EAAKhB,EAAIyC,EACZxC,MAAQuC,EACRtC,OAAQoC,KAGhBd,EAAU,SAACY,EAASpB,GAChB,GAAA0B,GAAAC,EAAAb,EAAAc,CAAAA,MACAd,EAAAH,EAAAX,EAAA,KAAA2B,IAAAb,UAAkDR,EAAqBc,EAASM,IAC5EE,EAAMC,KAAKF,SACfC,IAGJlB,EAAU,SAACG,EAAMb,GACb,GAAA8B,SAAAA,GAAiB,SAACC,SACdlB,GAAK,IAAIkB,GAAclB,EAAKkB,GAC5BC,OAAOC,eAAepB,EAAMkB,GACxBG,IAAK,SAACC,SACFnC,GAAKoC,OAAO1D,MACZA,KAAE,IAAIqD,GAAcI,EACpBnC,EAAK6B,KAAKnD,OACd2B,IAAK,iBACD3B,MAAE,IAAIqD,IACVM,cAAc,KAEtBP,EAAe,KACfA,EAAe,KACfA,EAAe,SACfA,EAAe,uBAMnBD,KAAM,SAAChB,EAAMyB,SACT5D,MAAC6D,SAAS1B,GAAOyB,gBAGrBC,QAAU,SAACC,EAAOF,GACd,GAAAG,GAAAC,EAAAC,EAAAhB,EAAAP,EAAAwB,EAAAC,EAAAC,EAAAC,EAAAlC,EAAAmC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAvC,EAAAC,EAAAuC,EAAAtD,CAAA,KAAAgD,EAAA,EAAAG,EAAAX,EAAAe,OAAAP,EAAAG,EAAAH,WACIpC,EAAgBC,GACGyB,GAAnB5B,EAAQG,EAAMnC,KAIlB,KAFAmE,IAAQ7C,KAAMtB,KAAGkE,SAAUJ,IAErBK,EAAKU,OAAS,GAApB,CAKI,IAJAzC,EAAqB+B,EAAKW,QAAxBxD,EAAAc,EAAAd,KAAM4C,EAAA9B,EAAA8B,SAERE,GAAmBnD,GAAM,KAAMM,GAAM,KAAME,GAAM,KAAMC,GAAM,MAE7D6C,EAAA,EAAAG,EAAAR,EAAAW,OAAAN,EAAAG,EAAAH,IAKI,UAJAjD,EAAKT,OAELwD,EAAOvC,EAAQY,EAASpB,GAEJ,IAAjB+C,EAAKQ,QAA+B,IAAdvD,EAAKf,OAA6B,IAAfe,EAAKd,OAC7Cc,EAAKV,UAAUuC,KAAKT,OAEnB,IAAIpB,EAAKT,KAAOS,EAAKV,UAAUiE,QAAWvD,EAAKb,YAChDa,EAAKX,SAASwC,KAAKT,OADlB,CASD,IALAO,EAAYoB,EAAK,GACjBO,EAAetD,EAAKN,SAASiC,gBAC7BmB,EAAenB,IAAgB3B,KAAMsD,EAAajD,MAAOuC,cACzDE,EAAenB,GAAWiB,SAASf,KAAKT,GAExCL,EAAAf,EAAAX,SAAA6D,EAAA,EAAAG,EAAAtC,EAAAwC,OAAAL,EAAAG,EAAAH,WACIP,EAAcnC,EAAQkC,EAAS1C,GAAM,gBACrC8C,EAAeH,IAAiB3C,KAAMA,EAAKN,SAASiD,GAAYtC,MAAOuC,cACvEE,EAAeH,GAAYC,SAASf,KAAKa,EAE7C1C,GAAKX,YAEb,IAAAsC,IAAAmB,GACO,gBAAgBD,EAAKhB,KAAKY,SAErC/D,mBAGJ0D,OAAQ,SAACvB,GACL,GAAA4C,GAAAH,CAGA,OAHA1C,GAAgBC,IAEhB4C,EAAQ/E,KAACY,UAAUoE,QAAQ7C,KACd,GACTnC,KAACY,UAAUqE,OAAOF,EAAO,GACzB/E,KAACa,QACM,IAEXkE,EAAQ/E,KAACW,SAASqE,QAAQ7C,KACb,GACTnC,KAACW,SAASsE,OAAOF,EAAO,GACxB/E,KAACa,QACM,IAEX+D,EAAe5E,KAACgB,SAASa,EAAmBM,EAAMnC,SAE/C,MAAA4E,EAAAtD,OAAuBsD,EAAatD,KAAKoC,OAAOvB,MAC/CnC,KAACa,OACqD,IAA1B+D,EAAatD,KAAKT,OAA9C+D,EAAatD,KAAO,OACb,iBAcf4D,UAAW,SAAC/C,EAAMgD,GACd,GAAAhF,GAAAiF,EAAAjB,EAAAE,EAAAP,EAAAQ,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAvC,EAAAC,EAAAgD,CAOA,KAPAnD,EAAgBC,aAEhBgD,EAAqBvD,GAErBkC,KACAK,GAASnE,MAEHmE,EAAKU,OAAS,GAApB,CAGI,IAFAQ,EAAMlB,EAAKW,QAEX1C,EAAAiD,EAAAzE,UAAA0D,EAAA,EAAAG,EAAArC,EAAAyC,OAAAP,EAAAG,EAAAH,eAAuCnC,GAASgD,EAAkBhD,EAAMiD,IAAStB,EAAMX,KAAKiC,EAC5F,KAAA/C,EAAAgD,EAAA1E,SAAA4D,EAAA,EAAAG,EAAArC,EAAAwC,OAAAN,EAAAG,EAAAH,eAAuCpC,GAASgD,EAAkBhD,EAAMiD,IAAStB,EAAMX,KAAKiC,EAc5F,KAZAf,EAAOvC,EAAQK,EAAMkD,GAGH,IAAfhB,EAAKQ,SACJR,KACGlC,EAAK9B,GAAKgF,EAAIhF,EAAIgF,EAAI9E,OACrB8D,EAAKlB,KAAK,MACXhB,EAAK7B,GAAK+E,EAAI/E,EAAI+E,EAAI7E,QACrB6D,EAAKlB,KAAK,MACXkB,EAAKQ,OAAS,IACK,IAAfR,EAAKQ,OAAiBR,EAAKlB,KAAK,MAAUkB,GAAQ,QAE7DG,EAAA,EAAAG,EAAAN,EAAAQ,OAAAL,EAAAG,EAAAH,WAAuB,MAAAa,EAAArE,SAAAb,GAAAmB,MACnB6C,EAAKhB,KAAKkC,EAAIrE,SAASb,GAAOmB,YAEtCwC,gBAGJnC,IAAK,SAAC2D,SACFtF,MAACkD,MAAMoC,gBAEXpC,MAAO,SAACoC,GAEJ,GAAAC,GAAAH,EAAAjB,EAAAL,EAAAQ,EAAAC,EAAAiB,EAAAf,EAAAC,EAAAtC,EAAAC,EAAAuC,EAAAS,CAAA,IAAmB,gBAATC,KAA2B,MAAAA,EAAAjF,GAAgB,MAAAiF,EAAAhF,GACjD,MAAON,MAACyF,KAAK,SAACL,GACV,GAAAG,GAAAC,CAAAD,IAAQ,CACR,KAAAC,IAAAF,GAAsBA,EAAME,KAAUJ,EAAII,KAAUD,GAAQ,SAC5DA,IAQR,KALArD,EAAgBoD,GAEhBxB,KACAK,GAAQnE,MAEFmE,EAAKU,OAAS,GAApB,CAGI,IAFAQ,EAAMlB,EAAKW,QAEX1C,EAAAiD,EAAAzE,UAAA0D,EAAA,EAAAG,EAAArC,EAAAyC,OAAAP,EAAAG,EAAAH,IAAA,QACIiB,GAAQ,CACR,KAAAC,IAAAF,GAAsBA,EAAME,KAAUJ,EAAII,KAAUD,GAAQ,EAC1CA,IAAlBzB,EAAMX,KAAKiC,GACf,IAAA/C,EAAAgD,EAAA1E,SAAA4D,EAAA,EAAAG,EAAArC,EAAAwC,OAAAN,EAAAG,EAAAH,IAAA,QACIgB,GAAQ,CACR,KAAAC,IAAAF,GAAsBA,EAAME,KAAUJ,EAAII,KAAUD,GAAQ,EAC1CA,IAAlBzB,EAAMX,KAAKiC,GAEfR,EAAeS,EAAIrE,SAASa,EAAmByD,EAAOD,IAEnD,MAAAT,EAAAtD,MACC6C,EAAKhB,KAAKyB,EAAatD,YAE/BwC,gBAMJ4B,KAAM,SAACC,GACH,GAAAxF,GAAAgE,EAAAyB,EAAAtB,EAAAC,EAAAE,EAAAC,EAAAtC,EAAAC,EAAAgD,CAEA,KAFAlB,GAAQnE,MAEFmE,EAAKU,OAAS,GAApB,CAEI,IADAQ,EAAMlB,EAAKW,QACX1C,EAAAiD,EAAAzE,UAAA0D,EAAA,EAAAG,EAAArC,EAAAyC,OAAAP,EAAAG,EAAAH,iCAA4BqB,EAAQC,EACpC,KAAAvD,EAAAgD,EAAA1E,SAAA4D,EAAA,EAAAG,EAAArC,EAAAwC,OAAAN,EAAAG,EAAAH,iCAA2BoB,EAAQC,EAEnC,KAAAzF,IAAAkF,GAAArE,SAA+B,MAAAqE,EAAArE,SAAAb,GAAAmB,MAC3B6C,EAAKhB,KAAKkC,EAAIrE,SAASb,GAAOmB,YACtCtB,mBAGJyF,KAAM,SAACI,GACH,GAAA1F,GAAAgE,EAAAyB,EAAA9B,EAAAQ,EAAAC,EAAAE,EAAAC,EAAAtC,EAAAC,EAAAgD,CAGA,KAHAlB,GAAQnE,MACR8D,KAEMK,EAAKU,OAAS,GAApB,CAEI,IADAQ,EAAMlB,EAAKW,QACX1C,EAAAiD,EAAAzE,UAAA0D,EAAA,EAAAG,EAAArC,EAAAyC,OAAAP,EAAAG,EAAAH,iCAA4BuB,EAAWD,GAAA,SAAQ9B,EAAMX,KAAKyC,EAC1D,KAAAvD,EAAAgD,EAAA1E,SAAA4D,EAAA,EAAAG,EAAArC,EAAAwC,OAAAN,EAAAG,EAAAH,iCAA2BsB,EAAWD,GAAA,SAAQ9B,EAAMX,KAAKyC,EAEzD,KAAAzF,IAAAkF,GAAArE,SAA+B,MAAAqE,EAAArE,SAAAb,GAAAmB,MAC3B6C,EAAKhB,KAAKkC,EAAIrE,SAASb,GAAOmB,YACtCwC,gBAGJgC,OAAQ,SAACD,GACL,GAAAE,UAAAA,EAAY,SAACC,GACT,GAAA7F,GAAA8F,EAAA9D,EAAAmC,EAAAC,EAAAE,EAAAC,EAAAtC,EAAAC,EAAAG,EAAAC,CAAAwD,GAAU,GAAIhG,IAASI,EAAG2F,EAAO3F,EAAGC,EAAG0F,EAAO1F,EAAGC,MAAOyF,EAAOzF,MAAOC,OAAQwF,EAAOxF,OAAQC,YAAauF,EAAOvF,cACjHwF,EAAQpF,KAAO,CACf,KAAAV,IAAA6F,GAAAhF,SAAkC,MAAAgF,EAAAhF,SAAAb,GAAAmB,OAC9B2E,EAAQjF,SAASb,GAAOmB,KAAOyE,EAAUC,EAAOhF,SAASb,GAAOmB,MAChE2E,EAAQpF,MAAR,OAAAuB,EAAA,OAAAC,EAAA4D,EAAAjF,SAAAb,GAAAmB,MAAAe,EAAAxB,KAAA,QAAAuB,EAAqD,EAEzD,KAAAI,EAAAwD,EAAApF,UAAA0D,EAAA,EAAAG,EAAAjC,EAAAqC,OAAAP,EAAAG,EAAAH,YAAsC,MAAAuB,IAAJ,kBAAAA,GAAkBA,EAAW1D,GAAA,UAC3D8D,EAAQrF,UAAUuC,KAAKhB,EAC3B,KAAAM,EAAAuD,EAAArF,SAAA4D,EAAA,EAAAG,EAAAjC,EAAAoC,OAAAN,EAAAG,EAAAH,YAAqC,MAAAsB,IAAJ,kBAAAA,GAAkBA,EAAW1D,GAAA,UAC1D8D,EAAQtF,SAASwC,KAAKhB,EAG1B,OADA8D,GAAQpF,MAAQoF,EAAQrF,UAAUiE,OAASoB,EAAQtF,SAASkE,OACzC,IAAhBoB,EAAQpF,KAAe,KAAUoF,IAE9BjG,mBAGdkG,OAAQ,SAACL,SACL7F,MAAC8F,OAAO,SAACF,WACL,kBAAAC,GAAIA,EAAWD,GAAA,uBAIvBO,MAAO,SAACR,GACJ,GAAAxF,GAAAgE,EAAA/D,CAEA,KAFA+D,GAAQnE,MAEFmE,EAAKU,OAAS,GAApB,CACIzE,EAAO+D,EAAKW,QACZa,EAAOS,KAAKhG,IAEZ,KAAAD,IAAAC,GAAAY,SAAgC,MAAAZ,EAAAY,SAAAb,GAAAmB,MAC5B6C,EAAKhB,KAAK/C,EAAKY,SAASb,GAAOmB,YACvCtB,mBAGJqG,OAAQ,WACJ,GAAAlG,GAAAgE,EAAAmC,EAAAC,EAAAC,EAAAC,EAAApB,CAQA,KARAoB,EAAM,GAENH,EAAS,SAACI,GACN,GAAApC,GAAAlC,EAAAuE,CACA,KADAA,EAAM,GACoBrC,EAAAlC,EAAAsE,EAAAtE,GAAA,EAAAkC,EAAA,EAAAA,EAAA,EAAAlC,GAAA,IAAAkC,IAAAA,EAA1BqC,GAAO,YACPA,IAEJxC,IAAWyC,MAAO,OAAQtF,KAAMtB,KAAG0G,MAAO,IACpCvC,EAAKU,OAAS,GAApB,CACIQ,EAAMlB,EAAKW,QACXyB,EAAcD,EAAOjB,EAAIqB,OACzBD,GACSF,EAAY,KAAIlB,EAAIuB,MAAM,KAC1BL,EAAY,mBAGlBlB,EAAI/D,KAAKV,UAAUiE,OAAS,IAC3B4B,GACSF,EAAY,6BACZA,EAAY,OAAMlB,EAAI/D,KAAKV,UAAU,MAG/CyE,EAAI/D,KAAKX,SAASkE,OAAS,IAC1B4B,GACSF,EAAY,uBACZA,EAAY,OAAMlB,EAAI/D,KAAKX,SAAS,MAGjD6F,GAAW,CACX,KAAArG,IAAAkF,GAAA/D,KAAAN,SAAoC,MAAAqE,EAAA/D,KAAAN,SAAAb,GAAAmB,OAChCkF,GAAW,EACXrC,EAAK0C,SAAUD,MAAOzG,EAAOmB,KAAM+D,EAAI/D,KAAKN,SAASb,GAAOmB,KAAMoF,MAAOrB,EAAIqB,MAAQ,IAEtFF,KAAcC,GAAUF,EAAY,gBAE3CE","file":"quadtree.min.js","sourcesContent":["# quadtree-lib\n# ============\n#\n# **Quadtree-lib** is an easy to use, developer friendly quadtree library\n# which contains many helper methods to add, remove, iterate, filter, simulate\n# collisions over 2d elements and more.\n\n# #### UMD bundling related code\n((root, factory) ->\n if typeof define is 'function' and define.amd\n define [], factory\n else if typeof exports is 'object' and module.exports\n module.exports = factory()\n else\n root[\"Quadtree\"] = factory()\n) @, (-> class Quadtree\n # The Quadtree class\n # -------------------\n\n # ### Constructor\n\n # The quadtree constructor accepts a single parameter object containing the following properties :\n # - width / length : dimensions of the quadtree. [ *mandatory* ]\n # - maxElements : the maximum number of elements before the leaf 'splits' into subtrees. [ *defaults to 1* ]\n # - x / y : these coordinates are used internally by the library to position subtrees. [ *internal use only* ]\n constructor: ({@x, @y, @width, @height, @maxElements}) ->\n\n # An error is thrown when the width & length are not passed as constructor arguments.\n throw new Error \"Missing quadtree dimensions.\" if not @width? or not @height?\n @x ?= 0\n @y ?= 0\n @maxElements ?= 1\n @contents = []\n @oversized = []\n @size = 0\n\n # Dimension & coordinates are checked, an error is thrown in case of bad input.\n throw new Error \"Dimensions must be positive integers.\" if @width < 1 or @height < 1\n throw new Error \"Coordinates must be integers\" if not Number.isInteger(@x) or not Number.isInteger(@y)\n throw new Error \"The maximum number of elements before a split must be a positive integer.\" if @maxElements < 1\n\n that = @\n\n # The subtrees list, by position.\n @children = {\n # Northwest tree.\n \"NW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Northeast tree.\n \"NE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y\n width: Math.ceil that.width / 2\n height: Math.max (Math.floor that.height / 2), 1\n maxElements: that.maxElements\n })\n tree: null\n # Southwest tree.\n \"SW\":\n create: ->\n new Quadtree({\n x: that.x\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.max (Math.floor that.width / 2), 1\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n # Southeast tree.\n \"SE\":\n create: ->\n new Quadtree({\n x: that.x + Math.max (Math.floor that.width / 2), 1\n y: that.y + Math.max (Math.floor that.height / 2), 1\n width: Math.ceil that.width / 2\n height: Math.ceil that.height / 2\n maxElements: that.maxElements\n })\n tree: null\n }\n # Adding a getter which lazily creates the tree.\n for child of @children\n @children[child].get = ->\n if @tree? then @tree else @tree = @create(); @tree\n\n # ### Internal methods & vars\n\n # Retrieves the center coordinates of a rectangle.\n getCenter = (item) ->\n x: Math.floor((item.width ? 1) / 2) + item.x\n y: Math.floor((item.height ? 1) / 2) + item.y\n\n # Bounding box collision algorithm.\n boundingBoxCollision = (elt1, elt2) ->\n not(elt1.x >= elt2.x + (elt2.width ? 1) or\n elt1.x + (elt1.width ? 1) <= elt2.x or\n elt1.y >= elt2.y + (elt2.height ? 1) or\n elt1.y + (elt1.height ? 1) <= elt2.y)\n\n # Determines which subtree an element belongs to.\n calculateDirection = (element, tree) ->\n quadCenter = getCenter tree\n\n if element.x < quadCenter.x\n if element.y < quadCenter.y then \"NW\"\n else \"SW\"\n else\n if element.y < quadCenter.y then \"NE\"\n else \"SE\"\n\n # Validates a potential element of the tree.\n validateElement = (element) ->\n if not (typeof element is \"object\")\n throw new Error \"Element must be an Object.\"\n if not element.x? or not element.y?\n throw new Error \"Coordinates properties are missing.\"\n if element?.width < 0 or element?.height < 0\n throw new Error \"Width and height must be positive integers.\"\n\n # Returns splitted coordinates and dimensions.\n splitTree = (tree) ->\n leftWidth = Math.max (Math.floor tree.width / 2), 1\n rightWidth = Math.ceil tree.width / 2\n topHeight = Math.max (Math.floor tree.height / 2), 1\n bottomHeight = Math.ceil tree.height / 2\n \"NW\":\n x: tree.x\n y: tree.y\n width: leftWidth\n height: topHeight\n \"NE\":\n x: tree.x + leftWidth\n y: tree.y\n width: rightWidth\n height: topHeight\n \"SW\":\n x: tree.x\n y: tree.y + topHeight\n width: leftWidth\n height: bottomHeight\n \"SE\":\n x: tree.x + leftWidth\n y: tree.y + topHeight\n width: rightWidth\n height: bottomHeight\n\n # Determines wether an element fits into subtrees.\n fitting = (element, tree) ->\n where = []\n for direction, coordinates of splitTree tree when boundingBoxCollision element, coordinates\n where.push direction\n where\n\n # Add getters and setters for coordinates and dimensions properties in order to automatically reorganize the elements on change.\n observe = (item, tree) ->\n writeAccessors = (propName) ->\n item[\"_#{propName}\"] = item[propName]\n Object.defineProperty item, propName, {\n set: (val) ->\n tree.remove @\n @[\"_#{propName}\"] = val\n tree.push @\n get: ->\n @[\"_#{propName}\"]\n configurable: true\n }\n writeAccessors \"x\"\n writeAccessors \"y\"\n writeAccessors \"width\"\n writeAccessors \"height\"\n\n # ### Exposed methods\n\n # Add an element to the quadtree.\n # Elements can be observed to reorganize them into the quadtree automatically whenever their coordinates or dimensions are set (for ex. obj.x = ...).\n push: (item, doObserve) ->\n @pushAll([item], doObserve)\n\n # Push an array of elements.\n pushAll : (items, doObserve) ->\n for item in items\n validateElement item\n observe item, @ if doObserve\n\n fifo = [tree: @, elements: items]\n\n while fifo.length > 0\n { tree, elements } = fifo.shift()\n\n fifoCandidates = { \"NW\": null, \"NE\": null, \"SW\": null, \"SE\": null }\n\n for element in elements\n tree.size++\n\n fits = fitting element, tree\n\n if fits.length isnt 1 or tree.width is 1 or tree.height is 1\n tree.oversized.push element\n\n else if (tree.size - tree.oversized.length) <= tree.maxElements\n tree.contents.push element\n\n else\n direction = fits[0]\n relatedChild = tree.children[direction]\n fifoCandidates[direction] ?= { tree: relatedChild.get(), elements: [] }\n fifoCandidates[direction].elements.push(element)\n\n for content in tree.contents\n contentDir = (fitting content, tree)[0]\n fifoCandidates[contentDir] ?= { tree: tree.children[contentDir].get(), elements: [] }\n fifoCandidates[contentDir].elements.push(content)\n\n tree.contents = []\n\n for direction, candidate of fifoCandidates\n if candidate? then fifo.push candidate\n\n @\n\n # Removes an element from the quadtree.\n remove: (item) ->\n validateElement item\n\n index = @oversized.indexOf item\n if index > - 1\n @oversized.splice index, 1\n @size--\n return true\n\n index = @contents.indexOf item\n if index > - 1\n @contents.splice index, 1\n @size--\n return true\n\n relatedChild = @children[calculateDirection item, @]\n\n if relatedChild.tree? and relatedChild.tree.remove item\n @size--\n relatedChild.tree = null if relatedChild.tree.size is 0\n return true\n\n false\n\n # Returns an array of elements which collides with the `item` argument.\n # `item` being an object having x, y, width & height properties.\n\n # The default collision function is a basic bounding box algorithm.\n # You can change it by providing a function as a second argument.\n #```javascript\n #colliding({x: 10, y: 20}, function(element1, element2){\n # return // Place predicate here //\n #})\n #```\n colliding: (item, collisionFunction) ->\n validateElement item\n\n collisionFunction ?= boundingBoxCollision\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized when elt isnt item and collisionFunction item, elt then items.push elt\n for elt in top.contents when elt isnt item and collisionFunction item, elt then items.push elt\n\n fits = fitting item, top\n\n # Special case for elements located outside of the quadtree on the right / bottom side\n if fits.length is 0\n fits = []\n if item.x >= top.x + top.width\n fits.push \"NE\"\n if item.y >= top.y + top.height\n fits.push \"SW\"\n if fits.length > 0\n if fits.length is 1 then fits.push \"SE\" else fits = [\"SE\"]\n\n for child in fits when top.children[child].tree?\n fifo.push top.children[child].tree\n\n items\n\n # Alias of `where`.\n get: (query) ->\n @where query\n # Returns an array of elements that match the `query` argument.\n where: (query) ->\n # Naïve parsing (missing coordinates)\n if typeof query is \"object\" and (not query.x? or not query.y?)\n return @find (elt) ->\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n check\n\n # Optimised parsing\n validateElement query\n\n items = []\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n\n for elt in top.oversized\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n for elt in top.contents\n check = true\n for key of query when query[key] isnt elt[key] then check = false\n items.push elt if check\n\n relatedChild = top.children[calculateDirection query, top]\n\n if relatedChild.tree?\n fifo.push relatedChild.tree\n\n items\n\n # For each element of the quadtree, performs the `action` function.\n #```javascript\n #quad.each(function(item){ console.log(item) })\n #```\n each: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized then action?(i)\n for i in top.contents then action?(i)\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n @\n\n # Returns an array of elements which validates the predicate.\n find: (predicate) ->\n fifo = [@]\n items = []\n\n while fifo.length > 0\n top = fifo.shift()\n for i in top.oversized when predicate?(i) then items.push i\n for i in top.contents when predicate?(i) then items.push i\n\n for child of top.children when top.children[child].tree?\n fifo.push top.children[child].tree\n items\n\n # Returns a **cloned** `Quadtree` object which contains only the elements that validate the predicate.\n filter: (predicate) ->\n deepclone = (target) ->\n copycat = new Quadtree x: target.x, y: target.y, width: target.width, height: target.height, maxElements: target.maxElements\n copycat.size = 0\n for child of target.children when target.children[child].tree?\n copycat.children[child].tree = deepclone target.children[child].tree\n copycat.size += copycat.children[child].tree?.size ? 0\n\n for item in target.oversized when not predicate? or predicate?(item)\n copycat.oversized.push item\n for item in target.contents when not predicate? or predicate?(item)\n copycat.contents.push item\n\n copycat.size += copycat.oversized.length + copycat.contents.length\n if copycat.size is 0 then null else copycat\n\n deepclone @\n\n # Opposite of filter.\n reject: (predicate) ->\n @filter (i) ->\n not predicate?(i)\n\n # Visits each tree & subtree contained in the `Quadtree` object.\n # For each node, performs the `action` function, inside which `this` is bound to the node tree object.\n visit: (action) ->\n fifo = [@]\n\n while fifo.length > 0\n that = fifo.shift()\n action.bind(that)()\n\n for child of that.children when that.children[child].tree?\n fifo.push that.children[child].tree\n @\n\n # Pretty printing function.\n pretty: ->\n str = \"\"\n\n indent = (level) ->\n res = \"\"\n res += \" \" for times in [level...0]\n res\n\n fifo = [{ label: \"ROOT\", tree: @, level: 0 }]\n while fifo.length > 0\n top = fifo.shift()\n indentation = indent(top.level)\n str += \"\"\"\n #{indentation}| #{top.label}\n #{indentation}| ------------\\n\n \"\"\"\n\n if top.tree.oversized.length > 0\n str += \"\"\"\n #{indentation}| * Oversized elements *\n #{indentation}| #{top.tree.oversized}\\n\n \"\"\"\n\n if top.tree.contents.length > 0\n str += \"\"\"\n #{indentation}| * Leaf content *\n #{indentation}| #{top.tree.contents}\\n\n \"\"\"\n\n isParent = false\n for child of top.tree.children when top.tree.children[child].tree?\n isParent = true\n fifo.unshift { label: child, tree: top.tree.children[child].tree, level: top.level + 1 }\n\n if isParent then str += \"#{indentation}└──┐\\n\"\n\n str\n)\n"]} \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index bada3cd..bd5938b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -87,7 +87,8 @@

Constructor

Dimension & coordinates are checked, an error is thrown in case of bad input.

-
        throw new Error "Dimensions and coordinates must be positive integers." if @x < 0 or @y < 0 or @width < 1 or @height < 1
+          
        throw new Error "Dimensions must be positive integers." if @width < 1 or @height < 1
+        throw new Error "Coordinates must be integers" if not Number.isInteger(@x) or not Number.isInteger(@y)
         throw new Error "The maximum number of elements before a split must be a positive integer." if @maxElements < 1
 
         that = @
diff --git a/docs/quadtree.html b/docs/quadtree.html index bada3cd..bd5938b 100644 --- a/docs/quadtree.html +++ b/docs/quadtree.html @@ -87,7 +87,8 @@

Constructor

Dimension & coordinates are checked, an error is thrown in case of bad input.

-
        throw new Error "Dimensions and coordinates must be positive integers." if @x < 0 or @y < 0 or @width < 1 or @height < 1
+          
        throw new Error "Dimensions must be positive integers." if @width < 1 or @height < 1
+        throw new Error "Coordinates must be integers" if not Number.isInteger(@x) or not Number.isInteger(@y)
         throw new Error "The maximum number of elements before a split must be a positive integer." if @maxElements < 1
 
         that = @
diff --git a/src/quadtree.coffee b/src/quadtree.coffee index f7bb7da..a62e04e 100644 --- a/src/quadtree.coffee +++ b/src/quadtree.coffee @@ -35,7 +35,8 @@ @size = 0 # Dimension & coordinates are checked, an error is thrown in case of bad input. - throw new Error "Dimensions and coordinates must be positive integers." if @x < 0 or @y < 0 or @width < 1 or @height < 1 + throw new Error "Dimensions must be positive integers." if @width < 1 or @height < 1 + throw new Error "Coordinates must be integers" if not Number.isInteger(@x) or not Number.isInteger(@y) throw new Error "The maximum number of elements before a split must be a positive integer." if @maxElements < 1 that = @ diff --git a/test/test.coffee b/test/test.coffee index 3f53303..d03239c 100644 --- a/test/test.coffee +++ b/test/test.coffee @@ -12,10 +12,9 @@ describe 'quadtree', -> assert.throws (-> new Quadtree x:1, y:1), Error assert.throws (-> new Quadtree x:1, y:1, width:10), Error assert.throws (-> new Quadtree x:1, y:1, height:10), Error - assert.throws (-> new Quadtree x:-1, y:1, width:10, height: 10), Error - assert.throws (-> new Quadtree x:1, y:-1, width:10, height: 10), Error assert.throws (-> new Quadtree x:1, y:1, width:0, height: 10), Error assert.throws (-> new Quadtree x:1, y:1, width:10, height: -1), Error + assert.throws (-> new Quadtree x:{}, y:1, width:10, height: 10), Error assert.throws (-> new Quadtree x:1, y:1, width:10, height: 10, maxElements: -1), Error it 'should reject improper elements', -> @@ -29,7 +28,7 @@ describe 'quadtree', -> assert.throws (-> quadtree.push x:1, y:0, height: -1), Error it 'should add a fitting element properly', -> - quadtree = new Quadtree width: 100, height: 100 + quadtree = new Quadtree x: -10, y: -10, width: 20, height: 20 quadtree.push element = x: 0, y: 0, content: 'element 0' assert.equal quadtree.size, 1 assert.equal quadtree.contents[0], element