internal void BuildTree(List<VectorData> points) { if (!points.Any()) { return; } DimensionCount = points.First().Data.Count(); root = GenerateNode(0, points, 0, points.Count() - 1); }
void FindPointsWithinRadius(KDNode node, VectorData targetPoint, List<VectorData> result, double radius) { if (node.Values != targetPoint) { TryToSaveRadius(node, targetPoint, result, radius); } var dMinus1 = node.Dimension - 1; if (dMinus1 < 0) { dMinus1 = DimensionCount - 1; } var perpendicularDistance = Math.Abs(node.Values.Data.Skip(node.Dimension).First() - targetPoint.Data.Skip(dMinus1).First()); if (perpendicularDistance < radius || node.Values == targetPoint) { if (node.Above != null) { FindPointsWithinRadius(node.Above, targetPoint, result, radius); } if (node.Below != null) { FindPointsWithinRadius(node.Below, targetPoint, result, radius); } } else { if (targetPoint.Data.Skip(dMinus1).First() < node.Values.Data.Skip(node.Dimension).First()) { if (node.Below != null) { FindPointsWithinRadius(node.Below, targetPoint, result, radius); } } else { if (node.Above != null) { FindPointsWithinRadius(node.Above, targetPoint, result, radius); } } } }
void TryToSaveRadius(KDNode node, VectorData target, List<VectorData> result, double radius) { if (node == null) { return; } var distance = AbstractDistanceFunction.CalculateDistance(target, node.Values); if (radius < distance) { return; } result.Add(node.Values); }
void TryToSaveRadiusWithDistance(KDNode node, VectorData target, List<KNNPoint> result, double radius) { if (node == null) { return; } double distance = AbstractDistanceFunction.CalculateDistance(target, node.Values); if (radius < distance) { return; } result.Add(new KNNPoint(node.Values, distance)); }
KDNode GenerateNode(int currentD, List<VectorData> points, int left, int right) { if (right < left) { return null; } if (right == left) { return new KDNode(points[left], currentD); } var m = (right - left) / 2; var medianNode = RandomizedSelect(points, m, left, right, currentD); var node = new KDNode(medianNode, currentD); currentD++; if (currentD == DimensionCount) { currentD = 0; } node.Below = GenerateNode(currentD, points, left, left + m - 1); node.Above = GenerateNode(currentD, points, left + m + 1, right); return node; }