凸面外壳中的额外点(使用graham扫描)错误+;JAVA

凸面外壳中的额外点(使用graham扫描)错误+;JAVA,java,convex,grahams-scan,Java,Convex,Grahams Scan,我的代码使用graham算法来查找凸包,它运行得非常好(它向我显示了它应该显示的多边形),但我可以看到它向我发送了一个额外的共线点(尽管我在代码中处理共线点) 这是我的密码: public Collection<Coord> territoire() { double checkPoints; Collection<Coord> sommets = new ArrayList<Coord>(this);

我的代码使用graham算法来查找凸包,它运行得非常好(它向我显示了它应该显示的多边形),但我可以看到它向我发送了一个额外的共线点(尽管我在代码中处理共线点) 这是我的密码:

    public Collection<Coord> territoire()
    {
        double checkPoints;
        Collection<Coord> sommets = new ArrayList<Coord>(this);
        Stack<Coord> stackOfConvexHull = new Stack<Coord>();
        ArrayList<Coord> thisToArrList = new ArrayList<Coord>();
        for(Coord c : this)
            thisToArrList.add(c);


        //sorting the array by Y
        ArrayList<Coord> sortedPointsByY = sortedArrayByY(thisToArrList); 

        //sorting the set of points with increasing order of angle
        // they and the base point (basePoint) make with X axis 
        List<Coord> sortedPointsByAngle = new ArrayList<Coord>(sortPointsByAngle(sortedPointsByY));

        if(sortedPointsByAngle.size() < 3)
            System.out.println("the convex hull of less than 3 points is not possible");
        if(collinear(sortedPointsByAngle)) 
            System.out.println("can't make a convex hull of collinear points");


        stackOfConvexHull.push(sortedPointsByAngle.get(0));
        stackOfConvexHull.push(sortedPointsByAngle.get(1));

            for (int i = 2; i < sortedPointsByAngle.size(); i++) 
            {

                Coord p1 = sortedPointsByAngle.get(i);
                Coord p2 = stackOfConvexHull.pop();
                Coord p3 = stackOfConvexHull.peek();

                checkPoints = ccw(p3, p2, p1);

                // counter-clockwise
                if(checkPoints > 0) 
                {
                    stackOfConvexHull.push(p2);
                    stackOfConvexHull.push(p1);
                }

                // collinear
                if(checkPoints == 0)
                    stackOfConvexHull.push(p1);

                // clockwise
                else
                    i--;
            }

            // end of the hull
            stackOfConvexHull.push(sortedPointsByAngle.get(0));
            sommets = new ArrayList<Coord>(stackOfConvexHull);

        return sommets;

    }

//**********************************Auxiliary méthods****************************************************

                            //***** sorting points by Y and angles *****

    //sorting the points by their y in ascending order
    public ArrayList<Coord> sortedArrayByY(ArrayList<Coord> arrayOfPoints)
    {
        Coord temp = null;
        for(int i = 0; i< arrayOfPoints.size(); i++)
        { 
            for(int j = 0; j< arrayOfPoints.size()-1; j++)
            {
                if(arrayOfPoints.get(j+1).y < arrayOfPoints.get(j).y)
                {
                    temp = arrayOfPoints.get(j+1);
                    arrayOfPoints.set(j+1, arrayOfPoints.get(j));
                    arrayOfPoints.set(j, temp);  
                }
            }
        }
        return arrayOfPoints;
    }


    public Set<Coord> sortPointsByAngle(ArrayList<Coord> points) 
    {
        int min = minYIndex(points);
        final Coord basePoint = points.get(min);

        TreeSet<Coord> set = new TreeSet<Coord>(new Comparator<Coord>() 
        {
            public int compare(Coord a, Coord b) {

                if(a == b || a.equals(b))
                    return 0;

               double firstAngle = angle(basePoint, a);
               double secondAngle = angle(basePoint, b);

                if(firstAngle < secondAngle) 
                    return -1;

                else if(firstAngle > secondAngle) 
                    return 1;

                else 
                {
                    // collinear with the 'basePoint' point, let the point closest to it come first
                    double firstDistance = findDistance(basePoint, a);
                    double secondDistance = findDistance(basePoint, b);

                    if(firstDistance < secondDistance) 
                        return -1;    

                    else 
                        return 1;
                }
            }
        });

        set.addAll(points);
        return set;
    }


    // find the buttom most point (minimum Y)
    // if If the lowest y-coordinate exists in 
    // more than one point in the set, the point with the one with the lowest x-coordinate 
    // will be chosen

    public int minYIndex(ArrayList<Coord> sortedPointsByY)
    {   
        int min = 0;
        for ( int i = 1; i < sortedPointsByY.size(); i++ ) // O(n) => n number of points
        {
            if ( sortedPointsByY.get(i).y == sortedPointsByY.get(min).y) 
            {
                if ( sortedPointsByY.get(i).x < sortedPointsByY.get(min).x)
                    min = i;
            }
            else if ( sortedPointsByY.get(i).y < sortedPointsByY.get(min).y)
                min = i;
        }
        return min;
    }

    public double angle(Coord basePoint, Coord a) 
    {
        return Math.atan2(a.y - basePoint.y, a.x - basePoint.x);
    }


    public double findDistance(Coord basePoint, Coord a)
    {
        return Math.sqrt(((basePoint.x - a.x) * (basePoint.x - a.x)) + 
                ((basePoint.y - a.y) * (basePoint.y - a.y)));
    }


    //if the result is zero, the point is collinear 
    //if it is positive, the three points constitute left turn (counter clockwise)
    //else the three points constitute right turn (clockwise)    
    public double ccw(Coord p1, Coord p2, Coord p3)
    {
        return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x);
    }

 // check if the points are collinear   
    public boolean collinear(List<Coord> sortedPointsByAngle) 
    {

        Coord a, b, c;
        if(sortedPointsByAngle.size() < 2) 
            return true;

        a = sortedPointsByAngle.get(0);
        b = sortedPointsByAngle.get(1);

        for(int i = 2; i < sortedPointsByAngle.size(); i++) 
        {

            c = sortedPointsByAngle.get(i);

            if(ccw(a, b, c) != 0) 
                return false;
        }

        return true;
    }
