private KDTreeNode CreateTreeNode(List <KD_Point> pointList) { if (pointList.Count > 0) { // 计算方差 double xObtainVariance = ObtainVariance(CreateXList(pointList)); double yObtainVariance = ObtainVariance(CreateYList(pointList)); // 根据方差确定分裂维度 EnumDivisionType divisionType = SortListByXOrYVariances(xObtainVariance, yObtainVariance, ref pointList); // 获得中位数 KD_Point medianPoint = ObtainMedian(pointList); int medianIndex = pointList.Count / 2; // 构建节点 KDTreeNode treeNode = new KDTreeNode() { DivisionPoint = medianPoint, DivisionType = divisionType, LeftChild = CreateTreeNode(pointList.Take(medianIndex).ToList()), RightChild = CreateTreeNode(pointList.Skip(medianIndex + 1).ToList()) }; return(treeNode); } else { return(null); } }
public List <KD_Point> K_Nearest(KD_Point position, int K) { KDTreeNodeCollection collection = new KDTreeNodeCollection(K, position); collection = K_Nearest(this.rootNode, position, collection); return(collection.GetPoints()); }
//回溯搜索 private KD_Point BacktrcakSearch(KD_Point searchPoint, KD_Point nearestPoint) { if (backtrackStack.IsEmpty()) { return(nearestPoint); } else { KDTreeNode trackNode = backtrackStack.Pop(); double backtrackDistance = ObtainDistanFromTwoPoint(searchPoint, trackNode.DivisionPoint); double nearestPointDistance = ObtainDistanFromTwoPoint(searchPoint, nearestPoint); if (backtrackDistance < nearestPointDistance) { KDTreeNode searchNode = new KDTreeNode() { DivisionPoint = trackNode.DivisionPoint, DivisionType = trackNode.DivisionType, LeftChild = trackNode.LeftChild, RightChild = trackNode.RightChild }; nearestPoint = DFSBackTrackingSearch(searchNode, searchPoint); } return(BacktrcakSearch(searchPoint, nearestPoint)); } }
//向右节点搜寻 private KD_Point DFSRightSearch(KDTreeNode node, KD_Point searchPoint) { if (node.RightChild != null) { return(DFSSearch(node.RightChild, searchPoint)); } else { return(node.DivisionPoint); } }
//按照Y节点搜寻 private KD_Point DFSYsearch(KDTreeNode node, KD_Point searchPoint) { if (node.DivisionPoint.Y > searchPoint.Y) { return(DFSLeftSearch(node, searchPoint)); } else { return(DFSRightSearch(node, searchPoint)); } }
//向左节点回溯搜寻 private KD_Point DFSBackTrackLeftSearch(KDTreeNode node, KD_Point searchPoint) { if (node.LeftChild != null) { return(DFSSearch(node.LeftChild, searchPoint, false)); } else { return(node.DivisionPoint); } }
//向上回溯搜索 private KD_Point DFSBackTrackingSearch(KDTreeNode node, KD_Point searchPoint) { backtrackStack.Push(node); if (node.DivisionType == EnumDivisionType.X) { return(DFSBackTrackingXsearch(node, searchPoint)); } else { return(DFSBackTrackingYsearch(node, searchPoint)); } }
private KD_Point DFSSearch(KDTreeNode node, KD_Point searchPoint, bool pushStack = true) { if (pushStack == true) { backtrackStack.Push(node); } if (node.DivisionType == EnumDivisionType.X) { return(DFSXsearch(node, searchPoint)); } else { return(DFSYsearch(node, searchPoint)); } }
public void Add(KDTreeNode currentnode, double d) { KD_Point current = currentnode.DivisionPoint; if (collection.Count == 0) { collection.Add(current); this.max = d; } else if (collection.Count < this.k) { if (max < d) { this.max = d; location = collection.Count; collection.Add(current); } else { collection.Add(current); } } else { if (d <= max) { collection.RemoveAt(location); collection.Add(current); for (int i = 0; i < k; i++) { if (i == 0) { max = Math.Sqrt(Math.Pow(thepoint.X - collection[i].X, 2) + Math.Pow(thepoint.Y - collection[i].Y, 2)); location = i; } else { double distance = Math.Sqrt(Math.Pow(thepoint.X - collection[i].X, 2) + Math.Pow(thepoint.Y - collection[i].Y, 2)); if (distance > max) { max = distance; location = i; } } } } } }
//按照Y节点回溯搜寻 private KD_Point DFSBackTrackingYsearch(KDTreeNode node, KD_Point searchPoint) { if (node.DivisionPoint.Y > searchPoint.Y) { node.LeftChild = null; KD_Point rightSearchPoint = DFSBackTrackRightSearch(node, searchPoint); node.RightChild = null; return(rightSearchPoint); } else { node.RightChild = null; KD_Point leftSearchPoint = DFSBackTrackLeftSearch(node, searchPoint); node.LeftChild = null; return(leftSearchPoint); } }
public KDTreeNodeCollection K_Nearest(KDTreeNode current, KD_Point position, KDTreeNodeCollection collection) { double d = ObtainDistanFromTwoPoint(current.DivisionPoint, position); collection.Add(current, d); double value; double median; if (current.DivisionType == EnumDivisionType.X) { value = position.X; median = current.DivisionPoint.X; } else { value = position.Y; median = current.DivisionPoint.Y; } double u = value - median; if (u <= 0) { if (current.LeftChild != null) { K_Nearest(current.LeftChild, position, collection); } if (current.RightChild != null && Math.Abs(u) <= collection.max) { K_Nearest(current.RightChild, position, collection); } } else { if (current.RightChild != null) { K_Nearest(current.RightChild, position, collection); } if (current.LeftChild != null && Math.Abs(u) <= collection.max) { K_Nearest(current.LeftChild, position, collection); } } return(collection); }
public int k = 0;//k临近值 // public KDTreeNodeCollection(int num, KD_Point point) { this.k = num; this.thepoint = point; collection = new List <KD_Point>(); }
private double ObtainDistanFromTwoPoint(KD_Point start, KD_Point end) { return(Math.Sqrt(Math.Pow(start.X - end.X, 2) + Math.Pow(start.Y - end.Y, 2))); }
//上面是构建KD树 //下面是寻找最近点 public KD_Point FindNearest(KD_Point searchPoint) { KD_Point nearestPoint = DFSSearch(this.rootNode, searchPoint); return(BacktrcakSearch(searchPoint, nearestPoint)); }