コード例 #1
0
 internal KDTreeNode <TKey, TValue> this[int compare]
 {
     get
     {
         if (compare <= 0)
         {
             return(LeftChild);
         }
         else
         {
             return(RightChild);
         }
     }
     set
     {
         if (compare <= 0)
         {
             LeftChild = value;
         }
         else
         {
             RightChild = value;
         }
     }
 }
コード例 #2
0
        public static KDTreeNode BuildKdTree(BoundingBox boundingBox, int treeLevel)
        {
            treeLevel++;
            if ((boundingBox.Shapes.Count <= int.Parse(ConfigurationManager.AppSettings["maxBoundingBoxObjects"])) || (treeLevel >= int.Parse(ConfigurationManager.AppSettings["maxTreeDepth"])))
            {
                return new KDTreeNode(boundingBox);
            }
            else
            {
                SplitDirection splitDirection;

                if (boundingBox.Width > boundingBox.Hight)
                {
                    splitDirection = SplitDirection.X;
                }
                else
                {
                    splitDirection = SplitDirection.Y;
                }

                BoundingBox leftBox = null;
                BoundingBox rightBox = null;

                boundingBox.Split(0.5f, splitDirection, out leftBox, out rightBox);

                KDTreeNode root = new KDTreeNode(boundingBox);

                root.LeftChild = BuildKdTree(leftBox, treeLevel);
                root.RightChild = BuildKdTree(rightBox, treeLevel);

                return root;
            }
        }
コード例 #3
0
ファイル: KDTree.cs プロジェクト: DeepGameAnalysis/dga-core
        public bool Add(TKey[] point, TValue value)
        {
            var nodeToAdd = new KDTreeNode <TKey, TValue>(point, value);

            if (root == null)
            {
                root = new KDTreeNode <TKey, TValue>(point, value);
            }
            else
            {
                int dimension = -1;
                KDTreeNode <TKey, TValue> parent = root;

                do
                {
                    // Increment the dimension we're searching in
                    dimension = (dimension + 1) % dimensions;

                    // Does the node we're adding have the same hyperpoint as this node?
                    if (typeMath.AreEqual(point, parent.Point))
                    {
                        switch (AddDuplicateBehavior)
                        {
                        case AddDuplicateBehavior.Skip:
                            return(false);

                        case AddDuplicateBehavior.Error:
                            throw new DuplicateNodeError();

                        case AddDuplicateBehavior.Update:
                            parent.Value = value;
                            break;

                        default:
                            // Should never happen
                            throw new Exception("Unexpected AddDuplicateBehavior");
                        }
                    }

                    // Which side does this node sit under in relation to it's parent at this level?
                    int compare = typeMath.Compare(point[dimension], parent.Point[dimension]);

                    if (parent[compare] == null)
                    {
                        parent[compare] = nodeToAdd;
                        break;
                    }
                    else
                    {
                        parent = parent[compare];
                    }
                }while (true);
            }

            Count++;
            return(true);
        }
コード例 #4
0
ファイル: KDTree.cs プロジェクト: DeepGameAnalysis/dga-core
 private void RemoveChildNodes(KDTreeNode <TKey, TValue> node)
 {
     for (var side = -1; side <= 1; side += 2)
     {
         if (node[side] != null)
         {
             RemoveChildNodes(node[side]);
             node[side] = null;
         }
     }
 }
