コード例 #1
0
ファイル: QuadTree.cs プロジェクト: guccang/QuadTree
        // data是否在多个象限内
        // 多象限内,放到父节点上
        private bool isInMultipleSub(QuadNode node, QuadData data)
        {
            int cnt = 0;

            if (null == node.Sub)
            {
                split(node);
            }

            for (int i = 0; i < 4; ++i)
            {
                if (isRegionCross(node.Sub[i].mbr, data.mbr))
                {
                    cnt++;
                }
            }

            if (0 == cnt) // 大于整个象限了
            {
                return(true);
            }
            else
            if (cnt > 1)   // 处于多个象限
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
コード例 #2
0
ファイル: QuadTree.cs プロジェクト: guccang/QuadTree
        // 删除
        // 从四叉树中移除,调用时需要data数据修改前调用,如果data数据修改后调用,可能无法找到。
        // 导致数据错误
        public bool Remove(QuadData data)
        {
            var  tmp     = _root;
            bool rm      = false;
            bool success = false;

            // 没有节点
            do
            {
                // 节点数 满足,或者处于多个象限中
                if ((tmp.Cnt <= MAX_DATA_CNT && null == tmp.Sub) || isInMultipleSub(tmp, data))
                {
                    // 跳出循环
                    rm = true;

                    // 重复删除同一个数据
                    if (null == tmp.Child)
                    {
                        break;
                    }

                    // 本节点查找
                    var curNode = tmp.Child;
                    var preNode = tmp.Child;

                    do
                    {
                        if (curNode == data)
                        {
                            // 头
                            if (curNode == tmp.Child)
                            {
                                tmp.Child = curNode.Next;
                            }
                            else
                            {
                                preNode.Next = curNode.Next;
                            }

                            success = true;
                            tmp.Cnt--;
                            TotalCnt--;
                            LevelCnt[tmp.Level]--;
                            break;
                        }

                        preNode = curNode;
                        curNode = curNode.Next;
                    } while (null != curNode);
                }
                else
                {
                    // 获取所在象限
                    tmp = GetSubNode(tmp, data);
                }
            } while (false == rm);

            return(success);
        }
コード例 #3
0
ファイル: QuadTree.cs プロジェクト: guccang/QuadTree
        // 更新
        // 跟新data在四叉树中的位置
        public bool Update(QuadData data, QuadData newData)
        {
            bool success = Remove(data);

            if (false == success)
            {
                // 失败了,逻辑错误
                log($"error remove data. {data.Id}");
                return(false);
            }

            Add(newData);
            return(true);
        }
コード例 #4
0
ファイル: QuadTree.cs プロジェクト: guccang/QuadTree
        public QuadNode GetSubNode(QuadNode node, QuadData data)
        {
            QuadNode sub = null;

            for (int i = 0; i < MAX_QUADRANT; ++i)
            {
                if (false == isRegionCross(node.Sub[i].mbr, data.mbr))
                {
                    continue;
                }

                sub = node.Sub[i];
                break;
            }

            return(sub);
        }
コード例 #5
0
ファイル: QuadTree.cs プロジェクト: guccang/QuadTree
        // 添加
        public bool Add(QuadData data)
        {
            // 节点node数量判定
            // 寻找符合节点插入
            bool     success = false;
            QuadNode tmp     = _root;

            do
            {
                bool addToParentNode = false;
                // 当前节点child个数小于最大child个数,并且没有分裂过
                if (tmp.Cnt + 1 <= MAX_DATA_CNT && null == tmp.Sub)
                {
                    addToParentNode = true;
                }

                // 节点个数<MAX_DATA_CNT && 为分裂的
                // 多象限内直接插入本节点
                if (addToParentNode || isInMultipleSub(tmp, data))
                {
                    // 加入本节点
                    var n1 = tmp.Child;
                    tmp.Child = data;
                    data.Next = n1;
                    tmp.Cnt++;
                    TotalCnt++;
                    addLevelCnt(tmp.Level);
                    success = true;
                    // 跳出
                    break;
                }
                else
                {
                    split(tmp);
                    // 获取插入的指定象限,
                    tmp = GetSubNode(tmp, data);
                }
            }while (true);

            return(success);
        }
コード例 #6
0
ファイル: Program.cs プロジェクト: guccang/QuadTree
        static void Main(string[] args)
        {
            QuadTree tree = new QuadTree();
            Random   ran  = new Random((int)DateTime.Now.Ticks);

            // 长宽2000
            int hl = 1000;

            tree.Init(new MBR(-hl, hl, hl, -hl));
            var qd1 = (new QuadData()
            {
                Id = 1,
                mbr = new MBR(1, 20, 30, 1),
                Next = null,
            });
            var qd2 = (new QuadData()
            {
                Id = 2,
                mbr = new MBR(-30, -1, 10, 1),
                Next = null,
            });
            var qd3 = new QuadData()
            {
                Id   = 3,
                mbr  = new MBR(-30, -1, -1, -10),
                Next = null,
            };
            var qd4 = new QuadData()
            {
                Id   = 4,
                mbr  = new MBR(1, 20, -1, -40),
                Next = null,
            };

            // 1,2,3,4象限个插入一个
            tree.Add(qd1);
            tree.Add(qd2);
            tree.Add(qd3);
            tree.Add(qd4);


            //  随机插入100个
            int             insertCnt = 1000000;
            float           x, z;
            int             minwidth = 1, maxwidth = 10, minlen = 1, maxlen = 60;
            List <QuadData> rmList            = new List <QuadData>();
            QuadData        randomSelect      = null;
            int             randomSelectIndex = ran.Next(0, insertCnt);

            for (int i = 0; i < insertCnt; ++i)
            {
                var qd = new QuadData();
                qd.Id = i;
                float l, r, t, b;
                // 坐标
                x = ran.Next(-hl, hl);
                z = ran.Next(-hl, hl);
                //
                float hwidth = ran.Next(minwidth, maxwidth);
                float hlen   = ran.Next(minlen, maxlen);
                //
                l       = x - hwidth;
                r       = x + hwidth;
                t       = z + hlen;
                b       = z - hlen;
                qd.mbr  = new MBR(l, r, t, b);
                qd.Next = null;
                tree.Add(qd);
                rmList.Add(qd);

                if (i == randomSelectIndex)
                {
                    randomSelect = qd;
                }
            }

            string info = "";

            foreach (var levelData in tree.LevelCnt)
            {
                info += $"({levelData.Key}:{levelData.Value})-";
            }

            Console.WriteLine($"tree level:{tree.Current_Max_Level} {info}");

            //
            var circle = new Circle()
            {
                x      = 30,
                z      = 30,
                radius = 30,
            };
            var circle1 = new Circle()
            {
                x      = 0,
                z      = 0,
                radius = 500,
            };
            Stopwatch sw = new Stopwatch();

            // 每秒一次搜索, 这些单位平均一秒执行搜索次数
            double ms = 0;

            find(sw, tree, circle, insertCnt);
            find(sw, tree, circle1, insertCnt);

            sw.Restart();
            int  rmCnt = 0;
            bool rm    = tree.Remove(qd1);

            if (rm)
            {
                rmCnt++;
            }
            ms = sw.Elapsed.TotalMilliseconds;
            //for (int i = 0; i < rmList.Count; ++i)
            //{
            //    rm = tree.Remove(rmList[i]);
            //    if (rm)
            //        rmCnt++;
            //    if (false == rm)
            //        Console.WriteLine($"rm rmList[i] {rmList[i].Id} not success");
            //}
            Console.WriteLine($"remove qd1 ms={ms} rm:{rm} rmCnt:{rmCnt}");

            sw.Restart();
            rm = tree.Remove(randomSelect);
            ms = sw.Elapsed.TotalMilliseconds;
            Console.WriteLine($"remove randomSelect index={randomSelectIndex} ms={ms} rm:{rm} rmCnt:{rmCnt}");

            sw.Restart();
            tree.Remove(qd2);
            tree.Clear();
            tree.Remove(qd3);
            ms = sw.Elapsed.TotalMilliseconds;
            Console.WriteLine($"clear ms={ms}");
            Console.WriteLine("Hello World!");
        }