视野检测

来源:互联网 发布:现代文转换文言文软件 编辑:程序博客网 时间:2024/04/30 12:21
昨天晚上想了个方法。想象1个从地图左上角开始,向右下角的水平逐行扫描线(类似CRT的电子枪扫描轨迹),那么,这个轨迹上一定包含有全部的点(也就是地图中的对象),每个对象都有唯一的1D上的扫描距离,也就是相对左上角的扫描折线段长度。


首先,
对每个对象计算其扫描折线长度,Obj.y*(mapwidth+1)+ obj.x +1 , 结果与其handle结合1个记录,全部的点计算完放在数组中,然后按照地图的垂直高度为每个水平扫描线起点计算1个起点距离,Line*(mapwidth+1),赋予0handle也加入数组,(这里对地图做了虚拟扩展1单位,原有对象在新虚拟图中水平有1单位offset , 可知每个水平扫描线的起点折线长度值一定是唯一的,)对结果数组按照其折线长值做快速排序。对排序结果2分查找出全部水平扫描线起点在排序结果中的位置保存在数组中。

下面开始正式获取每个物体的AOI对象集合。

对物体做循环,设循环条件 Y = (Obj.Y - r) ~ (obj.y + r)

可得到其在当前 Y 扫描线与obj aio圆形相交点的水平offset及相交线段的宽度w。涉及1个三角函数,可以查表近似快速计算。
按照该offset和y可知该交点的折线距离crossd, 从前述全部水平扫描线位置数组中获得对应的该水平线段在排序结果中的起点下标Low和下一水平线段的下标high.在low 和 high-1之间做2分比较,得到位置 pos ( V[pos] <= crossd < V[pos+1]);

从pos起就是该水平坐标上处在obj aio圆中的连续物体,一直向下取直到物体的折线距离增长超过宽度w

2*r个循环下来 就得到了该物体的全部aio对象。



做了测试,设地图为10k x 10K单位,对象10k个 ,全部具有40的aio半径,全部计算1次的代价大约是50ms (P4 3.0G)
这个算法速度与地图大小无关,只和对象数量及aio半径有关。也没什么内存占用,而且在遍历物体aio对象的时候
还可以进行多线程并行处理。