Java分区表面成小方块

我想知道是否有任何算法做这样的事情:

给定一个特定的表面,它将它分成相同大小的较小矩形。

像这个示例图:

在此处输入图像描述

灰色区域是表面,红色方块是分区本身。

我在想是否有一种优化的方法来做到这一点。

一个非常糟糕的方法是在所有像素中使用for循环并检查是否有特定点的矩形,如果没有,将创建一个矩形,依此类推。

也许有人知道已经完成的算法? 还是更好的解决方案?

非常感谢提前;)

这是一种方法。

  1. 创建图像的蒙版。 (我刚用Photoshop)

    在此处输入图像描述在此处输入图像描述

  2. 窃取AndrewThompson 从图像创建区域的代码,并使用它来创建图像Area

     Area imageArea = getOutline(Color.BLACK, imageMask); 
  3. 为整个图像创建一个网格Rectangle2D对象。

     Rectangle2D[][] grid = new Rectangle2D[rows][cols]; for (int i = 0; i < grid.length; i++) { int y = i * CELL_SIZE; for (int j = 0; j < grid[i].length; j++) { int x = j * CELL_SIZE; grid[i][j] = new Rectangle2D.Double(x, y, cellSize, cellSize); } } 
  4. 获得网格后,您可以遍历Rectangle2D对象并检查Area.contains网格中是否Area.contains每个单独的Rectangle2D ,您只需将其添加到List 。 只会添加区域中包含的矩形,为您绘制最终的矩形网格。 在下面的例子中,我只是将视图绘制为矩形。

     for (Rectangle2D[] rects : imageGrid) { for (Rectangle2D rect : rects) { if (imageArea.contains(rect)) { g2.drawRect((int) rect.getX(), (int) rect.getY(), (int) rect.getWidth(), (int) rect.getHeight()); } } } 

完整的例子

在此处输入图像描述

 import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.geom.Area; import java.awt.geom.GeneralPath; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; public class SquaresInArea extends JPanel { private static final int CELL_SIZE = 30; BufferedImage image; BufferedImage imageMask; Area imageArea; Rectangle2D[][] imageGrid; public SquaresInArea() { try { image = ImageIO.read(getClass().getResource("/resources/floorplan.png")); imageMask = ImageIO.read(getClass().getResource("/resources/floorplan-black.png")); } catch (IOException ex) { Logger.getLogger(SquaresInArea.class.getName()).log(Level.SEVERE, null, ex); } imageArea = getOutline(Color.BLACK, imageMask); imageGrid = createGrid(); } private Rectangle2D[][] createGrid() { int width = image.getWidth(); int height = image.getHeight(); int rows = height / CELL_SIZE; int cols = width / CELL_SIZE; Rectangle2D[][] grid = new Rectangle2D[rows][cols]; for (int i = 0; i < grid.length; i++) { int y = i * CELL_SIZE; for (int j = 0; j < grid[i].length; j++) { int x = j * CELL_SIZE; grid[i][j] = new Rectangle2D.Double(x, y, CELL_SIZE, CELL_SIZE); } } return grid; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; g2.drawImage(image, 0, 0, this); g2.setColor(Color.YELLOW); g2.setStroke(new BasicStroke(3f)); for (Rectangle2D[] rects : imageGrid) { for (Rectangle2D rect : rects) { if (imageArea.contains(rect)) { g2.drawRect((int) rect.getX(), (int) rect.getY(), (int) rect.getWidth(), (int) rect.getHeight()); } } } } @Override public Dimension getPreferredSize() { return image == null ? new Dimension(300, 300) : new Dimension(image.getWidth(), image.getHeight()); } private Area getOutline(Color target, BufferedImage bi) { // construct the GeneralPath GeneralPath gp = new GeneralPath(); boolean cont = false; int targetRGB = target.getRGB(); for (int xx = 0; xx < bi.getWidth(); xx++) { for (int yy = 0; yy < bi.getHeight(); yy++) { if (bi.getRGB(xx, yy) == targetRGB) { if (cont) { gp.lineTo(xx, yy); gp.lineTo(xx, yy + 1); gp.lineTo(xx + 1, yy + 1); gp.lineTo(xx + 1, yy); gp.lineTo(xx, yy); } else { gp.moveTo(xx, yy); } cont = true; } else { cont = false; } } cont = false; } gp.closePath(); // construct the Area from the GP & return it return new Area(gp); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { JFrame frame = new JFrame(); frame.add(new SquaresInArea()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } } 

这是另一种清晰的观点

在此处输入图像描述

 private final BasicStroke thin = new BasicStroke(1f); private final BasicStroke thick = new BasicStroke(4f); @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; g2.drawImage(image, 0, 0, this); for (Rectangle2D[] rects : imageGrid) { for (Rectangle2D rect : rects) { if (imageArea.contains(rect)) { g2.setStroke(thick); g2.setColor(Color.GREEN); g2.draw(rect); } else { g2.setStroke(thin); g2.setColor(Color.RED); g2.draw(rect); } } } } 

你只是想用方块填充它 – 或者你想用最佳数量的方块填充它?

第二种算法更难。

对于第一步,通过图像一次一个正方形大小。 如果该点处的像素被填满,则扫描整个正方形,如果全部填充则绘制正方形。 如果没有,那么步骤到下一点。

即如果正方形是10 * 10像素:

 for (int x=0;x