我正在尝试实现Gilbert–Johnson–Keerthi distance algorithm(GJK),但我遇到了“距离子算法”的问题,也称为“约翰逊算法”,它用于确定单纯形上的点最接近原点的。我得到的结果不正确但我在代码中找不到任何错误,所以问题必须在我对算法的解释中。
在Johnson的算法中(如Gino van den Bergen的书“交互式3D环境中的碰撞检测”中所述),给出了最接近原点的单X = {yi : i ∈ Ix}
的仿射壳上的点由:
其中Δi^ X值以增加X的基数的顺序递归地确定:
......和Δ^ X由下式给出:
对于两个维度,我使用以下方法找到与原点最接近的点:
Point ClosestPointToOrigin(Simplex simplex)
{
float dx = 0;
for (int i = 0; i < simplex.size(); ++i)
dx += dj(simplex, i);
Point closest_point(0,0);
for (int i = 0; i < simplex.size(); ++i)
closest_point += dj(simplex, i) / dx * simplex[i];
return closest_point;
}
其中Δi值由下式确定:
float dj(Simplex simplex, int j)
{
if (j == 0)
{
return 1;
}
else
{
float d = 0;
for (int i = 0; i < j; ++i)
d += dj(simplex, i) * (simplex[0] - simplex[j]).dotProduct(simplex[i]);
return d;
}
}
对于X = {y1, y2}
,y1 = (1,1)
的单一y2 = (1,-1)
,上述代码返回(1.0, -0.333333)
,而最近的点实际上是(1, 0)
。< / p>
我一定做错了什么,但我无法弄清楚那是什么。
答案 0 :(得分:1)
您的错误是dj
函数,可能您误解了dxi
等式,或者您没有写出您想要的内容。
我会尝试解释自己,如果你不理解某事,请不要犹豫评论(我正在编写伪python代码,但它应该很容易理解)。
假设我有以下Simplex:
S = Simplex ({
1: Point (1, 1) # y1
2: Point (1,-1) # y2
})
我可以立即计算2个增量值:
然后,我可以计算另外两个增量值:
希望到现在你将开始看到你的错误:Δ值是基于指数的,因此对于尺寸为n的每个单纯形X,你有n个Δ值。你的一个错误是假设你可以计算Δ X 0 和Δ X i ,无论其内容如何X,这是假的。
现在最后一个Δ:
请注意:
你来到这里:
这是一个用Python编写的代码,如果你不理解它,我会尝试用你理解的语言写一个:
import numpy
class Point (numpy.ndarray):
def __new__ (cls, x, y):
return numpy.asarray([x, y]).astype(float).view(cls)
def __str__ (self):
return repr(self)
def __repr__ (self):
return 'Point ({}, {})'.format(self.x, self.y)
x = property (fget = lambda s: s[0])
y = property (fget = lambda s: s[1])
class Simplex (dict):
def __init__ (self, points):
super(Simplex, self).__init__ (enumerate(points))
def __str__ (self):
return repr(self)
def __repr__ (self):
return 'Simplex <' + dict.__repr__ (self) + '>'
def closest_point (s):
dx = sum(dj(s, i) for i in range(len(s)))
return sum(dj(s, i) / dx * v for i, v in s.items())
def dj (s, j):
if len(s) == 0 or (len(s) == 1 and not j in s):
print(s, j)
raise ValueError ()
if len(s) == 1:
return 1
ts = s.copy()
yj = s[j]
del ts[j]
return sum(dj(ts, i) * (ts[list(ts.keys())[0]] - yj).dot(v) for i, v in ts.items())
S = Simplex([Point(1, 1), Point(1, -1)])
print(closest_point (S))