コード例 #5
0
        /// <summary>
        /// 递归寻找方法
        /// </summary>
        /// <param name="inputNode">输入的节点</param>
        /// <param name="inputValue">输入的值</param>
        /// <returns>找到的值若为Null则未找到</returns>
        private KDTreeNode searchRecursion(KDTreeNode inputNode, IDimensionValueBean inputValue)
        {
            if (null == inputNode)
            {
                return(null);
            }
            //若两节点相同
            else if
            (UtilityMethod.IfDDimensionIsEqula
                 (inputNode.ThisDataValue, inputValue, ifUseRecursionCheck))
            {
                //若节点已删除
                if (inputNode.IsDeleteTag)
                {
                    return(null);
                }
                else
                {
                    return(inputNode);
                }
            }
            else
            {
                //获取维度索引
                int dimensionIndex = inputNode.NowDimisionIndex;
                //获取多维数据封装
                IDimensionValueBean nodeValue = inputNode.ThisDataValue;
                //获得当前节点维度的值
                double tempDimensionValue = nodeValue.GetValueAtDimensionIndex(dimensionIndex);
                //获得输入数值在节点维度的值
                double tempInputValue = inputValue.GetValueAtDimensionIndex(dimensionIndex);

                //比较两值
                CompareResultEnum compareResult = UtilityMethod.CompareDoulbe(tempInputValue, tempDimensionValue);
                //比较结果调整
                compareResult = equalStrategy(compareResult);

                //次轮迭代使用的节点
                KDTreeNode nextRoundNode = null;

                //若小于去左节点
                if (compareResult == CompareResultEnum.Less)
                {
                    nextRoundNode = inputNode.LeftChild;
                }
                //其它去右节点
                else
                {
                    nextRoundNode = inputNode.RightChild;
                }
                //递归执行
                return(searchRecursion(nextRoundNode, inputValue));
            }
        }
コード例 #6
0
        /// <summary>
        /// 寻找一个节点
        /// </summary>
        /// <param name="inputValue">输入的多维封装</param>
        /// <returns>找到的节点</returns>
        public IDimensionValueBean Search(IDimensionValueBean inputValue)
        {
            KDTreeNode tempNode = SearchNode(inputValue);

            if (null == tempNode)
            {
                return(null);
            }
            else
            {
                return(tempNode.ThisDataValue);
            }
        }
コード例 #7
0
ファイル: KDTree.cs プロジェクト: DeepGameAnalysis/dga-core
        public void RemoveAt(TKey[] point)
        {
            // Is tree empty?
            if (root == null)
            {
                return;
            }

            KDTreeNode <TKey, TValue> node;

            if (typeMath.AreEqual(point, root.Point))
            {
                node = root;
                root = null;
                Count--;
                ReaddChildNodes(node);
                return;
            }

            node = root;

            int dimension = -1;

            do
            {
                dimension = (dimension + 1) % dimensions;

                int compare = typeMath.Compare(point[dimension], node.Point[dimension]);

                if (node[compare] == null)
                {
                    // Can't find node
                    return;
                }

                if (typeMath.AreEqual(point, node[compare].Point))
                {
                    var nodeToRemove = node[compare];
                    node[compare] = null;
                    Count--;

                    ReaddChildNodes(nodeToRemove);
                }
                else
                {
                    node = node[compare];
                }
            }while (node != null);
        }
コード例 #8
0
ファイル: KDTree.cs プロジェクト: DeepGameAnalysis/dga-core
        private void ReaddChildNodes(KDTreeNode <TKey, TValue> removedNode)
        {
            if (removedNode.IsLeaf)
            {
                return;
            }

            // The folllowing code might seem a little redundant but we're using
            // 2 queues so we can add the child nodes back in, in (more or less)
            // the same order they were added in the first place
            var nodesToReadd = new Queue <KDTreeNode <TKey, TValue> >();

            var nodesToReaddQueue = new Queue <KDTreeNode <TKey, TValue> >();

            if (removedNode.LeftChild != null)
            {
                nodesToReaddQueue.Enqueue(removedNode.LeftChild);
            }

            if (removedNode.RightChild != null)
            {
                nodesToReaddQueue.Enqueue(removedNode.RightChild);
            }

            while (nodesToReaddQueue.Count > 0)
            {
                var nodeToReadd = nodesToReaddQueue.Dequeue();

                nodesToReadd.Enqueue(nodeToReadd);

                for (int side = -1; side <= 1; side += 2)
                {
                    if (nodeToReadd[side] != null)
                    {
                        nodesToReaddQueue.Enqueue(nodeToReadd[side]);

                        nodeToReadd[side] = null;
                    }
                }
            }

            while (nodesToReadd.Count > 0)
            {
                var nodeToReadd = nodesToReadd.Dequeue();

                Count--;
                Add(nodeToReadd.Point, nodeToReadd.Value);
            }
        }
