示例#1
0
        public static WavefrontFormat DrawClothoRadius(this WavefrontFormat wf,
                                                       bool invertY, double a,
                                                       string radiusColor)
        {
            List <int> indices = new List <int>();

            double lmax = ClothoUtils.GetMaxL(a);
            int    c    = 100;

            for (int i = -c; i <= c; i++)
            {
                double s = i * lmax / c;

                double r = ClothoUtils.ClothoRadius(s, invertY, a);
                if (double.IsInfinity(r))
                {
                    r = SysMath.Sign(r) * 1000;
                }

                int v0 = wf.AddVertex(new Point2d(s, r));
                indices.Add(v0);

                //double dx, dy;
                //MathUtils.DClotho(s, r, a, out dx, out dy);
            }

            wf.UseMaterial(radiusColor);
            wf.AddLines(indices, false);
            return(wf);
        }
示例#2
0
        public override Vector2d GetFirstDerivative(double t)
        {
            /*
             *  Maxima:
             *  s:      t * m + n;
             *  x:      a*sqrt(%pi)*fresnel_c(s/(a*sqrt(%pi)));
             *  y:      a*sqrt(%pi)*fresnel_s(s/(a*sqrt(%pi)));
             *  z:      1;
             *  result: diff([ x, y, z ], t, 1);
             *
             *  result: [m*cos((m*t+n)^2 / (2*a^2)),
             *           m*sin((m*t+n)^2 / (2*a^2)),
             *           0]
             *
             *          m*[cos((m*t+n)^2 / (2*a^2)),
             *             sin((m*t+n)^2 / (2*a^2)),
             *             0]
             *
             *          m*[cos(s^2 / (2*a^2)),
             *             sin(s^2 / (2*a^2)),
             *             0]
             */
            double m = this.ttransform.A;

            double   dl = this.GetL(t);
            Vector2d v  = ClothoUtils.DClotho(dl, this.InvertY, this.A);

            v = v.Mul(m);
            return(this.transform.DoTransform(v));
        }
示例#3
0
        public ClothoidArc2(double l0,
                            Vec2d point0, Vec2d point1,
                            double radius0, double radius1,
                            double a)
        {
            // Correccion sobre los radios.
            if (SysMath.Sign(radius1) != SysMath.Sign(radius0))
            {
                if (double.IsInfinity(radius0))
                {
                    radius0 = SysMath.Sign(radius1) * double.PositiveInfinity;
                }
                else if (double.IsInfinity(radius1))
                {
                    radius1 = SysMath.Sign(radius0) * double.PositiveInfinity;
                }
                else
                {
                    // Se deja tal cual.
                    //// Se toma el radio inicio como infinito.
                    ////radius0 = SysMath.Sign(radius1) * double.PositiveInfinity;
                }
            }

            if (SysMath.Abs(radius0) > SysMath.Abs(radius1))
            { // t positivas
                this.invertY = radius1 < 0;
            }
            else
            { // t negativa
                this.invertY = radius1 > 0;
            }

            // Diferencia de puntos en coordenadas reales.
            Vec2d v01 = point1.Sub(point0);

            this.a = a;

            // Desarrollo segun el radio en el punto (0) y (1).
            double l0_n = ClothoUtils.ClothoL(radius0, this.invertY, this.a);
            double l1_n = ClothoUtils.ClothoL(radius1, this.invertY, this.a);

            // Coordenadas en el punto (0) y (1) para una clotoide normalizada.
            Vec2d p0_n = ClothoUtils.Clotho(l0_n, this.invertY, this.a);
            Vec2d p1_n = ClothoUtils.Clotho(l1_n, this.invertY, this.a);

            Vec2d v01_n = p1_n.Sub(p0_n);

            // Rotacion de v01_n -> v01.
            double r = vecMath.Angle(v01_n, v01);

            // Transformacion a aplicar.
            this.transform = Transform2.Translate(point1.X - p1_n.X, point1.Y - p1_n.Y)
                             .Mult(Transform2.Rotate(p1_n.X, p1_n.Y, r));

            this.l0 = l0_n;
            this.l1 = l1_n;

            this.SetTInterval(l0, l0 + (this.l1 - this.l0));
        }
