예제 #1
0
        public Node[] RadialSearch(GetIndex <K> center, K radius, int count)
        {
            var nearestNeighbours = new NearestNeighbourList <Node, K>(count, this._minValue, this._compareKey);

            AddNearestNeighbours(
                _root,
                center,
                HyperRect <K> .Infinite(_dimensions, this._minValue, this._maxValue, this._compareKey),
                0,
                nearestNeighbours,
                this._multiply(radius, radius));

            count = nearestNeighbours.Count;

            var neighbourArray = new Node[count];

            for (var index = 0; index < count; index++)
            {
                neighbourArray[count - index - 1] = nearestNeighbours.RemoveFurtherest();
            }

            return(neighbourArray);
        }
예제 #2
0
        public Node[] GetNearestNeighbours(GetIndex <K> point, int count)
        {
            if (count > Count)
            {
                count = Count;
            }

            if (count < 0)
            {
                throw new ArgumentException("Number of neighbors cannot be negative");
            }

            if (count == 0)
            {
                return(new Node[0]);
            }

            var neighbours = new Node[count];

            var nearestNeighbours = new NearestNeighbourList <Node, K>(count, this._minValue, this._compareKey);

            var rect = HyperRect <K> .Infinite(_dimensions, this._minValue, this._maxValue, this._compareKey);

            AddNearestNeighbours(_root, point, rect, 0, nearestNeighbours, this._maxValue);

            count = nearestNeighbours.Count;

            var neighbourArray = new Node[count];

            for (var index = 0; index < count; index++)
            {
                neighbourArray[count - index - 1] = nearestNeighbours.RemoveFurtherest();
            }

            return(neighbourArray);
        }
예제 #3
0
        internal void AddNearestNeighbours(
            Node node,
            GetIndex <K> target,
            HyperRect <K> rect,
            int depth,
            NearestNeighbourList <Node, K> nearestNeighbours,
            K maxSearchRadiusSquared)
        {
            if (node == null)
            {
                return;
            }

            // Work out the current dimension
            int dimension = depth % _dimensions;

            // Split our hyper-rect into 2 sub rects along the current
            // node's point on the current dimension
            var leftRect = rect.Clone();

            leftRect.MaxPoint[dimension] = this._locate(node.Value)(dimension);

            var rightRect = rect.Clone();

            rightRect.MinPoint[dimension] = this._locate(node.Value)(dimension);

            // Which side does the target reside in?
            CompareResult compareTargetPoint = this._compareKey(target(dimension), this._locate(node.Value)(dimension));
            int           compareTargetPoint_as_int;

            switch (compareTargetPoint)
            {
            case Equal:
                compareTargetPoint_as_int = 0;
                break;

            case Less:
                compareTargetPoint_as_int = -1;
                break;

            case Greater:
                compareTargetPoint_as_int = 1;
                break;

            default:
                throw new System.NotImplementedException();
            }

            var nearerRect  = compareTargetPoint_as_int <= 0 ? leftRect : rightRect;
            var furtherRect = compareTargetPoint_as_int <= 0 ? rightRect : leftRect;

            var nearerNode  = compareTargetPoint_as_int <= 0 ? node.LeftChild : node.RightChild;
            var furtherNode = compareTargetPoint_as_int <= 0 ? node.RightChild : node.LeftChild;

            // Let's walk down into the nearer branch
            if (nearerNode != null)
            {
                AddNearestNeighbours(
                    nearerNode,
                    target,
                    nearerRect,
                    depth + 1,
                    nearestNeighbours,
                    maxSearchRadiusSquared);
            }

            K distanceSquaredToTarget;

            // Walk down into the further branch but only if our capacity hasn't been reached
            // OR if there's a region in the further rect that's closer to the target than our
            // current furtherest nearest neighbour
            GetIndex <K> closestPointInFurtherRect = furtherRect.GetClosestPoint(target, this._dimensions);

            distanceSquaredToTarget = DistanceSquaredBetweenPoints(closestPointInFurtherRect, target);

            if (this._compareKey(distanceSquaredToTarget, maxSearchRadiusSquared) == (Less | Equal))
            {
                if (nearestNeighbours.IsCapacityReached)
                {
                    if (this._compareKey(distanceSquaredToTarget, nearestNeighbours.GetFurtherestDistance()) == Less)
                    {
                        AddNearestNeighbours(
                            furtherNode,
                            target,
                            furtherRect,
                            depth + 1,
                            nearestNeighbours,
                            maxSearchRadiusSquared);
                    }
                }
                else
                {
                    AddNearestNeighbours(
                        furtherNode,
                        target,
                        furtherRect,
                        depth + 1,
                        nearestNeighbours,
                        maxSearchRadiusSquared);
                }
            }

            // Try to add the current node to our nearest neighbours list
            distanceSquaredToTarget = DistanceSquaredBetweenPoints(this._locate(node.Value), target);

            if (this._compareKey(distanceSquaredToTarget, maxSearchRadiusSquared) == (Less | Equal))
            {
                nearestNeighbours.Add(node, distanceSquaredToTarget);
            }
        }