# Source: math/QuadTree.js

    /**
     * @author       Richard Davey <rich@photonstorm.com>
     * @copyright    2014 Photon Storm Ltd.
     * @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
     */

    /**
    * Javascript QuadTree
    * @version 1.0
    * @author Timo Hausmann
    *
    * @version 1.3, March 11th 2014
    * @author Richard Davey
    * The original code was a conversion of the Java code posted to GameDevTuts. However I've tweaked
    * it massively to add node indexing, removed lots of temp. var creation and significantly
    * increased performance as a result.
    *
    * Original version at https://github.com/timohausmann/quadtree-js/
    */

    /**
    * @copyright © 2012 Timo Hausmann
    *
    * Permission is hereby granted, free of charge, to any person obtaining
    * a copy of this software and associated documentation files (the
    * "Software"), to deal in the Software without restriction, including
    * without limitation the rights to use, copy, modify, merge, publish,
    * distribute, sublicense, and/or sell copies of the Software, and to
    * permit persons to whom the Software is furnished to do so, subject to
    * the following conditions:
    *
    * The above copyright notice and this permission notice shall be
    * included in all copies or substantial portions of the Software.
    *
    * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    */

    /**
    * QuadTree Constructor
    *
    * @class Phaser.QuadTree
    * @classdesc A QuadTree implementation. The original code was a conversion of the Java code posted to GameDevTuts.
    * However I've tweaked it massively to add node indexing, removed lots of temp. var creation and significantly increased performance as a result.
    * Original version at https://github.com/timohausmann/quadtree-js/
    * @constructor
    * @param {number} x - The top left coordinate of the quadtree.
    * @param {number} y - The top left coordinate of the quadtree.
    * @param {number} width - The width of the quadtree in pixels.
    * @param {number} height - The height of the quadtree in pixels.
    * @param {number} [maxObjects=10] - The maximum number of objects per node.
    * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
    * @param {number} [level=0] - Which level is this?
    */
    Phaser.QuadTree = function(x, y, width, height, maxObjects, maxLevels, level) {

        /**
        * @property {number} maxObjects - The maximum number of objects per node.
        * @default
        */
        this.maxObjects = 10;

        /**
        * @property {number} maxLevels - The maximum number of levels to break down to.
        * @default
        */
        this.maxLevels = 4;

        /**
        * @property {number} level - The current level.
        */
        this.level = 0;

        /**
        * @property {object} bounds - Object that contains the quadtree bounds.
        */
        this.bounds = {};

        /**
        * @property {array} objects - Array of quadtree children.
        */
        this.objects = [];

        /**
        * @property {array} nodes - Array of associated child nodes.
        */
        this.nodes = [];

        /**
        * @property {array} _empty - Internal empty array.
        * @private
        */
        this._empty = [];

        this.reset(x, y, width, height, maxObjects, maxLevels, level);

    };

    Phaser.QuadTree.prototype = {

        /**
        * Resets the QuadTree.
        *
        * @method Phaser.QuadTree#reset
        * @param {number} x - The top left coordinate of the quadtree.
        * @param {number} y - The top left coordinate of the quadtree.
        * @param {number} width - The width of the quadtree in pixels.
        * @param {number} height - The height of the quadtree in pixels.
        * @param {number} [maxObjects=10] - The maximum number of objects per node.
        * @param {number} [maxLevels=4] - The maximum number of levels to iterate to.
        * @param {number} [level=0] - Which level is this?
        */
        reset: function (x, y, width, height, maxObjects, maxLevels, level) {

            this.maxObjects = maxObjects || 10;
            this.maxLevels = maxLevels || 4;
            this.level = level || 0;

            this.bounds = {
                x: Math.round(x),
                y: Math.round(y),
                width: width,
                height: height,
                subWidth: Math.floor(width / 2),
                subHeight: Math.floor(height / 2),
                right: Math.round(x) + Math.floor(width / 2),
                bottom: Math.round(y) + Math.floor(height / 2)
            };

            this.objects.length = 0;
            this.nodes.length = 0;

        },

        /**
        * Populates this quadtree with the children of the given Group. In order to be added the child must exist and have a body property.
        *
        * @method Phaser.QuadTree#populate
        * @param {Phaser.Group} group - The Group to add to the quadtree.
        */
        populate: function (group) {

            group.forEach(this.populateHandler, this, true);

        },

        /**
        * Handler for the populate method.
        *
        * @method Phaser.QuadTree#populateHandler
        * @param {Phaser.Sprite|object} sprite - The Sprite to check.
        */
        populateHandler: function (sprite) {

            if (sprite.body && sprite.exists)
            {
                this.insert(sprite.body);
            }

        },

        /**
        * Split the node into 4 subnodes
        *
        * @method Phaser.QuadTree#split
        */
        split: function () {

            this.level++;

            //  top right node
            this.nodes[0] = new Phaser.QuadTree(this.bounds.right, this.bounds.y, this.bounds.subWidth, this.bounds.subHeight, this.maxObjects, this.maxLevels, this.level);

            //  top left node
            this.nodes[1] = new Phaser.QuadTree(this.bounds.x, this.bounds.y, this.bounds.subWidth, this.bounds.subHeight, this.maxObjects, this.maxLevels, this.level);

            //  bottom left node
            this.nodes[2] = new Phaser.QuadTree(this.bounds.x, this.bounds.bottom, this.bounds.subWidth, this.bounds.subHeight, this.maxObjects, this.maxLevels, this.level);

            //  bottom right node
            this.nodes[3] = new Phaser.QuadTree(this.bounds.right, this.bounds.bottom, this.bounds.subWidth, this.bounds.subHeight, this.maxObjects, this.maxLevels, this.level);

        },

        /**
        * Insert the object into the node. If the node exceeds the capacity, it will split and add all objects to their corresponding subnodes.
        *
        * @method Phaser.QuadTree#insert
        * @param {Phaser.Physics.Arcade.Body|object} body - The Body object to insert into the quadtree. Can be any object so long as it exposes x, y, right and bottom properties.
        */
        insert: function (body) {

            var i = 0;
            var index;

            //  if we have subnodes ...
            if (this.nodes[0] != null)
            {
                index = this.getIndex(body);

                if (index !== -1)
                {
                    this.nodes[index].insert(body);
                    return;
                }
            }

            this.objects.push(body);

            if (this.objects.length > this.maxObjects && this.level < this.maxLevels)
            {
                //  Split if we don't already have subnodes
                if (this.nodes[0] == null)
                {
                    this.split();
                }

                //  Add objects to subnodes
                while (i < this.objects.length)
                {
                    index = this.getIndex(this.objects[i]);

                    if (index !== -1)
                    {
                        //  this is expensive - see what we can do about it
                        this.nodes[index].insert(this.objects.splice(i, 1)[0]);
                    }
                    else
                    {
                        i++;
                    }
                }
            }

        },

        /**
        * Determine which node the object belongs to.
        *
        * @method Phaser.QuadTree#getIndex
        * @param {Phaser.Rectangle|object} rect - The bounds in which to check.
        * @return {number} index - Index of the subnode (0-3), or -1 if rect cannot completely fit within a subnode and is part of the parent node.
        */
        getIndex: function (rect) {

            //  default is that rect doesn't fit, i.e. it straddles the internal quadrants
            var index = -1;

            if (rect.x < this.bounds.right && rect.right < this.bounds.right)
            {
                if (rect.y < this.bounds.bottom && rect.bottom < this.bounds.bottom)
                {
                    //  rect fits within the top-left quadrant of this quadtree
                    index = 1;
                }
                else if (rect.y > this.bounds.bottom)
                {
                    //  rect fits within the bottom-left quadrant of this quadtree
                    index = 2;
                }
            }
            else if (rect.x > this.bounds.right)
            {
                //  rect can completely fit within the right quadrants
                if (rect.y < this.bounds.bottom && rect.bottom < this.bounds.bottom)
                {
                    //  rect fits within the top-right quadrant of this quadtree
                    index = 0;
                }
                else if (rect.y > this.bounds.bottom)
                {
                    //  rect fits within the bottom-right quadrant of this quadtree
                    index = 3;
                }
            }

            return index;

        },

        /**
        * Return all objects that could collide with the given Sprite or Rectangle.
        *
        * @method Phaser.QuadTree#retrieve
        * @param {Phaser.Sprite|Phaser.Rectangle} source - The source object to check the QuadTree against. Either a Sprite or Rectangle.
        * @return {array} - Array with all detected objects.
        */
        retrieve: function (source) {

            if (source instanceof Phaser.Rectangle)
            {
                var returnObjects = this.objects;

                var index = this.getIndex(source);
            }
            else
            {
                if (!source.body)
                {
                    return this._empty;
                }

                var returnObjects = this.objects;

                var index = this.getIndex(source.body);
            }

            if (this.nodes[0])
            {
                //  If rect fits into a subnode ..
                if (index !== -1)
                {
                    returnObjects = returnObjects.concat(this.nodes[index].retrieve(source));
                }
                else
                {
                    //  If rect does not fit into a subnode, check it against all subnodes (unrolled for speed)
                    returnObjects = returnObjects.concat(this.nodes[0].retrieve(source));
                    returnObjects = returnObjects.concat(this.nodes[1].retrieve(source));
                    returnObjects = returnObjects.concat(this.nodes[2].retrieve(source));
                    returnObjects = returnObjects.concat(this.nodes[3].retrieve(source));
                }
            }

            return returnObjects;

        },

        /**
        * Clear the quadtree.
        * @method Phaser.QuadTree#clear
        */
        clear: function () {

            this.objects.length = 0;

            var i = this.nodes.length;

            while (i--)
            {
                this.nodes[i].clear();
                this.nodes.splice(i, 1);
            }

            this.nodes.length = 0;
        }

    };

    Phaser.QuadTree.prototype.constructor = Phaser.QuadTree;