Пример #1
0
 public List <QuadTreeObj> GetColliObjs(QuadTreeObj obj)
 {
     _findCollObjLists.Clear();
     _rootNode.FindObjInQuadNode(obj, _rootNode, _findCollObjLists);
     Debug.Log("查询结果对象数量=" + _findCollObjLists.Count);
     return(_findCollObjLists);
 }
Пример #2
0
        /// <summary>
        ///  对象 添加到子节点中,   如果仅在一个子节点区域中直接加入, 如果跨子节点区域加到 父节点中
        /// </summary>
        /// <param name="rect"></param>
        private void AddRectToChildNode(QuadTreeObj quadObj)
        {
            if (ChildNodes == null || ChildNodes.Count <= 0)
            {
                return;
            }
            int tInserId     = -1;
            int tInsertCount = 0;

            for (int j = 0; j < 4; j++)
            {
                if (ChildNodes[j].IsRectInArea(quadObj.Rect))                         // 对象加入对应区域的节点内
                {
                    tInserId = j;
                    tInsertCount++;
                }
            }
            if (tInsertCount == 1)
            {
                ChildNodes[tInserId].AddRectToNode(quadObj);    // 仅在一个子区域内时直接  加入该子区域
            }
            else
            {
                ManageObjs.Add(quadObj);                // 对象不在子节点区域内 或者对象在两个子区域内  直接加入到本区域内
            }
        }
Пример #3
0
 /// <summary>
 ///  将对象添加到区域内,  如果 当前节点深度等级已达到最大值 则直接加入, 否则 如果区域管理对象数量已达到最大 则分割区域为四块并调整各块管理对象, 其他情况直接加入
 ///     防止树的深度太大影响检索效率
 /// </summary>
 /// <param name="quadObj"></param>
 public void AddRectToNode(QuadTreeObj quadObj)
 {
     if (DeepLevel >= MaxDeepLevel)
     {
         ManageObjs.Add(quadObj);                // 直接加入
     }
     else
     {
         if (ChildNodes == null || ChildNodes.Count <= 0) // 不存在子区域, 检测管理数量上限
         {
             if (ManageObjCount >= MaxObjCount)           // 超过管理上限  必须加入子节点中
             {
                 SplitToFourNode();                       // 细分出子节点
                 AddRectToChildNode(quadObj);             // 将对象加入子节点中
             }
             else
             {
                 ManageObjs.Add(quadObj);                    // 直接加入
             }
         }
         else
         {
             AddRectToChildNode(quadObj);                    // 将对象加入子节点中
         }
     }
 }
Пример #4
0
        /// <summary>
        ///  根据 节点内的区域边界线 将对象切割成 子区域内的对象, 由于都是矩形 所以结果就 一个或两个或四个
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="rootNode"></param>
        /// <returns></returns>
        public List <QuadTreeObj> SplitObjWithNodeBound(QuadTreeObj obj, QuadTreeNode node)
        {
            List <QuadTreeObj> tList = null;

            if (node.ChildNodes != null && node.ChildNodes.Count > 0)
            {
                float tMidX = node.Rect.Right - node.Rect.W * 0.5f;         // 四分象限 中间竖线
                float tMidY = node.Rect.Up - node.Rect.H * 0.5f;            // 四分象限 中间横线

                tList = obj.SplitObjRectWithTwoLine(tMidY, tMidX);
            }

            return(tList);
        }
Пример #5
0
        /// <summary>
        ///  获取给定对象所在的 四叉树节点,  用于从中获取要检测碰撞的对象
        ///     全部用矩阵碰撞盒子筛选碰撞数据
        ///     如果对象跨区域, 则分割对象, 然后分别在子区域内检测. 跨区域只可能是 两个或四个
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public void FindObjInQuadNode(QuadTreeObj obj, QuadTreeNode rootNode, List <QuadTreeObj> objList)
        {
            //Debug.Log("对象矩阵:  X=" + obj.Rect.X + ", Y=" + obj.Rect.Y + ", W=" + obj.Rect.W + ", H=" + obj.Rect.H);
            //Debug.Log("节点矩阵:  X=" + rootNode.Rect.X + ", Y=" + rootNode.Rect.Y + ", W=" + rootNode.Rect.W + ", H=" + rootNode.Rect.H);
            if (rootNode.IsRectInArea(obj.Rect))
            {
                if (rootNode.ChildNodes != null)
                {
                    int        childCount     = rootNode.ChildNodes.Count;
                    List <int> tInChildNodeId = new List <int>(4);
                    for (int i = 0; i < childCount; i++)
                    {
                        if (rootNode.ChildNodes[i].IsRectInArea(obj.Rect))
                        {
                            tInChildNodeId.Add(i);
                            //FindObjInQuadNode(obj, rootNode.ChildNodes[i], objList);
                        }
                    }
                    switch (tInChildNodeId.Count)
                    {
                    case 1:                             // 仅在一个子区域内, 直接递归检测该子节点
                        FindObjInQuadNode(obj, rootNode.ChildNodes[tInChildNodeId[0]], objList);
                        break;

                    case 2:                                                      // 跨两个区域
                    case 4:                                                      // 跨四个区域
                        var objSplitList = SplitObjWithNodeBound(obj, rootNode); // 分割对象
                        int tCount       = objSplitList.Count;
                        for (int i = 0; i < tCount; i++)
                        {
                            FindObjInQuadNode(objSplitList[i], rootNode, objList);      // 每个子对象分别检测
                        }
                        break;

                    default:
                        break;
                    }
                    objList.AddRange(rootNode.ManageObjs);
                }
                else
                {
                    objList.AddRange(rootNode.ManageObjs);           //没有子区域 又在本区域内, 直接加入本节点区域内的全部对象
                }
            }
        }