public Rect2D( Vector2D min, Vector2D max )
 {
     Min = new Vector2D( Math.Min( min.X, max.X ), Math.Min( min.Y, max.Y ) );
     Max = new Vector2D( Math.Max( min.X, max.X ), Math.Max( min.Y, max.Y ) );
     _Min = Min;
     _Max = Max;
 }
        public static Vector2D? IntersectLineLine( Vector2D s1, Vector2D e1, Vector2D s2, Vector2D e2 )
        {
            Rect2D aabb1 = new Rect2D( s1, e1 );
            Rect2D aabb2 = new Rect2D( s2, e2 );
            if ( !aabb1.IntersectsWith( aabb2 ) ) return null;

            double x1 = s1.X;
            double x2 = e1.X;
            double x3 = s2.X;
            double x4 = e2.X;
            double y1 = s1.Y;
            double y2 = e1.Y;
            double y3 = s2.Y;
            double y4 = e2.Y;

            double denom = ( x1 - x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 - x4 );
            if ( Math.Abs( denom ) < 1e-4 ) return null;
            double px = ( ( x1 * y2 - y1 * x2 ) * ( x3 - x4 ) - ( x1 - x2 ) * ( x3 * y4 - y3 * x4 ) ) / denom;
            double py = ( ( x1 * y2 - y1 * x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 * y4 - y3 * x4 ) ) / denom;

            Vector2D p = new Vector2D( px, py );
            double l1 = ( p - s1 ).Length;
            double l2 = ( p - e1 ).Length;
            if ( l1 + l2 > ( s1 - e1 ).Length + 1e-3 ) return null;
            return p;
        }
 public static double DistanceLinePoint( Vector2D start, Vector2D end, Vector2D v, out Vector2D nearest )
 {
     Vector2D dir = v - start;
     Vector2D borderDir = ( end - start ).Normalized( );
     double dot = borderDir.Dot( dir );
     if ( dot < 0 )
     {
         nearest = start;
         return ( v - start ).Length;
     }
     if ( dot > ( end - start ).Length )
     {
         nearest = end;
         return ( v - end ).Length;
     }
     Vector2D tangent = borderDir * dot;
     nearest = start + tangent;
     Vector2D normal = dir - tangent;
     return normal.Length;
 }
 public bool Contains( Vector2D v )
 {
     return v.X >= Min.X && v.Y >= Min.Y && v.Y <= Max.Y && v.X <= Max.X;
 }
       // public Vector2D RandomPoint( Random r ) { return new Vector2D( r.NextBetween( Left, Right ), r.NextBetween( Top, Bottom ) ); }

        public Rect2D( Vector2D v )
        {
            Min = Max = v;
            _Min = _Max = v;
        }
 public Rect2D Assimilate( Vector2D v )
 {
     /*if ( v.X < Min.X ) Min.X = v.X;
     if ( v.Y < Min.Y ) Min.Y = v.Y;
     if ( v.X > Max.X ) Max.X = v.X;
     if ( v.Y > Max.Y ) Max.Y = v.Y;*/
     return new Rect2D(
         new Vector2D(
             Math.Min( Left, v.X ),
             Math.Min( Top, v.Y ) ),
         new Vector2D(
             Math.Max( Right, v.X ),
             Math.Max( Bottom, v.Y ) )
         );
 }
        //public Vector2D RandomRotate( double minAngle, double maxAngle, Random r )
        //{
        //    double angle = r.NextBetween( minAngle, maxAngle );
        //    return Rotate( angle );
        //}

        public static bool EpsilonEquals( Vector2D v1, Vector2D v2, double epsilon = 1e-5 )
        {
            return ( v1 - v2 ).Length < epsilon;
        }
 public static double DistanceLinePoint( Vector2D start, Vector2D end, Vector2D v )
 {
     Vector2D n;
     return DistanceLinePoint( start, end, v, out n );
 }
 public double Dot( Vector2D p )
 {
     return p.X * X + p.Y * Y;
 }