我试图解决一个问题,我需要在P0的某个距离到 P1周围投射一个关于已知半径的球体的弧,但是我的知识解决相当有限这种问题超出了标准的笛卡尔语境。
为了简化,如果我在飞机上这样做,我会简单地执行以下操作
float distance = 30;
Vector3 direction = (P1 - P0).Normalize();
Vector3 endPoint = P0 + (direction * distance);
我基本上试图看看是否有办法可以解决同样的问题,只能在球体上而不是在飞机上。这在概念上很困难,因为我需要考虑到P0和P1可以(并且将会)在球体上任意不同的高度。
我有一种感觉,我可能需要从笛卡尔转换为球形空间,但是在这里找到跳跃点已经证明非常困难。
思考?
答案 0 :(得分:2)
设P0和P1为点,并考虑半径为r的球体。
首先,假设P0和P1位于球体上,并且我们想要行进距离d。首先请注意,我们需要P0≠P1,就像在线性代数情况下一样。 (否则,P0 = P1,因此通过P0和P1没有唯一的弧。)同样,我们需要P0≠-P1,否则通过P0和P1没有唯一的弧。
现在从P0到P1的弧位于所谓的球体的great circle。基本上,这是球体与某个平面通过O =(0,0,0)的交点。更确切地说,这是通过点O,P1和P2的唯一平面。
一些基本的线性代数将向您显示这是垂直于矢量P0×P1的平面,P0和P1的交叉积。注意,本产品中P0和P1的顺序为重要:通常,P0×P1≠P1×P0,如果我们取P1×P0,则运动方向将反转。 (即我们将从P1变为P0。)因此,P0到P1的“方向”由绕P0×P1的旋转给出。
现在考虑一般点P0,P1。正如melak47指出的那样,我们可以先将P0和P1投射到球体上,这样我们就可以在“方向”P0到P1上方进行旋转。为了将这些投影到球体上,我们还需要P0和P1都不为零,即不是原点。当P0和P1位于原点的同一条线上时,我们也遇到了一个问题,因为它们投射到球体上的相同点(或对映点),所以不要定义一个独特的弧:所以一般来说,我们需要检查P0和P1是linearly independent。现在注意P0位于半径为|| P0 ||的球体上,其中|| P0 ||是向量P0的范数。
请注意,上面介绍的半径r实际上还没有在任何地方使用过,所以我们可以设置r = || P0 ||。为了在弧P0到P1'上行进d的总距离,其中P1'被P1投影到半径为|| P0 ||的球上,角度变为d / || P0 ||,如上所述。好消息是P0×P1仍然是一个有效的旋转轴。
总而言之,您希望将P0绕P0×P1旋转d / || P0 ||弧度。在伪代码中,
float d;
Vector3 P0, P1;
float r = norm(P0);
float angle = d / r;
Vector3 axis = crossProduct(P0, P1);
Matrix3 rotationMatrix = RotationMatrix(angle, axis);
Vector3 endPoint = rotationMatrix * P0;
检查P0和P1是否线性独立与检查P0×P1非零相同,因此通常您可能需要在构造旋转之前检查axis != Vector3(0,0,0)
基质
如果您想要沿着弧P0'到P1的P0到P1方向行进,其中P0'被P0投影到半径为|| P1 ||的球上,我们首先需要替换r = norm(P0)
r = norm(P1)
(显然)。此外,P0'= || P1 || / || P0 || * P0,因此如果您愿意,我们还需要将rotationMatrix * P0
替换为rotationMatrix * (r / norm(P0) * P0)
,或rotationMatrix * r * normalize(P0)
。
答案 1 :(得分:0)