Java分区表面变成小方块 [英] Java Partition Surface into Little Squares

查看:108
本文介绍了Java分区表面变成小方块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有任何算法可以做到这一点:

给定一个特定曲面,它将它分成相同大小的小矩形。 / p>

类似这样的例子:


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



我想如果有一个优化的方式来做到这一点。



一个非常糟糕的方法将是一个for循环像素,并检查是否有一个矩形的特定点,如果没有,将创建一个矩形,等等。



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



非常感谢!)

>这是一种解决方法。


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




  2. 偷AndrewThompson的从图像创建区域的代码并使用它创建区域

     区域imageArea = getOutline(Color.BLACK,imageMask); 


  3. 创建网格 Rectangle2D objects
    $ b

      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 每个单独的 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.

    1. Create a mask of the image. (I just used Photoshop)

    2. 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);
      

    3. 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);
          }
      }
      

    4. Once you have the grid, you can just traverse the Rectangle2D objects and check if the Area.contains each individual Rectangle2D in the grid, and you can just add it to a List<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分区表面变成小方块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