示例#1
0
        public double ToDouble()
        {
            const double shift64 = 18446744073709551616.0;             //2^64
            const double bit64   = 9223372036854775808.0;

            if (hi < 0)
            {
                Int128 tmp = -this;
                if (tmp.lo < 0)
                {
                    return((double)tmp.lo - bit64 - tmp.hi * shift64);
                }
                else
                {
                    return(-(double)tmp.lo - tmp.hi * shift64);
                }
            }
            else if (lo < 0)
            {
                return(-(double)lo + bit64 + hi * shift64);
            }
            else
            {
                return((double)lo + (double)hi * shift64);
            }
        }
 internal static bool SlopesEqual(TEdge e1, TEdge e2, bool UseFullRange)
 {
     if (UseFullRange)
     {
         return(Int128.Int128Mul(e1.Delta.Y, e2.Delta.X) == Int128.Int128Mul(e1.Delta.X, e2.Delta.Y));
     }
     return(e1.Delta.Y * e2.Delta.X == e1.Delta.X * e2.Delta.Y);
 }
 protected static bool SlopesEqual(IntPoint pt1, IntPoint pt2, IntPoint pt3, IntPoint pt4, bool UseFullRange)
 {
     if (UseFullRange)
     {
         return(Int128.Int128Mul(pt1.Y - pt2.Y, pt3.X - pt4.X) == Int128.Int128Mul(pt1.X - pt2.X, pt3.Y - pt4.Y));
     }
     return((pt1.Y - pt2.Y) * (pt3.X - pt4.X) - (pt1.X - pt2.X) * (pt3.Y - pt4.Y) == 0);
 }
示例#4
0
        public override bool Equals(System.Object obj)
        {
            if (obj == null || !(obj is Int128))
            {
                return(false);
            }
            Int128 i128 = (Int128)obj;

            return(i128.hi == hi && i128.lo == lo);
        }
示例#5
0
        public static Int128 operator /(Int128 lhs, Int128 rhs)
        {
            if (rhs.lo == 0 && rhs.hi == 0)
            {
                throw new ArithmeticException("Int128: divide by zero");
            }
            bool   negate = (rhs.hi < 0) != (lhs.hi < 0);
            Int128 result = new Int128(lhs), denom = new Int128(rhs);

            if (result.hi < 0)
            {
                result = -result;
            }
            if (denom.hi < 0)
            {
                denom = -denom;
            }
            if (denom > result)
            {
                return(new Int128(0));                //result is only a fraction of 1
            }
            denom = -denom;

            Int128 p = new Int128(0);

            for (int i = 0; i < 128; ++i)
            {
                p.hi = p.hi << 1;
                if (p.lo < 0)
                {
                    p.hi++;
                }
                p.lo = (long)p.lo << 1;
                if (result.hi < 0)
                {
                    p.lo++;
                }
                result.hi = result.hi << 1;
                if (result.lo < 0)
                {
                    result.hi++;
                }
                result.lo = (long)result.lo << 1;
                if (p.hi >= 0)
                {
                    p += denom;
                    result.lo++;
                }
            }
            if (negate)
            {
                return(-result);
            }
            return(result);
        }
示例#6
0
        //------------------------------------------------------------------------------

        internal static bool SlopesEqual(TEdge e1, TEdge e2, bool UseFullRange)
        {
            if (UseFullRange)
            {
                return(Int128.Int128Mul(e1.Delta.Y, e2.Delta.X) ==
                       Int128.Int128Mul(e1.Delta.X, e2.Delta.Y));
            }
            else
            {
                return((int)(e1.Delta.Y) * (e2.Delta.X) ==
                       (int)(e1.Delta.X) * (e2.Delta.Y));
            }
        }
示例#7
0
        //------------------------------------------------------------------------------

        internal static bool SlopesEqual(IntPoint pt1, IntPoint pt2,
                                         IntPoint pt3, IntPoint pt4, bool UseFullRange)
        {
            if (UseFullRange)
            {
                return(Int128.Int128Mul(pt1.Y - pt2.Y, pt3.X - pt4.X) ==
                       Int128.Int128Mul(pt1.X - pt2.X, pt3.Y - pt4.Y));
            }
            else
            {
                return
                    ((int)(pt1.Y - pt2.Y) * (pt3.X - pt4.X) - (int)(pt1.X - pt2.X) * (pt3.Y - pt4.Y) == 0);
            }
        }
