Search code examples
javaalgorithmgeometrypointsdivide

Skyline of 2D points-Divide and conquer algorithm


I'm working on a project where I have to find the skyline of the points that are not dominated by any other point in the set. A point A(x1,y1) dominates point B(x2,y2) if x1<=x2 && y1<=y2. Here's an example

This is my code:

public static ArrayList<Point> findSkyline(ArrayList<Point> pointsList){
    if (pointsList.size()<=1){
        return pointsList;
    }

    ArrayList<Point> leftSkylinePoints=new ArrayList<>();
    ArrayList<Point> rightSkylinePoints=new ArrayList<>();
    ArrayList<Point> leftPoints=new ArrayList<>();
    ArrayList<Point> rightPoints=new ArrayList<>();

    for (int i=0;i<pointsList.size()/2;i++){
        leftPoints.add(pointsList.get(i));
    }
    for (int i=pointsList.size()/2;i<pointsList.size();i++){
        rightPoints.add(pointsList.get(i));
    }

    leftSkylinePoints=findSkyline(leftPoints);
    rightSkylinePoints=findSkyline(rightPoints);

    int minY=1001;
    for (int i=0;i<leftSkylinePoints.size();i++){
        if (leftSkylinePoints.get(i).y<minY){
            minY=leftSkylinePoints.get(i).y;
        }
    }
    for (int i=0;i<rightSkylinePoints.size();i++){
        if (rightSkylinePoints.get(i).y>=minY){
            rightSkylinePoints.remove(i);
        }
    }

    System.out.println("MINY: "+minY);

    System.out.print("Left: ");
    for (int i=0;i<leftSkylinePoints.size();i++){
        System.out.print("("+leftSkylinePoints.get(i).x+","+leftSkylinePoints.get(i).y+") ");
    }
    System.out.println();
    System.out.print("Right: ");
    for (int i=0;i<rightSkylinePoints.size();i++){
        System.out.print("("+rightSkylinePoints.get(i).x+","+rightSkylinePoints.get(i).y+") ");
    }
    System.out.println();
    System.out.println();


    leftSkylinePoints.addAll(rightSkylinePoints);
    return leftSkylinePoints;
}

These are the results.

As you can see point (6,2) appears to be in the skyline but it shouldn't be because it should have been deleted in the second for loop. Does anyone know why this is happening? Thanks!

*For more points I get a lot more that shouldn't be there but for now I want to know about this situation.

**Points are sorted based on their x values (ascending)


Solution

  • Ok, I've understood logic flaw. It is here:

     for (int i=0;i<rightSkylinePoints.size();i++){
           if (rightSkylinePoints.get(i).y>=minY){
               rightSkylinePoints.remove(i);
    

    When you remove a point, the rest is shifted left (as far as I understand remove sense), so the next (non-treated yet) item gets current index i and is excluded from further treatment.

    The simplest solutions - use while loop and omit incrementing index if removing occurs.

    Another method - loop from larger indexes to lower ones (seems that such direction should not break algorithm)

     for (int i=rightSkylinePoints.size() -1; i >=0; i--)