_formBarnesHutTree(nodes, nodeIndices) {
    let node;
    const nodeCount = nodeIndices.length;

    let minX = nodes[nodeIndices[0]].x;
    let minY = nodes[nodeIndices[0]].y;
    let maxX = nodes[nodeIndices[0]].x;
    let maxY = nodes[nodeIndices[0]].y;

    // get the range of the nodes
    for (let i = 1; i < nodeCount; i++) {
      const node = nodes[nodeIndices[i]];
      const x = node.x;
      const y = node.y;
      if (node.options.mass > 0) {
        if (x < minX) {
          minX = x;
        }
        if (x > maxX) {
          maxX = x;
        }
        if (y < minY) {
          minY = y;
        }
        if (y > maxY) {
          maxY = y;
        }
      }
    }
    // make the range a square
    const sizeDiff = Math.abs(maxX - minX) - Math.abs(maxY - minY); // difference between X and Y
    if (sizeDiff > 0) {
      minY -= 0.5 * sizeDiff;
      maxY += 0.5 * sizeDiff;
    } // xSize > ySize
    else {
      minX += 0.5 * sizeDiff;
      maxX -= 0.5 * sizeDiff;
    } // xSize < ySize

    const minimumTreeSize = 1e-5;
    const rootSize = Math.max(minimumTreeSize, Math.abs(maxX - minX));
    const halfRootSize = 0.5 * rootSize;
    const centerX = 0.5 * (minX + maxX),
      centerY = 0.5 * (minY + maxY);

    // construct the barnesHutTree
    const barnesHutTree = {
      root: {
        centerOfMass: { x: 0, y: 0 },
        mass: 0,
        range: {
          minX: centerX - halfRootSize,
          maxX: centerX + halfRootSize,
          minY: centerY - halfRootSize,
          maxY: centerY + halfRootSize,
        },
        size: rootSize,
        calcSize: 1 / rootSize,
        children: { data: null },
        maxWidth: 0,
        level: 0,
        childrenCount: 4,
      },
    };
    this._splitBranch(barnesHutTree.root);

    // place the nodes one by one recursively
    for (let i = 0; i < nodeCount; i++) {
      node = nodes[nodeIndices[i]];
      if (node.options.mass > 0) {
        this._placeInTree(barnesHutTree.root, node);
      }
    }

    // make global
    return barnesHutTree;
  }
This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes.
@param {Array.<Node>} nodes
@param {Array.<number>} nodeIndices
@returns {{root: {centerOfMass: {x: number, y: number}, mass: number, range: {minX: number, maxX: number, minY: number, maxY: number}, size: number, calcSize: number, children: {data: null}, maxWidth: number, level: number, childrenCount: number}}} BarnesHutTree
@private