Algorithm 如何计算某人身上是否存在某种东西';人的视野
我有一个物体,它在二维空间中有一个位置和一个速度,两者都用矢量表示。主体两侧的视野为135度。它看起来与运动方向相同(速度矢量) 我有一个物体,它在二维空间中的位置由一个向量表示 在图形中,蓝色背景上的对象可见,而红色背景上的对象对主体不可见 如何计算在给定时刻主体视野中的物体Algorithm 如何计算某人身上是否存在某种东西';人的视野,algorithm,math,vector,language-agnostic,geometry,Algorithm,Math,Vector,Language Agnostic,Geometry,我有一个物体,它在二维空间中有一个位置和一个速度,两者都用矢量表示。主体两侧的视野为135度。它看起来与运动方向相同(速度矢量) 我有一个物体,它在二维空间中的位置由一个向量表示 在图形中,蓝色背景上的对象可见,而红色背景上的对象对主体不可见 如何计算在给定时刻主体视野中的物体 您只需找到与对象的距离以及与对象的角度即可。然后,检查距离是否不大于浅蓝色圆圈的半径,以及速度矢量与对象矢量之间的角度是否过大 欧几里德距离只是sqrt((x2-x1)^2+(y2-y1)^2)() 对于角度,表示矢量(
您只需找到与对象的距离以及与对象的角度即可。然后,检查距离是否不大于浅蓝色圆圈的半径,以及速度矢量与对象矢量之间的角度是否过大 欧几里德距离只是
sqrt((x2-x1)^2+(y2-y1)^2)
()
对于角度,表示矢量(x2-x1,y2-y1)
和速度(vx,vy)
,然后检查角度之间的绝对差是否不超过135度。在编程语言中,通常有一个方便的函数atan2(y,x)
来查找单个向量的极角()
点的极角从矢量Ox沿逆时针方向测量。考虑我们有两点:速度向量的终结点<代码>(Vx,Vy)< /C>(左PIC)和从我们的对象<代码>(x1,y1)的向量的端点到对象<代码>(x2,y2)< /代码>:它是向量<代码>(x2-x1,y2-y1)(中心pic)。假设极角分别为
alpha
和beta
。然后(vx,vy)
和(x2-x1,y2-y1)
之间的角度就是这些极角的差(右图)
然而,有一个诀窍。您得到的alpha
和beta
值通常从-PI到+PI,或者从0到2PI。因此,beta-alpha的差值将在-2PI和+2PI之间,您希望它在-PI(从当前方向顺时针180度)和+PI(从当前方向逆时针180度)之间。为此,一些简单的转换就足够了,例如以下伪代码:
if angle > +PI:
angle := angle - 2PI
if angle < -PI:
angle := angle + 2PI
如果角度>+PI:
角度:=角度-2PI
如果角度<-PI:
角度:=角度+2PI
假设每个对象的FOV都需要同时测试(即每个对象都成为主题),一种可能的优化方法是使用对象的Delaunay三角剖分,将其视为图形,以允许BFS进行排序搜索。此BFS有两个限制
O(N log N + NT)
式中,N是物体的数量,T是被测物体的平均数量。这与理想的输出敏感算法O(N*V)进行了比较,其中V是视野中对象的平均数量。平均来说,O(T)应该是O(V)。不利的一面是,因为所有的东西都在FOV区域,所以V很可能是N/C,其中C是一个常数因子,从技术上讲是O(N),但这个常数可能非常低。一种近似C的方法是“(物体凸包的面积)/(视野的面积)”。其基础是凸面外壳的一小部分区域平均可能包含大致相等的一小部分对象
psudoCode假定每个对象(包括主题)都是类的一部分,为简单起见,将其称为Object,该类提供了一些类方法和类成员。方法和成员概述如下:
班级成员:
- 位置:对象的二维位置
- minDistFOV:最小视场距离。很可能为0.0,但可能更高
- 最大视场距离:最大视场距离。未知,但算法假定它是固定距离
- isWithinFOV(对象):确定给定对象是否在此对象的视野内。如果是,则返回True
- (点、角度、方向):返回将二维点偏移给定角度和距离而产生的二维点
- (段1、段2):确定两条线段是否相交
function lineSegmentFOV(subject, angle):
# This function gets the one of line segments that represent the edges of the FOV
# That is one of the red lines in the image
segmentNearPos = offset(subject.pos, angle, subject.minDistFOV)
segmentFarPos = offset(subject.pos, angle, subject.maxDistFOV)
return (segmentNearPos, segmentFarPos)
function findObjectsInFOV(subject, objects, triangulation, kdTree):
objectsInFOV = new Set() # A set seemed like the best overall choice here
checkedObjects = new Set()
# Get subject's edge of FOV line segments
halfFOV = subject.FOV / 2
lowerSegment = lineSegmentFOV(subject, subject.dir - halfFOV)
higherSegment = lineSegmentFOV(subject, subject.dir + halfFOV)
# Check nearest object to subject
nearestNeighbor = kdTree.nearestNeighbor(subject)
if not subject.equals(nearestNeighbor): # Subject cannot be in it's FOV
if subject.isWithinFOV(nearestNeighbor):
objectsInFOV.add(nearestNeighbor)
checkedObjects.add(nearestNeighbor)
# Begin the search for objects within the FOV
objectsToExpand = new Queue(nearestNeighbor) # Always expand subject's nearest neighbor
while objectsToExpand.length > 0:
object = objectsToExpand.dequeue() # Get the next object to expand
if object not in checkedObjects: # Don't check an object twice
# Find expandable objects and note those that are in the FOV as well.
for adjacent in triangulation[object]:
edge = (object.pos, adjacent.pos)
# Check if object in FOV
if subject.isWithinFOV(object):
objectsInFOV.add(adjacent)
objectsToExpand.enqueue(adjacent)
# Check if object-adjacent edge intersects one of the FOV line segments
else if intersects(edge, lowerSegment) or intersects(edge, higherSegment):
objectsToExpand.enqueue(adjacent)
checkedObjects.add(adjacent)
return objectsInFOV
function findObjectsInAllFOVs(objects):
triangulation= new DelaunayTriangulation(objects)
kdTree = new KDTree(objects)
allObjectsInFOVs = new Dictionary()
# Cycle through each object to find other objects in it's FOV
for subject in objects:
allObjectsInFOVs = findObjectsInFOV(subject, objects, triangulation, kdTree)
return allObjectsInFOVs
如果你对如何用图片计算角度展开一点讨论,这个答案将更有教育意义。另外,atan是不够的,因为它是围绕原点对称的,所以你也应该看看cos的符号。@Visa是种族主义:
atan2
正是这样区分的,因此两个参数而不是一个参数。至于图片,好吧,我已经给出了一个,它应该更明显吗?链接的问题是。因此,提取(甚至引用,如果足够简短的话)其中最重要的部分是一个好主意。进一步的