我正在编写一个小应用程序,允许用户绘制多个形状,然后删除或调整它们。它完美地适用于矩形和椭圆形,但我遇到线条问题。
这是我写的一个方法,用于查找屏幕上点击的点是否是特定行的一部分:
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 公式并替换 y 和 x ,这是当场点击的坐标,查找点击的点是否是该行的一部分。
使用getters getX(),getY()和getX2(),getY2()
确定原始坐标问题是当我点击屏幕去除线条时,它只有在我点击线条开始的第一个坐标(x,y)时才有效。
当我点击该行的其他任何地方时,没有任何反应。
由于数学不是最强的诉讼,任何人都可以解释我做错了吗?
这是我的Line全班:
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));
}
答案 0 :(得分:2)
您使用整数除法来计算斜率。我使用了(100,100)到(120,153)的例子,它给了我一个2的斜率。它应该是2.65的斜率。
但无论如何,你永远不会在我的线中间找到任何整数点 - 我的线上没有点,x和y都是整数。如果您正确计算斜率,您将能够识别端点,但您需要找到一种不同的计算中间点的方法。也许在你的方法中引入某种epsilon?
答案 1 :(得分: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;
}
}