1

我正在编写一个小应用程序,允许用户绘制多个形状,然后删除或调整它们的大小。它在矩形和椭圆形上完美运行,但我遇到了线条问题。

这是我编写的用于查找屏幕上单击的位置是否是特定行的一部分的方法:

    public boolean containsLocation(int x, int y) {
    int m = (getY2() - getY()) / (getX2() - getX());
    int b = getY() - (m * getX());
    if (y == (m * x) +  b) {
        return true;
    }
    return false;

我正在使用著名的y = mx + b公式并替换yx,这是单击点的坐标,以查找单击的点是否是线的一部分。

使用 getX()、getY() 和 getX2()、getY2() 方法确定原始坐标

问题是当我点击屏幕删除线条时,它只有在我点击线条开始的第一个坐标(x,y)时才有效。

当我单击沿线的其他任何位置时,什么也没有发生。

由于数学不是最强的西装,任何人都可以阐明我做错了什么吗?

这是我的全班课程:

    public class Line extends Shape{

private int x2, y2; 

public Line (int x, int y, int x2, int y2, Color lineColor) {
    super(x, y, lineColor);
    this.x2 = x2;
    this.y2 = y2;
}

public void draw(Graphics g) {
    g.setColor(getLineColor());
    g.drawLine(getX(), getY(), getX2(), getY2());

}

@Override
public boolean containsLocation(int x, int y) {
    int m = (getY2() - getY()) / (getX2() - getX());
    int b = getY() - (m * getX());
    if (y == (m * x) +  b) {
        return true;
    }
    return false;
}

public int getX2() {
    return x2;
}

public void setX2(int x2) {
    this.x2 = x2;
}

public int getY2() {
    return y2;
}

public void setY2(int y2) {
    this.y2 = y2;
}

}

这是 Line 扩展的 Shape 类:

    public abstract class Shape {
    private int x, y;
    private Color lineColor;

     public Shape(int x, int y, Color lineColor) {
    this.x = x;
    this.y = y;
    this.lineColor = lineColor;
    }

    public abstract void draw(Graphics g);
    public abstract boolean containsLocation(int x, int y);

    public int getX() {
    return x;
    }

    public void setX(int x) {
    this.x = x;
    }

    public int getY() {
    return y;
    }

    public void setY(int y) {
    this.y = y;
    }

    public Color getLineColor() {
    return lineColor;
    }

    public void setLineColor(Color lineColor) {
    this.lineColor = lineColor;
    }

    }

这是调用 containsLocation 的方法:

    public Shape shapeFinder(int x, int y){
    for (int i = shapes.size()-1; i >=0; i--){
        if (shapes.get(i).containsLocation(x, y)){
            return shapes.get(i);
        }
    }

    return null;

}

这是应该删除线的方法(它适用于椭圆和矩形):

    public void mousePressed(MouseEvent e) {
    if (model.getAction() == Model.REMOVE) {
            startX = e.getX();
            startY = e.getY();
            shape = model.shapeFinder(startX, startY);
            if (shape != null) {
                model.getShape().remove(model.shapeFinder(startX, startY));
            } 
4

2 回答 2

2

您正在使用整数除法来计算斜率。我使用了 (100,100) 到 (120, 153) 的示例,它给了我 2 的斜率。它应该是 2.65 的斜率。

但无论如何,你永远不会在我的行中间找到任何整数点 - 我的行中没有 x 和 y 都是整数的点。如果您正确计算斜率,您将能够识别端点,但您需要找到另一种计算中间点的方法。也许在您的方法中引入某种 epsilon?

于 2013-11-01T16:07:01.817 回答
1

实际上,您需要使用 Math.atan2 之类的东西来计算线的方向(以弧度为单位的角度)。然后,您可以对线的一个点应用反向旋转,以另一点为中心,以及鼠标坐标。你的线现在是水平线,所以检查鼠标是否在它上面是直截了当的。

请参阅旋转矩阵。

public class LineDemo {
    public static void main(String[] args) {
        System.out.println(containsLocation(50, 75, 50, 50, 50, 100));
    }

    public static boolean containsLocation(int x, int y, int x1, int y1, int x2, int y2) {
        double dy = y2 - y1;
        double dx = x2 - x1;
        double dist = Math.sqrt(dx*dx + dy*dy);

        double angle = Math.atan2(dy, dx);
        double cos = Math.cos(-angle);
        double sin = Math.sin(-angle);

        double xRot = (x - x1) * cos - (y - y1) * sin;
        double yRot = (x - x1) * sin + (y - y1) * cos;

        // Actually, I only rotated the mouse point, since
        // I can use the first point of the line and its
        // euclidian distance to know where the rotated
        // second point would end.

        if (0 <= xRot && xRot <= dist) {
            double tolerance = 3; // distance tolerance in pixels

            if (Math.abs(yRot) <= tolerance) {
                return true;
            }
        }

        return false;
    }
}
于 2013-11-01T16:02:21.273 回答