我需要一个占据一条线的函数(以其坐标表示) 并返回一行相同角度,但限制为一定长度。
当线路转为'右'时,我的代码会提供正确的值
(经验证明,对不起)。
我错过了什么吗?
public static double getAngleOfLine(int x1, int y1, int x2, int y2) {
double opposite = y2 - y1;
double adjacent = x2 - x1;
if (adjacent == Double.NaN) {
return 0;
}
return Math.atan(opposite / adjacent);
}
// returns newly calculated destX and destY values as int array
public static int[] getLengthLimitedLine(int startX, int startY,
int destX, int destY, int lengthLimit) {
double angle = getAngleOfLine(startX, startY, destX, destY);
return new int[]{
(int) (Math.cos(angle) * lengthLimit) + startX,
(int) (Math.sin(angle) * lengthLimit) + startY
};
}
BTW:我知道在Java中返回数组是愚蠢的,
但这仅仅是为了这个例子。
答案 0 :(得分:3)
将它视为矢量会更容易。通过将其大小除以然后乘以所需长度的因子来归一化它。
但是,在您的示例中,请尝试Math.atan2。
答案 1 :(得分:2)
在Python中,因为我没有方便的Java编译器:
import math
def getLengthLimitedLine(x1, y1, x2, y2, lengthLimit):
length = math.sqrt((x2-x1)**2 + (y2-y1)**2)
if length > lengthLimit:
shrink_factor = lengthLimit / length
x2 = x1 + (x2-x1) * shrink_factor
y2 = y1 + (y2-y1) * shrink_factor
return x2, y2
print getLengthLimitedLine(10, 20, 25, -5, 12)
# Prints (16.17, 9.71) which looks right to me 8-)
答案 2 :(得分:1)
如果您了解有关矢量的内容,这是一个简单的问题。
给定两个点(x1,y1)和(x2,y2),可以计算从第1点到第2点的向量:
v12 =(x2-x1)i +(y2-y2)j
其中i和j是x和y方向的单位向量。
您可以通过获取组件的平方和的平方根来计算v的大小:
v = sqrt((x2-x2)^ 2 +(y2-y1)^ 2)
从点1到点2的单位矢量等于v12除以其幅度。
鉴于此,你可以通过将单位向量乘以长度并将其加到第1点来计算单位向量上所需距离的点。
答案 3 :(得分:1)
在一个类中封装Line,添加一个单位方法和一个缩放方法。
public class Line {
private float x;
private float y;
public Line(float x1, float x2, float y1, float y2) {
this(x2 - x1, y2 - y1);
}
public Line(float x, float y) {
this.x = x;
this.y = y;
}
public float getLength() {
return (float) Math.sqrt((x * x) + (y * y));
}
public Line unit() {
return scale(1 / getLength());
}
public Line scale(float scale) {
return new Line(x * scale, y * scale);
}
}
现在你可以通过调用
获得任意长度为l的行Line result = new Line(x1, x2, y1, y2).unit().scale(l);
答案 4 :(得分:1)
不需要使用trig,它可能有一些令人讨厌的边缘情况。只需使用类似的三角形:
public static int[] getLengthLimitedLine(int startX, int startY,
int destX, int destY, int lengthLimit)
{
int deltaX = destX - startX;
int deltaY = destY - startY;
int lengthSquared = deltaX * deltaX + deltaY * deltaY;
// already short enough
if(lengthSquared <= lengthLimit * lengthLimit)
return new int[]{destX, destY};
double length = Math.sqrt(lengthSquared);
double newDeltaX = deltaX * lengthLimit / length;
double newDeltaY = deltaY * lengthLimit / length;
return new int[]{(int)(startX + newDeltaX), (int)(startY + newDeltaY)};
}
答案 5 :(得分:0)
只需使用Pythagorean theorem,就像这样:
public static int[] getLengthLimitedLine(int start[], int dest[], int lengthLimit) {
int xlen = dest[0] - start[0]
int ylen = dest[1] - start[1]
double length = Math.sqrt(xlen * xlen + ylen * ylen)
if (length > lengthLimit) {
return new int[] {start[0], start[1],
start[0] + xlen / lengthLimit,
start[1] + ylen / lengthLimit}
} else {
return new int[] {start[0], start[1], dest[0], dest[1];}
}
}