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);

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值