コード例 #9
0
ファイル: KDTree.cs プロジェクト: DeepGameAnalysis/dga-core
        private void AddNodesToList(KDTreeNode <TKey, TValue> node, List <KDTreeNode <TKey, TValue> > nodes)
        {
            if (node == null)
            {
                return;
            }

            nodes.Add(node);

            for (var side = -1; side <= 1; side += 2)
            {
                if (node[side] != null)
                {
                    AddNodesToList(node[side], nodes);
                    node[side] = null;
                }
            }
        }
コード例 #10
0
        /// <summary>
        /// 节点删除(不进行平衡调整)
        /// </summary>
        /// <param name="inputValue"></param>
        /// <returns></returns>
        public bool DeleteNoneBlace(IDimensionValueBean inputValue)
        {
            //寻找节点
            KDTreeNode findedNode = SearchNode(inputValue);

            //若没找到或目前节点已删除
            if (null == findedNode || findedNode.IsDeleteTag == true)
            {
                return(false);
            }
            //正常情况仅调整标签
            else
            {
                findedNode.IsDeleteTag = true;
                nodeCount--;
                return(true);
            }
        }
コード例 #11
0
 /// <summary>
 /// 节点插入(不进行平衡调整)
 /// </summary>
 /// <param name="inputValue">输入的多维数据值</param>
 /// <returns>插入结果</returns>
 public bool InsertNoneBlance(IDimensionValueBean inputValue)
 {
     //若根节点为Null
     if (null == rootNode)
     {
         inputCheck(inputValue, false);
         int        tempIndex    = GetUseDimensionIndex();
         KDTreeNode tempTreeNode = new KDTreeNode(inputValue, tempIndex);
         rootNode = tempTreeNode;
         nodeCount++;
         return(true);
     }
     else
     {
         inputCheck(inputValue);
         return(insertLoopMethod(inputValue));
     }
 }
コード例 #12
0
        /// <summary>
        /// 设置相应的子节点
        /// </summary>
        /// <param name="ifLeftChild">是否是左子节点</param>
        /// <param name="inputTreeNode">输入的节点</param>
        internal void SetChildNode(bool ifLeftChild, KDTreeNode inputTreeNode)
        {
            //获得当前的相应子节点
            KDTreeNode nowNode = GetChildNode(ifLeftChild);

            //插入位置子节点声明
            KDTreeNode tempLeftNode  = null;
            KDTreeNode tempRightNode = null;

            //若当前位置有子节点
            if (null != nowNode)
            {
                //临时变量赋值
                tempLeftNode  = nowNode.LeftChild;
                tempRightNode = nowNode.RightChild;
                //清空目前节点与树的连接关系
                nowNode.Parent     = null;
                nowNode.LeftChild  = null;
                nowNode.RightChild = null;
            }

            //将输入节点的父节点设为自身
            inputTreeNode.Parent = this;

            //将输入节点与父节点连接
            if (ifLeftChild)
            {
                this.LeftChild = inputTreeNode;
            }
            else
            {
                this.RightChild = inputTreeNode;
            }

            //将输入节点与子节点连接
            inputTreeNode.LeftChild  = tempLeftNode;
            inputTreeNode.RightChild = tempRightNode;
        }
コード例 #13
0
ファイル: KDTree.cs プロジェクト: DeepGameAnalysis/dga-core
        public KDTreeNode <TKey, TValue>[] RangeQuery(TKey[] center, TKey radius, int count)
        {
            var nearestNeighbours = new NearestNeighbourList <KDTreeNode <TKey, TValue>, TKey>(count, typeMath);

            AddNearestNeighbours(
                root,
                center,
                KDTreeHyperRect <TKey> .Infinite(dimensions, typeMath),
                0,
                nearestNeighbours,
                typeMath.Multiply(radius, radius));

            count = nearestNeighbours.Count;

            var neighbourArray = new KDTreeNode <TKey, TValue> [count];

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

            return(neighbourArray);
        }