示例#8
0
        //nb: Constructing two new Int128 objects every time we want to multiply longs
        //is slow. So, although calling the Int128Mul method doesn't look as clean, the
        //code runs significantly faster than if we'd used the * operator.

        public static Int128 Int128Mul(Int64 lhs, Int64 rhs)
        {
            bool negate = (lhs < 0) != (rhs < 0);

            if (lhs < 0)
            {
                lhs = -lhs;
            }
            if (rhs < 0)
            {
                rhs = -rhs;
            }
            UInt64 int1Hi = (UInt64)lhs >> 32;
            UInt64 int1Lo = (UInt64)lhs & 0xFFFFFFFF;
            UInt64 int2Hi = (UInt64)rhs >> 32;
            UInt64 int2Lo = (UInt64)rhs & 0xFFFFFFFF;

            //nb: see comments in clipper.pas
            UInt64 a = int1Hi * int2Hi;
            UInt64 b = int1Lo * int2Lo;
            UInt64 c = int1Hi * int2Lo + int1Lo * int2Hi;

            UInt64 lo;
            Int64  hi;

            hi = (Int64)(a + (c >> 32));

            unchecked
            {
                lo = (c << 32) + b;
            }

            if (lo < b)
            {
                hi++;
            }
            Int128 result = new Int128(hi, lo);

            return(negate ? -result : result);
        }
示例#9
0
        //------------------------------------------------------------------------------

        internal bool PointOnLineSegment(IntPoint pt,
                                         IntPoint linePt1, IntPoint linePt2, bool UseFullRange)
        {
            if (UseFullRange)
            {
                return(((pt.X == linePt1.X) && (pt.Y == linePt1.Y)) ||
                       ((pt.X == linePt2.X) && (pt.Y == linePt2.Y)) ||
                       (((pt.X > linePt1.X) == (pt.X < linePt2.X)) &&
                        ((pt.Y > linePt1.Y) == (pt.Y < linePt2.Y)) &&
                        ((Int128.Int128Mul((pt.X - linePt1.X), (linePt2.Y - linePt1.Y)) ==
                          Int128.Int128Mul((linePt2.X - linePt1.X), (pt.Y - linePt1.Y))))));
            }
            else
            {
                return(((pt.X == linePt1.X) && (pt.Y == linePt1.Y)) ||
                       ((pt.X == linePt2.X) && (pt.Y == linePt2.Y)) ||
                       (((pt.X > linePt1.X) == (pt.X < linePt2.X)) &&
                        ((pt.Y > linePt1.Y) == (pt.Y < linePt2.Y)) &&
                        ((pt.X - linePt1.X) * (linePt2.Y - linePt1.Y) ==
                         (linePt2.X - linePt1.X) * (pt.Y - linePt1.Y))));
            }
        }
示例#10
0
        //------------------------------------------------------------------------------

        internal bool PointInPolygon(IntPoint pt, OutPt pp, bool UseFulllongRange)
        {
            OutPt pp2    = pp;
            bool  result = false;

            if (UseFulllongRange)
            {
                do
                {
                    if ((((pp2.Pt.Y <= pt.Y) && (pt.Y < pp2.Prev.Pt.Y)) ||
                         ((pp2.Prev.Pt.Y <= pt.Y) && (pt.Y < pp2.Pt.Y))) &&
                        new Int128(pt.X - pp2.Pt.X) <
                        Int128.Int128Mul(pp2.Prev.Pt.X - pp2.Pt.X, pt.Y - pp2.Pt.Y) /
                        new Int128(pp2.Prev.Pt.Y - pp2.Pt.Y))
                    {
                        result = !result;
                    }
                    pp2 = pp2.Next;
                } while (pp2 != pp);
            }
            else
            {
                do
                {
                    if ((((pp2.Pt.Y <= pt.Y) && (pt.Y < pp2.Prev.Pt.Y)) ||
                         ((pp2.Prev.Pt.Y <= pt.Y) && (pt.Y < pp2.Pt.Y))) &&
                        (pt.X - pp2.Pt.X < (pp2.Prev.Pt.X - pp2.Pt.X) * (pt.Y - pp2.Pt.Y) /
                         (pp2.Prev.Pt.Y - pp2.Pt.Y)))
                    {
                        result = !result;
                    }
                    pp2 = pp2.Next;
                } while (pp2 != pp);
            }

            return(result);
        }
