【问题标题】:Point and line segment intersection point. Both moving点和线段的交点。两者都在移动
【发布时间】:2012-10-06 01:29:22
【问题描述】:

我如何知道以固定速度移动的点和端点正在移动的线段之间的时间和交点?端点独立移动,但仅沿正 y 方向移动,并且以固定速度移动。

情况图片:

所以随着时间 t,L1 移动到 L2,R1 移动到 R2,P1 移动到 P2。在某一时刻,P 在 t 时刻的位置应该位于 L 和 R 在 t 时刻形成的线段上的某处。

我坚持了我在mathematica中可以提出的每一个关系,并让它解决了t,这让我得到了答案,但是当我尝试实现它时它似乎不起作用(没有检测到碰撞。我'我对mathematica很陌生,我真的不知道我在做什么,所以我有点希望有更多经验的人会注意到我试图解决方程组的方式存在根本性的错误。感谢阅读!

其中U是t时刻的线段。

  • Ly = L1y + (L2y - L1y) * t
  • Ry = R1y + (R2y - R1y) * t
  • Py = P1y + (P2y - P1y) * t
  • Px = P1x + (P2x - P1x) * t
  • Ux = L1x + (R1x - L1x) * 米
  • Uy = Ly + (Ry - Ly) * m
  • m = (Px - L1x) / (R1x - L1x)

求解 t 其中:

  • Ux = Px
  • Uy = Py

解决方案:

  • A = (P2x - P1x) * (L2y - L1y) - (P2x - P1x) * (R2y - R1y)
  • B = (P2x - P1x) * L1y + (P2x - P1x) * R1y - P1x * (L2y - L1y) + L1x * (L2y - L1y) + P1x * (R2y - R1y) - L1x * (R2y - R1y) + (P2y - P1y) * (R1x - L1x) - (R1x - L1x) * (L2y - L1y)
  • C = P1x * L1y - P1x * R1y - L1y * L1x + R1y * L1x + P1y * (R1x - L1x) - L1y * (R1x - L1x)

t = (-B + -sqrt(B^2 - 4AC)) / 2A

【问题讨论】:

  • 尝试计算点线距离,然后找到最小值。

标签: wolfram-mathematica 2d collision-detection point line-segment


【解决方案1】:

数值解:

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 阶多项式的根。要稳健,您需要查看所有实根。

edit -- 基于 Mr Wizard 解决方案的更好版本。我通过检查交点是否在 on 段上,而不仅仅是在点之间的无限线上,对它进行了一些改进。 此示例生成随机问题并在找到具有有效解决方案的问题后停止。


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

第一种形式更漂亮:-)

【讨论】:

  • 为了完整起见,您可以直接使用 Solve[] 而不是 FindMinimum。你仍然有 6 个根来检查有效性。
  • 流畅的图形。恕我直言,您应该在帖子中包含其中一些。 :-)
  • 我无法从这里访问任何类型的文件共享站点以发布动画图形。如果可能,请随意添加它
【解决方案2】:

定义点:

{L1, L2, R2, R1, P1, P2} =
   {{0.01`, 0.31`}, {0, 2.`}, {2.985`, 1.9`}, {2.995`, 0.95`},
    {1.7`, 1.82`}, {1.23`, 0.87`}};

定义函数:

L := L1 (1 - t) + L2 t
R := R1 (1 - t) + R2 t
P := P1 (1 - t) + P2 t

可视化问题:

Manipulate[
 Block[{t = tt},
  Graphics[{
    {Red, Polygon[{L1, L2, R2, R1}]},
    {White, Thick, Line[{P1, P2}]},
    {Black, PointSize[Large], Point@{L, R, P}, Line[{L, R}]}
   }, Background -> Gray, PlotRangePadding -> 0.7]
 ],
 {tt, 0, 1}
]

求解t,观察解与可视化匹配:

Reduce[{Det[{R - L, P - L}] == 0, 0 < t < 1}, t]

t == 0.525873

利润。

【讨论】:

  • 感谢您的回复。我很难理解这里到底发生了什么。我是mathematica的新手,实际上刚刚开始在这个项目中使用它。您能否提供一些伪代码或者只是向我解释最后一行?谢谢。
  • @user1713472 最后一行只是一个测试(我在 Google 上找到的),看看一条无限线是否与一个点 (Det[{R - L, P - L}] == 0) 相交并结合 Reduce,你可以使用它的语法可以在集成的帮助文件中找到。您仍然需要测试该点是否在您的线段内以确认解决方案,我在上面以图形方式完成了。
猜你喜欢
  • 1970-01-01
  • 2015-07-03
  • 2021-10-29
  • 1970-01-01
  • 2016-12-22
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 2017-09-26
相关资源
最近更新 更多