/**

* 四叉树(基于2D平面空间分割)数据结构

* 四叉树或四元树也被称为Q树(Q-Tree)。

* 四叉树广泛应用于图像处理、空间数据索引、2D中的快速碰撞检测、存储稀疏数据等

* 为提升性能

* 1、广度优先搜索

* 2、仅搜索叶节点

*/

export class QuadTree {

/** 树的高度 */

protected _height: number;

/** 树的深度 */

protected _depth: number;

/** 根节点 */

protected _rootNode: QuadTreeNode;

/** 矩形区域 */

protected _rect: Rectangle;

/** 广度搜索队列(仅包含叶节点) */

public breadthSearchQueue: Queue>;

/** 对象与叶节点的映射表 */

public targetNodeMap: HashTable>;

/**

* 构造函数

* @param rect 二维空间数据

* @param depth 树的深度

*/

constructor(rect: Rectangle, depth: number, targets?: T[]) {

this._rect = rect;

this._depth = depth;

this._height = this._depth;

this.breadthSearchQueue = new Queue>();

this.targetNodeMap = new HashTable>();

if (depth >= 0) {

this._rootNode = new QuadTreeNode(this, null, rect, depth);

}

this.initBreadthSearchQueue();

}

/**

* 创建广度搜索队列

* 仅包含叶节点

*/

protected initBreadthSearchQueue(): void {

let node: QuadTreeNode;

let findFromLeft = function(nodes: QuadTreeNode[]) {

if (nodes.length <= 0) {

return;

}

let childsArr = [];

// 先遍历邻节点

for (let i = 0; i

node = nodes[i];

if (node.isLeaf()) {

this.breadthSearchQueue.push(node);

}

childsArr = childsArr.concat(node.getChildsAsArray());

}

// 再访问子节点数组

findFromLeft(childsArr);

}.bind(this);

findFromLeft([this._rootNode]);

}

// /**

//  * 绑定对象集合

//  */

// public bindTargets(targets: T[]): void {

//     for (let i = 0; i

//         const target = targets[i];

//         let node = this.find(target["x"], target["y"]);

//         if (node) {

//             this.targetNodeMap.insert(target["hashCode"], node, true);

//         }else {

//             console.debug(this, "未找到关联的节点1", target["x"], target["y"], this._rootNode);

//         }

//     }

// }

/**

* 获取对象所属节点

*/

public getTargetNode(target: T): QuadTreeNode {

// LogUtils.debug(this, "状态表", target["x"], target["y"], this.targetNodeMap.get(target["hashCode"]));

return this.targetNodeMap.get(target["hashCode"]);

}

/**

* 获取所有对象合集

*/

public get targets(): T[] {

return this._rootNode.targets;

}

/**

* 获取树的高度

*/

public get height(): number {

return this._height;

}

/**

* 获取树的深度

*/

public get depth(): number {

return this._depth;

}

/**

* 搜索目标对象所在区域节点

* @param x 目标对象x坐标

* @param y 目标对象y坐标

* @param skipEmpty 是否忽略空数据节点

*/

public find(x: number, y: number, skipEmpty: boolean = false): QuadTreeNode {

let node: QuadTreeNode = null;

let findFromNode: Function = (pNode: QuadTreeNode): QuadTreeNode => {

if (!pNode) {

return null;

}

if (skipEmpty && pNode.isDataEmpty) {

return null;

}

if (!pNode.isContains(x, y)) {

return null;

}

if (pNode.isLeaf()) {

return pNode;

}

let leftChild = pNode.getLeftChild();

while (leftChild) {

node = findFromNode(leftChild);

if (node) {

return node;

}else {

leftChild = leftChild.nextNode;

}

}

};

// 从根节点开始查找

return findFromNode(this._rootNode);

}

/**

* 搜索圆形目标对象所在树根区域节点

* @param x 目标对象x坐标

* @param y 目标对象y坐标

* @param skipEmpty 是否忽略空数据节点

*/

public findNodesInCircle(x: number, y: number, radius: number, skipEmpty: boolean = false): QuadTreeNode[] {

let nodes: QuadTreeNode[] = [];

let findFromNode: Function = (pNode: QuadTreeNode): QuadTreeNode => {

if (!pNode) {

return null;

}

if (skipEmpty && pNode.isDataEmpty) {

return null;

}

if (pNode.isLeaf()) {

if (BaseTool.isPointsInCircle(x, y, radius, [pNode.leftTop.x, pNode.leftTop.y, pNode.leftBottom.x, pNode.leftBottom.y,

pNode.rightBottom.x, pNode.rightBottom.y, pNode.rightTop.x, pNode.rightTop.y])) {

nodes.push(pNode);

}

return;

}

let leftChild = pNode.getLeftChild();

while (leftChild) {

findFromNode(leftChild);

leftChild = leftChild.nextNode;

}

};

// 从根节点开始查找

findFromNode(this._rootNode);

return nodes;

}

/**

* 搜索矩形目标对象所在树根区域节点

* @param x 目标对象x坐标

* @param y 目标对象y坐标

* @param width 目标对象宽

* @param height 目标对象高

* @param skipEmpty 是否忽略空数据节点

*/

public findNodesInRect(x: number, y: number, width: number, height: number, skipEmpty: boolean = false): QuadTreeNode[] {

let nodes: QuadTreeNode[] = [];

let findFromNode: Function = (pNode: QuadTreeNode): QuadTreeNode => {

if (!pNode) {

return null;

}

if (skipEmpty && pNode.isDataEmpty) {

return null;

}

// if (pNode.isLeaf()) {

//     if (BaseTool.isRectIntersect(x, y, width, height, pNode.rect.x, pNode.rect.y, pNode.rect.width, pNode.rect.height)) {

//         nodes.push(pNode);

//     }

//     return;

// }

if (BaseTool.isRectIntersect(x, y, width, height, pNode.rect.x, pNode.rect.y, pNode.rect.width, pNode.rect.height)) {

if (pNode.isLeaf()) {

nodes.push(pNode);

}else {

let leftChild = pNode.getLeftChild();

while (leftChild) {

findFromNode(leftChild);

leftChild = leftChild.nextNode;

}

}

}else {

// console.log("不相交====", x, y, width, height, "///", pNode.rect.x, pNode.rect.y, pNode.rect.width, pNode.rect.height);

}

};

// 从根节点开始查找

findFromNode(this._rootNode);

return nodes;

}

/**

* 搜索凸多边形目标对象所在树根区域节点

* @param x 目标对象x坐标

* @param y 目标对象y坐标

* @param width 目标对象宽

* @param height 目标对象高

* @param skipEmpty 是否忽略空数据节点

*/

public findNodesInPolygon(polygonPoints: number[], skipEmpty: boolean = false): QuadTreeNode[] {

let nodes: QuadTreeNode[] = [];

let findFromNode: Function = (pNode: QuadTreeNode): QuadTreeNode => {

if (!pNode) {

return null;

}

if (skipEmpty && pNode.isDataEmpty) {

return null;

}

// if (pNode.isLeaf()) {

//     if (BaseTool.isRectIntersect(x, y, width, height, pNode.rect.x, pNode.rect.y, pNode.rect.width, pNode.rect.height)) {

//         nodes.push(pNode);

//     }

//     return;

// }

if (BaseTool.isPointsInRect(pNode.rect.x, pNode.rect.y, pNode.rect.width, pNode.rect.height, polygonPoints)) {

if (pNode.isLeaf()) {

nodes.push(pNode);

}else {

let leftChild = pNode.getLeftChild();

while (leftChild) {

findFromNode(leftChild);

leftChild = leftChild.nextNode;

}

}

}else {

// console.log("不相交====", x, y, width, height, "///", pNode.rect.x, pNode.rect.y, pNode.rect.width, pNode.rect.height);

}

};

// 从根节点开始查找

findFromNode(this._rootNode);

return nodes;

}

/**

* 搜索椭圆形目标对象所在树根区域节点

* @param cx 椭圆中心x坐标

* @param cy 椭圆中心y坐标

* @param rx 椭圆横半轴

* @param ry 椭圆纵半轴

* @param angle 旋转角度

* @param skipEmpty 是否忽略空数据节点

*/

public findNodesInEllipse(cx: number, cy: number, rx: number, ry: number, angle: number, skipEmpty: boolean = false): QuadTreeNode[] {

let nodes: QuadTreeNode[] = [];

let findFromNode: Function = (pNode: QuadTreeNode): QuadTreeNode => {

if (!pNode) {

return null;

}

if (skipEmpty && pNode.isDataEmpty) {

return null;

}

// if (pNode.isLeaf()) {

//     if (BaseTool.isRectIntersect(x, y, width, height, pNode.rect.x, pNode.rect.y, pNode.rect.width, pNode.rect.height)) {

//         nodes.push(pNode);

//     }

//     return;

// }

if (BaseTool.isRectIntersectEllipse(pNode.rect.x, pNode.rect.y, pNode.rect.width, pNode.rect.height, cx, cy, rx, ry, angle)) {

if (pNode.isLeaf()) {

nodes.push(pNode);

}else {

let leftChild = pNode.getLeftChild();

while (leftChild) {

findFromNode(leftChild);

leftChild = leftChild.nextNode;

}

}

}else {

// console.log("不相交====", x, y, width, height, "///", pNode.rect.x, pNode.rect.y, pNode.rect.width, pNode.rect.height);

}

};

// 从根节点开始查找

findFromNode(this._rootNode);

return nodes;

}

/**

* 对象坐标发生更新的通知

*/

public onTargetPosUpdate(target: T): void {

// let x = target["x"];

// let y = target["y"];

// let curNode = this.targetNodeMap.get(target["hashCode"]);

// if (curNode && curNode.isContains(x, y)) {

//     return;

// }else {

//     let node = this.find(x, y);

//     if (node) {

//         this.targetNodeMap.insert(target["hashCode"], node, true);

//         this._onTargetNodeChanged(target, curNode, node);

//     }else {

//         console.debug(this, "未找到关联的节点2", x, y, this._rootNode);

//     }

// }

}

/**

* 通知对象 节点发生切换

*/

public _onTargetNodeChanged(target: T, oldNode: QuadTreeNode, newNode: QuadTreeNode): void {

if (oldNode) {

oldNode.removeTarget(target);

}

if (newNode) {

newNode.addTarget(target);

}

if (target["onTreeNodeChanged"]) {

target["onTreeNodeChanged"](oldNode, newNode);

}

}

}