示例#11
0
 internal bool PointOnLineSegment(IntPoint pt, IntPoint linePt1, IntPoint linePt2, bool UseFullRange)
 {
     if (UseFullRange)
     {
         if ((pt.X != linePt1.X || pt.Y != linePt1.Y) && (pt.X != linePt2.X || pt.Y != linePt2.Y))
         {
             if (pt.X > linePt1.X == pt.X < linePt2.X && pt.Y > linePt1.Y == pt.Y < linePt2.Y)
             {
                 return(Int128.Int128Mul(pt.X - linePt1.X, linePt2.Y - linePt1.Y) == Int128.Int128Mul(linePt2.X - linePt1.X, pt.Y - linePt1.Y));
             }
             return(false);
         }
         return(true);
     }
     if ((pt.X != linePt1.X || pt.Y != linePt1.Y) && (pt.X != linePt2.X || pt.Y != linePt2.Y))
     {
         if (pt.X > linePt1.X == pt.X < linePt2.X && pt.Y > linePt1.Y == pt.Y < linePt2.Y)
         {
             return((pt.X - linePt1.X) * (linePt2.Y - linePt1.Y) == (linePt2.X - linePt1.X) * (pt.Y - linePt1.Y));
         }
         return(false);
     }
     return(true);
 }
示例#12
0
        //nb: Constructing two new Int128 objects every time we want to multiply longs
        //is slow. So, although calling the Mul method doesn't look as clean, the
        //code runs significantly faster than if we'd used the * operator.
        public static Int128 Mul(long lhs, long rhs)
        {
            bool negate = (lhs < 0) != (rhs < 0);

            if (lhs < 0)
            {
                lhs = -lhs;
            }
            if (rhs < 0)
            {
                rhs = -rhs;
            }
            ulong int1Hi = (ulong)lhs >> 32;
            ulong int1Lo = (ulong)lhs & 0xFFFFFFFF;
            ulong int2Hi = (ulong)rhs >> 32;
            ulong int2Lo = (ulong)rhs & 0xFFFFFFFF;

            //nb: see comments in clipper.pas
            ulong a = int1Hi * int2Hi;
            ulong b = int1Lo * int2Lo;
            ulong c = int1Hi * int2Lo + int1Lo * int2Hi;

            long lo, hi;

            hi = (long)(a + (c >> 32));

            lo  = (long)(c << 32);
            lo += (long)b;
            if ((ulong)lo < b)
            {
                hi++;
            }
            var result = new Int128(lo, hi);

            return(negate ? -result : result);
        }
        public static Int128 operator /(Int128 lhs, Int128 rhs)
        {
            if (rhs.lo == 0 && rhs.hi == 0)
                throw new ClipperException("Int128: divide by zero");
            bool negate = (rhs.hi < 0) != (lhs.hi < 0);
            Int128 result = new Int128(lhs), denom = new Int128(rhs);
            if (result.hi < 0) Negate(result);
            if (denom.hi < 0) Negate(denom);
            if (denom > result) return new Int128(0); //result is only a fraction of 1
            Negate(denom);

            Int128 p = new Int128(0), p2 = new Int128(0);
            for (int i = 0; i < 128; ++i)
            {
                p.hi = p.hi << 1;
                if (p.lo < 0) p.hi++;
                p.lo = (Int64)p.lo << 1;
                if (result.hi < 0) p.lo++;
                result.hi = result.hi << 1;
                if (result.lo < 0) result.hi++;
                result.lo = (Int64)result.lo << 1;
                p2.Assign(p);
                p += denom;
                if (p.hi < 0) p.Assign(p2);
                else result.lo++;
            }
            if (negate) Negate(result);
            return result;
        }
 public static Int128 operator -(Int128 lhs, Int128 rhs)
 {
     Int128 tmp = new Int128(rhs);
     Negate(tmp);
     lhs += tmp;
     return lhs;
 }
 public Int128(Int128 val)
 {
     Assign(val);
 }
 //------------------------------------------------------------------------------
 public static double Area(Polygon poly)
 {
     int highI = poly.Count - 1;
     if (highI < 2) return 0;
     bool UseFullInt64Range = false;
     RangeTest rt = TestRange(poly);
     switch (rt)
     {
         case RangeTest.rtHi:
             UseFullInt64Range = true;
             break;
         case RangeTest.rtError:
             throw new ClipperException("Coordinate exceeds range bounds.");
     }
     if (UseFullInt64Range)
     {
         Int128 a = new Int128(0);
         a = Int128.Int128Mul(poly[highI].X, poly[0].Y) -
             Int128.Int128Mul(poly[0].X, poly[highI].Y);
         for (int i = 0; i < highI; ++i)
             a += Int128.Int128Mul(poly[i].X, poly[i + 1].Y) -
             Int128.Int128Mul(poly[i + 1].X, poly[i].Y);
         return a.ToDouble() / 2;
     }
     else
     {
         double area = (double)poly[highI].X * (double)poly[0].Y -
             (double)poly[0].X * (double)poly[highI].Y;
         for (int i = 0; i < highI; ++i)
             area += (double)poly[i].X * (double)poly[i + 1].Y -
                 (double)poly[i + 1].X * (double)poly[i].Y;
         return area / 2;
     }
 }