コード例 #14
0
ファイル: KDTree.cs プロジェクト: DeepGameAnalysis/dga-core
        private void AddNodeToStringBuilder(KDTreeNode <TKey, TValue> node, StringBuilder sb, int depth)
        {
            sb.AppendLine(node.ToString());

            for (var side = -1; side <= 1; side += 2)
            {
                for (var index = 0; index <= depth; index++)
                {
                    sb.Append("\t");
                }

                sb.Append(side == -1 ? "L " : "R ");

                if (node[side] == null)
                {
                    sb.AppendLine("");
                }
                else
                {
                    AddNodeToStringBuilder(node[side], sb, depth + 1);
                }
            }
        }
コード例 #15
0
 public static void IntersectTree(KDTreeNode node, Point point, UserMessaging messagingAgent)
 {
     if (node.IsNodeLeaf)
     {
         foreach (Shape shape in node.NodeBox.Shapes)
         {
             if (shape.Intersects(point))
             {
                 messagingAgent.SendMessage(shape.Name);
             }
         }
     }
     else
     {
         if (node.LeftChild.NodeBox.Intersects(point))
         {
             IntersectTree(node.LeftChild, point, messagingAgent);
         }
         else
         {
             IntersectTree(node.RightChild, point, messagingAgent);
         }
     }
 }
コード例 #16
0
ファイル: KDTree.cs プロジェクト: DeepGameAnalysis/dga-core
        public KDTreeNode <TKey, TValue>[] NearestNeighboursQuery(TKey[] 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 KDTreeNode <TKey, TValue> [0]);
            }

            var neighbours = new KDTreeNode <TKey, TValue> [count];

            var nearestNeighbours = new NearestNeighbourList <KDTreeNode <TKey, TValue>, TKey>(count, typeMath);

            var rect = KDTreeHyperRect <TKey> .Infinite(dimensions, typeMath);

            AddNearestNeighbours(root, point, rect, 0, nearestNeighbours, typeMath.MaxValue);

            count = nearestNeighbours.Count;

            var neighbourArray = new KDTreeNode <TKey, TValue> [count];

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

            return(neighbourArray);
        }
コード例 #17
0
 /// <summary>
 /// 比较输入的多维节点是否与此节点数据相同
 /// </summary>
 /// <param name="inputValue">输入的多维节点</param>
 /// <returns>是否相同</returns>
 internal bool IfEqula(KDTreeNode inputValue)
 {
     return(IfEqula(inputValue.thisDataValue));
 }
コード例 #18
0
        /// <summary>
        /// 添加节点的递归方法
        /// </summary>
        /// <param name="inputValue">输入的值</param>
        /// <returns></returns>
        private bool insertLoopMethod(IDimensionValueBean inputValue)
        {
            //当前递归节点
            KDTreeNode currentNode = rootNode;
            //当前节点的父节点
            KDTreeNode parentNode = null;
            //临时节点
            KDTreeNode tempNode = null;
            //父节点的索引
            int tempDimensionIndex = -1;

            //当前节点应当使用的索引
            int tempNowIndex = -1;

            //表征节点前进方向是否是向左节点
            bool ifIsLeftTag = true;

            double tempParentValue  = 0.0d;
            double tempCurrentValue = 0.0d;

            CompareResultEnum tempCompareResult;

            //递归寻找添加位点
            while (true)
            {
                //当前递归层级节点变为父节点
                parentNode = currentNode;
                //获得父节点的索引
                tempDimensionIndex = parentNode.NowDimisionIndex;
                //获得父节点的值
                tempParentValue = parentNode.ThisDataValue.
                                  GetValueAtDimensionIndex(tempDimensionIndex);
                //获取此节点的值
                tempCurrentValue = inputValue.
                                   GetValueAtDimensionIndex(tempDimensionIndex);
                //比较节点值
                tempCompareResult = UtilityMethod.
                                    CompareDoulbe(tempCurrentValue, tempParentValue);
                //按相等策略调整
                tempCompareResult = equalStrategy(tempCompareResult);

                //小于:左子树方向
                if (tempCompareResult == CompareResultEnum.Less)
                {
                    ifIsLeftTag = true;
                }
                //其它右子树方向
                else
                {
                    ifIsLeftTag = false;
                }

                //获取父节点相应位置处的子节点
                currentNode = parentNode.GetChildNode(ifIsLeftTag);
                //获得子节点的索引
                tempNowIndex = GetUseDimensionInde(tempDimensionIndex);
                if (null == currentNode)
                {
                    tempNode = new KDTreeNode(inputValue, tempNowIndex);
                    parentNode.SetChildNode(ifIsLeftTag, tempNode);
                    break;
                }

                //若多维值相同
                if (UtilityMethod.IfDDimensionIsEqula(currentNode.ThisDataValue, inputValue))
                {
                    //若需要替换或当前节点是已删除状态
                    if (ifEqualValueReplace || currentNode.IsDeleteTag)
                    {
                        currentNode.ThisDataValue = inputValue;
                        currentNode.IsDeleteTag   = false;
                    }
                    break;
                }
            }
            nodeCount++;
            return(true);
        }
