|   | 
| /* | 
| * Licensed to the Apache Software Foundation (ASF) under one | 
| * or more contributor license agreements.  See the NOTICE file | 
| * distributed with this work for additional information | 
| * regarding copyright ownership.  The ASF licenses this file | 
| * to you under the Apache License, Version 2.0 (the | 
| * "License"); you may not use this file except in compliance | 
| * with the License.  You may obtain a copy of the License at | 
| * | 
| *   http://www.apache.org/licenses/LICENSE-2.0 | 
| * | 
| * Unless required by applicable law or agreed to in writing, | 
| * software distributed under the License is distributed on an | 
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
| * KIND, either express or implied.  See the License for the | 
| * specific language governing permissions and limitations | 
| * under the License. | 
| */ | 
|   | 
|   | 
| /** | 
|  * AUTO-GENERATED FILE. DO NOT MODIFY. | 
|  */ | 
|   | 
| /* | 
| * Licensed to the Apache Software Foundation (ASF) under one | 
| * or more contributor license agreements.  See the NOTICE file | 
| * distributed with this work for additional information | 
| * regarding copyright ownership.  The ASF licenses this file | 
| * to you under the Apache License, Version 2.0 (the | 
| * "License"); you may not use this file except in compliance | 
| * with the License.  You may obtain a copy of the License at | 
| * | 
| *   http://www.apache.org/licenses/LICENSE-2.0 | 
| * | 
| * Unless required by applicable law or agreed to in writing, | 
| * software distributed under the License is distributed on an | 
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
| * KIND, either express or implied.  See the License for the | 
| * specific language governing permissions and limitations | 
| * under the License. | 
| */ | 
| import quickSelect from './quickSelect.js'; | 
| var KDTreeNode = /** @class */function () { | 
|   function KDTreeNode(axis, data) { | 
|     this.axis = axis; | 
|     this.data = data; | 
|   } | 
|   return KDTreeNode; | 
| }(); | 
| /** | 
|  * @constructor | 
|  * @alias module:echarts/data/KDTree | 
|  * @param {Array} points List of points. | 
|  * each point needs an array property to represent the actual data | 
|  * @param {Number} [dimension] | 
|  *        Point dimension. | 
|  *        Default will use the first point's length as dimension. | 
|  */ | 
| var KDTree = /** @class */function () { | 
|   function KDTree(points, dimension) { | 
|     // Use one stack to avoid allocation | 
|     // each time searching the nearest point | 
|     this._stack = []; | 
|     // Again avoid allocating a new array | 
|     // each time searching nearest N points | 
|     this._nearstNList = []; | 
|     if (!points.length) { | 
|       return; | 
|     } | 
|     if (!dimension) { | 
|       dimension = points[0].array.length; | 
|     } | 
|     this.dimension = dimension; | 
|     this.root = this._buildTree(points, 0, points.length - 1, 0); | 
|   } | 
|   /** | 
|    * Recursively build the tree. | 
|    */ | 
|   KDTree.prototype._buildTree = function (points, left, right, axis) { | 
|     if (right < left) { | 
|       return null; | 
|     } | 
|     var medianIndex = Math.floor((left + right) / 2); | 
|     medianIndex = quickSelect(points, left, right, medianIndex, function (a, b) { | 
|       return a.array[axis] - b.array[axis]; | 
|     }); | 
|     var median = points[medianIndex]; | 
|     var node = new KDTreeNode(axis, median); | 
|     axis = (axis + 1) % this.dimension; | 
|     if (right > left) { | 
|       node.left = this._buildTree(points, left, medianIndex - 1, axis); | 
|       node.right = this._buildTree(points, medianIndex + 1, right, axis); | 
|     } | 
|     return node; | 
|   }; | 
|   ; | 
|   /** | 
|    * Find nearest point | 
|    * @param  target Target point | 
|    * @param  squaredDistance Squared distance function | 
|    * @return Nearest point | 
|    */ | 
|   KDTree.prototype.nearest = function (target, squaredDistance) { | 
|     var curr = this.root; | 
|     var stack = this._stack; | 
|     var idx = 0; | 
|     var minDist = Infinity; | 
|     var nearestNode = null; | 
|     if (curr.data !== target) { | 
|       minDist = squaredDistance(curr.data, target); | 
|       nearestNode = curr; | 
|     } | 
|     if (target.array[curr.axis] < curr.data.array[curr.axis]) { | 
|       // Left first | 
|       curr.right && (stack[idx++] = curr.right); | 
|       curr.left && (stack[idx++] = curr.left); | 
|     } else { | 
|       // Right first | 
|       curr.left && (stack[idx++] = curr.left); | 
|       curr.right && (stack[idx++] = curr.right); | 
|     } | 
|     while (idx--) { | 
|       curr = stack[idx]; | 
|       var currDist = target.array[curr.axis] - curr.data.array[curr.axis]; | 
|       var isLeft = currDist < 0; | 
|       var needsCheckOtherSide = false; | 
|       currDist = currDist * currDist; | 
|       // Intersecting right hyperplane with minDist hypersphere | 
|       if (currDist < minDist) { | 
|         currDist = squaredDistance(curr.data, target); | 
|         if (currDist < minDist && curr.data !== target) { | 
|           minDist = currDist; | 
|           nearestNode = curr; | 
|         } | 
|         needsCheckOtherSide = true; | 
|       } | 
|       if (isLeft) { | 
|         if (needsCheckOtherSide) { | 
|           curr.right && (stack[idx++] = curr.right); | 
|         } | 
|         // Search in the left area | 
|         curr.left && (stack[idx++] = curr.left); | 
|       } else { | 
|         if (needsCheckOtherSide) { | 
|           curr.left && (stack[idx++] = curr.left); | 
|         } | 
|         // Search the right area | 
|         curr.right && (stack[idx++] = curr.right); | 
|       } | 
|     } | 
|     return nearestNode.data; | 
|   }; | 
|   ; | 
|   KDTree.prototype._addNearest = function (found, dist, node) { | 
|     var nearestNList = this._nearstNList; | 
|     var i = found - 1; | 
|     // Insert to the right position | 
|     // Sort from small to large | 
|     for (; i > 0; i--) { | 
|       if (dist >= nearestNList[i - 1].dist) { | 
|         break; | 
|       } else { | 
|         nearestNList[i].dist = nearestNList[i - 1].dist; | 
|         nearestNList[i].node = nearestNList[i - 1].node; | 
|       } | 
|     } | 
|     nearestNList[i].dist = dist; | 
|     nearestNList[i].node = node; | 
|   }; | 
|   ; | 
|   /** | 
|    * Find nearest N points | 
|    * @param  target Target point | 
|    * @param  N | 
|    * @param  squaredDistance Squared distance function | 
|    * @param  output Output nearest N points | 
|    */ | 
|   KDTree.prototype.nearestN = function (target, N, squaredDistance, output) { | 
|     if (N <= 0) { | 
|       output.length = 0; | 
|       return output; | 
|     } | 
|     var curr = this.root; | 
|     var stack = this._stack; | 
|     var idx = 0; | 
|     var nearestNList = this._nearstNList; | 
|     for (var i = 0; i < N; i++) { | 
|       // Allocate | 
|       if (!nearestNList[i]) { | 
|         nearestNList[i] = { | 
|           dist: 0, | 
|           node: null | 
|         }; | 
|       } | 
|       nearestNList[i].dist = 0; | 
|       nearestNList[i].node = null; | 
|     } | 
|     var currDist = squaredDistance(curr.data, target); | 
|     var found = 0; | 
|     if (curr.data !== target) { | 
|       found++; | 
|       this._addNearest(found, currDist, curr); | 
|     } | 
|     if (target.array[curr.axis] < curr.data.array[curr.axis]) { | 
|       // Left first | 
|       curr.right && (stack[idx++] = curr.right); | 
|       curr.left && (stack[idx++] = curr.left); | 
|     } else { | 
|       // Right first | 
|       curr.left && (stack[idx++] = curr.left); | 
|       curr.right && (stack[idx++] = curr.right); | 
|     } | 
|     while (idx--) { | 
|       curr = stack[idx]; | 
|       var currDist_1 = target.array[curr.axis] - curr.data.array[curr.axis]; | 
|       var isLeft = currDist_1 < 0; | 
|       var needsCheckOtherSide = false; | 
|       currDist_1 = currDist_1 * currDist_1; | 
|       // Intersecting right hyperplane with minDist hypersphere | 
|       if (found < N || currDist_1 < nearestNList[found - 1].dist) { | 
|         currDist_1 = squaredDistance(curr.data, target); | 
|         if ((found < N || currDist_1 < nearestNList[found - 1].dist) && curr.data !== target) { | 
|           if (found < N) { | 
|             found++; | 
|           } | 
|           this._addNearest(found, currDist_1, curr); | 
|         } | 
|         needsCheckOtherSide = true; | 
|       } | 
|       if (isLeft) { | 
|         if (needsCheckOtherSide) { | 
|           curr.right && (stack[idx++] = curr.right); | 
|         } | 
|         // Search in the left area | 
|         curr.left && (stack[idx++] = curr.left); | 
|       } else { | 
|         if (needsCheckOtherSide) { | 
|           curr.left && (stack[idx++] = curr.left); | 
|         } | 
|         // Search the right area | 
|         curr.right && (stack[idx++] = curr.right); | 
|       } | 
|     } | 
|     // Copy to output | 
|     for (var i = 0; i < found; i++) { | 
|       output[i] = nearestNList[i].node.data; | 
|     } | 
|     output.length = found; | 
|     return output; | 
|   }; | 
|   return KDTree; | 
| }(); | 
| export default KDTree; |