Convex Hull Algorithm

Convex hull: the smallest polygon that covers all the points in the given set.

Application: Farthest pair problem, shortest Path across the boundary.

Algorithm: Find the point with the lowest y-coordinates p, then iterate through all the points in the order of polar-angle relative to the p. Check if they can form a counter clock wise angle with the previous point, if so include it in the context hull, otherwise discard it. There is a video clip explaining the convex hull algorithm

https://www.youtube.com/watch?v=0HZaRu5IupM

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Stack;
 
 
public class ConvexHull {
    //assume no duplicate points 
    public static void main(String [] args) {
        ArrayList<Point> points = new ArrayList<Point> ();
        points.add(new Point(0, 0));
        points.add(new Point(1, 1));
        points.add(new Point(3, 10));
        points.add(new Point(8, 7));
        points.add(new Point(11, 8));
        points.add(new Point(12, 1));
        ArrayList<Point> result = new ArrayList<Point>();
        //check if there are more than three points in the array
        if (points.size() < 3) {
            System.out.println("Too few points");
            return;
        }
         
        //find the point with the lowest y
        int oIndex = 0;
        for (int i = 1; i < points.size(); i++) {
            if (points.get(i).y < points.get(oIndex).y)
                oIndex = i;
        }
        //remove the origin points and put it into the stack
        final Point origin = points.get(oIndex);
        points.remove(oIndex);
         
        //stack that we use to iterate through the 
        Stack<Point> hullStack = new Stack<Point>();
        hullStack.push(origin); //put origin point in stack
        //sort the points according to their polarity relative to origin
        Collections.sort(points, new Comparator<Point>() {
            @Override
            public int compare(Point p1, Point p2) {
                float polar1 = getPolar(origin, p1);
                float polar2 = getPolar(origin, p2);
                if (polar1 > polar2)
                    return -1;
                else if (polar1 < polar2)
                    return 1;
                return 0;
            }       
        });
        //add origin to as the last element
        points.add(origin);
        for (Point p : points) {
            Point pre = hullStack.pop();
            while(!hullStack.isEmpty() && !isLeftTurn(hullStack.peek(), pre, p)) {
                pre = hullStack.pop();//discard the pre and take new top of the stack as pre
            }
            hullStack.push(pre);
            hullStack.push(p);
        }
        //remove the duplicate origin
        hullStack.pop();
        while(!hullStack.isEmpty()) {
            result.add(hullStack.pop());
        }
    }
     
    private static float getPolar(Point start, Point end) {
        //get the cosin between end and start
        float r = ((end.x - start.x)*(end.x - start.x) + (end.y - start.y)*(end.y - start.y));
        return (float) ((end.x - start.x)/Math.pow(r, 0.5)); 
    }
     
    private static boolean isLeftTurn(Point a, Point b, Point c) {
        if ((c.y - a.y)/(c.x - a.x) > (b.y - a.y)/(b.x - a.x))
            return true;
        return false;
    }
}

  

The above program shows an way get a convex hull from a set of points.
The running time is dominated by the sorting so it is nlogn.

Two things need to pay attention:
1. the original point is the one with the lowest y coordinate. So all the other point was above it. We want the points to be sorted according to the polar angle relative to the original point, in the order of counterclockwise. So we should use cosin which on the uppper part of coordinate system, decrease in the order of counterclock direction.

2. To find out whether we make a left (counter clock wise) turn in a three point a->b->c, there is a simple way. We should check if (c.y – a.y)*(b.x – a.x) – (b.y – a.y)*(c.x – a.x). If it is equals to 0, then a, b and c are on the same line. if positive, it is making a left turn, otherwise it is making a right turn.

 

From:

https://hellosmallworld123.wordpress.com/2014/08/01/convex-hull-algorithm/

你可能感兴趣的:(Convex Hull Algorithm)