public Collection territoire()
{
双重检查站;
Collection sommets=new ArrayList(this);
Stack stackOfConvexHull=新堆栈();
ArrayList thisToArrList=新建ArrayList();
对于(Coord c:此)
这是ToArrList。添加(c);
//按Y排序数组
ArrayList SortedPointsBy=SortedDarrayByy(此ToArrList);
//按角度的递增顺序对点集进行排序
//它们和基点(基点)与X轴相交
List SORTDPOINTSBYANGLE=新阵列列表(sortPointsByAngle(SORTDPOINTSBYY));
if(分拣点杨格尺寸()<3)
System.out.println(“不可能有少于3个点的凸包”);
if(共线(分拣点杨格))
System.out.println(“无法生成共线点的凸包”);
Convexhull.push堆栈(sortedPointsByAngle.get(0));
堆栈Convexhull.push(分拣点Yangle.get(1));
对于(int i=2;i0)
{
Convexhull.push堆栈(p2);
Convexhull.push(p1)的堆栈;
}
//共线
如果(检查点==0)
Convexhull.push(p1)的堆栈;
//顺时针
其他的
我--;
}
//船尾
Convexhull.push堆栈(sortedPointsByAngle.get(0));
sommets=新的ArrayList(stackOfConvexHull);
返帽;
}
//**********************************辅助方法****************************************************
//*****按Y和角度对点进行排序*****
//按y按升序对点进行排序
公共阵列列表排序DarrayBy(阵列列表阵列点)
{
坐标温度=null;
对于(int i=0;i第二角度)
返回1;
其他的
{
//与“基点”点共线,让最靠近它的点排在第一位
双第一距离=findDistance(基点,a);
双秒距离=findDistance(基点b);
如果(第一距离<第二距离)
返回-1;
其他的
返回1;
}
}
});
set.addAll(点);
返回集;
}
//找到按钮最远点(最小Y)
//如果最低y坐标存在于
//集合中的多个点,具有最低x坐标的点
//将被选中
公共int最小索引(ArrayList SortedPointsBy)
{   
int min=0;
对于(int i=1;in个点数
{
if(sortedPointsByY.get(i).y==sortedPointsByY.get(min).y)
{
if(sortedPointsByY.get(i).x(p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x)
if (Math.abs(checkPoints) < 0.0000001) // colinear