import { Point } from "./point";

 // 计算 |p1 p2| X |p1 p|
 function GetCross( p1:Point, p2:Point, p:Point)
 {
     return (p2.x - p1.x) * (p.y - p1.y) -(p.x - p1.x) * (p2.y - p1.y);
 }
 
 function IsPointInRect(p:Point, rect:any)
 {
     const p1 = rect.p1;
     const p2 = rect.p2;
     const p3 = rect.p3;
     const p4 = rect.p4;
     return GetCross(p1,p2,p) * GetCross(p3,p4,p) >= 0 && GetCross(p2,p3,p) * GetCross(p4,p1,p) >= 0;
     //return false;
 }

 function areVecsEqual(v1:any, v2:any) {
     return v1.x == v2.x && v1.y == v2.y;
 }
 
 /**
  * Returns an indicator of where the specified point
  * {@code (px,py)} lies with respect to the line segment from
  * {@code (x1,y1)} to {@code (x2,y2)}.
  * The return value can be either 1, -1, or 0 and indicates
  * in which direction the specified line must pivot around its
  * first end point, {@code (x1,y1)}, in order to point at the
  * specified point {@code (px,py)}.
  * <p>A return value of 1 indicates that the line segment must
  * turn in the direction that takes the positive X axis towards
  * the negative Y axis.  In the default coordinate system used by
  * Java 2D, this direction is counterclockwise.
  * <p>A return value of -1 indicates that the line segment must
  * turn in the direction that takes the positive X axis towards
  * the positive Y axis.  In the default coordinate system, this
  * direction is clockwise.
  * <p>A return value of 0 indicates that the point lies
  * exactly on the line segment.  Note that an indicator value
  * of 0 is rare and not useful for determining collinearity
  * because of floating point rounding issues.
  * <p>If the point is colinear with the line segment, but
  * not between the end points, then the value will be -1 if the point
  * lies "beyond {@code (x1,y1)}" or 1 if the point lies
  * "beyond {@code (x2,y2)}".
  *
  * @param x1 the X coordinate of the start point of the
  *           specified line segment
  * @param y1 the Y coordinate of the start point of the
  *           specified line segment
  * @param x2 the X coordinate of the end point of the
  *           specified line segment
  * @param y2 the Y coordinate of the end point of the
  *           specified line segment
  * @param px the X coordinate of the specified point to be
  *           compared with the specified line segment
  * @param py the Y coordinate of the specified point to be
  *           compared with the specified line segment
  * @return an integer that indicates the position of the third specified
  *                  coordinates with respect to the line segment formed
  *                  by the first two specified coordinates.
  */
 
  function relativeCCW( x1:number,  y1:number, x2:number, y2:number, px:number, py:number)
 {
     x2 -= x1;
     y2 -= y1;
     px -= x1;
     py -= y1;
     let ccw = px * y2 - py * x2;
     if (ccw == 0.0) {
         // The point is colinear, classify based on which side of
         // the segment the point falls on.  We can calculate a
         // relative value using the projection of px,py onto the
         // segment - a negative value indicates the point projects
         // outside of the segment in the direction of the particular
         // endpoint used as the origin for the projection.
         ccw = px * x2 + py * y2;
         if (ccw > 0.0) {
             // Reverse the projection to be relative to the original x2,y2
             // x2 and y2 are simply negated.
             // px and py need to have (x2 - x1) or (y2 - y1) subtracted
             //    from them (based on the original values)
             // Since we really want to get a positive answer when the
             //    point is "beyond (x2,y2)", then we want to calculate
             //    the inverse anyway - thus we leave x2 & y2 negated.
             px -= x2;
             py -= y2;
             ccw = px * x2 + py * y2;
             if (ccw < 0.0) {
                 ccw = 0.0;
             }
         }
     }
     return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0);
 }
 
 /**
      * Tests if the line segment from {@code (x1,y1)} to
      * {@code (x2,y2)} intersects the line segment from {@code (x3,y3)}
      * to {@code (x4,y4)}.
      *
      * @param x1 the X coordinate of the start point of the first
      *           specified line segment
      * @param y1 the Y coordinate of the start point of the first
      *           specified line segment
      * @param x2 the X coordinate of the end point of the first
      *           specified line segment
      * @param y2 the Y coordinate of the end point of the first
      *           specified line segment
      * @param x3 the X coordinate of the start point of the second
      *           specified line segment
      * @param y3 the Y coordinate of the start point of the second
      *           specified line segment
      * @param x4 the X coordinate of the end point of the second
      *           specified line segment
      * @param y4 the Y coordinate of the end point of the second
      *           specified line segment
      * @return <code>true</code> if the first specified line segment
      *                  and the second specified line segment intersect
      *                  each other; <code>false</code> otherwise.
      * @since 1.2
      */
 
 export function isLineIntersect( line1:any, line2:any)
 {
     const x1 = line1.p1.x, x2=line1.p2.x, y1 = line1.p1.y,y2 = line1.p2.y;
 
     const x3 = line2.p1.x, x4 = line2.p2.x, y3 = line2.p1.y, y4 = line2.p2.y;
 
     return ((relativeCCW(x1, y1, x2, y2, x3, y3) * relativeCCW(x1, y1, x2, y2, x4, y4) <= 0)
             && (relativeCCW(x3, y3, x4, y4, x1, y1) * relativeCCW(x3, y3, x4, y4, x2, y2) <= 0));
 }
 
 export  function isRectInter(rect1:any, rect2:any)
 {
    const lines1 = [
         {p1:rect1.p1, p2:rect1.p2},
         {p1:rect1.p3, p2:rect1.p4},
         {p1:rect1.p1, p2:rect1.p4},
         {p1:rect1.p2, p2:rect1.p3},
     ];
     const lines2 = [
         {p1:rect2.p1, p2:rect2.p2},
         {p1:rect2.p3, p2:rect2.p4},
         {p1:rect2.p1, p2:rect2.p4},
         {p1:rect2.p2, p2:rect2.p3},
     ]
 
     //判定线段是否相交
     for( let i=0; i<4; i++) {    
         for(let k=0; k<4;k++) {
             const isIn = isLineIntersect(lines1[i], lines2[k]);
             if( isIn ) return true;
         }
     }
     
     let isIn = IsPointInRect(rect1.p1, rect2);
     if( isIn ) return true;
     isIn = IsPointInRect(rect1.p2, rect2);
     if( isIn ) return true;
     isIn = IsPointInRect(rect1.p3, rect2);
     if( isIn ) return true;
     isIn = IsPointInRect(rect1.p4, rect2);
     if( isIn ) return true;
 
     isIn = IsPointInRect(rect2.p1, rect1);
     if( isIn ) return true;
 
     isIn = IsPointInRect(rect2.p2, rect1);
     if( isIn ) return true;
 
     isIn = IsPointInRect(rect2.p3, rect1);
     if( isIn ) return true;
     
     isIn = IsPointInRect(rect2.p4, rect1);
     if( isIn ) return true;
 
 
     return false;
 };
 
 //v1 向量到v2的投影
 export function Project(v1:any,v2:any)
 {
    return Vectordot(v1, v2) / VectorLenth(v2.x, v2.y)
 }
 const MATH_FLOAT_SMALL = 1.0e-37;
 
 export function Angle(v1:any, v2:any)
 {
    const dz = v1.x * v2.y - v1.y * v2.x;
     return Math.atan2(Math.abs(dz) + MATH_FLOAT_SMALL, Vectordot(v1, v2));
 }
 
 export function Vectordot(v1:any,v2:any)
 {
     return (v1.x * v2.x + v1.y * v2.y);
 }
 
 export function VectorLenth(x:number,y:number)
 {
     return Math.sqrt(x * x + y * y);
 }