Java 如何使用坐标很少的仿射变换?

Java 如何使用坐标很少的仿射变换?,java,coordinates,graphics2d,affinetransform,Java,Coordinates,Graphics2d,Affinetransform,我有一组二维点。它们的X和Y大于-2且小于2。这一点可以是:(-0.00012;1.2334) 我想用矩形在图形上显示这些点(矩形表示一个点,并将其坐标设置为其点的坐标-此外,它的大小为10*10) 类似于(…;Y)的矩形应显示在类似于(…;Y-1)的任何矩形上方(正Y方向向上)。因此,我必须将图形的原点设置在其他地方,而不是左上角 我正在尝试使用Graphics2D的AffineTransform来实现这一点 我得到所有X坐标的最小值 我得到所有Y坐标的最小值 我得到所有X坐标的最大值 我得到

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

我想用矩形在图形上显示这些点(矩形表示一个点,并将其坐标设置为其点的坐标-此外,它的大小为10*10)

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

我正在尝试使用
Graphics2D
AffineTransform
来实现这一点

  • 我得到所有X坐标的最小值
  • 我得到所有Y坐标的最小值
  • 我得到所有X坐标的最大值
  • 我得到所有Y坐标的最大值
  • 我得到距离
    xmax xmin
    ymax ymin
  • 然后,我写了下面的代码

  • 屏幕截图

    几天前,我使用自己的方法进行缩放,得到了以下图表:
    (正如我所解释的,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));
        }
    }
    
    要绘制图表,请执行以下操作:

    @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);
        }
    }
    
    公共类图扩展了JPanel{
    私有静态int gridSize=6;
    专用静态整数刻度=100;
    私有静态int size=gridSize*scale;
    私有静态int translate=大小/2;
    私有静态int pointSize=10;
    列出数据点、缩放点;
    图(){
    挫折地面(颜色:白色);
    //从你的例子中得出的观点
    点p1=新点(-1,-2);
    点p2=新点(-1,0);
    点p3=新点(1,0);
    点p4=新点(1,-2);
    dataPoints=Arrays.asList(p1、p2、p3、p4);
    scaledPoints=dataPoints.stream()
    .map(p->新点(p.x*缩放+平移,-p.y*缩放+平移))
    .collect(Collectors.toList());
    }
    @凌驾
    公共维度getPreferredSize(){
    返回新维度(大小、大小);
    }
    @凌驾
    受保护组件(图形g){
    超级组件(g);
    Graphics2D g2d=(Graphics2D)g;
    //画网格
    对于(int i=0;ip.x).toArray(),
    scaledPoints.stream().mapToInt(p->p.y).toArray(),
    scaledPoints.size());
    //划清界限
    g2d.setPaint(颜色:蓝色);
    //起源
    g2d.fillRect(translate,translate,pointSize,pointSize);
    g2d.拉丝(“(0,0)”,翻译,翻译);
    //资料
    对于(int i=0;i

    还有一个:

    您可能希望使点在栅格交点上对齐,而不是在其下方和右侧对齐。我相信你会解决这个问题的


    此外,我还对点进行了排序,以便
    drawPolygon
    能够以正确的顺序绘制线条。如果你的观点是任意排列的,那就想办法找到轮廓。如果你想在所有点之间画线,就像你的例子中那样,用
    drawLine

    迭代所有点的组合。在这种情况下,screeshot将非常有助于理解你当前看到的内容和你想看到的内容。我编辑了我的文章,添加一个截图和我想要的结果我还添加了一些代码我不知道为什么你需要翻译这些点。如果给您准备了一份它们的列表,为什么不直接将它们绘制到它们需要的位置呢?组件的坐标系的原点位于左上角,
    x
    向右为正,
    y
    向下为正。只需将您的
    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);
        }
    }