【问题标题】:Convex Hull For User-Drawn Circle用户绘制圆的凸包
【发布时间】:2019-10-05 15:43:37
【问题描述】:

我正在开发一个游戏,我必须在其中找到一组点的凸包。我正在尝试选择正确的算法。点集是用户绘制的形状,因此它们是有顺序的。理想情况下,用户画一个椭圆,但他们可以画任何东西,只要它是单笔画。一些例子如下:

我想找到这些形状的凸包。我发现的所有凸包算法都假设一组随机、无序的点。哪种算法最适合我的特定情况,当用户通过单击和拖动鼠标绘制点时,点是有序的。

注意事项:

特别是,许多是输出敏感算法。 O(n log h) 其中 n 是所有点的集合中的点数,原始点,h 是凸包中的点集合。有了这些形状,我期望 h ~= n,因为它们本身就是轮廓。

最后,整个目标是找到点的最小面积矩形,例如:

除了首先找到凸包之外,谁能想到找到矩形的更好方法?经过研究,这似乎是最好的方法,但我的特殊情况可能会有所不同。

提前谢谢你!

【问题讨论】:

    标签: c# algorithm computational-geometry convex-hull


    【解决方案1】:

    远离 O(N Log H) 算法。它们既困难又缓慢!

    使用 O(N Log N) 是一个更好的选择。我推荐monotone chain 方法,既简单又快速。

    您不应该担心复杂度 O(N Log N),这只是由于排序阶段。额外的 Log N / Log H 因子并不是那么灾难性(对于凸点集也不存在),而排序的渐近常数非常好。

    如果您追求最大效率,您的点的特定排列建议了另一种方法:这些点将形成较长的递增(递减)序列,您可以通过合并步骤轻松检测和排序。复杂度将下降到 O(N Log K),其中 K 是单调序列的数量,因此实际上是 O(N)(这称为自然合并排序)。

    您离 Melkman 的 O(N) 算法的用例并不远,该算法可用于简单多边形的外壳。不幸的是,简单条件可能会在曲线接近结束时失效,我认为没有简单的方法可以解决这个问题。


    对于边界矩形,旋转卡尺绝对是您最好的朋友。

    【讨论】:

    • 谢谢,这正是我需要的!关于曲线的闭合,我计划通过检查用户是否在起点附近结束线并轻轻调整曲线以适当地加入来解决这个问题。我会测试您的解决方案,并在有任何问题时与您联系。
    【解决方案2】:

    要找到在特定方向上对齐的最小封闭矩形,您需要知道该方向和正交方向上的极值点,而凸包以特别方便的方式对这些信息进行编码,例如旋转卡尺。如果您愿意近似,您可以每五度(或其他)尝试一次方向,运行时间为 O(nd),其中 d 是方向数。如果你有 SIMD 支持,这很适用。

    【讨论】:

    • 那么你的意思是算法已经很适合我的目的了?此外,SIMD 代表什么?谢谢!
    【解决方案3】:

    我只是想知道如果你应用以下方法会发生什么:

    把你的多边形想象成一个 2 x N 矩阵

    P = [x1, x2, ..., xN;
         y1, y2, ..., yN]; 
    

    其中每列包含多边形顶点的 x 和 y 坐标。然后,对于 0pi/2 之间的任何角度 phi 定义旋转矩阵

    U(phi) = [cos(phi) -sin(phi);
              sin(phi)  cos(phi)];
    

    然后,通过乘以矩阵将多边形旋转到角度 phi

    P_phi = U(phi)*P;
    

    然后是函数

    f(phi) = ( max( P_phi[1][] ) - min( P_phi[1][] ) )*( max( P_phi[2][] ) - min( P_phi[2][] ) )
    

    是具有水平和垂直边缘的矩形区域,上标在旋转的多边形P(phi) 周围。这里P_phi[1][]是矩阵P_phi的第一行x坐标,P_phi[2][]是第二行y坐标。 因此,您想要找到角度 phi 和顶点,收集在 2 x 4 矩阵 R_phi 中,轴对齐矩形给出函数的最小值 f(phi) 代表phi in [0, pi/2],因为这是多边形周围最小面积矩形的面积。找到phiR_phi 之后 只需旋转如下 R = U(-phi)*R_phi 这是您正在寻找的矩形。

    我不确定这个建议是否有效......

    【讨论】:

    • 这与 David Eisenstat 给出的解决方案相同。要获得精确的解决方案,您应该尝试凸包边缘隐含的所有方向,这是非常低效的 (O(N²))。具有中等 d 的近似解是可能的,但很容易被旋转卡尺(实际上是旋转方法的增量版本)击败。
    猜你喜欢
    • 1970-01-01
    • 2015-07-29
    • 2015-06-01
    • 2018-06-20
    • 2021-05-13
    • 1970-01-01
    • 2020-04-22
    • 2014-04-11
    • 2020-12-20
    相关资源
    最近更新 更多