"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var THREE = _interopRequireWildcard(require("three"));
var _Fetcher = _interopRequireDefault(require("../Provider/Fetcher"));
var _PointCloudNode = _interopRequireDefault(require("./PointCloudNode"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const size = new THREE.Vector3();
const position = new THREE.Vector3();
const translation = new THREE.Vector3();
function buildId(depth, x, y, z) {
  return `${depth}-${x}-${y}-${z}`;
}

/**
 * @extends PointCloudNode
 *
 * @property {boolean} isEntwinePointTileNode - Used to checkout whether this
 * node is a EntwinePointTileNode. Default is `true`. You should not change
 * this, as it is used internally for optimisation.
 * @property {number} depth - The depth of the node in the tree - see the
 * [Entwine
 * documentation](https://entwine.io/entwine-point-tile.html#ept-data)
 * @property {number} x - The x coordinate of the node in the tree - see the
 * [Entwine
 * documentation](https://entwine.io/entwine-point-tile.html#ept-data)
 * @property {number} y - The x coordinate of the node in the tree - see the
 * [Entwine
 * documentation](https://entwine.io/entwine-point-tile.html#ept-data)
 * @property {number} z - The x coordinate of the node in the tree - see the
 * [Entwine
 * documentation](https://entwine.io/entwine-point-tile.html#ept-data)
 * @property {string} id - The id of the node, constituted of the four
 * components: `depth-x-y-z`.
 */
class EntwinePointTileNode extends _PointCloudNode.default {
  /**
   * Constructs a new instance of EntwinePointTileNode.
   *
   * @constructor
   *
   * @param {number} depth - The depth of the node in the tree - see the
   * [Entwine
   * documentation](https://entwine.io/entwine-point-tile.html#ept-data)
   * @param {number} x - The x coordinate of the node in the tree - see the
   * [Entwine
   * documentation](https://entwine.io/entwine-point-tile.html#ept-data)
   * @param {number} y - The x coordinate of the node in the tree - see the
   * [Entwine
   * documentation](https://entwine.io/entwine-point-tile.html#ept-data)
   * @param {number} z - The x coordinate of the node in the tree - see the
   * [Entwine
   * documentation](https://entwine.io/entwine-point-tile.html#ept-data)
   * @param {EntwinePointTileLayer} layer - The layer the node is attached to.
   * @param {number} [numPoints=0] - The number of points in this node. If
   * `-1`, it means that the octree hierarchy associated to this node needs to
   * be loaded.
   */
  constructor(depth, x, y, z, layer) {
    let numPoints = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
    super(numPoints, layer);
    this.isEntwinePointTileNode = true;
    this.depth = depth;
    this.x = x;
    this.y = y;
    this.z = z;
    this.id = buildId(depth, x, y, z);
    this.url = `${this.layer.source.url}/ept-data/${this.id}.${this.layer.source.extension}`;
  }
  createChildAABB(node) {
    // factor to apply, based on the depth difference (can be > 1)
    const f = 2 ** (node.depth - this.depth);

    // size of the child node bbox (Vector3), based on the size of the
    // parent node, and divided by the factor
    this.bbox.getSize(size).divideScalar(f);

    // initialize the child node bbox at the location of the parent node bbox
    node.bbox.min.copy(this.bbox.min);

    // position of the parent node, if it was at the same depth than the
    // child, found by multiplying the tree position by the factor
    position.copy(this).multiplyScalar(f);

    // difference in position between the two nodes, at child depth, and
    // scale it using the size
    translation.subVectors(node, position).multiply(size);

    // apply the translation to the child node bbox
    node.bbox.min.add(translation);

    // use the size computed above to set the max
    node.bbox.max.copy(node.bbox.min).add(size);
  }
  get octreeIsLoaded() {
    return this.numPoints >= 0;
  }
  loadOctree() {
    return _Fetcher.default.json(`${this.layer.source.url}/ept-hierarchy/${this.id}.json`, this.layer.source.networkOptions).then(hierarchy => {
      this.numPoints = hierarchy[this.id];
      const stack = [];
      stack.push(this);
      while (stack.length) {
        const node = stack.shift();
        const depth = node.depth + 1;
        const x = node.x * 2;
        const y = node.y * 2;
        const z = node.z * 2;
        node.findAndCreateChild(depth, x, y, z, hierarchy, stack);
        node.findAndCreateChild(depth, x + 1, y, z, hierarchy, stack);
        node.findAndCreateChild(depth, x, y + 1, z, hierarchy, stack);
        node.findAndCreateChild(depth, x + 1, y + 1, z, hierarchy, stack);
        node.findAndCreateChild(depth, x, y, z + 1, hierarchy, stack);
        node.findAndCreateChild(depth, x + 1, y, z + 1, hierarchy, stack);
        node.findAndCreateChild(depth, x, y + 1, z + 1, hierarchy, stack);
        node.findAndCreateChild(depth, x + 1, y + 1, z + 1, hierarchy, stack);
      }
    });
  }
  findAndCreateChild(depth, x, y, z, hierarchy, stack) {
    const id = buildId(depth, x, y, z);
    const numPoints = hierarchy[id];
    if (typeof numPoints == 'number') {
      const child = new EntwinePointTileNode(depth, x, y, z, this.layer, numPoints);
      this.add(child);
      stack.push(child);
    }
  }
}
var _default = EntwinePointTileNode;
exports.default = _default;