// 区域相交 private bool isRegionCross(MBR m1, MBR m2) { /* * [矩形相交](https://blog.csdn.net/qq_40482358/article/details/86537747) * cx1=max(ax1,bx1) //左下x为最大的左下x集合 * cy1=max(ay1,by1) //左下y为最大的左下y集合 * cx2=min(ax2,bx2) //右上x为最小的右上x集合 * cy2=min(ay2,by2) //右上y为最小的右上y集合 * 矩形相交后仍然是矩形 */ float cx1 = Math.Max(m1.left, m2.left); float cy1 = Math.Max(m1.bottom, m2.bottom); float cx2 = Math.Min(m1.right, m2.right); float cy2 = Math.Min(m1.top, m2.top); if (cx1 > cx2) { return(false); } if (cy1 > cy2) { return(false); } return(true); }
private bool isPointInRegion(float x, float z, MBR mbr) { // if (x < mbr.left || x > mbr.right || z > mbr.top || z < mbr.bottom) { return(false); } return(true); }
// 初始化四叉树范围 public void Init(MBR mbr) { if (null != _root) { return; } _root = new QuadNode(); _root.mbr = mbr; _root.Quadrant = EQuadrant.ROOT; _root.Level = 0; // debug LevelCnt = new Dictionary <int, int>(); TotalCnt = 0; CorssCircleTestCnt = 0; // debug }
// 判断mbr和圆是否相交 private bool isCrossCricle(MBR mbr, Circle circle) { CorssCircleTestCnt++; // 1. 矩形的四点判断 点在圆内 // 2. 矩形的四边判断 边与圆相交 // [算法](https://www.cnblogs.com/llkey/p/3707351.html) // 01 点在圆内 if (isPointInCricle(mbr.left, mbr.top, circle)) { return(true); } else if (isPointInCricle(mbr.right, mbr.top, circle)) { return(true); } else if (isPointInCricle(mbr.right, mbr.bottom, circle)) { return(true); } else if (isPointInCricle(mbr.left, mbr.bottom, circle)) { return(true); } // 02 边与圆相交 float rec_x = (mbr.right - mbr.left) * 0.5f; float rec_z = (mbr.top - mbr.bottom) * 0.5f; float deltaX = Math.Abs(rec_x - circle.x); float deltaZ = Math.Abs(rec_z - circle.z); if (deltaX * deltaX + deltaZ * deltaZ <= circle.radius * circle.radius) { return(true); } // 03 圆点在矩形内 if (isPointInRegion(circle.x, circle.z, mbr)) { return(true); } return(false); }
// mbr被圆包围 private bool isInCircle(MBR mbr, Circle circle) { CorssCircleTestCnt++; if (false == isPointInCricle(mbr.left, mbr.top, circle)) { return(false); } if (false == isPointInCricle(mbr.right, mbr.top, circle)) { return(false); } if (false == isPointInCricle(mbr.right, mbr.bottom, circle)) { return(false); } if (false == isPointInCricle(mbr.left, mbr.bottom, circle)) { return(false); } return(true); }
// 象限分裂 // 分裂后,node节点的数据,尝试插入到子象限内 private void split(QuadNode node) { // 已经分裂过了 if (null != node.Sub) { return; } // 分裂为四个象限 /* | | | UL | UR | --------------------- | | LL | LR | | */ // mbr = (x,z,w,l) var mbr = node.mbr; float hw = (mbr.right - mbr.left) * 0.5f; float hl = (mbr.top - mbr.bottom) * 0.5f; var mbr_ur = new MBR(mbr.right - hw, mbr.right, mbr.top, mbr.top - hl); var mbr_ul = new MBR(mbr.left, mbr.left + hw, mbr.top, mbr.top - hl); var mbr_ll = new MBR(mbr.left, mbr.left + hw, mbr.bottom + hl, mbr.bottom); var mbr_lr = new MBR(mbr.right - hw, mbr.right, mbr.bottom + hl, mbr.bottom); node.Sub = new QuadNode[4]; node.Sub[0] = new QuadNode() { Level = node.Level + 1, Quadrant = EQuadrant.UR, Cnt = 0, mbr = mbr_ur, Child = null, Sub = null, }; node.Sub[1] = new QuadNode() { Level = node.Level + 1, Quadrant = EQuadrant.UL, Cnt = 0, mbr = mbr_ul, Child = null, Sub = null, }; node.Sub[2] = new QuadNode() { Level = node.Level + 1, Quadrant = EQuadrant.LL, Cnt = 0, mbr = mbr_ll, Child = null, Sub = null, }; node.Sub[3] = new QuadNode() { Level = node.Level + 1, Quadrant = EQuadrant.LR, Cnt = 0, mbr = mbr_lr, Child = null, Sub = null, }; if (node.Level + 1 > Current_Max_Level) { Current_Max_Level = node.Level + 1; } // 尝试插入当前节点的child TotalCnt -= node.Cnt; LevelCnt[node.Level] -= node.Cnt; node.Cnt = 0; if (node.Child != null) { var tmp = node.Child; var tmp1 = tmp.Next; node.Child = null; while (null != tmp) { Add(tmp); tmp = tmp1; if (null != tmp) { tmp1 = tmp.Next; tmp.Next = null; } } } }