示例#17
0
        //------------------------------------------------------------------------------

        double Area(OutRec outRec, bool UseFull64BitRange)
        {
          OutPt op = outRec.pts;
          if (op == null) return 0;
          if (UseFull64BitRange) 
          {
            Int128 a = new Int128(0);
            do
            {
                a += Int128.Int128Mul(op.pt.X + op.prev.pt.X, op.prev.pt.Y - op.pt.Y);
                op = op.next;
            } while (op != outRec.pts);
            return a.ToDouble() / 2;          
          }
          else
          {
            double a = 0;
            do {
                a = a + (op.pt.X + op.prev.pt.X) * (op.prev.pt.Y - op.pt.Y);
              op = op.next;
            } while (op != outRec.pts);
            return a/2;
          }
        }
示例#18
0
        //------------------------------------------------------------------------------

        public static double Area(Polygon poly)
        {
            int highI = poly.Count - 1;
            if (highI < 2) return 0;
            if (FullRangeNeeded(poly))
            {
                Int128 a = new Int128(0);
                a = Int128.Int128Mul(poly[highI].X + poly[0].X, poly[0].Y - poly[highI].Y);
                for (int i = 1; i <= highI; ++i)
                    a += Int128.Int128Mul(poly[i - 1].X + poly[i].X, poly[i].Y - poly[i - 1].Y);
                return a.ToDouble() / 2;
            }
            else
            {
                double area = ((double)poly[highI].X + poly[0].X) * ((double)poly[0].Y - poly[highI].Y);
                for (int i = 1; i <= highI; ++i)
                    area += ((double)poly[i - 1].X + poly[i].X) * ((double)poly[i].Y - poly[i -1].Y);
                return area / 2;
            }
        }
示例#19
0
 public Int128(Int128 val)
 {
     hi = val.hi;
     lo = val.lo;
 }
示例#20
0
        //nb: Constructing two new Int128 objects every time we want to multiply longs  
        //is slow. So, although calling the Int128Mul method doesn't look as clean, the 
        //code runs significantly faster than if we'd used the * operator.
        
        public static Int128 Int128Mul(Int64 lhs, Int64 rhs)
        {
            bool negate = (lhs < 0) != (rhs < 0);
            if (lhs < 0) lhs = -lhs;
            if (rhs < 0) rhs = -rhs;
            UInt64 int1Hi = (UInt64)lhs >> 32;
            UInt64 int1Lo = (UInt64)lhs & 0xFFFFFFFF;
            UInt64 int2Hi = (UInt64)rhs >> 32;
            UInt64 int2Lo = (UInt64)rhs & 0xFFFFFFFF;

            //nb: see comments in clipper.pas
            UInt64 a = int1Hi * int2Hi;
            UInt64 b = int1Lo * int2Lo;
            UInt64 c = int1Hi * int2Lo + int1Lo * int2Hi;

            UInt64 lo; 
            Int64 hi;
            hi = (Int64)(a + (c >> 32));

            unchecked { lo = (c << 32) + b; }
            if (lo < b) hi++;
            Int128 result = new Int128(hi, lo);
            return negate ? -result : result;            
        }
示例#21
0
 public Int128(Int128 val)
 {
     hi = val.hi;
     lo = val.lo;
 }
