找到离线最远的点

时间:2012-02-23 18:27:04

标签: java algorithm convex-hull

我有一系列积分,还有两个积分(A和B)。最后两个点形成一条线,我试图找到我的阵列中的哪个点距离线最远。我怎么用Java做这个?

我想知道这是否与寻找A和B的距离有关,但这并不适合我。

其他信息: 我认为这是一个线段。鉴于这是QuickHull,我不知道它是否有所作为。 在数学和公式方面,我从来都不是最好的,所以更多的解释更好。谢谢!

6 个答案:

答案 0 :(得分:2)

请注意,数组中每个[a,b,p]的每3分p形成一个trianle,其区域表示为:(ab) * h /2 [其中h是距离p {1}}到ab]

您可以compute the area创建这些trianles,选择最小值。由于ab对所有人来说都是常数 - 它保证具有最小区域的trianle也将具有最小h

您可以使用

找到[每个三角形的区域]
T=(1/2)* abs((x_a - x_p) * (y_b-y_a) - (x_a - x_b)* (y_p - y_a))

[其中x_a,x_b,x_py_a,y_b,y_p分别是x,y的{​​{1}}坐标。

  • 虽然我发现这种方法非常优雅,但我相信还有更好的方法 如何做到这一点。

答案 1 :(得分:1)

    ArrayList<Point> points=new ArrayList();//YOUR POINTS


    Point a=new Point(1,1);
    Point b=new Point(1,1);
    Point ABcenter=new Point((a.x+b.x)/2,(a.y+b.y)/2);//THE CENTER OF THE A AND B POINTS ,USE A OR B IF YOU WANT
    int furthestid=0;
    float furthestdis=0;
    for(int c=0;c<points.size();c++)
    {
        if(calculate_distance(ABcenter.x,ABcenter.y,points.get(c).x,points.get(c).y)>furthestdis)
        {
            furthestid=c;
        }
    }

//closestid  now contains the id of the furthest point ,use it like this points.get(c).x ...




public static double calculate_distance (float x1,float y1,float x2 ,float y2){
        return Math.sqrt((((x1-x2) * (x1-x2)) + ((y1- y2) * (y1- y2))));
}

答案 2 :(得分:0)

我假设你在谈论线段而不是线。首先,您应该找到距线段的点距离,然后按照this similar question中建议的方式,在找到所有输入的最小/最大距离后,您可以这样做。

编辑:同样来自this top coder article,您只需找到距离:

//Compute the dot product AB ⋅ BC
int dot(int[] A, int[] B, int[] C){
    AB = new int[2];
    BC = new int[2];
    AB[0] = B[0]-A[0];
    AB[1] = B[1]-A[1];
    BC[0] = C[0]-B[0];
    BC[1] = C[1]-B[1];
    int dot = AB[0] * BC[0] + AB[1] * BC[1];
    return dot;
}
//Compute the cross product AB x AC
int cross(int[] A, int[] B, int[] C){
    AB = new int[2];
    AC = new int[2];
    AB[0] = B[0]-A[0];
    AB[1] = B[1]-A[1];
    AC[0] = C[0]-A[0];
    AC[1] = C[1]-A[1];
    int cross = AB[0] * AC[1] - AB[1] * AC[0];
    return cross;
}
//Compute the distance from A to B
double distance(int[] A, int[] B){
    int d1 = A[0] - B[0];
    int d2 = A[1] - B[1];
    return sqrt(d1*d1+d2*d2);
}
//Compute the distance from AB to C
//if isSegment is true, AB is a segment, not a line.
double linePointDist(int[] A, int[] B, int[] C, boolean isSegment){
    double dist = cross(A,B,C) / distance(A,B);
    if(isSegment){
        int dot1 = dot(A,B,C);
        if(dot1 > 0)return distance(B,C);
        int dot2 = dot(B,A,C);
        if(dot2 > 0)return distance(A,C);
    }
    return abs(dist);
}

我认为代码有自我解释,如果你熟悉基本几何,但如果你不熟悉,你应该阅读这篇文章,如果你有什么问题我们可以帮助你。

答案 3 :(得分:0)

我假设你的意思是欧几里德距离。如果你在飞机上工作,那么答案很简单。

首先,以

的形式计算线的方程
ax + by + c = 0

在斜率截距形式中,这与

相同
y = (-a/b)x + (-c/b)

现在计算从任意点(p,q)到线的距离

|a*p + b*q + c| / (a^2 + b^2)^(1/2)

对于超过2个维度,从参数化向量的角度来考虑可能最容易。这意味着将线上的点视为

p(t) = (A1 + (B1-A1)*t, A2 + (B2-A2)*t, ..., An + (Bn-An)*t)

这两点是A = (A1,...,An)B = (B1,...,Bn)。让X = (X1,...,Xn)成为任何其他观点。然后,Xp(t)之间的距离(对应于t的行上的点)是

的平方根
[(A1-X1) + (B1-A1)t]^2 + ... + [(An-Xn) + (Bn-An)t]^2

到该行的距离是到p(t)的距离,其中t是最小化此距离的唯一值。要计算出来,只需采用相对于t的导数并将其设置为0。这是一个非常直截了当的问题,所以我会留给你一点。

如果您想进一步提示,请查看this link以查看三维情况,该情况会很好地减少。

答案 4 :(得分:0)

我快速谷歌搜索运作良好。

http://www.codeguru.com/forum/printthread.php?t=194400

答案 5 :(得分:0)

如果问题是你所说的那样,你就不能做得更好,然后计算每个点的距离并选择其中最小的一个。

但是,您可以通过使用通过A和B的直线的广义线方程来简化距离的计算。这将是ax + by + c = 0

形式的等式

您可以非常轻松地计算通过两个任意点的直线的等式:

x * (A.y - B.y) + y * (B.x - A.x) + A.x * B.y - A.y * B.x

即。 a = A.y - B.yb = B.x - A.xc = A.x * B.y - A.y * B.x

现在您已经为线计算了这样的等式,您可以通过用坐标P代替x和y来计算从平面中任意点P到线a * x + b * y + c的距离:

abs(a * P.x + b * P.y + c) / sqrt(a * a + b * b)。但由于分母对于所有点都是相同的,你可能会对其进行igonore而只选择abs(a * P.x + b * P.y + c)最小的点

这是一个link,解释了如何计算一条直线的二维距离。