// Path: kendzi-math-geometry/src/main/java/kendzi/math/geometry/point/Vector2dUtil.java
// public class Vector2dUtil {
// 
//     private static double EPSILON = 0.00000001;
// 
//     public static Vector2d orthogonalLeft(Vector2d v) {
//         return new Vector2d(-v.y, v.x);
//     }
// 
//     public static Vector2d orthogonalRight(Vector2d v) {
//         return new Vector2d(v.y, -v.x);
//     }
// 
//     public static Vector2d bisector(Point2d p1, Point2d p2, Point2d p3) { // left
//         // XXX rename to bisectorLeft
//         return Vector2dUtil.bisector(Vector2dUtil.fromTo(p1, p2), Vector2dUtil.fromTo(p2, p3));
//     }
// 
//     public static Vector2d bisector(Vector2d v1, Vector2d v2) {
//         // XXX rename to bisectorLeft
//         Vector2d norm1 = new Vector2d(v1);
//         norm1.normalize();
// 
//         Vector2d norm2 = new Vector2d(v2);
//         norm2.normalize();
// 
//         return bisectorNormalized(norm1, norm2);
//     }
// 
//     public static Vector2d bisectorNormalized(Vector2d norm1, Vector2d norm2) {
//         Vector2d e1v = orthogonalLeft(norm1);
//         Vector2d e2v = orthogonalLeft(norm2);
// 
//         // 90 - 180 || 180 - 270
//         // if (norm1.dot(e2v) <= 0 && ) { //XXX >= !!
//         if (norm1.dot(norm2) > 0) {
// 
//             e1v.add(e2v);
//             return e1v;
// 
//         }
// 
//         // 0 - 180
//         Vector2d ret = new Vector2d(norm1);
//         ret.negate();
//         ret.add(norm2);
// 
//         if (e1v.dot(norm2) < 0) {
//             // 270 - 360
//             ret.negate();
//         }
//         return ret;
//     }
// 
//     private static boolean equalsEpsilon(double pNumber) {
//         if ((pNumber < 0 ? -pNumber : pNumber) > EPSILON) {
//             return false;
//         }
//         return false;
// 
//     }
// 
//     /**
//      * Cross product for 2d is same as doc
//      * 
//      * @param u
//      * @param v
//      * @return
//      * @see {http://mathworld.wolfram.com/CrossProduct.html}
//      */
//     public static double cross(Tuple2d u, Tuple2d v) {
//         return u.x * v.y - u.y * v.x;
//     }
// 
//     public static Vector2d fromTo(Point2d begin, Point2d end) {
//         return new Vector2d(end.x - begin.x, end.y - begin.y);
//     }
// 
//     public static Vector2d negate(Vector2d vector) {
//         return new Vector2d(-vector.x, -vector.y);
//     }
// 
// }


