检查鼠标是否在Bézier曲线上方[重复]

问题描述 投票:0回答:2

这个问题在这里已有答案:

我的方法是循环曲线并检查鼠标到各个点的距离

但随着曲线越来越陡,点越来越近,如果鼠标距离阈值太高,则优先考虑循环中的第一个点而不是鼠标的壁橱。

有没有办法在其中获得统一的分数?或者检查鼠标是否在Bézier曲线上并获得曲线中的位置?

c# math bezier
2个回答
1
投票

我是这样做的:

  1. 将你的曲线细分为几个块 块的数量取决于曲线的顺序。由于我通常使用立方体,我凭经验发现~8个块就足够了(为了我的目的)。
  2. 计算最接近块的点 因此,只需将每个块作为线处理,并计算线上最靠近鼠标位置的点(最小垂直距离)。通过为每个块计算它并记住最接近的块。 chunks 在此之后我们知道哪个块包含“最接近”的点,所以从线和垂直线之间的交点到前一步的鼠标位置我们应该有一个参数u=<0,1>告诉我们在块线上最近点的位置和我们也知道块线(t)的两个端点的曲线参数t0,t1。从这里我们可以通过这样做来近似t最近点: t = t0 + (t1-t0)*u 在图像t0=0.25t1=0.375。这有时候足够了,但是如果你想要更好的解决方案,那么在此之后只需设 dt = (t1-t0)/4 t0 = t-dt t1 = t+dt 使用t0,t,t1计算2个块的3个端点并再次查找最近的点。您可以递归执行此操作,因为每次迭代都会增加结果的精度 increase accuracy

点与线的垂直距离是通过计算直线与穿过所讨论的点的轴之间的交点来计算的。因此,如果线由端点p0,p1定义并且查询点(鼠标)是q那么2D中的轴将是:

dp=p1-p0        // line direction
dq=(dp.y,-dp.x) // axis direction is perpendicular to dp
dq/= |dq|       // normalize
p(u) = p0+dp*u  // point on line
p(v) = q +dq*v  // point on axis
u = <0,1>       // parameter on line
v = <-inf,+inf> // parameter on axis

我们想知道来自的u,v

p0+dp*u = q +dq*v

这是2D中的2个线性方程组。在3D中,您需要利用交叉产品来获得dq,系统将包含3个方程式。解决这个系统会给你u,v,其中u将告诉你最近点的块在哪里,|v|是垂直距离本身。不要忘记,如果u不在<0,1>范围内,那么你必须使用该线的更近端点作为最近点。

系统可以用代数方式求解(但要注意边缘情况,因为2D中有两个方程解决方案)或使用逆矩阵...


1
投票

主要有两种方法 - 将曲线细分为小线段和解析解。

对于第二种情况,您必须根据参数t建立从点到曲线的平方距离的多项式,对其进行微分,并找到结果的零(5阶多项式)。然后从t[i], t=0, t=1的距离选择最小值。另一个观点 - 将点投影到曲线上,因此此点的曲线切线垂直于矢量点 - 曲线点,它应该给出相同的表达式。

enter image description here

关于均匀点 - 这是一个相当困难的问题,因为无法通过分析计算曲线长度。但细分给出了很好的近似。

© www.soinside.com 2019 - 2024. All rights reserved.