NGL@1.0.0-beta.7 Home Manual Reference Source Gallery

src/geometry/kdtree.js

/**
 * @file Kdtree
 * @author Alexander Rose <alexander.rose@weirdbyte.de>
 * @private
 */

import { Debug, Log } from '../globals.js'
import _Kdtree from '../utils/kdtree.js'

function Kdtree (entity, useSquaredDist) {
  if (Debug) Log.time('Kdtree build')

  var metric

  if (useSquaredDist) {
    metric = function (a, b) {
      var dx = a[0] - b[0]
      var dy = a[1] - b[1]
      var dz = a[2] - b[2]
      return dx * dx + dy * dy + dz * dz
    }
  } else {
    metric = function (a, b) {
      var dx = a[0] - b[0]
      var dy = a[1] - b[1]
      var dz = a[2] - b[2]
      return Math.sqrt(dx * dx + dy * dy + dz * dz)
    }
  }

  var points = new Float32Array(entity.atomCount * 3)
  var atomIndices = new Uint32Array(entity.atomCount)
  var i = 0

  entity.eachAtom(function (ap) {
    points[ i + 0 ] = ap.x
    points[ i + 1 ] = ap.y
    points[ i + 2 ] = ap.z
    atomIndices[ i / 3 ] = ap.index
    i += 3
  })

  this.atomIndices = atomIndices
  this.points = points
  this.kdtree = new _Kdtree(points, metric)

  if (Debug) Log.timeEnd('Kdtree build')

    // console.log("this.kdtree.verify()", this.kdtree.verify())
}

Kdtree.prototype = {

  nearest: (function () {
    var pointArray = new Float32Array(3)

    return function nearest (point, maxNodes, maxDistance) {
            // Log.time( "Kdtree nearest" );

      if (point.toArray) {
        point.toArray(pointArray)
      } else if (point.positionToArray) {
        point.positionToArray(pointArray)
      }

      var nodeList = this.kdtree.nearest(
                pointArray, maxNodes, maxDistance
            )

      var indices = this.kdtree.indices
      var nodes = this.kdtree.nodes
      var atomIndices = this.atomIndices
      var resultList = []

      for (var i = 0, n = nodeList.length; i < n; ++i) {
        var d = nodeList[ i ]
        var nodeIndex = d[ 0 ]
        var dist = d[ 1 ]

        resultList.push({
          index: atomIndices[ indices[ nodes[ nodeIndex ] ] ],
          distance: dist
        })
      }

            // Log.timeEnd( "Kdtree nearest" );

      return resultList
    }
  }())

}

export default Kdtree