Пример #1
0
        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);
            }
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
            }
        }
Пример #4
0
        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));
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
            }
        }
Пример #8
0
        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);
        }