mysql 四叉树的应用_游戏算法(2):查找优化之四叉树的应用相关推荐

  1. mysql 四叉树的应用_树(简单应用-四叉树).ppt

    树的简单应用 四叉树 问题提出 请看这幅图 问题 在上面的这幅图中,总共有1000个小球在做随机移动.如何检测其两两之间是否相撞? 用两重循环,将每个小球取出做检测,如果有1000个小球,没有优化的情 ...

  2. 搜索优化之四叉树算法(一)

    最近闲来无事,打算写点东西,最为一名从事游戏开发行业多年的程序,温故而知新,多做总结整理,用最通俗易懂的文字,阐述晦涩难懂的原理,于人于己,都是一件有意义的事情,很多程序同学写了很多年的逻辑代码,没有 ...

  3. mysql聚类函数排序_聚类算法大盘点 - 如鱼饮水,冷暖自知 - OSCHINA - 中文开源技术交流社区...

    最近在关注聚类分析,了解了之后才发现,原来聚类分析里已经有这么丰富的成果,因此希望对其做个较全面的总结. 本文涉及到的聚类算法较多,请允许我慢慢更新. 1 层次聚类 (Agglomerative Cl ...

  4. mysql 家谱树查询_无限级分类之查找子孙树和家谱树

    $area=array( array('id'=>'1','name'=>'河南','parent'=>0), array('id'=>'2','name'=>'吉林', ...

  5. 棋牌类游戏算法–牌分类_快速分类–三向和双枢轴

    棋牌类游戏算法–牌分类 毫无疑问,Quicksort被认为是本世纪最重要的算法之一,并且它是许多语言的事实上的系统排序,包括Java中的Arrays.sort . 那么,quicksort有何新功能? ...

  6. java语言麻将游戏代码_麻将游戏算法深入解析及实现代码

    麻将游戏算法深入解析及实现代码 这两天为了工具箱的完善,整理了这些年引擎开发的一些资料,无意中发现06年写的一个麻将算法,编译运行了一下,还是有点意思的,拿出来整理一下分享给大家. 麻将是一种大家最喜 ...

  7. 精华游戏算法整理_整理游戏

    精华游戏算法整理 在HTML5 2D游戏开发系列的上一部分文章结尾,Snail Bait处于可玩但原始的状态. 在这一期的最后一部分中,我将向您展示如何将Snail Bait从该状态带到最终版本,如图 ...

  8. 跳一跳j算法ava代码_麻将游戏算法深入解析及实现代码

    麻将游戏算法深入解析及实现代码 这两天为了工具箱的完善,整理了这些年引擎开发的一些资料,无意中发现06年写的一个麻将算法,编译运行了一下,还是有点意思的,拿出来整理一下分享给大家. 麻将是一种大家最喜 ...

  9. mysql datetime 默认值_老大让我整理下公司内部MySQL使用规范,分享给大家

    作者:白程序员的自习室 链接:https://www.studytime.xin/article/mysql-internal-specifications.html 最近涉及数据库相关操作较多,公司 ...

最新文章

  1. 22年前被嘲养猪的北大学子,如今带领200多户住上别墅,90后研究生也跟他加入养猪行列...
  2. ExtJS学习:MVC模式案例(三)
  3. 《精通移动app测试实战:技术、工具和案例》新书上市
  4. Java线程中断机制-如何中断线程
  5. Oracle中各个命中率的总结及调优笔记整理
  6. Lesson 73-74 The quality of our lives
  7. 在线预览word接口
  8. 监控freeswitch sip信令
  9. content=IE=Edge是什么意思?
  10. H5+ 常用API(拨打电话,设备震动,屏幕方向,屏幕亮度,设备信息...等)
  11. 公司注册的种类及英文缩写
  12. linux下安装MySQL遇到的坑
  13. 成功操盘手必经的5个阶段
  14. 米兔机器人终于拼完了_找回童年的DIY乐趣 米兔积木机器人拼装体验
  15. ios开发工具_7个基本的ios开发人员工具
  16. 李大学:互联网裂变里最重要的是资金流|正和岛|正和岛联席总裁黄丽陆|2015正和岛东部(海宁)论坛_新浪财经_新浪网...
  17. WCF的服务部署方法
  18. h5 app 热更新
  19. 星之河电子商务亚马逊代理的运营详情
  20. 会声会影Video Studio 2023旗舰版怎么安装、激活教程

热门文章

  1. 使用ExtJS做一个用户的增删改查
  2. 虚拟机 centos 7 nginx安装
  3. Neville 插值方法
  4. 5 Transforms 转移 笔记
  5. android intent 5.1
  6. SQL Server 本地语言版本
  7. 32/64位平台printf uint64的方法
  8. wpf(第一个应用实例)
  9. 运行初始化过程代码笔记
  10. 20本重磅图书等你认领:前沿、创业、个人成长全有了