コード例 #19
0
ファイル: KDTree.cs プロジェクト: DeepGameAnalysis/dga-core
        /*
         * 1. Search for the target
         *
         *   1.1 Start by splitting the specified hyper rect
         *       on the specified node's point along the current
         *       dimension so that we end up with 2 sub hyper rects
         *       (current dimension = depth % dimensions)
         *
         *	 1.2 Check what sub rectangle the the target point resides in
         *	     under the current dimension
         *
         *   1.3 Set that rect to the nearer rect and also the corresponding
         *       child node to the nearest rect and node and the other rect
         *       and child node to the further rect and child node (for use later)
         *
         *   1.4 Travel into the nearer rect and node by calling function
         *       recursively with nearer rect and node and incrementing
         *       the depth
         *
         * 2. Add leaf to list of nearest neighbours
         *
         * 3. Walk back up tree and at each level:
         *
         *    3.1 Add node to nearest neighbours if
         *        we haven't filled our nearest neighbour
         *        list yet or if it has a distance to target less
         *        than any of the distances in our current nearest
         *        neighbours.
         *
         *    3.2 If there is any point in the further rectangle that is closer to
         *        the target than our furtherest nearest neighbour then travel into
         *        that rect and node
         *
         *  That's it, when it finally finishes traversing the branches
         *  it needs to we'll have our list!
         */

        private void AddNearestNeighbours(
            KDTreeNode <TKey, TValue> node,
            TKey[] target,
            KDTreeHyperRect <TKey> rect,
            int depth,
            NearestNeighbourList <KDTreeNode <TKey, TValue>, TKey> nearestNeighbours,
            TKey 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] = node.Point[dimension];

            var rightRect = rect.Clone();

            rightRect.MinPoint[dimension] = node.Point[dimension];

            // Which side does the target reside in?
            int compare = typeMath.Compare(target[dimension], node.Point[dimension]);

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

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

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

            TKey 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
            TKey[] closestPointInFurtherRect = furtherRect.GetClosestPoint(target, typeMath);
            distanceSquaredToTarget = typeMath.DistanceSquaredBetweenPoints(closestPointInFurtherRect, target);

            if (typeMath.Compare(distanceSquaredToTarget, maxSearchRadiusSquared) <= 0)
            {
                if (nearestNeighbours.IsCapacityReached)
                {
                    if (typeMath.Compare(distanceSquaredToTarget, nearestNeighbours.GetFurtherestDistance()) < 0)
                    {
                        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 = typeMath.DistanceSquaredBetweenPoints(node.Point, target);

            if (typeMath.Compare(distanceSquaredToTarget, maxSearchRadiusSquared) <= 0)
            {
                nearestNeighbours.Add(node, distanceSquaredToTarget);
            }
        }