检测矩形中已知点的位置

时间:2016-11-23 08:53:05

标签: java android point

我有一组4个PointF个对象。此数组中的每个点都是一个矩形的角。现在我想根据它们的位置按特定顺序设置该数组中的Points。例如PointF[0]应为topleft点,PointF[1]为leftleft(依此类推,顺时针方向)。

我试图检查坐标,例如如果点x和y坐标是阵列中每个点的最低点,那么它就是一个点(图像坐标系)。如果每个坐标都是最大的,那就是最重要的一点。

该解决方案的问题在于,该阵列中的点也可能表示平行四边形或梯形意义,角落之间的角度不必为90度。

这是一个图像,我试图想象我想要实现的目标:

Example

1 个答案:

答案 0 :(得分:0)

我找到了一个很好的解决方案,适合我的问题。

首先,我尝试检测矩形的左上角和右下角。为此,我从坐标系的源计算二维Vector的长度。 4个向量中最短的是左上角,最右边是右下角。我尝试通过两个已知点的简单坐标检查来检测另外两点。为了避免一个小错误,右上角将通过与左下角相同的检查,我通过x坐标对点进行排序。

以下是代码:

private PointF[] checkPointLocation(PointF[] points){

    double minLength = 100000000;
    double maxLength = 0;
    int minPos = 0;
    int maxPos = 0;

    for(int i = 0; i < points.length; i++){
        double vLength = Math.abs(Math.sqrt((points[i].x * points[i].x) + (points[i].y * points[i].y)));

        if(vLength < minLength) {
            minLength = vLength;
            minPos = i;
        }
        if(vLength > maxLength) {
            maxLength = vLength;
            maxPos = i;
        }
    }

    PointF topLeft = points[minPos];
    PointF bottomRight = points[maxPos];

    Log.d(TAG, "TopLeft: " + topLeft);
    Log.d(TAG, "BottomRight: " + bottomRight);

    PointF topRight = null;
    PointF bottomLeft = null;

    Arrays.sort(points, (o1, o2) -> Float.compare(o1.x, o2.x));

    for(int i = 0; i < points.length; i++){
        PointF p = points[i];
        Log.d(TAG, "Point: " + p);

        if( p.equals(topLeft) || p.equals(bottomRight))
            continue;

        if(bottomLeft == null && p.x < bottomRight.x && p.y > topLeft.y)
            bottomLeft = p;

        if(topRight == null && p.x > topLeft.x && p.y < bottomRight.y)
            topRight = p;
    }

    if(topRight == null){
        throw new NullPointerException("topRight is null");
    }
    if(bottomLeft == null){
        throw new NullPointerException("BottomLeft is null");
    }

    Log.d(TAG, "BottomLeft = " + bottomLeft);
    Log.d(TAG, "TopRight = " + topRight);

    PointF[] ccwPoints = {topLeft, bottomLeft, bottomRight, topRight};

    return ccwPoints;
}

就我而言,这个解决方案适用于所有可能的用户输入。