繁体   English   中英

如何使用坐标很少的AffineTransform?

[英]How to use AffineTransform with very little coordinates?

我有一组二维点。 它们的X和Y大于-2且小于2。这样的点可能是: (-0.00012 ; 1.2334 )

我想使用矩形在图形上显示这些点(一个矩形说明了一个点,并且将其坐标设置为其点的坐标-而且,其大小为10 * 10)。

像(...; Y)之类的矩形应显示像(...; Y-1)之类的任何矩形上方 (正的Y方向朝上)。 因此,我必须不将图形的原点设置在左上角,而是设置在其他地方。

我正在尝试使用Graphics2DAffineTransform来做到这一点。

  1. 我得到所有X坐标的最小值
  2. 我得到所有Y坐标的最小值
  3. 我得到所有X坐标的最大值
  4. 我得到所有Y坐标的最大值
  5. 我得到距离xmax-xminymax-ymin
  6. 然后,我编写了下面提供的代码。

截图

几天前,使用我自己的方法进行缩放,得到了以下图表: 在此处输入图片说明
(因此,正如我所解释的,Y是倒置的,这不是一件好事)

就目前而言,即使用我在下面提供的代码,我只有一点取代了所有图表! 一点都不好。

我想要拥有:
在此处输入图片说明
(没有线,也没有图的轴。这里重要的是根据点的坐标正确显示点)。


要获取最小和最大坐标值:

x_min = Double.parseDouble((String) list_all_points.get(0).get(0));
x_max = Double.parseDouble((String) list_all_points.get(0).get(0));
y_min = Double.parseDouble((String) list_all_points.get(0).get(1));
y_max = Double.parseDouble((String) list_all_points.get(0).get(1));
for(StorableData s : list_all_points) {
    if(Double.parseDouble((String) s.get(0)) < x_min) {
        x_min = Double.parseDouble((String) s.get(0));
    }
    if(Double.parseDouble((String) s.get(0)) > x_max) {
        x_max = Double.parseDouble((String) s.get(0));
    }

    if(Double.parseDouble((String) s.get(1)) < y_min) {
        y_min = Double.parseDouble((String) s.get(1));
    }
    if(Double.parseDouble((String) s.get(1)) > y_max) {
        y_max = Double.parseDouble((String) s.get(1));
    }
}

画一个点:

int x, y;
private void drawPoint(Cupple storable_data) {
    //x = (int) (storable_data.getNumber(0) * scaling_coef + move_x);
    //y = (int) (storable_data.getNumber(1) * scaling_coef + move_y);
    x = storable_data.getNumber(0).intValue();
    y = storable_data.getNumber(1).intValue();
    graphics.fillRect(x, y, 10, 10);
    graphics.drawString(storable_data.toString(), x - 5, y - 5);
}

绘制图形:

@Override
public void paint(Graphics graphics) {
    this.graphics = graphics;
    Graphics2D graphics_2d = ((Graphics2D) this.graphics);

    AffineTransform affine_transform = graphics_2d.getTransform();
    affine_transform.scale(getWidth()/(x_max - x_min), getHeight()/(y_max - y_min));
    affine_transform.translate(x_min, y_min);
    graphics_2d.transform(affine_transform);

    for(StorableData storable_data : list_all_points) {
        graphics_2d.setColor(Color.WHITE);
        this.drawPoint((Cupple) storable_data);
    }

建议您将每个数据点映射到屏幕上的一个点,从而避免出现以下坐标系陷阱。 获取点列表并从中创建要绘制的点列表。 考虑到:

  • 绘图是基于像素的,因此您将需要缩放点(或者您将拥有1到4像素宽的矩形...)。
  • 您将需要平移所有点,因为负值将超出绘制对象的边界。
  • y轴的方向在图形坐标中反转。

完成后,将新的点列表用于工程图,并将初始的点列表用于计算。 这是一个例子:

public class Graph extends JPanel {

    private static int gridSize = 6;
    private static int scale = 100;
    private static int size = gridSize * scale;
    private static int translate = size / 2;
    private static int pointSize = 10;

    List<Point> dataPoints, scaledPoints;

    Graph() {
        setBackground(Color.WHITE);

        // points taken from your example
        Point p1 = new Point(-1, -2);
        Point p2 = new Point(-1, 0);
        Point p3 = new Point(1, 0);
        Point p4 = new Point(1, -2);
        dataPoints = Arrays.asList(p1, p2, p3, p4);

        scaledPoints = dataPoints.stream()
                .map(p -> new Point(p.x * scale + translate, -p.y * scale + translate))
                .collect(Collectors.toList());
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(size, size);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        // draw a grid
        for (int i = 0; i < gridSize; i++) {
            g2d.drawLine(i * scale, 0, i * scale, size);
            g2d.drawLine(0, i * scale, size, i * scale);
        }

        // draw the rectangle
        g2d.setPaint(Color.RED);
        g2d.drawPolygon(scaledPoints.stream().mapToInt(p -> p.x).toArray(),
                        scaledPoints.stream().mapToInt(p -> p.y).toArray(),
                        scaledPoints.size());

        // draw the points
        g2d.setPaint(Color.BLUE);
        // origin
        g2d.fillRect(translate, translate, pointSize, pointSize);
        g2d.drawString("(0, 0)", translate, translate);
        // data
        for (int i = 0; i < dataPoints.size(); i++) {
            Point sp = scaledPoints.get(i);
            Point dp = dataPoints.get(i);
            g2d.fillRect(sp.x, sp.y, pointSize, pointSize);
            g2d.drawString("(" + dp.x + ", " + dp.y + ")", sp.x, sp.y);
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setContentPane(new Graph());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

在此处输入图片说明

还有一个: 在此处输入图片说明

您可能需要使点在网格交叉点上对齐,而不是在它们的下方和右侧。 我相信您会弄清楚这一点。

另外,我对点进行了排序,以便drawPolygon将以正确的顺序绘制线条。 如果您的点是任意排列的,请寻找找到轮廓的方法。 如果您希望像示例一样在所有点之间drawLine线,请使用drawLine遍历它们的所有组合。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM