计算map上的一些点是否在某个范围内
计算地图上的一些点是否在某个范围内
大家好 最近在做一个东西 遇到麻烦了。
就是在一个矩形的地图内 采用(x,y)的坐标形式来表示地图内的一个点,现在有一个点A,假设坐标是 (680,860),以该坐标为圆心,半径为330的圆定为指定范围
请问如何可以判断地图内哪些点在该范围内,地图上的点的数量以及坐标时刻变化 我需要时刻知道进入该范围内的所有的点。
目前我的做法是遍历所有的点,根据每个点的坐标来求出该点到达A点的距离
比如c点的坐标是(x,y)则:
当地图上的点数量一多的时候 比如几百个点 这样子计算就很耗时间 希望各位可以想个更好的解决方案 或者优化一下
------解决方案--------------------
你的A点是圆心,其他点是计算距离的点,所以这是一个类似的master-slave模式,可以用监听者模式来处理
这里给一个示例的处理方式:其他任意点位置发生变化时,触发locationChange事件,事件的Event为变化后的位置信息(x,y),所有其他点都register A做为监听者,其他点fire locationChange事件后,A做为监听者收到事件,触发自身的eventHandle,在eventHandle中计算圆点与event中的位置信息的距离并判断是否在范围内,这样避免遍历每个点
具体监听者模式网上资料很多
------解决方案--------------------
不需要每个点都计算。先把x坐标超过圆半径的去掉(正负),再把y坐标超过圆半径的去掉,同样注意正负。剩下的再计算
------解决方案--------------------
如果这个区域A的圆和整个地图面积比比例较小,可以考虑将整个地图分成若干版图,每个版图一个Set<Point>容器来维护当前在此版图内的点,每个点在跳动 的时候,根据其坐标的变化来改变它所在的版图。
因为每个点跳动基本是在它的周围跳动,所以跨版图的运动可以认为相对频率较低,维护操作量少。
可以根据统计划分地图版图,在点相对密集的地方版图小一点,点稀松的地方版图大一点(比如地图的边缘),每个版图内的点数量达到理论上的相对平衡状态。
对一个点为中心的圆区域A,判断这个圆落在哪几个版图内,只取这些版图对应的Set内的Point做判断。
------解决方案--------------------
用加减法先判断:
圆的外接矩形外的,在范围外
圆的内接矩形内的,在范围内
在外接矩形和内接矩形之间的部分
再考虑用圆的公式计算
------解决方案--------------------
我觉得你代码有问题,我用了2万个点,进行是否在圆内的判断,都能在1ms内完成,几百个点消耗的时间,绝对不会超过0.1ms,可以肯定耗时的不是这个判断,而是你其他的操作。
下面代码运行结果
Time consumed: 0.927 ms.
不过注意不要用Math.round,这是一个相当耗时的方法,直接用(int)强制转换是会自动舍弃小数的,但即便加了这个方法,上面程序的耗时也不超过3ms,对应的几百个点的耗时也不应该超过0.2ms,所以肯定不是这个问题造成的游戏卡顿。
------解决方案--------------------
可以考虑切割地图,点的移动除了变动坐标,还会变动板块,每次计算只需要遍历可能满足需求的板块中的点
大家好 最近在做一个东西 遇到麻烦了。
就是在一个矩形的地图内 采用(x,y)的坐标形式来表示地图内的一个点,现在有一个点A,假设坐标是 (680,860),以该坐标为圆心,半径为330的圆定为指定范围
请问如何可以判断地图内哪些点在该范围内,地图上的点的数量以及坐标时刻变化 我需要时刻知道进入该范围内的所有的点。
目前我的做法是遍历所有的点,根据每个点的坐标来求出该点到达A点的距离
比如c点的坐标是(x,y)则:
float f1 = 680 - x;
float f2 = 860 - y;
int distance = (int)Math.round(Math.sqrt(f1 * f1 + f2 * f2));
当地图上的点数量一多的时候 比如几百个点 这样子计算就很耗时间 希望各位可以想个更好的解决方案 或者优化一下
------解决方案--------------------
你的A点是圆心,其他点是计算距离的点,所以这是一个类似的master-slave模式,可以用监听者模式来处理
这里给一个示例的处理方式:其他任意点位置发生变化时,触发locationChange事件,事件的Event为变化后的位置信息(x,y),所有其他点都register A做为监听者,其他点fire locationChange事件后,A做为监听者收到事件,触发自身的eventHandle,在eventHandle中计算圆点与event中的位置信息的距离并判断是否在范围内,这样避免遍历每个点
具体监听者模式网上资料很多
------解决方案--------------------
不需要每个点都计算。先把x坐标超过圆半径的去掉(正负),再把y坐标超过圆半径的去掉,同样注意正负。剩下的再计算
------解决方案--------------------
如果这个区域A的圆和整个地图面积比比例较小,可以考虑将整个地图分成若干版图,每个版图一个Set<Point>容器来维护当前在此版图内的点,每个点在跳动 的时候,根据其坐标的变化来改变它所在的版图。
因为每个点跳动基本是在它的周围跳动,所以跨版图的运动可以认为相对频率较低,维护操作量少。
可以根据统计划分地图版图,在点相对密集的地方版图小一点,点稀松的地方版图大一点(比如地图的边缘),每个版图内的点数量达到理论上的相对平衡状态。
对一个点为中心的圆区域A,判断这个圆落在哪几个版图内,只取这些版图对应的Set内的Point做判断。
------解决方案--------------------
用加减法先判断:
圆的外接矩形外的,在范围外
圆的内接矩形内的,在范围内
在外接矩形和内接矩形之间的部分
再考虑用圆的公式计算
------解决方案--------------------
我觉得你代码有问题,我用了2万个点,进行是否在圆内的判断,都能在1ms内完成,几百个点消耗的时间,绝对不会超过0.1ms,可以肯定耗时的不是这个判断,而是你其他的操作。
下面代码运行结果
Time consumed: 0.927 ms.
public static void main(String[] args) {
int count = 20000;
float[] x = generateFloats(count);
float[] y = generateFloats(count);
long time = System.nanoTime();
for (int i = 0; i < count; i++) {
float _x = x[i] + 1, _y = y[i] + 1;
int distance2 = (int) Math.sqrt(_x * _x + _y * _y);
}
time = System.nanoTime() - time;
System.out.printf("Time consumed: %.3f ms.", (double)time / 1000000);
}
public static float[] generateFloats(int count) {
Random rand = new Random();
float[] fs = new float[count];
for (int i = 0; i < count; i++) {
fs[i] = rand.nextFloat();
}
return fs;
}
不过注意不要用Math.round,这是一个相当耗时的方法,直接用(int)强制转换是会自动舍弃小数的,但即便加了这个方法,上面程序的耗时也不超过3ms,对应的几百个点的耗时也不应该超过0.2ms,所以肯定不是这个问题造成的游戏卡顿。
------解决方案--------------------
可以考虑切割地图,点的移动除了变动坐标,还会变动板块,每次计算只需要遍历可能满足需求的板块中的点