Beispiel #1
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;
            }
        }
Beispiel #2
0
        //------------------------------------------------------------------------------

        public static double Area(PolygonClp 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;
            }
        }
Beispiel #3
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;
        }
Beispiel #4
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);
        }
Beispiel #5
0
 public Int128(Int128 val)
 {
     hi = val.hi;
     lo = val.lo;
 }