如何用较小的正方形/矩形填充正方形?

时间:2009-12-16 17:06:59

标签: c# algorithm drawing

在我工作的办公室里,我们不允许画墙,所以我决定将正方形和矩形框起来,在上面贴上一些漂亮的布料,并将它们排列在墙上。

我正在尝试编写一个方法,它将采用我的输入尺寸(9'x 8'8“)和最小/最大尺寸(1'x 3',2',4'等)并生成正方形和矩形的随机模式填充墙。我尝试手工完成这个,但我对我得到的布局感到不满意,每次我想“随机化”布局需要大约35分钟。 / p>

10 个答案:

答案 0 :(得分:14)

一种解决方案是从x * y方块开始,并将方块随机合并以形成矩形。你需要给不同大小的方块赋予不同的权重,以防止算法最终得到大量的小矩形(即大矩形应该有更高的机会被选中进行合并,直到它们变得太大)。

答案 1 :(得分:4)

听起来像Treemap

答案 2 :(得分:4)

另一个想法:

1. Randomly generate points on the wall
    Use as many points as the number of rectangles you want
    Introduce sampling bias to get cooler patterns
2. Build the kd-tree of these points

kd-tree将以多个矩形分割空间。可能有太多的结构,你想要的,但它仍然是一个整洁的怪异算法。

(见:http://en.wikipedia.org/wiki/Kd-tree

编辑:刚刚看过JTreeMap,看起来有点像这样做。

答案 3 :(得分:3)

如果你正在谈论一个纯粹的编程问题;)有一种称为Bin Packing的技术,它试图将一些二进制数据包装到可能的最小区域。那里有很多材料:

http://en.wikipedia.org/wiki/Bin_packing_problem

http://mathworld.wolfram.com/Bin-PackingProblem.html

http://www.cs.sunysb.edu/~algorith/files/bin-packing.shtml

所以你'可以'创建一堆随机方块并通过bin packer运行它来生成你的模式。

我自己没有实施过bin打包算法,但是我已经看到一位同事为Nike网站做过。祝你好运

答案 4 :(得分:2)

由于你可以选择矩形的大小,这不是一个难题。

我会说你可以做一些简单的事情:

   Pick an (x,y) coordinate that is not currently inside a rectangle.
   Pick a second (x,y) coordinate so that when you draw a rectangle between
      the two coordinates, it won't overlap anything. The bounding box of
      valid points is just bounded by the nearest rectangles' walls.
   Draw that rectangle.
   Repeat until, say, you have 90% of the area covered. At that point you
      can either stop, or fill in the remaining holes with as big rectangles
      as possible.

参数化点的生成,然后制作遗传算法可能会很有趣。健身功能将是您喜欢的安排 - 它会为您绘制数百个安排,您可以按照1-10的等级对它们进行评分。然后它将采取最好的并调整它们,并重复,直到你得到你真正喜欢的安排。

答案 5 :(得分:1)

箱包装或方包装?

Bin包装: http://www.cs.sunysb.edu/~algorith/files/bin-packing.shtml

方形包装: http://www.maa.org/editorial/mathgames/mathgames_12_01_03.html

这实际上听起来更像是一个古老的学校随机方形绘画演示,大约8位计算日,特别是如果你不介意重叠。但如果你想变得特别怪异,可以创建随机方块并解决包装问题。

答案 6 :(得分:1)

建立Philippe Beaudoin的答案。

您也可以使用其他语言的树形图实现。在Ruby中使用RubyTreeMap可以做到

require 'Treemap' 
require 'Treemap/image_output.rb'

root = Treemap::Node.new 0.upto(100){|i| root.new_child(:size => rand) } 

output = Treemap::ImageOutput.new do |o| 
   o.width = 800 
   o.height = 600 
end 

output.to_png(root, "C:/output/test.png") 

然而,它对矩形进行排序,因此它看起来不是很随机,但它可能是一个开始。有关详细信息,请参阅rubytreemap.rubyforge.org/docs/index.html

答案 7 :(得分:0)

我会以螺旋形式缓慢地生成所有内容。如果在任何时候你达到了一个点,你的解决方案被证明是“无法解决的”(IE,不能在剩下的中间放置任何方块以满足约束) ,转到较早的草案并改变一些方格,直到找到一个快乐的解决方案。

Pseudocode看起来像:

public Board GenerateSquares(direction, board, prevSquare)
{
   Rectangle[] rs = generateAllPossibleNextRectangles(direction, prevSquare, board);
   for(/*all possible next rectangles in some random order*/)){
      if(board.add(rs[x]){
           //see if you need to change direction)
           Board nBoard = GenerateSquares(direction, board, rs[x]);
           if(nBoard != null) return nBoard; //done
           else board.remove(rs[x]);
      }
  }
  //all possibilities tried, none worked
  return null;
}

}

答案 8 :(得分:0)

我建议:

首先设置一个带有四个顶点的多边形,以便以不同的大小(最大为maxside)矩形块进行食用:

public double[] fillBoard(double width, double height, double maxside) {
  double[] dest = new int[0];
  double[] poly = new int[10];
  poly[0] = 0; poly[1] = 0; poly[2] = width; poly[3] = 0;
  poly[4] = width; poly[5] = height; poly[6] = 0; poly[7] = height;
  poly[8] = 0; poly[9] = 0;
  ...
  return dest; /* x,y pairs */
}

然后选择一个随机顶点,在该行的2 X最大值范围内找到多边形线。 找到所有水平线的所有垂直线和y值的x值。为选择每个x和y值的“优点”创建等级,并为这些值之间的值生成等式的等式。优良度测量为减少剩余多边形中的线数。使用伪随机生成器为两个x坐标或两个y坐标之间的每个值范围生成三个选项。在加权平均基础上评估和选择x对和y对的对,倾向于良好的选择。通过从多边形阵列中剪切其形状并将矩形坐标添加到dest数组,将新矩形应用于列表。

问题没有说明最小的参数。但是如果需要一个算法,那么算法应该(在碰到一个间隙太小的障碍时)不要在选择列表中包含太小的候选者(偶尔会使它们变空)并在某个半径范围内取消选择一些周围的矩形。大小的问题,并执行该区域的新再生尝试,并希望问题区域,直到满足标准。如果较小的切换中继失败,则递归可以逐渐删除更大的区域。

修改

进行一些命中测试以消除潜在的重叠。在开始打字前吃一些菠菜。 ;)

答案 9 :(得分:0)

  1. 定义输入区域;
  2. 在整个高度的几个随机水平位置绘制垂直线;
  3. 在整个宽度的几个垂直位置绘制水平线;
  4. 向上或向下移动一些“列”任意数量;
  5. 向左或向右移动一些“行”任意数量(可能需要细分一些单元格以获得完整的水平接缝;
  6. 按照美学要求去除接缝。
  7. 此图形方法与Brian's answer具有相似性。