图例

  • 划分示例图
  • 查询示例图
  • 解释一下,黄线是射线表面点到哪里,记为点P
    • 小蓝色框表明能包含点P的最小空间节点
    • 红框表明能包含点P的三角形,记为三角形T
    • 大蓝色框表明能包含三角形T的最小空间节点
  • 可以看到已经使用四叉树只需要遍历少量三角形就可以查询到目标三角形

应用

  • 本文应用于2D三角形导航网格中三角形查询

    • 给一个坐标,找到包含这个坐标的三角形

情景分析

  • 导航三角形网格中的三角形不可能互相包含
  • 从根节点开始找到包含三角形的最小的子节点,遍历这个节点下的所有物体,找到包含顶点的三角形

要解决的问题

  • 肯定会存在多个很大的shape横跨多个区域,所以非叶子节点要能存物体
  • 需要根据一个物体的位置和尺寸定位到节点
  • 最小的尺寸怎么确定
    • 如果用最大的物体的尺寸作为分割大小会导致树节点很少,性能退化成O(n)
    • 如果用最小的物体的尺寸作为分割大小会导致节点特别细碎
    • 根据使用时的性能,看自己的数据情况,如果小三角形比较多,最小节点设置的小一些,否则大一些

实现

  • 本文的运行环境:Unity + c#
