数値解:
l1 = {0.969, 0.594};
l2 = {0.892, 0.895};
r1 = {0.75880, 0.90366};
r2 = {0.22, 0.57};
p = {0.337+ 0.8764 t, 0.726 + 0.252 t};
s1 = l1 + ( l2 - l1) t;
s2 = r1 + (r2 - r1) t;
lx = ( (1 + ci) s1 + (1 - ci) s2 )/2 ;
ciz = (ci /.
Solve[ Dot[ {px,
py} - ( (1 + ci) {s1x, s1y} + (1 - ci) {s2x, s2y} )/
2 , {s1x, s1y} - {s2x, s2y}] == 0, ci][[1]]);
cizt = Simplify[
ciz /. { px -> p[[1]] , py -> p[[2]] ,
s1x -> (l1 + ( l2 - l1) t)[[1]],
s1y -> (l1 + ( l2 - l1) t)[[2]] ,
s2x -> (r1 + ( r2 - r1) t)[[1]],
s2y -> (r1 + ( r2 - r1) t)[[2]] }];
distance[t_] =
Simplify[Norm[lx - p]^2 /. ci -> cizt , Assumptions -> {Im[t] == 0} ];
Plot[distance[t], {t, 0, 1}]
possiblesolution = FindMinimum[distance[t], {t, 0, 1}]
If[ Chop[possiblesolution[[1]]] == 0,
tp = (t /. possiblesolution[[2]]); Print["possible hit at t=", tp];
If[Abs[cizt /. possiblesolution[[2]]] > 1,
Print["missed off the end"],
Animate[Show[Graphics[{Point[{p /. t -> 0, p /. t -> 1} ]}],
Graphics[{Line[{l1, r1} ]}], Graphics[{Line[{l2, r2} ]}],
Graphics[{Dashed, Line[{s1, s2} /. t -> a]}],
If[a < tp, Graphics[{Red, Line[{p /. t -> 0, p /. t -> a}]}],
Graphics[{Red, Line[{p /. t -> 0, p /. t -> a}], Blue,
Line[{p /. t -> tp, p /. t -> a}]}]]], {a, 0, 1}]]]
距離関数を見ると、最小値が 7 次多項式の根であることがわかります。ロバストであるためには、すべての実根を調べる必要があります。
編集 -- Mr Wizard のソリューションに基づくより良いバージョン。交差点がポイント間の無限の線だけでなく、セグメント上にあることを確認することで、少し改善しました。この例では、ランダムな問題が生成され、有効な解を含む問題が見つかった後に停止します。
solutions = {}
While[Length[solutions] == 0,
{l1, l2, r1, r2, p1, p2} = RandomReal[{0, 1}, 2] & /@ Range[6];
p = p1 + (p2 - p1) t ;
s1 = l1 + ( l2 - l1) t;
s2 = r1 + (r2 - r1) t;
realsols =
Solve[ { 0 < t < 1 , Det[ { s1 - s2 , p - s2}] == 0 ,Dot[ p - s2 , p - s1 ] < 0 } ];
If[Length[realsols] > 0, solutions = Sort[ (t /. realsols)];
tp = solutions[[1]]];]
Animate[Show[
Graphics[{Point[{p1, p2} ]}],
Graphics[{Green, Line[{l1, r1} ]}],
Graphics[{Orange, Line[{l2, r2} ]}],
Graphics[{Dashed, Line[{s1, s2} /. t -> a]}],
If[a < tp,
Graphics[{Red, Line[{p1, p /. t -> a}]}],
Graphics[{
Red, Line[{p1, p /. t -> a}],
Blue, Line[{p /. t -> tp, p /. t -> a}]}
]]], {a, 0, 1}]
ちなみに、Solve[] にすべての解を見つけさせてから有効な解を選択させる方が、制約を解くよりもはるかに高速です。
(Do [ realsols =
Solve[ { Det[ { s1 - s2 , p - s2}] == 0 , 0 < t < 1,
Dot[ p - s2 , p - s1 ] < 0 } ] , {10} ]; realsols) // Timing
(Do [realsols =
Select[ Solve[ { Det[ { s1 - s2 , p - s2}] == 0 ,
0 < t < 1} ] ,
Dot[ p - s2 , p - s1 ] < 0 /. # & ] , {100} ];
realsols) // Timing
(Do [realsols =
Select[ Solve[ { Det[ { s1 - s2 , p - s2}] == 0 } ] , 0 <= t <= 1 && Dot[ p - s2 , p - s1 ] < 0 /. # & ] , {100} ];
realsols ) // Timing
ただし、最初のフォームの方がきれいです:-)