示例#22
0
        public static Int128 operator /(Int128 lhs, Int128 rhs)
        {
            if (rhs.lo == 0 && rhs.hi == 0)
                throw new ClipperException("Int128: divide by zero");
            bool negate = (rhs.hi < 0) != (lhs.hi < 0);
            Int128 result = new Int128(lhs), denom = new Int128(rhs);
            if (result.hi < 0) result = -result;
            if (denom.hi < 0) denom = -denom;
            if (denom > result) return new Int128(0); //result is only a fraction of 1
            denom = -denom;

            Int128 p = new Int128(0), p2 = new Int128(0);
            for (int i = 0; i < 128; ++i)
            {
                p.hi = p.hi << 1;
                if (p.lo < 0) p.hi++;
                p.lo = (Int64)p.lo << 1;
                if (result.hi < 0) p.lo++;
                result.hi = result.hi << 1;
                if (result.lo < 0) result.hi++;
                result.lo = (Int64)result.lo << 1;
                if (p.hi >= 0)
                {
                    p += denom;
                    result.lo++;
                }
            }
            return negate ? -result : result;
        }
 public double ToDouble()
 {
     const double shift64 = 18446744073709551616.0; //2^64
     const double bit64 = 9223372036854775808.0;
     if (hi < 0)
     {
         Int128 tmp = new Int128(this);
         Negate(tmp);
         if (tmp.lo < 0)
             return (double)tmp.lo - bit64 - tmp.hi * shift64;
         else
             return -(double)tmp.lo - tmp.hi * shift64;
     }
     else if (lo < 0)
         return -(double)lo + bit64 + hi * shift64;
     else
         return (double)lo + (double)hi * shift64;
 }
示例#24
0
        public static Int128 operator /(Int128 lhs, Int128 rhs)
        {
            if (rhs.lo == 0 && rhs.hi == 0)
            {
                throw new ClipperException("Int128: divide by zero");
            }

            bool negate = (rhs.hi < 0) != (lhs.hi < 0);

            if (lhs.hi < 0)
            {
                lhs = -lhs;
            }
            if (rhs.hi < 0)
            {
                rhs = -rhs;
            }

            if (rhs < lhs)
            {
                Int128 result = new Int128(0);
                Int128 cntr   = new Int128(1);
                while (rhs.hi >= 0 && !(rhs > lhs))
                {
                    rhs.hi <<= 1;
                    if ((Int64)rhs.lo < 0)
                    {
                        rhs.hi++;
                    }
                    rhs.lo <<= 1;

                    cntr.hi <<= 1;
                    if ((Int64)cntr.lo < 0)
                    {
                        cntr.hi++;
                    }
                    cntr.lo <<= 1;
                }

                rhs.lo >>= 1;
                if ((rhs.hi & 1) == 1)
                {
                    rhs.lo |= 0x8000000000000000;
                }
                rhs.hi = (Int64)((UInt64)rhs.hi >> 1);

                cntr.lo >>= 1;
                if ((cntr.hi & 1) == 1)
                {
                    cntr.lo |= 0x8000000000000000;
                }
                cntr.hi >>= 1;

                while (cntr.hi != 0 || cntr.lo != 0)
                {
                    if (!(lhs < rhs))
                    {
                        lhs       -= rhs;
                        result.hi |= cntr.hi;
                        result.lo |= cntr.lo;
                    }

                    rhs.lo >>= 1;
                    if ((rhs.hi & 1) == 1)
                    {
                        rhs.lo |= 0x8000000000000000;
                    }
                    rhs.hi >>= 1;

                    cntr.lo >>= 1;
                    if ((cntr.hi & 1) == 1)
                    {
                        cntr.lo |= 0x8000000000000000;
                    }
                    cntr.hi >>= 1;
                }

                return(negate ? -result : result);
            }
            else if (rhs == lhs)
            {
                return(new Int128(1));
            }
            else
            {
                return(new Int128(0));
            }
        }
        //nb: Constructing two new Int128 objects every time we want to multiply longs
        //is slow. So, although calling the Int128Mul method doesn't look as clean, the
        //code runs significantly faster than if we'd used the * operator.
        public static Int128 Int128Mul(Int64 lhs, Int64 rhs)
        {
            bool negate = (lhs < 0) != (rhs < 0);
            if (lhs < 0) lhs = -lhs;
            if (rhs < 0) rhs = -rhs;
            UInt64 int1Hi = (UInt64)lhs >> 32;
            UInt64 int1Lo = (UInt64)lhs & 0xFFFFFFFF;
            UInt64 int2Hi = (UInt64)rhs >> 32;
            UInt64 int2Lo = (UInt64)rhs & 0xFFFFFFFF;

            //nb: see comments in clipper.pas
            UInt64 a = int1Hi * int2Hi;
            UInt64 b = int1Lo * int2Lo;
            UInt64 c = int1Hi * int2Lo + int1Lo * int2Hi;

            Int128 result = new Int128();
            result.hi = (Int64)(a + (c >> 32));

            result.lo = (Int64)(c << 32);
            result.lo += (Int64)b;
            if ((UInt64)result.lo < b) result.hi++;
            if (negate) Negate(result);
            return result;
        }
 public void Assign(Int128 val)
 {
     hi = val.hi; lo = val.lo;
 }
