【问题标题】:Check if the mouse is over a Bézier curve [duplicate]检查鼠标是否在贝塞尔曲线上[重复]
【发布时间】:2018-09-07 03:52:07
【问题描述】:

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

但是随着曲线变得越来越陡,这些点会越来越靠近,如果鼠标距离阈值太高,它会优先考虑循环中的第一个点,而不是离鼠标最近的点。

有没有办法获得统一的分数?或者检查鼠标是否在贝塞尔曲线上并获取曲线中的位置?

【问题讨论】:

  • 更容易检测2个区域是否有交集。这是an example 在检测RegionGraphicsPath 之间的交叉点 - 您可以在鼠标指针周围定义一个区域,并创建一个GraphicsPath from the Bezier curve
  • 我在重复链接的问题中添加了一个新答案。我有一个python script here,您可以在其中单击绘图并显示最短距离。

标签: c# math bezier


【解决方案1】:

我是这样做的:

  1. 将曲线细分为几块

    块的数量取决于曲线的顺序。由于我通常使用立方体,我凭经验发现大约 8 个块就足够了(就我的目的而言)。

  2. 计算离块最近的点

    因此,只需将每个块作为线处理,并计算线上到鼠标位置的最近点(最小垂直距离)。通过为每个块计算它并记住最接近的一个。

    现在我们知道哪个块包含“最近”点,所以从直线和垂直线的交点到上一步的鼠标位置,我们应该有一个参数 u=<0,1> 告诉我们块线上的位置最近的点是并且我们也知道块线(t0,t1)两个端点的曲线参数t。从这里我们可以简单地通过这样做来近似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 个端点并再次寻找最近的点。您可以递归执行几次,因为每次迭代都会提高结果的精度

点到线的垂直距离是通过计算线和垂直于它的轴之间的交点来计算的。因此,如果线由端点p0,p1 定义,查询点(鼠标)是q,那么二维坐标轴将是:

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

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

系统可以通过代数求解(但要注意极端情况,因为二维方程有 2 个解)或使用逆矩阵...

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-12
      • 1970-01-01
      • 2011-03-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多