问题描述
我想知道是否有任何算法可以做到这一点:
给定一个特定曲面,它将它分成相同大小的小矩形。 / p>
类似这样的例子:
灰色区域是表面,红色方块是分区本身。
我想如果有一个优化的方式来做到这一点。
一个非常糟糕的方法将是一个for循环像素,并检查是否有一个矩形的特定点,如果没有,将创建一个矩形,等等。
也许有人知道一个算法已经完成?或更好的解决方案?
非常感谢!)
>这是一种解决方法。
-
创建图像的蒙版。 (我刚刚使用Photoshop)
-
-
偷AndrewThompson的的代码并使用它创建
区域$ c
区域imageArea = getOutline(Color.BLACK,imageMask);
-
创建网格
Rectangle2D
objects
$ bRectangle2D [] [] [] 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);
}
}
-
只需遍历
Rectangle2D
对象并检查Area.contains
每个单独的Rectangle2D
,你可以将它添加到List< Rectangle2D>
中。只有该区域中包含的矩形将被添加,从而为您提供要绘制的最终矩形网格。在下面的例子中,我只是将矩形绘制为一个视觉效果。for(Rectangle2D [] rects:imageGrid){$ b (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;
导入javax.swing.SwingUtilities;
public class SquaresInArea extends JPanel {
private static final int CELL_SIZE = 30;
BufferedImage图片;
BufferedImage imageMask;
区域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);
}
}
返回网格;
@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)); (Rectangle2D [] rects:imageGrid){
(Rectangle2D rect:rects){
if(imageArea.contains(rect)){
g2.drawRect((int )rect.getX(),(int)rect.getY(),
(int)rect.getWidth(),(int)rect.getHeight());
$ b @Override
public Dimension getPreferredSize(){
return image == null? new Dimension(300,300)
:new Dimension(image.getWidth(),image.getHeight());
$ b private Area getOutline(Color target,BufferedImage bi){
//构造GeneralPath
GeneralPath gp = new GeneralPath();
布尔值cont = false;
int targetRGB = target.getRGB();
for(int xx = 0; xx for(int yy = 0; 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();
//从GP&返回
返回新区域(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); (Rectangle2D [] rects:imageGrid){
(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);
}
}
}
}
I would like to know if there is any algorithm that does something like this:
Given a specific surface it divides it into smaller rectangles of the same size.
Something like this example figure:
The grey area is the surface, and the red squares is the partition itself.
I am thinking if there is a optimized way to do this.
A very bad approach would be a for loop in all the pixels and check if there is a rectangle for that specific spot, if not, would create a rectangle, and so on..
Maybe someone knows a algorithm already done? or a better solution?
Thanks alot in advance ;)
解决方案Here's one way to go about it.
Create a mask of the image. (I just used Photoshop)
Steal AndrewThompson's code for Creating an Area from an Image and use it to create an
Area
of the image.Area imageArea = getOutline(Color.BLACK, imageMask);
Create a grid
Rectangle2D
objects for the entirety of the image.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); } }
Once you have the grid, you can just traverse the
Rectangle2D
objects and check if theArea.contains
each individualRectangle2D
in the grid, and you can just add it to aList<Rectangle2D>
. Only rectangles contained in the area will be added, giving you your final grid of rectangles to draw. In the example below, I just painted to rectangles as a visual.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()); } } }
Full example
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); } }); } }
here's another view for clarity
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); } } } }
这篇关于Java分区表面变成小方块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!