示例#4
0
        public override Vector2d GetThirdDerivative(double t)
        {
            /*
             *  Maxima:
             *  s:      t * m + n;
             *  x:      a*sqrt(%pi)*fresnel_c(s/(a*sqrt(%pi)));
             *  y:      a*sqrt(%pi)*fresnel_s(s/(a*sqrt(%pi)));
             *  z:      1;
             *  result: diff([ x, y, z ], t, 3);
             *
             *  result: [-(m^3*sin((m*t+n)^2 / (2*a^2))) / a^2 - (m^3*(m*t+n)^2*cos((m*t+n)^2 / (2*a^2))) / a^4,
             *            (m^3*cos((m*t+n)^2 / (2*a^2))) / a^2 - (m^3*(m*t+n)^2*sin((m*t+n)^2 / (2*a^2))) / a^4,
             *            0]
             *
             *          m^3*[-(sin((m*t+n)^2 / (2*a^2))) / a^2 - ((m*t+n)^2*cos((m*t+n)^2 / (2*a^2))) / a^4,
             *                (cos((m*t+n)^2 / (2*a^2))) / a^2 - ((m*t+n)^2*sin((m*t+n)^2 / (2*a^2))) / a^4,
             *                0]
             *
             *          m^3*[-(sin(s^2 / (2*a^2))) / a^2 - (s^2*cos(s^2 / (2*a^2))) / a^4,
             *                (cos(s^2 / (2*a^2))) / a^2 - (s^2*sin(s^2 / (2*a^2))) / a^4,
             *                0]
             */
            double m  = this.ttransform.A;
            double m3 = m * m * m;

            double   dl = this.GetL(t);
            Vector2d v  = ClothoUtils.DClotho3(dl, this.InvertY, this.A);

            v = v.Mul(m3);
            return(this.transform.DoTransform(v));
        }
