private void GetNeighboursAtDistance(double[] center, double radius, CurveVertexNode <T> node, List <T> vertices) { if (node == null) { return; } var current = node.Value; double dist = this._sqrDist(center, _pointSelector(current)); if (dist <= radius) { vertices.Add(current); } int d = node.Depth % this._dimension; double coordCen = center[d]; double coordCur = _pointSelector(current)[d]; dist = coordCen - coordCur; if (dist * dist > radius) { if (coordCen < coordCur) { GetNeighboursAtDistance(center, radius, node.LeftChild, vertices); } else { GetNeighboursAtDistance(center, radius, node.RightChild, vertices); } } else { GetNeighboursAtDistance(center, radius, node.LeftChild, vertices); GetNeighboursAtDistance(center, radius, node.RightChild, vertices); } }
private T GetNeighbour(double[] center, CurveVertexNode <T> node, T currentBest, double bestDist) { if (node == null) { return(currentBest); } T current = node.Value; int d = node.Depth % this._dimension; double coordCen = center[d]; double coordCur = _pointSelector(current)[d]; double dist = this._sqrDist(center, _pointSelector(current)); if (dist >= 0.0 && dist < bestDist) { currentBest = current; bestDist = dist; } dist = coordCen - coordCur; if (bestDist < dist * dist) { currentBest = GetNeighbour( center, coordCen < coordCur ? node.LeftChild : node.RightChild, currentBest, bestDist); bestDist = this._sqrDist(center, _pointSelector(currentBest)); } else { currentBest = GetNeighbour(center, node.LeftChild, currentBest, bestDist); bestDist = this._sqrDist(center, _pointSelector(currentBest)); currentBest = GetNeighbour(center, node.RightChild, currentBest, bestDist); bestDist = this._sqrDist(center, _pointSelector(currentBest)); } return(currentBest); }
private void GetKNeighbours(double[] center, int number, CurveVertexNode <T> node, List <Tuple <double, T> > pairs) { if (node == null) { return; } var current = node.Value; double dist = this._sqrDist(center, _pointSelector(current)); int cnt = pairs.Count; if (cnt == 0) { pairs.Add(new Tuple <double, T>(dist, current)); } else if (cnt < number) { if (dist > pairs[0].Item1) { pairs.Insert(0, new Tuple <double, T>(dist, current)); } else { pairs.Add(new Tuple <double, T>(dist, current)); } } else if (dist < pairs[0].Item1) { pairs[0] = new Tuple <double, T>(dist, current); pairs.Sort((p1, p2) => p2.Item1.CompareTo(p1.Item1)); } int d = node.Depth % this._dimension; double coordCen = center[d]; double coordCur = _pointSelector(current)[d]; dist = coordCen - coordCur; if (dist * dist > pairs[0].Item1) { if (coordCen < coordCur) { GetKNeighbours(center, number, node.LeftChild, pairs); } else { GetKNeighbours(center, number, node.RightChild, pairs); } } else { GetKNeighbours(center, number, node.LeftChild, pairs); GetKNeighbours(center, number, node.RightChild, pairs); } }
private CurveVertexNode <T> GetRightParent(CurveVertexNode <T> node) { CurveVertexNode <T> parent = node.Parent; if (parent == null) { return(null); } if (node.IsLeft) { return(parent); } return(GetRightParent(parent)); }
private void GetRightParentsNeighbours(double[] center, CurveVertexNode <T> node, double radius, List <T> vertices) { CurveVertexNode <T> parent = GetRightParent(node); if (parent == null) { return; } int d = parent.Depth % this._dimension; double dist = center[d] - _pointSelector(parent.Value)[d]; if (dist * dist <= radius) { GetNeighboursAtDistance(center, radius, parent.RightChild, vertices); } GetRightParentsNeighbours(center, parent, radius, vertices); }
private CurveVertexNode <T> Create(T[] vertices, int depth, CurveVertexNode <T> parent, bool isLeft, int startIndex, int endIndex) { int length = vertices.Length; if (length == 0 || startIndex > endIndex) { return(null); } if (startIndex == endIndex) { return(new CurveVertexNode <T>(vertices[startIndex])); } int d = depth % this._dimension; T median = vertices.QuickSelectMedian((p1, p2) => _pointSelector(p1)[d].CompareTo(_pointSelector(p2)[d]), startIndex, endIndex); var node = new CurveVertexNode <T>(median); node.Depth = depth; node.Parent = parent; node.IsLeft = isLeft; int mid = (startIndex + endIndex) / 2; //int rlen = length - mid - 1; //var left = new T[mid]; //var right = new T[rlen]; ////此处会导致比较大的内存消耗 //Array.Copy(vertices, 0, left, 0, mid); //Array.Copy(vertices, mid + 1, right, 0, rlen); if (depth < this._parallelDepth) { System.Threading.Tasks.Parallel.Invoke( () => node.LeftChild = Create(vertices, depth + 1, node, true, startIndex, mid - 1), () => node.RightChild = Create(vertices, depth + 1, node, false, mid + 1, endIndex) ); } else { node.LeftChild = Create(vertices, depth + 1, node, true, startIndex, mid - 1); node.RightChild = Create(vertices, depth + 1, node, false, mid + 1, endIndex); } return(node); }
private void FindRange(double[] lowerLeft, double[] upperRight, CurveVertexNode <T> node, List <T> vertices) { if (node == null) { return; } var current = node.Value; var currentPoint = _pointSelector(current); if (_ignoreZ) { if (currentPoint[0] >= lowerLeft[0] && currentPoint[0] <= upperRight[0] && currentPoint[1] >= lowerLeft[1] && currentPoint[1] <= upperRight[1]) { vertices.Add(current); } } else { if (currentPoint[0] >= lowerLeft[0] && currentPoint[0] <= upperRight[0] && currentPoint[1] >= lowerLeft[1] && currentPoint[1] <= upperRight[1] && currentPoint[2] >= lowerLeft[2] && currentPoint[2] <= upperRight[2]) { vertices.Add(current); } } int d = node.Depth % this._dimension; if (upperRight[d] < currentPoint[d]) { FindRange(lowerLeft, upperRight, node.LeftChild, vertices); } else if (lowerLeft[d] > currentPoint[d]) { FindRange(lowerLeft, upperRight, node.RightChild, vertices); } else { FindRange(lowerLeft, upperRight, node.LeftChild, vertices); FindRange(lowerLeft, upperRight, node.RightChild, vertices); } }
private void GetConnexions(CurveVertexNode <T> node, double radius, List <Tuple <T, T> > connexions) { if (node == null) { return; } var vertices = new List <T>(); var center = node.Value; if (_ignoreZ) { GetRightParentsNeighbours(_pointSelector(center), node, radius, vertices); } GetNeighboursAtDistance(_pointSelector(center), radius, node.LeftChild, vertices); GetNeighboursAtDistance(_pointSelector(center), radius, node.RightChild, vertices); for (int i = 0; i < vertices.Count; i++) { connexions.Add(new Tuple <T, T>(center, vertices[i])); } GetConnexions(node.LeftChild, radius, connexions); GetConnexions(node.RightChild, radius, connexions); }