mysql 四叉树的应用_游戏算法(2):查找优化之四叉树的应用
/**
* 四叉树(基于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):查找优化之四叉树的应用相关推荐
- mysql 四叉树的应用_树(简单应用-四叉树).ppt
树的简单应用 四叉树 问题提出 请看这幅图 问题 在上面的这幅图中,总共有1000个小球在做随机移动.如何检测其两两之间是否相撞? 用两重循环,将每个小球取出做检测,如果有1000个小球,没有优化的情 ...
- 搜索优化之四叉树算法(一)
最近闲来无事,打算写点东西,最为一名从事游戏开发行业多年的程序,温故而知新,多做总结整理,用最通俗易懂的文字,阐述晦涩难懂的原理,于人于己,都是一件有意义的事情,很多程序同学写了很多年的逻辑代码,没有 ...
- mysql聚类函数排序_聚类算法大盘点 - 如鱼饮水,冷暖自知 - OSCHINA - 中文开源技术交流社区...
最近在关注聚类分析,了解了之后才发现,原来聚类分析里已经有这么丰富的成果,因此希望对其做个较全面的总结. 本文涉及到的聚类算法较多,请允许我慢慢更新. 1 层次聚类 (Agglomerative Cl ...
- mysql 家谱树查询_无限级分类之查找子孙树和家谱树
$area=array( array('id'=>'1','name'=>'河南','parent'=>0), array('id'=>'2','name'=>'吉林', ...
- 棋牌类游戏算法–牌分类_快速分类–三向和双枢轴
棋牌类游戏算法–牌分类 毫无疑问,Quicksort被认为是本世纪最重要的算法之一,并且它是许多语言的事实上的系统排序,包括Java中的Arrays.sort . 那么,quicksort有何新功能? ...
- java语言麻将游戏代码_麻将游戏算法深入解析及实现代码
麻将游戏算法深入解析及实现代码 这两天为了工具箱的完善,整理了这些年引擎开发的一些资料,无意中发现06年写的一个麻将算法,编译运行了一下,还是有点意思的,拿出来整理一下分享给大家. 麻将是一种大家最喜 ...
- 精华游戏算法整理_整理游戏
精华游戏算法整理 在HTML5 2D游戏开发系列的上一部分文章结尾,Snail Bait处于可玩但原始的状态. 在这一期的最后一部分中,我将向您展示如何将Snail Bait从该状态带到最终版本,如图 ...
- 跳一跳j算法ava代码_麻将游戏算法深入解析及实现代码
麻将游戏算法深入解析及实现代码 这两天为了工具箱的完善,整理了这些年引擎开发的一些资料,无意中发现06年写的一个麻将算法,编译运行了一下,还是有点意思的,拿出来整理一下分享给大家. 麻将是一种大家最喜 ...
- mysql datetime 默认值_老大让我整理下公司内部MySQL使用规范,分享给大家
作者:白程序员的自习室 链接:https://www.studytime.xin/article/mysql-internal-specifications.html 最近涉及数据库相关操作较多,公司 ...
最新文章
- 22年前被嘲养猪的北大学子,如今带领200多户住上别墅,90后研究生也跟他加入养猪行列...
- ExtJS学习:MVC模式案例(三)
- 《精通移动app测试实战:技术、工具和案例》新书上市
- Java线程中断机制-如何中断线程
- Oracle中各个命中率的总结及调优笔记整理
- Lesson 73-74 The quality of our lives
- 在线预览word接口
- 监控freeswitch sip信令
- content=IE=Edge是什么意思?
- H5+ 常用API(拨打电话,设备震动,屏幕方向,屏幕亮度,设备信息...等)
- 公司注册的种类及英文缩写
- linux下安装MySQL遇到的坑
- 成功操盘手必经的5个阶段
- 米兔机器人终于拼完了_找回童年的DIY乐趣 米兔积木机器人拼装体验
- ios开发工具_7个基本的ios开发人员工具
- 李大学:互联网裂变里最重要的是资金流|正和岛|正和岛联席总裁黄丽陆|2015正和岛东部(海宁)论坛_新浪财经_新浪网...
- WCF的服务部署方法
- h5 app 热更新
- 星之河电子商务亚马逊代理的运营详情
- 会声会影Video Studio 2023旗舰版怎么安装、激活教程