Multiple Point Polygon Intersection

Problem: Given N points and an L-side (simple but not convex) polygon, find out whether each point is contained entirely inside the polygon or on the border.

Average running time: N log N (In reality, 98% of the running time is spent reading in the data; fast input is necessary for larger problems)

class Point implements Comparable {    double x,y ; public Point(double a, double b) {x = a ; y = b ;} public int compareTo(Point P)    { if (this.y > P.y)            return 1 ; else if (this.y == P.y)            return 0 ; return -1 ; } } class Line {    Point A,B ; public Line(Point a, Point b) {A = new Point(a.x,a.y) ; B = new Point(b.x,b.y) ; } } public class SeveralPointsInPolygon {    public static boolean pointOnLine(Point A, Line B)     { if (B.A.x == B.B.x)        { if (A.x == B.A.x)            { double max = Math.max(B.A.y, B.B.y) ; double min = Math.min(B.A.y, B.B.y) ; if (A.y <= max && A.y >= min) return true ; }            return false ; }        double sl = B.A.y - B.B.y ; sl /= (B.A.x - B.B.x) ; double sl2 = B.A.y - A.y ; sl /= (B.A.x - A.x) ; if (Math.abs(sl-sl2) < 0.000000000001) {            double max = Math.max(B.A.y, B.B.y) ; double min = Math.min(B.A.y, B.B.y) ; if (A.y <= max && A.y >= min) return true ; }        return false ; }    public static void main(String[] args) throws IOException {        Scanner input = new Scanner(new File("out.txt")) ; //BufferedReader in = new BufferedReader(new FileReader(new File("out.txt"))) ; // for several points, may need a buffered reader int numP, numL, T ; T = input.nextInt ; while (T --> 0) {            numP = input.nextInt ; numL = input.nextInt ; Point[] arr = new Point[numP] ; Line[] l = new Line[numL] ; for (int i = 0 ; i < numP ; i ++) {                double temp,temp2 ; temp = input.nextDouble ; temp2 = input.nextDouble ; arr[i] = new Point(temp, temp2) ; }            Point one, two ; one = new Point(input.nextDouble, input.nextDouble) ; for (int i = 0 ; i < numL; i ++) {                two = new Point(input.nextDouble, input.nextDouble) ; l[i] = new Line(one,two) ; one.x = two.x ; one.y = two.y ; }            // sort points by y coord Arrays.sort(arr) ; int[] crN = new int[numP] ; Arrays.fill(crN,0) ; for (int i = 0 ; i < numL ; i ++) {                double min = Math.min(l[i].A.y,l[i].B.y) ; double max = Math.max(l[i].A.y,l[i].B.y) ; int index1,index2 ; Point hax = new Point(0,min) ; Point hax2 = new Point(0,max) ; index1 = Arrays.binarySearch(arr,hax) ; index2 = Arrays.binarySearch(arr,hax2) ; if (index1 < 0) index1 *= -1 ; if (index2 < 0) index2 *= -1 ; double sl = 0 ; if (l[i].A.x != l[i].B.x)                { sl = l[i].A.y - l[i].B.y ; sl /= (l[i].A.x - l[i].B.x) ; }                index1 -- ; index2 +=2 ;  index2 = Math.min(index2,numP-1) ; while (index1 > 0) {                    index1 -- ; if (arr[index1].y < min) break ; }                index1 = Math.max(index1,0) ; for (int j = index1 ; j <= index2 ; j ++) {                    if (pointOnLine(arr[j],l[i])) {                        crN[j] = -1337 ; }                    double Y = arr[j].y ; if (Y <= min || Y > max) continue ; double dx = 0 ; if (l[i].A.x != l[i].B.x)                    { dx = (Y - l[i].A.y)/sl ; }                    double X = l[i].A.x + dx ; if (arr[j].x >= X){ crN[j] ++ ; if (crN[j] < 0) crN[j] = -1337 ;} }            }             int c = 0 ; // counter for number of points inside for (int i = 0 ; i < crN.length ; i ++) {                if (crN[i]%2 != 0 || crN[i] < 0) {                    c ++ ; System.out.println(arr[i].x + " " + arr[i].y + " IN "); }                else {                    System.out.println(arr[i].x + " " + arr[i].y + " OUT "); }            }             System.out.println(c); }    } }