找到凸包的内部点而不先计算船体

时间:2015-03-21 04:13:54

标签: java algorithm list convex-hull

我试图使用四个嵌套的四个环来计算凸包的内部点。但是,这给了我正确的坐标,但这些重复了很多次。我不确定我做错了什么。

以下是我的方法

public final List<Point> interiorPoints(List<Point> TestPoints){
        int n = points.size();

        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                if(j != i){
                    for(int k = 0; k < n; k++){
                        if(k != j && j != i && i != k){
                            for(int L = 0; L < n; L++){
                                if(L != k && k != j && j != i && i != k && L != i && L != j){
                                    if(pointIsInsideTriangle(points.get(i), points.get(j), points.get(k), points.get(L)) == true){
                                        InsidePoints.add(points.get(L));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return InsidePoints;
    }

如果点L位于三角形i,j,k

内,则方法pointIsInside返回true

当我使用以下几点测试时:

        TestPoints.add(new Point(300,200));
        TestPoints.add(new Point(600,500));
        TestPoints.add(new Point(100,100));
        TestPoints.add(new Point(200,200));
        TestPoints.add(new Point(100,500));
        TestPoints.add(new Point(600,100));

我得到了

(200.0, 200.0)
(200.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(200.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)
(200.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(200.0, 200.0)
(200.0, 200.0)
(200.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(300.0, 200.0)
(200.0, 200.0)
(300.0, 200.0)

这只是(200.0,200.0)和(300.0,200.0),但我不知道如何解决这个问题。

这是我实现此方法的伪代码。

Algorithm: INTERIOR POINTS
for each i do
      for each j = i do
           for each k = j = i do
       for each L = k = j = i do 
        if pL in triangle(pi, pj, pk)
            then pL is non extreme

这是我的点类

public class Point 
{
    private final double x, y;

    public Point(double x, double y)
    {
        this.x = x;
        this.y = y;
    }

    public double getX() 
    {
        return x;
    }

    public double getY()
    {
        return y;
    }

    public void setX(double x)
    {
        return this.x;
    }

    public void setY(double y)
    {
        return this.y;
    }

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (!(obj instanceof Point)) {
        return false;
    }
    Point other = (Point) obj;
    EqualsBuilder equalsBuilder = new EqualsBuilder();
    equalsBuilder.append(x, other.x);
    equalsBuilder.append(y, other.y);
    return equalsBuilder.isEquals();
}

@Override
public int hashCode() {
    HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
    hashCodeBuilder.append(x);
    hashCodeBuilder.append(y);
    return hashCodeBuilder.toHashCode();
}
}

以下是我在课堂内的观点

public boolean pointIsInsideTriangle(Point P, Point Q, Point r, Point t) {

        final double sum;
        //Area of triangle PQr
        double Area_PQr = AreaOfTriangle(P, Q, r);

        // Area of triangle PQr
        double Area_tQr = AreaOfTriangle(t, Q, r);

        // Area of triangle PQr
        double Area_Ptr = AreaOfTriangle(P, t, r);

        // Area of triangle PQr
        double Area_PQt = AreaOfTriangle(P, Q, t);

        // sum of Area_tQr, Area_Ptr and Area_PQt
        sum = Area_tQr + Area_Ptr + Area_PQt;

        if (Area_PQr == sum) {
            System.out.println("Point t Lies inside the triangle");
            return true;
        }

        System.out.println("Point t does not Lie inside the triangle");
        return false;
    }

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

在您的示例中,点(200, 200)位于三个三角形内部,由点定义:

[(100, 100), (100, 500), (300, 200)]
[(100, 100), (100, 500), (600, 100)]
[(100, 100), (100, 500), (600, 500)]

请注意,上述三角形的点的任何排列都代表相同的三角形。这意味着每次(200, 200) L == 3ij的值都是k时,[2, 4, 0] [2, 4, 5] [2, 4, 1] 会被添加到您的列表中:

n

n!元素的排列数由6 + 6 + 6 = 18给出,因此我们会(200, 200)InsidePoints列出(200, 200)列表。如果算一算,您会看到 18是(300, 200)在输出中出现的确切次数。同样的理由适用于InsidePoints

如果您需要每个点在结果中只显示一次,则可以通过Set List而不是Set<Point> InsidePoints = new HashSet<>(); 轻松实现此目的:

equals()

当然,您还需要为hashCode()课程实施PointInsidePoints。你仍然在做很多无用的计算。

为了提高代码效率,除了将Set转换为j之外,您还可以检查每个三角形内是否只有一个点。这意味着kfor (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { for (int k = j + 1; k < n; k++) { for (int L = 0; L < n; L++) { if (L != i && L != j && L != k) { if (pointIsInsideTriangle( points.get(i), points.get(j), points.get(k), points.get(L))) { InsidePoints.add(points.get(L)); } } } } } } 应该从比前一个索引更大的值开始,如下所示:

i

要检查这是否有效,您只需为每次迭代打印jk和{{1}}的值,并验证没有行是另一行的排列。