示例#27
0
        public static Int128 operator /(Int128 lhs, Int128 rhs)
        {
            if (rhs.lo == 0 && rhs.hi == 0)
                throw new ClipperException("Int128: divide by zero");

            bool negate = (rhs.hi < 0) != (lhs.hi < 0);
            if (lhs.hi < 0) lhs = -lhs;
            if (rhs.hi < 0) rhs = -rhs;

            if (rhs < lhs)
            {
                Int128 result = new Int128(0);
                Int128 cntr = new Int128(1);
                while (rhs.hi >= 0 && !(rhs > lhs))
                {
                    rhs.hi <<= 1;
                    if ((Int64)rhs.lo < 0) rhs.hi++;
                    rhs.lo <<= 1;

                    cntr.hi <<= 1;
                    if ((Int64)cntr.lo < 0) cntr.hi++;
                    cntr.lo <<= 1;
                }
                rhs.lo >>= 1;
                if ((rhs.hi & 1) == 1)
                    rhs.lo |= 0x8000000000000000;
                rhs.hi = (Int64)((UInt64)rhs.hi >> 1);

                cntr.lo >>= 1;
                if ((cntr.hi & 1) == 1)
                    cntr.lo |= 0x8000000000000000;
                cntr.hi >>= 1;

                while (cntr.hi != 0 || cntr.lo != 0)
                {
                    if (!(lhs < rhs))
                    {
                        lhs -= rhs;
                        result.hi |= cntr.hi;
                        result.lo |= cntr.lo;
                    }
                    rhs.lo >>= 1;
                    if ((rhs.hi & 1) == 1)
                        rhs.lo |= 0x8000000000000000; 
                    rhs.hi >>= 1;

                    cntr.lo >>= 1;
                    if ((cntr.hi & 1) == 1)
                        cntr.lo |= 0x8000000000000000;
                    cntr.hi >>= 1;
                }
                return negate ? -result : result;
            }
            else if (rhs == lhs)
                return new Int128(1);
            else
                return new Int128(0);
        }
 private static void Negate(Int128 val)
 {
     if (val.lo == 0)
     {
     if( val.hi == 0) return;
     val.lo = ~val.lo;
     val.hi = ~val.hi +1;
     }
     else
     {
     val.lo = ~val.lo +1;
     val.hi = ~val.hi;
     }
 }
 internal bool PointOnLineSegment(IntPoint pt, IntPoint linePt1, IntPoint linePt2, bool UseFullRange)
 {
     if (UseFullRange)
     {
         return((pt.X == linePt1.X && pt.Y == linePt1.Y) || (pt.X == linePt2.X && pt.Y == linePt2.Y) || (pt.X > linePt1.X == pt.X < linePt2.X && pt.Y > linePt1.Y == pt.Y < linePt2.Y && Int128.Int128Mul(pt.X - linePt1.X, linePt2.Y - linePt1.Y) == Int128.Int128Mul(linePt2.X - linePt1.X, pt.Y - linePt1.Y)));
     }
     return((pt.X == linePt1.X && pt.Y == linePt1.Y) || (pt.X == linePt2.X && pt.Y == linePt2.Y) || (pt.X > linePt1.X == pt.X < linePt2.X && pt.Y > linePt1.Y == pt.Y < linePt2.Y && (pt.X - linePt1.X) * (linePt2.Y - linePt1.Y) == (linePt2.X - linePt1.X) * (pt.Y - linePt1.Y)));
 }