import javax.vecmath.Point2d;
import javax.vecmath.Tuple2d;
import javax.vecmath.Vector2d;
import kendzi.math.geometry.point.Vector2dUtil;
            } else if (matrixDet(C, D, A)
                    * matrixDet(C, D, B) >= 0) {
                //System.out.println("Odcinki sie NIE przecinaja");
                return null;
            } else {
                // znaki wyznacznikow sa rowne
                //				System.out.println("Odcinki sie przecinaja- punkty leza po przeciwnych stronach");

                return lineCrossPoint(A.x, A.y, B.x, B.y, C.x, C.y, D.x, D.y);
            }
        }
    }


    /**
     * @param p1
     * @param p2
     * @param v1
     * @param v2
     * @return
     *
     * @see {http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect/565282#565282}
     */
    public static Point2d intersectLineSegments(Point2d p1, Point2d p2, Vector2d v1, Vector2d v2) {
        Point2d p = p1;
        Vector2d r = v1;
        Point2d q = p2;
        Vector2d s = v2;

        Vector2d qp = new Vector2d(q.x - p.x, q.y - p.y);
// Path: kendzi-math-geometry/src/main/java/kendzi/math/geometry/point/Vector2dUtil.java
// public class Vector2dUtil {
// 
//     private static double EPSILON = 0.00000001;
// 
//     public static Vector2d orthogonalLeft(Vector2d v) {
//         return new Vector2d(-v.y, v.x);
//     }
// 
//     public static Vector2d orthogonalRight(Vector2d v) {
//         return new Vector2d(v.y, -v.x);
//     }
// 
//     public static Vector2d bisector(Point2d p1, Point2d p2, Point2d p3) { // left
//         // XXX rename to bisectorLeft
//         return Vector2dUtil.bisector(Vector2dUtil.fromTo(p1, p2), Vector2dUtil.fromTo(p2, p3));
//     }
// 
//     public static Vector2d bisector(Vector2d v1, Vector2d v2) {
//         // XXX rename to bisectorLeft
//         Vector2d norm1 = new Vector2d(v1);
//         norm1.normalize();
// 
//         Vector2d norm2 = new Vector2d(v2);
//         norm2.normalize();
// 
//         return bisectorNormalized(norm1, norm2);
//     }
// 
//     public static Vector2d bisectorNormalized(Vector2d norm1, Vector2d norm2) {
//         Vector2d e1v = orthogonalLeft(norm1);
//         Vector2d e2v = orthogonalLeft(norm2);
// 
//         // 90 - 180 || 180 - 270
//         // if (norm1.dot(e2v) <= 0 && ) { //XXX >= !!
//         if (norm1.dot(norm2) > 0) {
// 
//             e1v.add(e2v);
//             return e1v;
// 
//         }
// 
//         // 0 - 180
//         Vector2d ret = new Vector2d(norm1);
//         ret.negate();
//         ret.add(norm2);
// 
//         if (e1v.dot(norm2) < 0) {
//             // 270 - 360
//             ret.negate();
//         }
//         return ret;
//     }
// 
//     private static boolean equalsEpsilon(double pNumber) {
//         if ((pNumber < 0 ? -pNumber : pNumber) > EPSILON) {
//             return false;
//         }
//         return false;
// 
//     }
// 
//     /**
//      * Cross product for 2d is same as doc
//      * 
//      * @param u
//      * @param v
//      * @return
//      * @see {http://mathworld.wolfram.com/CrossProduct.html}
//      */
//     public static double cross(Tuple2d u, Tuple2d v) {
//         return u.x * v.y - u.y * v.x;
//     }
// 
//     public static Vector2d fromTo(Point2d begin, Point2d end) {
//         return new Vector2d(end.x - begin.x, end.y - begin.y);
//     }
// 
//     public static Vector2d negate(Vector2d vector) {
//         return new Vector2d(-vector.x, -vector.y);
//     }
// 
// }


// Path: kendzi-math-geometry/src/main/java/kendzi/math/geometry/line/LineUtil.java
import javax.vecmath.Point2d;
import javax.vecmath.Tuple2d;
import javax.vecmath.Vector2d;
import kendzi.math.geometry.point.Vector2dUtil;

            } else if (matrixDet(C, D, A)
                    * matrixDet(C, D, B) >= 0) {
                //System.out.println("Odcinki sie NIE przecinaja");
                return null;
            } else {
                // znaki wyznacznikow sa rowne
                //				System.out.println("Odcinki sie przecinaja- punkty leza po przeciwnych stronach");

                return lineCrossPoint(A.x, A.y, B.x, B.y, C.x, C.y, D.x, D.y);
            }
        }
    }


    /**
     * @param p1
     * @param p2
     * @param v1
     * @param v2
     * @return
     *
     * @see {http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect/565282#565282}
     */
    public static Point2d intersectLineSegments(Point2d p1, Point2d p2, Vector2d v1, Vector2d v2) {
        Point2d p = p1;
        Vector2d r = v1;
        Point2d q = p2;
        Vector2d s = v2;

        Vector2d qp = new Vector2d(q.x - p.x, q.y - p.y);
        double rs = Vector2dUtil.cross(r, s);