示例#5
0
        /// <summary>
        ///     Resuelve el parametro de la clotoide dado los radios <c>r0</c> y <c>r1</c> Con una distancia <c>d</c> entre los
        ///     puntos.
        /// </summary>
        private static double SolveParam(double d, double r0, double r1)
        {
            Func <double, double> f = (a) =>
            {
                double fs0, fc0;
                ClothoUtils.Fresnel(a / (r0 * sqrtpi), out fs0, out fc0);

                double fs1, fc1;
                ClothoUtils.Fresnel(a / (r1 * sqrtpi), out fs1, out fc1);

                double fc10 = (fc1 - fc0);
                double fs10 = (fs1 - fs0);

                return(a * a * SysMath.PI * (fc10 * fc10 + fs10 * fs10) - d * d);
            };

            //UnivariateSolver solver = new BisectionSolver(DEFAULT_ABSOLUTE_ACCURACY);
            //UnivariateSolver solver = new SecantSolver(DEFAULT_ABSOLUTE_ACCURACY);
            UnivariateSolver solver = new BrentSolver(DEFAULT_ABSOLUTE_ACCURACY);
            int maxEval             = 50; // 30

            try
            {
                double v = solver.solve(maxEval, new DelegateUnivariateFunction(f), 0, SysMath.Min(SysMath.Abs(r0), SysMath.Abs(r1)) * ClothoUtils.MAX_L);
                return(v);
            }
            catch (TooManyEvaluationsException e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
示例#6
0
        public static WavefrontFormat DrawClotho(this WavefrontFormat wf,
                                                 bool invertY, double a,
                                                 string clothoColor)
        {
            List <int> indices = new List <int>();

            int c = 100;

            for (int i = -c; i <= c; i++)
            {
                double lmax = ClothoUtils.GetMaxL(a);
                double s    = i * lmax / c;

                double x, y;
                ClothoUtils.Clotho(s, invertY, a, out x, out y);

                int v0 = wf.AddVertex(new Point2d(x, y));
                indices.Add(v0);

                //double dx, dy;
                //MathUtils.DClotho(s, r, a, out dx, out dy);
            }

            wf.UseMaterial(clothoColor);
            wf.AddLines(indices, false);
            return(wf);
        }
示例#7
0
        public static ClothoidArc2 BuildSimple(double radius0, double radius1, double a, ITransform2 transform)
        {
            // Correccion sobre los radios.
            if (SysMath.Sign(radius1) != SysMath.Sign(radius0))
            {
                if (double.IsInfinity(radius0))
                {
                    radius0 = SysMath.Sign(radius1) * double.PositiveInfinity;
                }
                else if (double.IsInfinity(radius1))
                {
                    radius1 = SysMath.Sign(radius0) * double.PositiveInfinity;
                }
                else
                {
                    // No se permite cambio de signo en el radio. Funcionaria???
                    Contract.Assert(false);
                }
            }

            // Desarrollo segun el radio en el punto (0) y (1).
            double l0 = ClothoUtils.ClothoL(radius0, false, a);
            double l1 = ClothoUtils.ClothoL(radius1, false, a);

            ClothoidArc2 clotho = new ClothoidArc2(transform, l0, l1, false, a);

            clotho.SetTInterval(0, Math.Abs(l1 - l0));
            return(clotho);
        }
示例#8
0
        public ClothoidArc2(double l0,
                            Vector2d point0, Vector2d point1,
                            double radius0, double radius1)
        {
            // Correccion sobre los radios.
            if (SysMath.Sign(radius1) != SysMath.Sign(radius0))
            {
                if (double.IsInfinity(radius0))
                {
                    radius0 = SysMath.Sign(radius1) * double.PositiveInfinity;
                }
                else if (double.IsInfinity(radius1))
                {
                    radius1 = SysMath.Sign(radius0) * double.PositiveInfinity;
                }
                else
                {
                    // No se permite cambio de signo en el radio. Funcionaria???
                    Contract.Assert(false);
                }
            }

            if (SysMath.Abs(radius0) > SysMath.Abs(radius1))
            {
                // t positivas
                this.InvertY = radius1 < 0;
            }
            else
            {
                // t negativa
                this.InvertY = radius1 > 0;
            }

            // Diferencia de puntos en coordenadas reales.
            Vector2d v01 = point1.Sub(point0);

            this.A = SolveParam(v01.Length, radius0, radius1);

            // Desarrollo segun el radio en el punto (0) y (1).
            double l0_n = ClothoUtils.ClothoL(radius0, this.InvertY, this.A);
            double l1_n = ClothoUtils.ClothoL(radius1, this.InvertY, this.A);

            // Coordenadas en el punto (0) y (1) para una clotoide normalizada.
            Point2d p0_n = ClothoUtils.Clotho(l0_n, this.InvertY, this.A);
            Point2d p1_n = ClothoUtils.Clotho(l1_n, this.InvertY, this.A);

            Vector2d v01_n = p1_n.Sub(p0_n);

            // Rotacion de v01_n -> v01.
            double r = v01_n.AngleTo(v01);

            // Transformacion a aplicar.
            this.transform = Transform2.Translate(point1.X - p1_n.X, point1.Y - p1_n.Y)
                             .Concat(Transform2.Rotate(p1_n.X, p1_n.Y, r));

            this.l0 = l0_n;
            this.l1 = l1_n;

            this.SetTInterval(l0, l0 + (this.l1 - this.l0));
        }
示例#9
0
        public void Test1()
        {
            for (double a = 0.5; a < 10; a += 0.5)
            {
                foreach (bool invertY in new[] { false, true })
                {
                    int ysign = invertY ? -1 : 1;

                    double[] angles =
                    {
                        ysign * 0,
                             ysign *SysMath.PI / 4,
                             ysign *SysMath.PI / 2,
                             ysign * 3 *SysMath.PI / 4
                    };
                    foreach (double angle in angles)
                    {
                        Vec2d v = vecMath.NewRotate(angle);

                        double l    = ClothoUtils.FindTangent(invertY, a, v);
                        double l_v2 = ClothoUtils.FindTangent(invertY, a, angle);

                        // Se comprueba que las busquedas de tangente sean equivalentes.
                        Assert.IsTrue(l.EpsilonEquals(l_v2));

                        // Se comprueba que la solucion corresponde con el vector tangente.
                        Vec2d d_pos = ClothoUtils.DClotho(l, invertY, a);
                        Assert.IsTrue(d_pos.Cross(v).EpsilonEquals(0));

                        Vec2d d_neg = ClothoUtils.DClotho(-l, invertY, a);
                        Assert.IsTrue(d_neg.Cross(v).EpsilonEquals(0));
                    }
                }
            }
        }
示例#10
0
        /// <summary>
        ///     Resuelve el parametro de la clotoide dado los radios <c>r0</c> y <c>r1</c> Con una distancia <c>d</c> entre los
        ///     puntos.
        /// </summary>
        private static double SolveParam(double d, double r0, double r1)
        {
            Func <double, double> f = (a) =>
            {
                double fs0, fc0;
                ClothoUtils.Fresnel(a / (r0 * sqrtpi), out fs0, out fc0);

                double fs1, fc1;
                ClothoUtils.Fresnel(a / (r1 * sqrtpi), out fs1, out fc1);

                double fc10 = (fc1 - fc0);
                double fs10 = (fs1 - fs0);

                return(a * a * SysMath.PI * (fc10 * fc10 + fs10 * fs10) - d * d);
            };

            int maxEval = 50; // 30

            try
            {
                double min = 0;
                double max = SysMath.Min(SysMath.Abs(r0), SysMath.Abs(r1)) * ClothoUtils.MAX_L;
                double v   = Solver.Solve(f, min, max, Solver.Type.BrentSolver, DEFAULT_ABSOLUTE_ACCURACY, maxEval);
                return(v);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
                throw;
            }
        }
示例#11
0
        public void Test1()
        {
            const double error = 1e-8;

            // desarrollo, r, parametro, x, y, c, normal ¿o direccion?,
            for (int i = 0; i < this.testData1.Length;)
            {
                double l     = this.testData1[i++];
                double r     = this.testData1[i++];
                double a     = this.testData1[i++];
                double x     = this.testData1[i++];
                double y     = this.testData1[i++];
                double radio = this.testData1[i++];
                double tg    = this.testData1[i++];

                bool invertY = ((l < 0 && r > 0) || (l > 0 && r < 0));

                double x2, y2;
                ClothoUtils.Clotho(l, invertY, a, out x2, out y2);
                double radio2 = ClothoUtils.ClothoRadius(l, invertY, a);
                double tg2    = ClothoUtils.ClothoTangent(l, invertY, a);

                Assert.IsTrue(x.EpsilonEquals(x2, error));
                Assert.IsTrue(y.EpsilonEquals(y2, error));
                Assert.IsTrue((double.IsInfinity(radio) && double.IsInfinity(radio2)) || radio.EpsilonEquals(radio2, error));
                Assert.IsTrue(AngleUtils.Ensure0To2Pi(tg).EpsilonEquals(AngleUtils.Ensure0To2Pi(tg2), error));
            }
        }
示例#12
0
        public static ITransform2 EvaluateTransform(Point2d point0, Point2d point1,
                                                    double radius0, double radius1,
                                                    double a)
        {
            // Correccion sobre los radios.
            if (SysMath.Sign(radius1) != SysMath.Sign(radius0))
            {
                if (double.IsInfinity(radius0))
                {
                    radius0 = SysMath.Sign(radius1) * double.PositiveInfinity;
                }
                else if (double.IsInfinity(radius1))
                {
                    radius1 = SysMath.Sign(radius0) * double.PositiveInfinity;
                }
                else
                {
                    // No se permite cambio de signo en el radio. Funcionaria???
                    Contract.Assert(false);
                }
            }

            bool invertY;

            if (SysMath.Abs(radius0) > SysMath.Abs(radius1))
            {
                // t positivas
                invertY = radius1 < 0;
            }
            else
            {
                // t negativa
                invertY = radius1 > 0;
            }

            // Diferencia de puntos en coordenadas reales.
            Vector2d v01 = point1.Sub(point0);

            // Desarrollo segun el radio en el punto (0) y (1).
            double l0_n = ClothoUtils.ClothoL(radius0, invertY, a);
            double l1_n = ClothoUtils.ClothoL(radius1, invertY, a);

            // Coordenadas en el punto (0) y (1) para una clotoide normalizada.
            Point2d p0_n = ClothoUtils.Clotho(l0_n, invertY, a);
            Point2d p1_n = ClothoUtils.Clotho(l1_n, invertY, a);

            Vector2d v01_n = p1_n.Sub(p0_n);

            // Rotacion de v01_n -> v01.
            double r = v01_n.AngleTo(v01);

            // Transformacion a aplicar.
            return(Transform2.Translate(point1.X - p1_n.X, point1.Y - p1_n.Y)
                   .Concat(Transform2.Rotate(p1_n.X, p1_n.Y, r)));
        }
示例#13
0
        private double GetL(double t)
        {
            t = t.Clamp(this.tmin, this.tmax);
            double dl = this.ttransform.Get(t);

            if (SysMath.Abs(dl) > ClothoUtils.GetMaxL(this.a))
            {
                throw new Exception("Longitud del arco por encima del máximo permitido.");
            }
            return(dl);
        }
示例#14
0
        public override Vec2d GetPosition(double t)
        {
            /*
             *  Maxima:
             *  s:      t * m + n;
             *  x:      a*sqrt(%pi)*fresnel_c(s/(a*sqrt(%pi)));
             *  y:      a*sqrt(%pi)*fresnel_s(s/(a*sqrt(%pi)));
             *  z:      1;
             *  result: [ x, y, z ];
             *
             *  result: [sqrt(%pi)*a*fresnel_c((m*t+n)/(sqrt(%pi)*a)),sqrt(%pi)*a*fresnel_s((m*t+n)/(sqrt(%pi)*a)),1]
             */
            double dl = this.GetL(t);
            Vec2d  pt = ClothoUtils.Clotho(dl, this.InvertY, this.A);

            return(this.transform.TransformPoint(pt));
        }
示例#15
0
        public void Test3()
        {
            int i = 0;

            while (i < this.testData3_sc.Length)
            {
                double v1 = this.testData3_sc[i++];
                double s1 = ClothoUtils.FresnelS(v1);
                double c1 = ClothoUtils.FresnelC(v1);

                double s2 = this.testData3_sc[i++];
                double c2 = this.testData3_sc[i++];

                Assert.IsTrue(s1.EpsilonEquals(s2));
                Assert.IsTrue(c1.EpsilonEquals(c2));
            }
        }
示例#16
0
        public override Vec2d GetSecondDerivative(double t)
        {
            /*
             *  Maxima:
             *  s:      t * m + n;
             *  x:      a*sqrt(%pi)*fresnel_c(s/(a*sqrt(%pi)));
             *  y:      a*sqrt(%pi)*fresnel_s(s/(a*sqrt(%pi)));
             *  z:      1;
             *  result: diff([ x, y, z ], t, 2);
             *
             *  result: [-(m^2*(m*t+n)*sin((m*t+n)^2/(2*a^2)))/a^2,(m^2*(m*t+n)*cos((m*t+n)^2/(2*a^2)))/a^2,0]
             */
            double m  = this.ttransform.A;
            double m2 = m * m;

            double dl = this.GetL(t);
            Vec2d  v  = ClothoUtils.DClotho2(dl, this.InvertY, this.A);

            v = v.Mul(m2);
            return(this.transform.TransformVector(v));
        }
示例#17
0
        public void Test2()
        {
            double a       = 10;
            bool   invertY = true;
            double maxL    = ClothoUtils.GetMaxL(a);

            int ysign = invertY ? -1 : 1;

            double[] angles =
            {
                ysign * 0,
                     ysign *SysMath.PI / 4,
                     ysign *SysMath.PI / 2,
                     ysign * 3 *SysMath.PI / 4
            };

            using (MaterialFormat mf = new MaterialFormat(@"C:\Temp\Default.mtl"))
            {
                mf.DefaultColors();
            }

            using (WavefrontFormat wf = new WavefrontFormat(@"C:\Temp\ClothoidArc2dTest_Test2.obj"))
            {
                wf.LoadMaterialLib("Default.mtl");
                wf.DrawClotho(invertY, a, "Red");

                foreach (double angle in angles)
                {
                    Vec2d  v = vecMath.NewRotate(angle);
                    double l = ClothoUtils.FindTangent(invertY, a, v);
                    wf.DrawLine("Green", ClothoUtils.Clotho(l, invertY, a), v);
                    wf.DrawLine("Magenta", ClothoUtils.Clotho(-l, invertY, a), v);
                }

                //wf.DrawLine("Yellow", new Vec2d(0, 0), new Vec2d(1, 0), 100);
                //wf.DrawLine("Yellow", new Vec2d(0, 0), new Vec2d(0, 1), 100);
            }
        }
示例#18
0
        public void Test1()
        {
            const double error = 1e-8;

            // desarrollo, r, parametro, x, y, c, normal ¿o direction?,
            for (int i = 0; i < this.testData1.Length;)
            {
                double s     = this.testData1[i++];
                double r     = this.testData1[i++];
                double a     = this.testData1[i++];
                double x     = this.testData1[i++];
                double y     = this.testData1[i++];
                double radio = this.testData1[i++];
                double tg    = this.testData1[i++];

                // NOTA: Clip toma las clotoides con s < 0 invertidas en Y.
                if (s < 0)
                {
                    y     = -y;
                    tg    = 2 * SysMath.PI - tg;
                    radio = -radio;
                }

                double x2, y2;
                ClothoUtils.Clotho(s, r < 0, a, out x2, out y2);
                double radio2     = ClothoUtils.ClothoRadious(s, r < 0, a);
                double tg2        = ClothoUtils.ClothoTangent(s, r < 0, a);
                double direction2 = ClothoUtils.ClothoTangent(s, r < 0, a);

                Assert.IsTrue(x.EpsilonEquals(x2, error));
                Assert.IsTrue(y.EpsilonEquals(y2, error));
                Assert.IsTrue((double.IsInfinity(radio) && double.IsInfinity(radio2)) || radio.EpsilonEquals(radio2, error));
                //Assert.IsTrue(AngleUtils.Ensure0To2Pi(normal).EpsilonEquals(AngleUtils.Ensure0To2Pi(normal2), error));

                //Assert.IsTrue(AngleUtils.Ensure0To2Pi(tg).EpsilonEquals(AngleUtils.Ensure0To2Pi(tg2), error));
            }
        }
示例#19
0
        public static ClothoidArc2[] Split(double l0,
                                           Vec2d point0, Vec2d point1,
                                           double radius0, double radius1,
                                           double a)
        {
            bool invertY = (radius1 < 0);

            double l0_n = ClothoUtils.ClothoL(radius0, invertY, a);
            double l1_n = ClothoUtils.ClothoL(radius1, invertY, a);

            Contract.Assert(l0_n < 0 && l1_n > 0);

            // Coordenadas en el punto (0) y (1) para una clotoide normalizada.
            Vec2d p0_n = ClothoUtils.Clotho(l0_n, invertY, a);
            Vec2d p1_n = ClothoUtils.Clotho(l1_n, invertY, a);

            // Diferencia de puntos en coordenadas reales.
            Vec2d v01 = point1.Sub(point0);

            Vec2d v01_n = p1_n.Sub(p0_n);

            // Rotacion de v01_n -> v01.
            double r = vecMath.Angle(v01_n, v01);

            // Transformacion a aplicar.
            Transform2 transform = Transform2.Translate(point1.X - p1_n.X, point1.Y - p1_n.Y)
                                   .Mult(Transform2.Rotate(p1_n.X, p1_n.Y, r));

            ClothoidArc2 left  = new ClothoidArc2(transform, l0_n, 0, invertY, a);
            ClothoidArc2 right = new ClothoidArc2(transform, 0, l1_n, invertY, a);

            left.SetTInterval(l0, l0 + (-l0_n)); // l0_n < 0
            right.SetTInterval(l0 + (-l0_n), l0 + (-l0_n) + l1_n);

            return(new[] { left, right });
        }
示例#20
0
        public static WavefrontFormat DrawClotho(this WavefrontFormat wf,
                                                 bool invertY, double a,
                                                 string clothoColor,
                                                 string dirColor,
                                                 string normalColor,
                                                 string radColor)
        {
            List <int> indices = new List <int>();
            List <Tuple <int, int> > normals = new List <Tuple <int, int> >();
            List <Tuple <int, int> > dirs    = new List <Tuple <int, int> >();
            List <Tuple <int, int> > radius  = new List <Tuple <int, int> >();

            int c = 100;

            for (int i = -c; i <= c; i++)
            {
                double lmax = ClothoUtils.GetMaxL(a);
                double s    = i * lmax / c;

                Point2d xy = ClothoUtils.Clotho(s, invertY, a);

                int v0 = wf.AddVertex(xy);
                indices.Add(v0);

                Vector2d n = ClothoUtils.ClothoLeftNormal(s, invertY, a).Unit;

                int v1 = wf.AddVertex(xy.Add(n));
                normals.Add(Tuple.Create(v0, v1));

                double   dir = ClothoUtils.ClothoTangent(s, invertY, a);
                Vector2d d   = Vector2d.NewRotate(dir);

                int v2 = wf.AddVertex(xy.Add(d.Mul(5)));
                dirs.Add(Tuple.Create(v0, v2));

                double r = ClothoUtils.ClothoRadius(s, invertY, a);
                if (double.IsInfinity(r))
                {
                    r = SysMath.Sign(r) * 100;
                }

                int v3 = wf.AddVertex(xy.Add(n.Mul(r)));
                radius.Add(Tuple.Create(v0, v3));

                //double dx, dy;
                //MathUtils.DClotho(s, r, a, out dx, out dy);
            }

            wf.UseMaterial(clothoColor);
            wf.AddLines(indices, false);

            wf.UseMaterial(normalColor);
            foreach (Tuple <int, int> normal in normals)
            {
                wf.AddLines(new[] { normal.Item1, normal.Item2 }, false);
            }

            wf.UseMaterial(dirColor);
            foreach (Tuple <int, int> dir in dirs)
            {
                wf.AddLines(new[] { dir.Item1, dir.Item2 }, false);
            }

            wf.UseMaterial(radColor);
            foreach (Tuple <int, int> rr in radius)
            {
                wf.AddLines(new[] { rr.Item1, rr.Item2 }, false);
            }
            return(wf);
        }
示例#21
0
        /// <summary>
        ///     Prueba el constructor ClothoidArc2d(double,Vec2d,Vec2d,double,double).
        /// </summary>
        private static void TestClotho(double a, bool invertY, bool negX, double tg0, double tg1, Vec2d p0, Vec2d dir,
                                       string fileName = null, bool toWavefront = false)
        {
            //double a = 5;
            //bool invertY = true;

            //double tg0 = -4 * SysMath.PI / 10;
            //double tg1 = -SysMath.PI / 10;

            // Si se indica negX, se invierten las tangentes.
            int sign = 1;

            if (negX)
            {
                sign = -1;
            }

            double l0 = sign * ClothoUtils.FindTangent(invertY, a, tg0);
            double l1 = sign * ClothoUtils.FindTangent(invertY, a, tg1);

            double r0  = ClothoUtils.ClothoRadious(l0, invertY, a);
            double r1  = ClothoUtils.ClothoRadious(l1, invertY, a);
            Vec2d  pp0 = ClothoUtils.Clotho(l0, invertY, a);
            Vec2d  pp1 = ClothoUtils.Clotho(l1, invertY, a);

            //Vec2d p0 = new Vec2d(5, 5);
            Vec2d p1 = p0.Add(dir.Mul(pp1.Sub(pp0).Length));

            ClothoidArc2 arc = new ClothoidArc2(l0, p0, p1, r0, r1);

            Assert.IsTrue(arc.Point0.EpsilonEquals(p0, ERROR));
            Assert.IsTrue(arc.Point1.EpsilonEquals(p1, ERROR));
            Assert.IsTrue(arc.GetRadius(arc.TMin).EpsilonEquals(r0, ERROR));
            Assert.IsTrue(arc.GetRadius(arc.TMax).EpsilonEquals(r1, ERROR)); // <-
            Assert.IsTrue(arc.InvertY == invertY);
            Assert.IsTrue(arc.A.EpsilonEquals(a, ERROR));

            // Salida por fichero de la prueba.
            if ((fileName != null) && toWavefront)
            {
                double figSize = 0.5;

                string mtl = Path.ChangeExtension(fileName, "mtl");

                using (MaterialFormat mf = new MaterialFormat(mtl))
                {
                    mf.DefaultColors();
                }

                using (WavefrontFormat wf = new WavefrontFormat(fileName))
                {
                    wf.LoadMaterialLib(Path.GetFileName(mtl));

                    wf.DrawLine("Yellow", Vec2d.Zero, new Vec2d(1, 0), 50);
                    wf.DrawLine("Yellow", Vec2d.Zero, new Vec2d(0, 1), 50);

                    wf.DrawFigure("Blue", WaveFigure.X, ClothoUtils.Clotho(l0, invertY, a), figSize);
                    wf.DrawFigure("Olive", WaveFigure.X, ClothoUtils.Clotho(l1, invertY, a), figSize);

                    wf.DrawClotho(invertY, a, "Red");

                    wf.DrawClotho("Magenta", arc);

                    wf.DrawFigure("Blue", WaveFigure.X, p0, figSize);
                    wf.DrawFigure("Olive", WaveFigure.X, p1, figSize);
                }
            }
        }
示例#22
0
        public double GetRadius(double t)
        {
            double dl = this.GetL(t);

            return(ClothoUtils.ClothoRadious(dl, this.InvertY, this.A));
        }
示例#23
0
        public new double GetTangent(double t)
        {
            double dl = this.GetL(t);

            return(ClothoUtils.ClothoTangent(dl, this.InvertY, this.A));
        }