1. 判断点和线的位置关系

    向量叉积是用来判断两个向量之间方向的
    他的计算方法如下:
    ccw - 图1
    假设两个向量分别为a-> =(x1,y1),b-> =(x2,y2),则a向量 与b向量 的叉积如下定义:
    a ×b =x1⋅y2−x2⋅y1
    其中,符号×用来表示向量叉积运算。而a向量 和b向量 都是以坐标原点为起点,以上面给出的坐标:(x1,y1), (x2,y2 为终点的两个向量。

    根据这个叉积的算法,我们不难得到以下规律:
    若a ×b >0,则a 在b 的顺时针方向
    若a ×b <0,则a 在b 的逆时针方向
    若a ×b =0,则a 与b 共线

    a x b = |a|.|b|.sinθ
    = x1.y2 - x2.y1
    例如:
    三个点: A:(x1,y1) B**:(x2,y2) C**:(x3,y3)
    判断点 C 在 向量 AB 的左边还是右边?
    交叉想成法 :
    x1 x2 x3 x1
    y1 y2 y3 y1
    AB x AC = (x1y2 + x2y3 + x3y1) -(y1x2 + y2x3 + y3x1)
    当 >0 时 ,则 C 点在 AB 的左侧

    1. static class Point{
    2. double x,y;
    3. public Point(double x,double y) {
    4. this.x = x;
    5. this.y = y;
    6. }
    7. }
    8. //ccw
    9. private static int CCW(Point p1, Point p2, Point p3) {
    10. return (p1.x*p2.y+p2.x*p3.y+p3.x*p1.y)-(p1.y*p2.x+p2.y*p3.x+p3.y*p1.x) >0? 1:-1;
    11. }

    例题: POJ_1912 CCW算法 http://poj.org/problem?id=1912

    package jihe;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Stack;
    import java.util.StringTokenizer;
    /**
     * poj_1912
     * @author Administrator
     */
    public class CCW_1912 {
        public static Point[] p;
        public static Point[] LineP;
        public static Point entry;
        public static Point entry2;
        public static Stack<Point> stack;
        public static List<Point> arrayList;
        public static int N;
        public static double X;
        public static double Y;
        public static double PX;
        public static double PY;
        public static double LSX;
        public static double LSY;
        public static double LEX;
        public static double LEY;
        static class Point{
            double x,y;
            public Point(double x,double y) {
                this.x = x;
                this.y = y;
            }
        }
        public static void main(String[] args) throws Exception {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st = new StringTokenizer(br.readLine());
            N = Integer.parseInt(st.nextToken());
            p = new Point[N];
            PX = Integer.MAX_VALUE;
            PY = Integer.MAX_VALUE;
            arrayList = new ArrayList<Point>();
            stack = new Stack<Point>();
            entry = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
    
            for (int i = 0; i < N; i++) {
                st = new StringTokenizer(br.readLine());
                X = Double.parseDouble(st.nextToken());
                Y = Double.parseDouble(st.nextToken());
                if ((entry.y > Y) || (entry.y == Y && (entry.x > X))) {
                    entry.y = Y;
                    entry.x = X;
                }
                Point p = new Point(X, Y);
                arrayList.add(p);
            }
            for (int i = 0; i < arrayList.size(); i++) {
                Point tp = arrayList.get(i);
                if (tp.x != entry.x || tp.y != entry.y) {
                    stack.push(tp);
                }
            }
    //        stack.push(entry);
            for (int i = 0; i < N; i++) {
                Collections.sort(stack, new Comparator<Point>() {
                    @Override
                    public int compare(Point p1, Point p2) {
                        if (CCW(entry, p1, p2) > 0) {
                            return 1;
                        } else if (CCW(entry, p1, p2) < 0) {
                            return -1;
                        } else {
                            double a = (p2.x - entry.x) * (p2.x - entry.x) + (p2.y - entry.y) * (p2.y - entry.y);
                            double b = (p1.x - entry.x) * (p1.x - entry.x) + (p1.y - entry.y) * (p1.y - entry.y);
                            return (int) (a - b);
                        }
                    }
                });
                entry2 = stack.pop();
                entry2 = stack.peek();
                if (entry2.x == entry.x && entry2.y == entry.y) {
                    break;
                }else {
                    p[i] = entry2;
                }
            }
    
            while (br.ready()) {
                LineP = new Point[2];
                st = new StringTokenizer(br.readLine());
                LSX= Double.parseDouble(st.nextToken());
                LSY= Double.parseDouble(st.nextToken());
                LEX= Double.parseDouble(st.nextToken());
                LEY= Double.parseDouble(st.nextToken());
                LineP[0] = new Point(LSX, LSY);
                LineP[1] = new Point(LEX, LEY);
                int res = CCW(LineP[0],LineP[1],p[0]);
                for (int i = 1; i < p.length; i++) {
                    int resNew = CCW(LineP[0],LineP[1],p[i]);
                    if (res != resNew) {
                        System.out.println("BAD");
                        break;
                    }
                    if (i == p.length-1 && res == resNew) {
                        System.out.println("GOOD");
                    }
                }
            }
    
        }
        //ccw
        private static int CCW(Point p1, Point p2, Point p3) {
            return (p1.x*p2.y+p2.x*p3.y+p3.x*p1.y)-(p1.y*p2.x+p2.y*p3.x+p3.y*p1.x) >0? 1:-1;
        }
    }