问题图片:
在我的代码中,我有4分:Q
,R
,S
,T
。
我知道以下
R
,T
和S
; RT < RQ < RS
; Q
。我已经知道点Q
可以在线段TS
上找到。但是我需要获取Q
和I
的坐标,这需要它是一个相对有效的计算。
对于这个问题,我有几个解决方案,但它们都是如此令人费解,我知道我必须做错事。我确信必须有一种简单优雅的方法来解决这个问题。最好的解决方案是最大限度地减少更密集计算的数量,但这也不会太长。
答案 0 :(得分:1)
Q是围绕R的半径d的圆与线TS之间的交叉点,这导致具有系数中的多个参数的二次方程。我不知道以下是否是“最好的”解决方案(在它们之间使用数值解算器甚至可能更好),但它完全解决了。因为我认为它更具可读性,所以我改变了坐标名称,将T置于(T1,T2),S置于(S1,S2),为了使公式更短,R为(0,0) - 只需调整S和T以及相应的返回值。
tmp1 = S1^2 - S2*T2 - S1*T1 + S2^2;
tmp2 = sqrt(- S1^2*T2^2 + S1^2*d^2 + 2*S1*S2*T1*T2 - 2*S1*T1*d^2 -
S2^2*T1^2 + S2^2*d^2 - 2*S2*T2*d^2 + T1^2*d^2 + T2^2*d^2);
tmp3 = S1^2 - 2*S1*T1 + S2^2 - 2*S2*T2 + T1^1 + T2^2;
t = (tmp1 + tmp2)/tmp3;
if (0 > t || t > 1) {
// pick the other solution instead
t = (tmp1 - tmp2)/tmp3;
}
Q1 = S1+t*(T1-S1);
Q2 = S2+t*(T2-S2);
显然,我不保证我没有拼写错误等等: - )
编辑:或者,你也可以通过一些迭代方法(比如牛顿)得到一个很好的近似值来找到dist(S+t*(T-S), R)-d
的零,作为[0,1]中t的函数。如果我算得正确的话,那将需要 9次七次乘法和每牛顿步骤一次除法。重新使用上面的名称,看起来像这样:
t = 0.5;
d2 = d^2;
S1T1 = S1 - T1;
S2T2 = S2 - T2;
do {
tS1T1 = S1 - t*S1T1;
tS2T2 = S2 - t*S2T2;
f = tS1T1*tS1T1 + tS2T2*tS2T2 - d2;
fp = 2*(S1T1*tS1T1 + S2T2*tS2T2);
t = t + f/fp;
} while (f > eps);
设置eps以控制所需的精度,但不要将其设置得太低 - 计算f确实涉及减法,在解决方案附近会出现严重的取消问题。
答案 1 :(得分:0)
由于(TS)线上有两个解决方案Q(T和S之间只有一个解决方案),任何解决方案可能都需要选择符号或arccos()等。
因此,一个好的解决方案可能是将Q放在(TS)线上(如图所示):
(1) TQ(t) = t * TS
(其中O是某些来源)。要求Q与R的距离d给出t中的二次方程,这很容易解决(同样,也暗示了向量):
d^2 = |RQ(t)|^2 = |RT + TQ(t)|^2
然后,通过将解t0置于等式(1)中,经由OQ(t0)= OT + TQ(t),可以获得Q的坐标。必须选择解0 <= t <= 1,使得Q位于T和S之间。
现在,可能会发生最终公式在三角函数方面有一些简单的解释......也许你可以告诉我们t的值是什么,你用这种方法找到什么坐标,我们可以找一个更简单的公式?