计算复杂性和形状嵌套

时间:2013-07-29 13:46:59

标签: time-complexity computational-geometry

我有SVG的无线路径,我需要在给定的矩形内尽可能有效地打包(尽可能少浪费空间)。经过一些研究后,我发现了bin打包算法,这些算法似乎是处理盒子而不是弯曲的随机形状(我的SVG形状非常复杂,包括beziers等)。

AFAIK,没有确定性算法来实际包装抽象形状。

我希望在这里被证明是错误的,这是理想的(用数学确定性的方法来包装它们)。如果我是对的而且没有,那么这个问题的最佳方法是什么

主题名称为 Shape Nesting, Nesting Problem or Nesting Process

在形状嵌套中,没有单一/统一的算法或数学方法来嵌套形状,并且可以减少空间浪费。

  • 第一种方法是打包算法(创建一个假想的边界 每个形状的框,并使用矩形2D算法打包 边界框)。 这种方法速度快但空间效率最低 浪费。

  • 第二种方法是某种增量旋转。算法 以增量步长旋转形状并检查它是否适合 空间。这在空间方面优于包装方法 浪费但却非常缓慢,

用于解决此问题的其他课堂示例是什么?

2 个答案:

答案 0 :(得分:3)

[编辑1]新答案

如前所述,bin-packing是NP完全(硬)所以忘记代数解决方案 已知的方法是:

  1. 生成并测试

    要么测试问题的所有可能性并记住最佳解决方案,要么以相同的方式逐个添加项目(不是一次性完成)。基本上你现在正在做的事情没有适当的启发式是非常慢的。但是具有最佳的空间效率(第一个更好但速度更慢)O(N!)

  2. 利用按大小排序项目

    类似于this,它快得多O(N.log(N))(根据使用的排序算法)。空间效率很大程度上取决于物品的尺寸范围和数量。对于矩形形状,这是最好的方法(即使对N>1000也是最快和可用的)。对于复杂的形状来说,这不是一个好方法,但无论如何都要看它,也许你会有所了解......

  3. 使用神经网络

    这是极端模糊的方法,没有任何解决方案,但可能的最佳空间效率/运行时间比率

  4. 我认为可能会有一些现场方法

    我播种了一些用于生成图形布局的内容。所有项目都创建了领域(展位吸引人和令人厌恶),因此他们正在进入半稳定状态。

    • 首先,所有项目都在随机位置
    • 当运动停止记住最佳解决方案并稍微摇动所有项目或再次随机化其位置时。
    • 循环这几次

    这种方法比 genere和test 快得多,并且可以提供非常接近的解决方案,但它可以挂在本地 min / max 或如果字段不是,则会振荡最佳选择。例如,所有物品彼此之间可以具有恒定的吸引力,并且只有当物品非常接近时,排斥力才会变强。你必须防止物品重叠(通过更强的排斥或碰撞测试)。你还需要创造一些旋转力矩,例如使用那种排斥力。它在任何顶点都不同,因此它会产生一个旋转力矩(可以自动将相似的边对齐得更近)。此外,您可以拥有半稳定状态,物品之间距离较远,找到最佳解决方案后,只需关闭排斥场,使它们粘在一起。有时它有时候会有更好的结果......这里是图形布局计算的好例子

    此处解决方案是将滑块放在2D中:


  5. 重新提出问题之前

    [编辑0]旧答案

    我不清楚你想要达到的目标。

    1. 有SVG图片,想要将其部分分成矩形区域
      • 尽可能充满
      • 其中空间最小
      • 图片中没有形状变化
    2. 有svg图片,并希望根据某些目的改变其形状
      • 如果是这种情况,则需要一些其他信息
    3. [解决方案1]

      1. 在全局SVG空间中创建整个SVG的点列表(所有点都被转换)
        • 对于您需要添加2分的行
        • for rectangleangles 4 points
        • circle / elipse / bezier / eliptic arc 8 points
      2. 找到当地的质心
        • 使用classical approach
        • 或者可以通过分别计算每个x,y轴的平均点密度来加快速度,之后只检查局部最大密度的找到位置的所有组合,如果它们确实是子群集中心的话。
      3. 所有子集群中心都是您所在地区的中心
        • 现在找到仍然是群集一部分的最远点(与邻居点足够接近)
        • 创建覆盖子群集中所有点的矩形区域。
        • 您还可以从列表中删除所有使用的点
      4. 重复所有有效的子群集
        • 直到使用所有点
      5. 另一个不精确但更简单的方法是:

        1. 查找SVG大小
        2. 以一定的精度创建svg的平面贴图,例如int map [256] [256]。
          • 地图的大小可以是常数或与SVG相同的方面
        3. 清除地图0
        4. 对于任何SVG点设置相关地图指向1(或inc或其他)
        5. 现在只是分割地图,您将找到您的对象
            分段后
          • 您拥有所有对象的位置和大小
          • 所以找到边界框应该很容易

答案 1 :(得分:1)

您可以从矩形bin-packing算法的变体开始并添加旋转。有一个方法“Guillotine bin packer”,您可以在github下载纸张和图书馆。