Java - Hexagon在网格中的位置

时间:2018-03-06 08:48:37

标签: java jcomponent hexagonal-tiles

我正在寻找一个算法来获得网格中六边形的位置。 我找到了这个,但它不起作用:

for(int i = 0; i < width; i++) {
        for(int j = 0; j < height; j++) {
            grid[i][j] = new Hexagon(x+(j*((3*Hexagon.S)/2)), y+((j%2)*Hexagon.A)+(2*i*Hexagon.A));
        }
    }

输出有点奇怪: output

这是创建窗口的类(只是一个测试类):

import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Grid extends JPanel {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        int width = 2;
        int height = 4;
        int x = 100;
        int y = 100;
        Hexagon[][] grid = new Hexagon[width][height];

        JFrame f = new JFrame();
        Container cp = f.getContentPane();


        for(int i = 0; i < width; i++) {
            for(int j = 0; j < height; j++) {
                grid[i][j] = new Hexagon(x+(j*((3*Hexagon.S)/2)), y+((j%2)*Hexagon.A)+(2*i*Hexagon.A));
                cp.add(grid[i][j]);
            }
        }

        f.setLayout(null);
        f.setBounds(100, 100, 300, 300);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }
}

Hexagon.java类:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;

import javax.swing.JButton;

 public class Hexagon extends JButton {

    public static final int S = 50;
    public static final int A = (int) (Math.sqrt(3)*(S/2));

    private static final long serialVersionUID = 1L;
    private final int x, y;
    private final Polygon shape;

    public Hexagon(int x, int y) {
        this.x = x;
        this.y = y;
        this.shape = initHexagon();
        setSize(2*S, 2*A);
        setLocation(x-S, y-A);
        setContentAreaFilled(false);
    }

    private Polygon initHexagon() {
        Polygon p = new Polygon();
        p.addPoint(x+(S/2), y-A);
        p.addPoint(x+S, y);
        p.addPoint(x+(S/2), y+A);
        p.addPoint(x-(S/2), y+A);
        p.addPoint(x-S, y);
        p.addPoint(x-(S/2), y-A);
        return p;
    }

    protected void paintComponent(Graphics g) {
        g.setColor(Color.BLACK);
        g.drawPolygon(this.shape);
    } 

    protected void paintBorder(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(Color.BLACK);
        g2.setStroke(new BasicStroke(4));
        g2.drawPolygon(this.shape);
    }

    public boolean contains(int x, int y) {
        return this.shape.contains(x, y);
    }
}

正如我所说,这个课程使用非矩形形状工作得很好。 没有裁剪等。

1 个答案:

答案 0 :(得分:1)

您发布了Hexagon的定义为时已晚,因此我从我的代码段集中复制粘贴了类似类的修改版本。

以下是生成六边形网格的一种方法:

import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JComponent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.GridLayout;
import java.util.function.*;

public class Hexagons extends JPanel {

    private static final long serialVersionUID = 1L;

    /** Height of an equilateral triangle with side length = 1 */
    private static final double H = Math.sqrt(3) / 2;

    static class Hexagon {
      final int row;
      final int col;
      final double sideLength;
      public Hexagon(int r, int c, double a) {
        this.row = r;
        this.col = c;
        this.sideLength = a;
      }

      double getCenterX() {
        return 2 * H * sideLength * (col + (row % 2) * 0.5);
      }

      double getCenterY() {
        return 3 * sideLength / 2  * row;
      }

      void foreachVertex(BiConsumer<Double, Double> f) {
        double cx = getCenterX();
        double cy = getCenterY();
        f.accept(cx + 0, cy + sideLength);
        f.accept(cx - H * sideLength, cy + 0.5 * sideLength);
        f.accept(cx - H * sideLength, cy - 0.5 * sideLength);
        f.accept(cx + 0, cy - sideLength);
        f.accept(cx + H * sideLength, cy - 0.5 * sideLength);
        f.accept(cx + H * sideLength, cy + 0.5 * sideLength);
      }
    }

    public static void main(String[] args) {
        final int width = 50;
        final int height = 50;
        final Hexagon[][] grid = new Hexagon[height][width];
        for(int row = 0; row < height; row++) {
            for(int col = 0; col < width; col++) {
                grid[row][col] = new Hexagon(row, col, 50);
            }
        }

        JFrame f = new JFrame("Hexagons");
        f.getContentPane().setLayout(new GridLayout());
        f.getContentPane().add(new JComponent() {
          @Override public void paint(Graphics g) {
            g.setColor(new Color(0xFF, 0xFF, 0xFF));
            g.fillRect(0,0,1000,1000);
            g.setColor(new Color(0,0,0));
            final int[] xs = new int[6];
            final int[] ys = new int[6];
            for (Hexagon[] row : grid) {
              for (Hexagon h: row) {
                final int[] i = {0};
                h.foreachVertex((x, y) -> {
                  xs[i[0]] = (int)((double)x);
                  ys[i[0]] = (int)((double)y);
                  i[0]++;
                });
                g.drawPolygon(xs, ys, 6);

                g.drawString(
                  "(" + h.row + "," + h.col + ")", 
                  (int)(h.getCenterX() - 15), 
                  (int)(h.getCenterY() + 12)
                );
              }
            }
          }
        });
        f.setBounds(0, 0, 500, 500);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        try {
            Thread.sleep(100);
        } catch (Throwable e) {

        } finally {
            f.repaint();
        }
    }
}

它产生以下输出:

enter image description here

很抱歉缺少抗锯齿功能。一些提示:

  • 等边三角形的高度H,单位边长为sqrt(3) / 2
  • 距离中心的六个偏移是(0, +1)(H, +1/2)(H, -1/2)(0, -1)(-H, -1/2)(-H, +1/2),所有时间都是边长
  • 行之间的距离为1.5,列之间的距离为2 * H(缩放常数=边长)。
  • 每个奇数行都移位(0, H)(缩放常数)。
  • (row,col) - 六边形的位置为(1.5 * row, 2 * H * (col + 0.5 * (row % 2)))(时间常数)。

如果要旋转六边形使其两边是水平的,则必须翻转行和列。