API Docs for: 0.1.1
Show:

File: src/components/map/core/utils/Quadtree.js

(function () {
  /*---------------------
  ------- IMPORT --------
  ----------------------*/
  var QuadMod = require('/assets/lib/quadtree-js/quadtree-js-hitman');

  /*---------------------
  --------- API ---------
  ----------------------*/
  class Quadtree {
    /**
     * NOTE! NOT IN USE AT THE MOMENT. THIS WAS LESS EFFICIENT THAN USING SUBCONTAINERS, SO IT WILL BE USED IN THE FUTURE IF NEEDED.
     *
     * This class handles the API for quadtree to search for the wanted objects on the certain coordinates. After this
     * the map should do it's own - more precise - hit detections.
     *
     * @class utils.Quadtree
     * @constructor
     * @requires Quadtree-js. Though this base library can be changed easily
     *
     * @param {Object} options    options for the QuadModule
     * @param {Object} max        How many levels deep
     * @return                    Quadtree instance
     */
    constructor(options, max) {
      var { objects: max_objects, levels: max_levels } = max;

      this.quadtree = new QuadMod(options, max_objects, max_levels);
    }
    /**
     * Add an object to the quadtree.
     *
     * @method add
     * @param {Object} coords                       Coordinates on the global / canvas element.
     * @param {Integer} coords.x                    X coordinate
     * @param {Integer} coords.y                    Y coordinate
     * @param {Object} size                         You can use bounds for the object "hit" detection
     * @param {Integer} size.width                  Width (in pixels)
     * @param {Integer} size.height                 Height (in pixels)
     * @param {Object} data                         Objects extra custom data. This is optional.
     * @return                                      Quadtree instance
     */
    add(coords, size, data) {
      var objToAdd = _creteQuadtreeObject(coords, size, data);

      this.quadtree.insert(objToAdd);
    }
    /**
     * Remove an object from the quadtree.
     *
     * @method remove
     * @param {Object} coords                       Coordinates on the global / canvas element.
     * @param {Integer} coords.x                    X coordinate
     * @param {Integer} coords.y                    Y coordinate
     * @param {Object} size                         You can use bounds for the object "hit" detection
     * @param {Integer} size.width                  Width (in pixels)
     * @param {Integer} size.height                 Height (in pixels)
     * @param {Object} data                         Objects extra custom data. This is optional.
     * @param {Boolean} refresh                     Should we refresh the quadtree setting, after removal. Can take some
     * resources to execute. So we want this to be optional.
     * @return                                      Quadtree instance
     */
    remove(coords, size, data, refresh) {
      var objToRemove = _creteQuadtreeObject(coords, size, data);

      this.quadtree.removeObject(objToRemove);
      refresh && this.quadtree.cleanup();
    }
    /**
     * @method retrieve
     * @param {Object} coords                       Coordinates on the global / canvas element.
     * @param {Integer} coords.x                    X coordinate
     * @param {Integer} coords.y                    Y coordinate
     * @param {Object} size                         You can use bounds for the object "hit" detection
     * @param {Integer} size.width                  Width (in pixels)
     * @param {Integer} size.height                 Height (in pixels)
     */
    retrieve(coords, size = { width: 0, height: 0 }) {
      const hitDimensions = {
        x: coords.x,
        y: coords.y,
        width: size.width,
        height: size.height,
      };
      var objects = [];

      objects = this.quadtree.retrieve(hitDimensions).map((object) => {
        return object.data;
      });

      return objects;
    }
    /**
     * Move an object on the quadtree
     *
     * @method move
     * @param {Object} coords                       Coordinates on the global / canvas element.
     * @param {Integer} coords.x                    X coordinate
     * @param {Integer} coords.y                    Y coordinate
     * @param {Object} size                         You can use bounds for the object "hit" detection
     * @param {Integer} size.width                  Width (in pixels)
     * @param {Integer} size.height                 Height (in pixels)
     * @param {Object} data                         Objects extra custom data. This is optional.
     * @param {Boolean} to                          Should we refresh the quadtree setting, after removal. Can take some
     * resources to execute. So we want this to be optional.
     * @return {Boolean}                            True of false
     */
    move(coords, size, data, to) {
      var foundObject = this.findObject(coords, size, data);

      if (foundObject) {
        this.quadtree.removeObject(foundObject);
        foundObject.x = to.x;
        foundObject.y = to.y;
        this.quadtree.insert(foundObject);
        this.refreshAll();

        return true;
      }

      return false;
    }
    /**
     * refresh the whole quadtree setting. Can spend some resources.
     *
     * @method refreshAll
     */
    refreshAll() {
      this.quadtree.cleanup();
    }
    /**
     * Find an object by hitDetection from the quadtree setting.
     *
     * @method findObject
     * @param {Object} coords                       Coordinates on the global / canvas element.
     * @param {Integer} coords.x                    X coordinate
     * @param {Integer} coords.y                    Y coordinate
     * @param {Object} size                         You can use bounds for the object "hit" detection
     * @param {Integer} size.width                  Width (in pixels)
     * @param {Integer} size.height                 Height (in pixels)
     * @param {Object} data                         Objects extra custom data. This is optional.
     * @return {Object}                             Found object
     */
    findObject(coords, size, data) {
      var foundObject = this.retrieve(coords, size).filter(function (object) {
        return object.data === data ? true : false;
      });

      return foundObject;
    }
  }

  /*----------------------
  ------- PRIVATE --------
  ----------------------*/
  /**
   * @private
   * @static
   * @method _creteQuadtreeObject
     * @param {Object} coords             Coordinates on the global / canvas element.
     * @param {Integer} coords.x          X coordinate
     * @param {Integer} coords.y          Y coordinate
   * @param  {Object} size                You can use bounds for the object if you wish, instead of point / coordinates
   * @param  {Integer} size.width         Width (in pixels)
   * @param  {Integer} size.height        Height (in pixels)
   * @param  {Object} data                Extra data stored for the quadtree object
   * @return {Object}                     Added quadtree object
   */
  function _creteQuadtreeObject(coords, size = { width: 0, height: 0 }, data = undefined) {
    var objToAdd = coords;

    if (coords.x === undefined && coords.y === undefined) {
      throw new Error('_createQuadtreeObject requires x and y coordinates as parameters');
    }
    objToAdd.width = size.width;
    objToAdd.height = size.height;
    objToAdd.data = data;

    return objToAdd;
  }

  window.flatworld.Quadtree = Quadtree;
})();