/// <summary>
        /// This routine simply tests for robustness of the ToString function.
        /// </summary>
        private static void WriteRepeatedSqrt(DD xdd)
        {
            int count = 0;

            while (xdd.ToDoubleValue() > 1e-300)
            {
                count++;
                // if (count == 100)
                //     count = count;
                double x     = xdd.ToDoubleValue();
                var    xSqrt = xdd.Sqrt();
                string s     = xSqrt.ToString();
                // System.Console.WriteLine((count + ": " + s);

                var    xSqrt2 = DD.Parse(s);
                var    xx     = xSqrt2.Multiply(xSqrt2);
                double err    = Math.Abs(xx.ToDoubleValue() - x);
                // assertTrue(err < 1e-10);

                xdd = xSqrt;

                // square roots converge on 1 - stop when very close
                var    distFrom1DD = xSqrt.Subtract(DD.ValueOf(1.0));
                double distFrom1   = distFrom1DD.ToDoubleValue();
                if (Math.Abs(distFrom1) < 1.0e-40)
                {
                    break;
                }
            }
        }
        /// <summary>
        /// Tests if a point is inside the circle defined by
        /// the triangle with vertices a, b, c (oriented counter-clockwise).
        /// </summary>
        /// <remarks>
        /// The computation uses <see cref="DD"/> arithmetic for robustness.
        /// </remarks>
        /// <param name="a">A vertex of the triangle</param>
        /// <param name="b">A vertex of the triangle</param>
        /// <param name="c">A vertex of the triangle</param>
        /// <param name="p">The point to test</param>
        /// <returns>true if this point is inside the circle defined by the points a, b, c</returns>
        public static bool IsInCircleDDSlow(
            Coordinate a, Coordinate b, Coordinate c,
            Coordinate p)
        {
            DD px = DD.ValueOf(p.X);
            DD py = DD.ValueOf(p.Y);
            DD ax = DD.ValueOf(a.X);
            DD ay = DD.ValueOf(a.Y);
            DD bx = DD.ValueOf(b.X);
            DD by = DD.ValueOf(b.Y);
            DD cx = DD.ValueOf(c.X);
            DD cy = DD.ValueOf(c.Y);

            DD aTerm = (ax.Multiply(ax).Add(ay.Multiply(ay)))
                       .Multiply(TriAreaDDSlow(bx, by, cx, cy, px, py));
            DD bTerm = (bx.Multiply(bx).Add(by.Multiply(by)))
                       .Multiply(TriAreaDDSlow(ax, ay, cx, cy, px, py));
            DD cTerm = (cx.Multiply(cx).Add(cy.Multiply(cy)))
                       .Multiply(TriAreaDDSlow(ax, ay, bx, by, px, py));
            DD pTerm = (px.Multiply(px).Add(py.Multiply(py)))
                       .Multiply(TriAreaDDSlow(ax, ay, bx, by, cx, cy));

            DD   sum        = aTerm.Subtract(bTerm).Add(cTerm).Subtract(pTerm);
            bool isInCircle = sum.ToDoubleValue() > 0;

            return(isInCircle);
        }
        private static void CheckErrorBound(String tag, DD x, DD y, double errBound)
        {
            DD err = x.Subtract(y).Abs();

            Console.WriteLine(tag + " err=" + err);
            var isWithinEps = err.ToDoubleValue() <= errBound;

            Assert.True(isWithinEps);
        }
        private static void CheckParse(String str, DD expectedVal,
                                       double relErrBound)
        {
            DD     xdd    = DD.Parse(str);
            double err    = xdd.Subtract(expectedVal).ToDoubleValue();
            double relErr = err / xdd.ToDoubleValue();

            Console.WriteLine("Parsed= " + xdd + " rel err= " + relErr);

            Assert.IsTrue(err <= relErrBound);
        }
        /// <summary>
        /// This routine simply tests for robustness of the toString function.
        /// </summary>
        static void WriteRepeatedSqr(DD xdd)
        {
            if (xdd.GreaterOrEqualThan(DD.ValueOf(1)))
            {
                throw new ArgumentException("Argument must be < 1");
            }

            int count = 0;

            while (xdd.ToDoubleValue() > 1e-300)
            {
                count++;
                double x    = xdd.ToDoubleValue();
                var    xSqr = xdd.Sqr();
                string s    = xSqr.ToString();
                // System.Console.WriteLine(count + ": " + s);

                var xSqr2 = DD.Parse(s);

                xdd = xSqr;
            }
        }
        /// <summary>
        /// Tests if a point is inside the circle defined by
        /// the triangle with vertices a, b, c (oriented counter-clockwise).
        /// </summary>
        /// <remarks>
        /// The computation uses <see cref="DD"/> arithmetic for robustness, but a faster approach.
        /// </remarks>
        /// <param name="a">A vertex of the triangle</param>
        /// <param name="b">A vertex of the triangle</param>
        /// <param name="c">A vertex of the triangle</param>
        /// <param name="p">The point to test</param>
        /// <returns>true if this point is inside the circle defined by the points a, b, c</returns>
        public static bool IsInCircleDDFast(
            Coordinate a, Coordinate b, Coordinate c,
            Coordinate p)
        {
            DD aTerm = (DD.Sqr(a.X) + DD.Sqr(a.Y)) * TriAreaDDFast(b, c, p);
            DD bTerm = (DD.Sqr(b.X) + DD.Sqr(b.Y)) * TriAreaDDFast(a, c, p);
            DD cTerm = (DD.Sqr(c.X) + DD.Sqr(c.Y)) * TriAreaDDFast(a, b, p);
            DD pTerm = (DD.Sqr(p.X) + DD.Sqr(p.Y)) * TriAreaDDFast(a, b, c);

            DD   sum        = aTerm - bTerm + cTerm - pTerm;
            bool isInCircle = sum.ToDoubleValue() > 0;

            return(isInCircle);
        }
        /// <summary>
        /// Tests that printing values with many decimal places works.
        /// This tests the correctness and robustness of both output and input.
        /// </summary>
        static void WriteAndReadSqrt(double x)
        {
            DD     xdd   = DD.ValueOf(x);
            DD     xSqrt = xdd.Sqrt();
            String s     = xSqrt.ToString();
//		System.out.println(s);

            DD     xSqrt2 = DD.Parse(s);
            DD     xx     = xSqrt2 * xSqrt2;
            String xxStr  = xx.ToString();
//		System.out.println("==>  " + xxStr);

            DD     xx2 = DD.Parse(xxStr);
            double err = Math.Abs(xx2.ToDoubleValue() - x);

            Assert.IsTrue(err < 1e-10);
        }
        /// <summary>
        /// Computes the arctangent based on the Taylor series expansion
        /// <para/>
        /// arctan(x) = x - x^3 / 3 + x^5 / 5 - x^7 / 7 + ...
        /// </summary>
        /// <param name="x">The argument</param>
        /// <returns>An approximation to the arctangent of the input</returns>
        private static DD ArcTan(DD x)
        {
            var t    = x;
            var t2   = t.Sqr();
            var at   = new DD(0.0);
            var two  = new DD(2.0);
            var k    = 0;
            var d    = new DD(1.0);
            var sign = 1;

            while (t.ToDoubleValue() > DD.Epsilon)
            {
                k++;
                at = sign < 0 ? at.Subtract(t.Divide(d)) : at.Add(t.Divide(d));

                d    = d.Add(two);
                t    = t.Multiply(t2);
                sign = -sign;
            }
            Console.WriteLine("Computed DD.atan(): " + at
                              + "    Math.atan = " + Math.Atan(x.ToDoubleValue()));
            return(at);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="c"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public static bool IsInCircleDDNormalized(
            Coordinate a, Coordinate b, Coordinate c,
            Coordinate p)
        {
            DD adx = DD.ValueOf(a.X) - p.X;
            DD ady = DD.ValueOf(a.Y) - p.Y;
            DD bdx = DD.ValueOf(b.X) - p.X;
            DD bdy = DD.ValueOf(b.Y) - p.Y;
            DD cdx = DD.ValueOf(c.X) - p.X;
            DD cdy = DD.ValueOf(c.Y) - p.Y;

            DD abdet = adx * bdy - bdx * ady;
            DD bcdet = bdx * cdy - cdx * bdy;
            DD cadet = cdx * ady - adx * cdy;
            DD alift = adx * adx + ady * ady;
            DD blift = bdx * bdx + bdy * bdy;
            DD clift = cdx * cdx + cdy * cdy;

            DD sum = alift * bcdet + blift * cadet + clift * abdet;

            bool isInCircle = sum.ToDoubleValue() > 0;

            return(isInCircle);
        }
Beispiel #10
0
        /// <summary>
        /// Tests if a point is inside the circle defined by the points a, b, c.
        /// The computation uses <see cref="NetTopologySuite.Mathematics.DD"/> arithmetic for robustness.
        /// </summary>
        /// <param name="a">A vertex of the triangle</param>
        /// <param name="b">A vertex of the triangle</param>
        /// <param name="c">A vertex of the triangle</param>
        /// <param name="p">The point to test</param>
        /// <returns><value>true</value> if this point is inside the circle defined by the points a, b, c</returns>
        public static bool IsInCircleDD3(
            Coordinate a, Coordinate b, Coordinate c,
            Coordinate p)
        {
            DD adx = DD.ValueOf(a.X) - (p.X);
            DD ady = DD.ValueOf(a.Y) - (p.Y);
            DD bdx = DD.ValueOf(b.X) - (p.X);
            DD bdy = DD.ValueOf(b.Y) - (p.Y);
            DD cdx = DD.ValueOf(c.X) - (p.X);
            DD cdy = DD.ValueOf(c.Y) - (p.Y);

            DD abdet = adx * bdy - (bdx * ady);
            DD bcdet = bdx * cdy - (cdx * bdy);
            DD cadet = cdx * ady - (adx * cdy);
            DD alift = adx * adx - (ady * ady);
            DD blift = bdx * bdx - (bdy * bdy);
            DD clift = cdx * cdx - (cdy * cdy);

            DD sum = alift * bcdet + blift * cadet + clift * abdet;

            var isInCircle = sum.ToDoubleValue() > 0;

            return(isInCircle);
        }
        /// <summary>
        /// Computes the arctangent based on the Taylor series expansion
        /// <para/>
        /// arctan(x) = x - x^3 / 3 + x^5 / 5 - x^7 / 7 + ...
        /// </summary>
        /// <param name="x">The argument</param>
        /// <returns>An approximation to the arctangent of the input</returns>
        private static DD ArcTan(DD x)
        {
            var t = x;
            var t2 = t.Sqr();
            var at = new DD(0.0);
            var two = new DD(2.0);
            var k = 0;
            var d = new DD(1.0);
            var sign = 1;
            while (t.ToDoubleValue() > DD.Epsilon)
            {
                k++;
                at = sign < 0 ? at.Subtract(t.Divide(d)) : at.Add(t.Divide(d));

                d = d.Add(two);
                t = t.Multiply(t2);
                sign = -sign;
            }
            Console.WriteLine("Computed DD.atan(): " + at
                              + "    Math.atan = " + Math.Atan(x.ToDoubleValue()));
            return at;
        }
	/**
	 * This routine simply tests for robustness of the toString function.
	 * 
	 * @param xdd
	 */
	static void WriteRepeatedSqr(DD xdd) 
	{
		if (xdd.GreaterOrEqualThan(DD.ValueOf(1)))
			throw new ArgumentException("Argument must be < 1");
		
		int count = 0;
		while (xdd.ToDoubleValue() > 1e-300) {
			count++;
			double x = xdd.ToDoubleValue();
			DD xSqr = xdd.Sqr();
			String s = xSqr.ToString();
			Console.WriteLine(count + ": " + s);

			DD xSqr2 = DD.Parse(s);
	
			xdd = xSqr;
		}
	}
	/**
	 * This routine simply tests for robustness of the toString function.
	 * 
	 * @param xdd
	 */
	private static void WriteRepeatedSqrt(DD xdd) 
	{
		int count = 0;
		while (xdd.ToDoubleValue() > 1e-300) {
			count++;
            //if (count == 100)
            //    count = count;
			double x = xdd.ToDoubleValue();
			DD xSqrt = xdd.Sqrt();
			String s = xSqrt.ToString();
//			System.out.println(count + ": " + s);

			DD xSqrt2 = DD.Parse(s);
			DD xx = xSqrt2.Multiply(xSqrt2);
			double err = Math.Abs(xx.ToDoubleValue() - x);
			//assertTrue(err < 1e-10);
	
			xdd = xSqrt;

			// square roots converge on 1 - stop when very close
			DD distFrom1DD = xSqrt.Subtract(DD.ValueOf(1.0));
			double distFrom1 = distFrom1DD.ToDoubleValue();
			if (Math.Abs(distFrom1) < 1.0e-40)
				break;
		}
	}