using System;
using System.Collections.Generic;
using UnityEngine;namespace DC.Lockstep.navigation
{public struct TriangleShape{public Vector2[] vertices;public int a, b, c;public Vector2 pA => vertices[a];public Vector2 pB => vertices[b];public Vector2 pC => vertices[c];public Vector2 GetCenter(){return (vertices[a] + vertices[b] + vertices[c]) / 3f;}}public class QuadTreeNode{public static float min_size = 4;protected QuadTreeNode[] mChildren;protected List<TriangleShape> mContent;protected Rect mArea;public QuadTreeNode(){}public QuadTreeNode(Rect area){SetArea(area);}public void SetArea(Rect area){mArea = area;}public Rect GetArea(){return mArea;}public QuadTreeNode[] GetChildren(){return mChildren;}public List<TriangleShape> GetContent(){if (null == mContent){return new List<TriangleShape>();}return new List<TriangleShape>(mContent);}public int GetShapeCnt(){return mContent?.Count ?? 0;}public bool Insert(TriangleShape shape){if (!Contains(shape)){return false;}// 已经是最小分割if (mArea.width <= min_size){Append(shape);return true;}var index = GetIndex(shape);// 如果在某个子节点里面if (index >= 0){if (null == mChildren){mChildren = new QuadTreeNode[4];}if (mChildren[index] == null){mChildren[index] = CreateChild(index);}var suc = mChildren[index].Insert(shape);if (suc) return true;}// 在当前节点Append(shape);return true;}protected void Append(TriangleShape shape){if (null == mContent){mContent = new List<TriangleShape>();}mContent.Add(shape);}public bool Contains(TriangleShape shape){return Contains(shape.pA) && Contains(shape.pB) && Contains(shape.pC);}public bool Contains(Vector2 pos){return mArea.Contains(pos);}protected QuadTreeNode CreateChild(int index){if (index < 0 || 3 < index){throw new ArgumentException("index must in [0,3], now is " + index);}//左下角0,左上角2,右上角3,右下角1var child = new QuadTreeNode();switch (index){case 0:child.SetArea(Rect.MinMaxRect(mArea.xMin, mArea.yMin, mArea.center.x, mArea.center.y));break;case 1:child.SetArea(Rect.MinMaxRect(mArea.center.x, mArea.yMin, mArea.xMax, mArea.center.y));break;case 2:child.SetArea(Rect.MinMaxRect(mArea.xMin, mArea.center.y, mArea.center.x, mArea.yMax));break;case 3:child.SetArea(Rect.MinMaxRect(mArea.center.x, mArea.center.y, mArea.xMax, mArea.yMax));break;}return child;}public void Remove(TriangleShape shape){if (Contains(shape)){var index = GetIndex(shape);if (index >= 0 && mChildren[index] != null){mChildren[index].Remove(shape);return;}mContent?.Remove(shape);}}public int GetIndex(TriangleShape shape){var i1 = GetIndex(shape.pA);var i2 = GetIndex(shape.pA);if (i1 != i2){return -1;}var i3 = GetIndex(shape.pA);if (i2 != i3){return -1;}return i1;}public int GetIndex(Vector2 point){if (!Contains(point)){return -1;}//左下角0,左上角2,右上角3,右下角1var index = 0;if (point.x > mArea.center.x){index += 1;}if (point.y > mArea.center.y){index += 2;}return index;}public void GetTriangleShapes(List<TriangleShape> list){if (null != mChildren){for (int i = 0; i < mChildren.Length; i++){mChildren[i]?.GetTriangleShapes(list);}}if (null != mContent){list.AddRange(mContent);}}public QuadTreeNode GetMinContainsNode(Vector2 pos){if (!Contains(pos)){return null;}if (null != mChildren){for (int i = 0; i < mChildren.Length; i++){if(mChildren[i] == null) continue;var node = mChildren[i].GetMinContainsNode(pos);if (null != node && node.GetShapeCnt() > 0){return node;}}}return this;}}
}

我的测试方式

  • 使用Unity生成导航数据
  • 合并导航网格中相同的三角形,导出成mesh模型文件
  • 使用mesh模型文件中的三角形构造QuadTreeNode
  • 编写QuadTreeNode的可视化脚本获得文中的示例图
  • 将mesh模型放到unity场景,添加检测脚本,检测鼠标点击到模型上的位置,定位到对应的QuadTreeNode

四叉树(QuadTree)图例、应用、实现相关推荐

  1. js小球与边框碰撞反弹_四叉树在碰撞检测中的应用

    缘起 <你被追尾了>中预告了加速碰撞检测的算法--四叉树(for 2D),所以本文就来学习一下. 分析 首先是为什么要使用四叉树进行优化,其实<你被追尾了>中已经说了,这里简单 ...

  2. 两个软件相互交换数据_面试需要知道的六种数据结构

    本文作者 拉勾教育专栏作者苏勇查看:13624回复:128 数据结构是算法的基石,若无扎实的数据结构基础,想把算法学好甚至融会贯通是非常困难的,而优秀的算法又往往取决于你采用哪种数据结构. --< ...

  3. 奥维互动地图GEE协议历史影像分析与应用

    Gee协议提供查看Google Earth,Google Maps,Bing Maps,DigitalGlobe,Kosmosnimki,Yandex.Maps等服务提供的高分辨率卫星图像和常规地图. ...

  4. 数据结构与算法 学习笔记(中)

    油管上的CS61B的视频 学习代码 随看随记 Dijkstra's algorithm再理解 Asymptotics 本意是渐近的意思:这里代指当参数为无穷大时,所需要进行运算的次数,和我们常说的复杂 ...

  5. 《游戏引擎架构》笔记一

    <游戏引擎架构>该系列的博文部分参考下面的博客: http://raytaylorlin.com/categories/%E6%8A%80%E6%9C%AF/%E6%B8%B8%E6%88 ...

  6. 1. 【Part3】 Contour Detection and Hierarchical Image Segmentation【轮廓检测图像分割】

    Reference from Arbelaez, P., Maire, M., Fowlkes, C., & Malik, J. (2011). Contour detection and h ...

  7. Game Engine Architecture by Jason Gregory:1.6 实时游戏引擎架构

    http://blog.csdn.net/skylmmm/article/details/6230420 一个游戏引擎一般是由工具集和一个运行时组件组成.下面部分我们将首先研究这个运行时组件,然后再看 ...

  8. arcmap创建空间索引_空间GIS索引算法介绍

    先看几个需要空间索引技术的场景: 如何根据给定位置来查询附近1000米的poi? 如何查找给定位置的最近poi? 如何查找给定矩形框内所有link和面数据? 1.用B-tree.B tree或者has ...

  9. 学习索引: 现状与研究展望

    摘 要: 索引是数据库系统中用于提升数据存取性能的主要技术之一.在大数据时代,随着数据量的不断增长,传 统索引(如 B+树)的问题日益突出:(1)空间代价过高.例如,B+树索引需要借助 O(n)规模的 ...

  10. 【数据结构Python描述】树的简介、基本概念和手动实现一个二叉树

    文章目录 一.树的简介 1. 树的定义 2. 相关概念 二.树的ADT 三.树的实现准备 1. 树的基本分类 2. 树的抽象基类 四.树的概念拾遗 1. 深度 2. 高度 五.二叉树的简介 1. 定义 ...

最新文章

  1. 利用tab_control控件在对话框中加入属性页的方法详细介绍
  2. 安卓开发37:自定义的HorizontalScrollView类,使其pageScroll的时候焦点不选中
  3. php使用mysql怎么连接浏览器_一个简单的php实现的MySQL数据浏览器
  4. vsftpd的不同安装方式及服务控制脚本
  5. 社区发现SLPA算法
  6. 关于oracle sql语句查询时表名和字段名要加双引号的问题详解
  7. 聊聊手游的那些惊喜与惊吓
  8. C/C++ typedef用法
  9. java qq聊天界面_用Java制作一个简单的QQ聊天界面
  10. 读书·2018(14本)
  11. 【计算机网络】实验一 Protocol Layer
  12. 【MySQL基本查询】Create(创建), Retrieve(读取),Update(更新),Delete(删除)
  13. 滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(10月31日~11月6日)...
  14. matlab 改变坐标轴间距,matlab坐标轴刻度间距
  15. 2、通过mos管构成的逻辑门电路
  16. 你知道我们常说的“向前兼容”和“向后兼容”都是什么意思吗?
  17. 使用python制作登录界面
  18. ffmpeg sws_scale详细分析
  19. 论文笔记---SSH
  20. 2020上海国际电力电工展——安科瑞参展产品提前剧透

热门文章

  1. 紫光拼音输入法 v6.9.0.22 绿色版
  2. Js拼接Json供echarts的地图使用
  3. 【python 走进NLP】机器学习和深度学习情感分类模型
  4. VUE3中使用粒子特效
  5. 面试经验|传音控股自动化测试
  6. 银行招聘计算机考试时间,秋季银行招聘考试时间是什么时候?
  7. php扩展-ioncube组件的安装方法_最新Phpstudy 安装 Ioncube Loader扩展方法分享
  8. DTCC 回顾:技术破局,分布式数据库创赢未来
  9. 图像处理中饱和度、色调、对比度的定义
  10. python变量四则运算_python_第一次作业 四则运算