如何使用坐标很少的AffineTransform? [英] How to use AffineTransform with very little coordinates?

查看:105
本文介绍了如何使用坐标很少的AffineTransform?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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



我正尝试使用 Graphics2D AffineTransform 来做到这一点。


  1. I得到所有X坐标的最小值

  2. 我得到所有Y坐标的最小值

  3. 我得到所有X坐标的最大值坐标

  4. 获得所有Y坐标的最大值

  5. 获得距离 xmax-xmin ymax-ymin

  6. 然后,我在下面编写了代码。






屏幕截图



有些几天前,使用我自己的方法进行缩放,我得到了以下图形:


(因此,正如我所解释的,Y是倒置的,不是好东西)



目前,即使用下面提供的代码,我只有一点占据了图表的 all 位!一点都不好。



我想拥有:



(无行) ,并且没有图形的轴。这里重要的是根据点的坐标正确显示点。)






代码



获取最小和最大坐标值:

  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)* scale_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 轴的方向相反。



完成后,将新的点列表用于图形,将初始的点列表用于计算。下面是一个示例:

 公共类图扩展了JPanel {

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

List< Point> dataPoints,scaledPoints;

Graph(){
setBackground(Color.WHITE);

//从示例中获取的点
Point p1 = new Point(-1,-2);
点p2 =新点(-1,0);
点p3 =新点(1,0);
点p4 =新点(1,-2);
dataPoints = Arrays.asList(p1,p2,p3,p4);

scaledPoints = dataPoints.stream()
.map(p-> new Point(px *标度+翻译,-py *标度+翻译))
.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;

//为(int i = 0; i {
g2d.drawLine(i * scale,0,i * scale,尺寸);
g2d.drawLine(0,i *比例尺,尺寸,i *比例尺);
}

//绘制矩形
g2d.setPaint(Color.RED);
g2d.drawPolygon(scaledPoints.stream()。mapToInt(p-> px).toArray(),
scaledPoints.stream()。mapToInt(p-> py).toArray(),
scaledPoints.size());

//绘制点
g2d.setPaint(Color.BLUE);
//原始
g2d.fillRect(翻译,翻译,pointSize,pointSize);
g2d.drawString((0,0),翻译,翻译);
//数据
for(int i = 0; i< dataPoints.size(); i ++){
Point sp = scaledPoints.get(i);
点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 遍历它们的所有组合。


I have a set of two dimensions points. Their X and Y are greater than -2 and lesser than 2. Such point could be : (-0.00012 ; 1.2334 ).

I would want to display these points on a graph, using rectangles (a rectangle illustrates a point, and has its coordinates set to its point's ones - moreover, it has a size of 10*10).

Rectangles like (... ; Y) should be displayed above any rectangles like (... ; Y-1) (positive Y direction is up). Thus, I must set the graph's origin not at the top-left hand-corner, but somewhere else.

I'm trying to use Graphics2D's AffineTransform to do that.

  1. I get the minimal value for all the X coordinates
  2. I get the minimal value for all the Y coordinates
  3. I get the maximal value for all the X coordinates
  4. I get the maximal value for all the Y coordinates
  5. I get the distance xmax-xmin and ymax-ymin
  6. Then, I wrote the code I give you below.


Screenshots

Some days ago, using my own method to scale, I had this graph:
(so as I explained, Y are inverted and that's not a good thing)

For the moment, i.e., with the code I give you below, I have only one point that takes all the graph's place! Not good at all.

I would want to have:

(without lines, and without graph's axis. The important here is that points are correctly displayed, according to their coordinates).


Code

To get min and max coordinates value:

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

To draw a point:

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

To paint the graph:

@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);
    }

解决方案

I suggest you map each data point to a point on the screen, thus avoiding the following coordinate system pitfalls. Take your list of points and create from them a list of points to draw. Take into account that:

  • The drawing is pixel-based, so you will want to scale your points (or you would have rectangles 1 to 4 pixels wide...).
  • You will need to translate all your points because negative values will be outside the boundaries of the component on which you draw.
  • The direction of the y axis is reversed in the drawing coordinates.

Once that is done, use the new list of points for the drawing and the initial one for calculations. Here is an example:

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

And another:

You might want to have the points aligned on the grid intersections and not below and to the right of them. I trust you will figure this one out.

Also, I ordered the points so that drawPolygon will paint the lines in the correct order. If your points are arbitrarily arranged, look for ways to find the outline. If you want lines between all points like in your example, iterate over all combinations of them with drawLine.

这篇关于如何使用坐标很少的AffineTransform?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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