【问题标题】:Computational complexity and shape nesting计算复杂度和形状嵌套
【发布时间】:2026-01-23 06:40:02
【问题描述】:

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

AFAIK,没有用于实际打包抽象形状的确定性算法。

我希望在这里被证明是错误的,这将是理想的(有一种数学确定性方法来打包它们)。如果我是对的但没有,那么解决这个问题的最佳方法是什么

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

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

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

  • 第二种方法是某种增量旋转。算法 以增量步长旋转形状并检查它是否适合 空间。就空间而言,这比打包方法要好 浪费,但它非常缓慢,

还有哪些其他课堂示例可以解决这个问题?

【问题讨论】:

  • 这个问题似乎是题外话,因为它是关于数学算法的。听起来在 math.stackexchange.com 上会更好
  • 算法的效率仍属于数学领域。
  • 如果它不要求库推荐,而只是询问有关布尔运算的问题怎么办?你还会投票关闭它吗?
  • 如果是关于联合、减法的实现,并且如果 OP 显示了一些解决它的尝试,那么不是,否则是。
  • 我深信不疑。在收集投票关闭它之前,我仍然会继续使用它。

标签: time-complexity computational-geometry


【解决方案1】:

[Edit1] 新答案

如前所述,装箱是 NP 完全(困难),所以忘记代数解决方案 已知的方法是:

  1. 生成和测试

    您要么测试问题的所有可能性并记住最佳解决方案,要么以相同的方式逐个添加项目(不是一次全部)。基本上,如果没有适当的启发式方法,您现在正在做的事情会非常缓慢。但是空间效率最好(第一个好很多但是慢很多)O(N!)

  2. 利用按大小对项目进行排序

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

  3. 神经网络的使用

    这是一种非常模糊的方法,没有任何解决方案的保证,但可能是最佳的空间效率/运行时间比率

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

    我播种了一些用于生成图形布局。所有项目都会创建场(展位吸引和排斥),因此它们正在进入半稳定状态。

    • 起初所有项目都在随机位置
    • 当运动停止时,记住最佳解决方案并稍微摇晃所有物品或再次随机化它们的位置。
    • 循环几次

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

    这里是用于在 2D 中放置滑块的求解器:


[Edit0] 重新提出问题之前的旧答案

我不清楚你想要实现什么。

  1. 拥有 SVG 图片并希望将其部分分隔为矩形区域
    • 尽可能填满
    • 其中的空白空间最少
    • 图片没有形状变化
  2. 有 svg 图片并想根据某些目的更改其形状
    • 如果是这种情况,需要一些额外的信息

[1的解决方案]

  1. 在全局 SVG 空间中为整个 SVG 创建点列表(所有点都已转换)
    • 对于需要加 2 分的线
    • 矩形 4 点
    • 圆/椭圆/贝塞尔/椭圆弧 8 点
  2. 找到当地的质心
    • 使用classical approach
    • 或者可以通过分别计算每个 x、y 轴的点的平均密度来加快速度,然后只需检查找到的局部最大密度位置的所有组合是否真的是子集群中心。
  3. 所有子集群中心都是你所在区域的中心
    • 现在找到仍然属于集群一部分的最远点(与相邻点足够近)
    • 创建覆盖子集群中所有点的矩形区域。
    • 您也可以从列表中删除所有使用的点
  4. 重复所有有效的子集群
    • 直到所有点都用完

另一种不精确但更简单的方法是:

  1. 查找 SVG 大小
  2. 创建具有一定精度的 svg 平面图,例如 int map[256][256]。
    • 地图的大小可以是恒定的,也可以与 SVG 具有相同的纵横比
  3. 用0清除地图
  4. 对于任何 SVG 点,将相关地图点设置为 1(或 inc 或其他)
  5. 现在只需分割地图,您就会找到您的对象
    • 分割后你有所有对象的位置和大小
    • 所以找到边界框应该很容易

【讨论】:

  • 是的,我现在知道你的意思了......它与 svg 无关,......如果有一些统一的算法,我不支持。害怕试错是你唯一安全的选择。如果您必须创建相同的形状,则某些用户预定义的填充模式可能比任何算法都好。 (这就是我用于等离子切割的)
  • @Nicholas Kyriakides 终于有时间重新编辑我的答案,看看是否有帮助。但正如我所看到的,无论如何,你的问题已经变得更好了:)
  • @Spektre....除非你已经准备好并准备好要传给我的东西:)
  • @Nicholas Kyriakides 遗憾的是,不,我只做了矩形包装,我的字段实现用于不同的用途。对于复杂的形状,我使用预定义的图案,但正如我之前所写,它们仅适用于相同形状的包装(这是我等离子切割机所需要的)
【解决方案2】:

您可以从矩形装箱算法的变体开始并添加旋转。有一个方法“Guillotine bin packer”,你可以在github下载论文和库。

【讨论】:

  • 装箱算法创建边界框。对于不规则形状效率非常低,因为形状例如是“星形”。例如,创建边界框会浪费星辐之间的空间。
  • 为什么不使用圆形包装来填充星星?有一个 d3 jquery 插件吗?你可以混合矩形、圆形和椭圆体吗?这只是星形吗?
  • 不,我说的是不规则的形状,它可以是任何东西。圆形包装对于明星来说仍然有很多空间浪费:)。