Beispiel #1
0
        public void Add()
        {
            var p2 = new Vec2d(1, 2);

            Assert.AreEqual(new Vec2d(2, 4), p2.Added(new Vec2d(1, 2)));
            p2.Add(new Vec2d(1, 2));
            Assert.AreEqual(new Vec2d(2, 4), p2);
        }
        public static WavefrontFormat DrawLine(this WavefrontFormat wf,
                                               string color,
                                               Vec2d point,
                                               Vec2d v,
                                               double ext = 1000)
        {
            wf.UseMaterial(color);
            Vec2d p0 = point.Sub(v.Mul(ext));
            Vec2d p1 = point.Add(v.Mul(ext));

            wf.AddLines(new Vec2d[] { p0, p1 }, false);
            return(wf);
        }
Beispiel #3
0
        /// <summary>
        ///     Obtiene el centro de la circunferencia que pasa por los 2 puntos, con el radio indicado.
        ///     Dependiendo del criterio (leftRule), se interpreta el signo del radio:
        ///     Si leftRule entonces el radio se multiplica por la normal a la izquierda (leftNormal) para obtener el centro de la
        ///     circunferencia.
        ///     Si rightRule (!leftRule) entonces el radio se multiplica por la normal a la derecha (rightNormal) para obtener el
        ///     centro de la circunferencia.
        ///     Clip utiliza un criterio rightRule.
        ///     <p />
        ///     Criterio rightRule:
        ///     <c><![CDATA[
        ///            _                  _
        ///         _ /                    \c
        ///       _/ O pf                   O
        ///     _/  /                      / \
        ///    /  _/             radio - _/  |
        ///   /   /|  radio +     <--    /|  |
        ///   |  /      -->             /    /
        ///   / /                      /   _/
        ///   |/                      /  _/
        ///   O pi                   O__/
        ///    \                   _/
        /// ]]></c>
        ///     <![CDATA[
        ///  p1   a/2  pm   a/2   p2
        ///  x---------+-------->x
        ///   \        |        /
        ///    \       |       /
        ///     \      |      /
        ///      \     |b    /
        ///       \    |    / r
        ///        \   |   /
        ///         \  |  /
        ///          \ | /
        ///           \|/
        ///            pc
        /// ]]>
        ///     Teniendo como dato p1, p2 y r, tenemos que obtener el centro del circulo que pasa por
        ///     p1 y p2, con radio r.
        ///     Con el vector 1-2 obtenemos la distancia a.
        ///     b es calculado mediante la fórmula b = raizcua(r * r + a/2 * a/2).
        ///     Creamos un vector perpendicular al 1-2 a una distacion a/2 desde p1 y obtenemos
        ///     el punto central de la circunferencia.
        ///     Con este dato y conociendo el radio ya simplemente calculamos la esquina del rectangulo.
        ///     Si el radio es positivo, avanza en sentido contrario a las agujas del reloj.
        ///     Si el radio es negativo, avanza en sentido de las agujas del reloj.
        ///     <![CDATA[
        ///                   + p2
        ///                  /|\
        ///                   |
        ///  /____            |            ____\
        ///  \    \___        |        ___/    /
        ///           \__     |     __/
        ///              \_   |   _/
        ///   radio -      \  |  /   radio +
        ///   (giro         \ | /    (giro horario)
        ///     antihorario) \|/
        ///                   |
        ///                   + p1
        /// ]]>
        /// </summary>
        /// <exception cref="CalculoImposibleException">
        ///     Indica que no se puede calcular el
        ///     centro.
        /// </exception>
        public static Vec2d EvaluateCenter(Vec2d pt0, Vec2d pt1, double radius, bool leftRule)
        {
            // Vector direccion normalizado y longitud.
            Vec2d  dir = pt1.Sub(pt0);
            double a   = dir.Length;

            if (a.EpsilonEquals(0))
            {
                throw new Exception("CalculoImposible: Puntos coincidentes.");
            }

            dir = dir.Div(a);

            // Punto medio.
            Vec2d pm = vecMath.Interpolate(pt0, pt1, 0.5);

            // Se tratan radios erroneos que no permitan generar un circunferencia.
            double v = radius * radius - a * a / 4;

            if (v.EpsilonEquals(0))
            {
                return(pm);
            }
            if (v < 0)
            {
                throw new Exception("CalculoImposible: Radio erroneo.");
            }

            double b = SysMath.Sign(radius) * SysMath.Sqrt(v);

            Vec2d normal;

            if (leftRule)
            {
                // Vector normal a la izquierda.
                normal = vecMath.PerpLeft(dir);
            }
            else
            {
                // Vector normal a la derecha.
                normal = vecMath.PerpRight(dir);
            }

            Vec2d vectorm1 = normal.Mul(b);

            return(pm.Add(vectorm1));
        }
        public void ValueType_Vec2d()
        {
            var p1 = new Vec2d(1, 0);
            var p2 = new Vec2d(0, 1);

            Assert.IsFalse(p1.IsEqual(p2, 0.99, 0.1));
            Assert.IsTrue(p1.IsEqual(p2, 1.01, 0.1));
            Assert.IsTrue(p1.IsEqual(p2, 0.99, Math.PI / 2));
            Assert.IsTrue(p1.IsNormal(p2, 0.1));
            Assert.IsFalse(p1.IsOpposite(p2, 0.1));
            Assert.IsTrue(p1.IsOpposite(p2, Math.PI / 2));
            Assert.IsFalse(p1.IsParallel(p2, 0.1));
            Assert.IsTrue(p1.IsParallel(p2, Math.PI / 2));

            p1 = new Vec2d(1, 2);
            p2 = new Vec2d(4, 5);

            Assert.AreEqual(5, p1.SquareMagnitude());
            Assert.AreEqual(Math.Sqrt(5), p1.Magnitude());

            p2 = p1;
            p2.Add(new Vec2d(1, 2));
            Assert.AreEqual(new Vec2d(2, 4), p2);
            Assert.AreEqual(new Vec2d(2, 4), p1.Added(new Vec2d(1, 2)));

            p2 = new Vec2d(1, 2);
            p2.Subtract(new Vec2d(3, 2));
            Assert.AreEqual(new Vec2d(-2, 0), p2);
            Assert.AreEqual(new Vec2d(-2, 0), p1.Subtracted(new Vec2d(3, 2)));

            p2 = new Vec2d(1, 2);
            Assert.AreEqual(-4, p1.Crossed(new Vec2d(3, 2)));

            Assert.AreEqual(Math.Sqrt(16), p1.CrossMagnitude(new Vec2d(3, 2)));
            Assert.AreEqual(16, p1.CrossSquareMagnitude(new Vec2d(3, 2)));

            p2 = new Vec2d(1, 2);
            p2.Divide(2);
            Assert.AreEqual(new Vec2d(0.5, 1), p2);
            Assert.AreEqual(new Vec2d(0.5, 1), p1.Divided(2));

            Assert.AreEqual(5, p1.Dot(new Vec2d(1, 2)));

            p2 = new Vec2d(1, 2);
            p2.Multiply(2);
            Assert.AreEqual(new Vec2d(2, 4), p2);
            Assert.AreEqual(new Vec2d(2, 4), p1.Multiplied(2));

            p2 = new Vec2d(1, 2);
            p2.Scale(2);
            Assert.AreEqual(new Vec2d(2, 4), p2);
            Assert.AreEqual(new Vec2d(2, 4), p1.Scaled(2));

            p2 = new Vec2d(1, 23);
            Assert.AreEqual("0.0434372242763069,0.99905615835506", p2.Normalized().ToString());
            p2.Normalize();
            Assert.AreEqual("0.0434372242763069,0.99905615835506", p2.ToString());

            p2 = new Vec2d(1, 2);
            p2.Reverse();
            Assert.AreEqual(new Vec2d(-1, -2), p2);
            Assert.AreEqual(new Vec2d(-1, -2), p1.Reversed());

            p2.SetLinearForm(new Vec2d(1, 2), new Vec2d(4, 5));
            Assert.AreEqual(new Vec2d(5, 7), p2);
            p2.SetLinearForm(2, new Vec2d(1, 2), new Vec2d(4, 5));
            Assert.AreEqual(new Vec2d(6, 9), p2);
            p2.SetLinearForm(2, new Vec2d(1, 2), 3, new Vec2d(4, 5));
            Assert.AreEqual(new Vec2d(14, 19), p2);
            p2.SetLinearForm(2, new Vec2d(1, 2), 3, new Vec2d(4, 5), new Vec2d(7, 8));
            Assert.AreEqual(new Vec2d(21, 27), p2);

            p2 = new Vec2d(2, 1);
            Assert.AreEqual(new Vec2d(1, 0), p2.Mirrored(new Vec2d(1, 0)));
            p2.Mirror(new Vec2d(1, 0));
            Assert.AreEqual(new Vec2d(1, 0), p2);

            var m2 = new Ax2d(new Pnt2d(-1, 2), new Dir2d(-1, 0));

            p2 = new Vec2d(2, 1);
            Assert.AreEqual(new Vec2d(2, -1), p2.Mirrored(m2));
            p2.Mirror(m2);
            Assert.AreEqual(new Vec2d(2, -1), p2);

            p2 = new Vec2d(2, 1);
            Assert.AreEqual("-1,2", p2.Rotated(Math.PI / 2).ToString());
            p2.Rotate(Math.PI / 2);
            Assert.AreEqual("-1,2", p2.ToString());

            //TestContext.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", gp2.x, gp2.y, gp2.z));

            Trsf2d t1 = new Trsf2d();

            t1.SetRotation(new Pnt2d(1, 2), Math.PI / 2);
            p2 = new Vec2d(2, 1);
            Assert.AreEqual("-1,2", p2.Transformed(t1).ToString());
            p2.Transform(t1);
            Assert.AreEqual("-1,2", p2.ToString());
        }
        /// <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);
                }
            }
        }
        public static WavefrontFormat DrawFigure(this WavefrontFormat wf,
                                                 string color,
                                                 WaveFigure figure,
                                                 Vec2d point,
                                                 double size)
        {
            wf.UseMaterial(color);
            switch (figure)
            {
            case WaveFigure.Circle:
            {
                wf.AddLines(MathUtils.For(0, 2 * SysMath.PI, 20).Select(t => point.Add(vecMath.NewRotate(t).Mul(size))), true);
                break;
            }

            case WaveFigure.Rectangle:
            {
                wf.AddLines(new Vec2d[]
                    {
                        point.Add(new Vec2d(size, size)),
                        point.Add(new Vec2d(-size, size)),
                        point.Add(new Vec2d(-size, -size)),
                        point.Add(new Vec2d(size, -size)),
                    }, true);
                break;
            }

            case WaveFigure.Diamond:
            {
                wf.AddLines(new Vec2d[]
                    {
                        point.Add(new Vec2d(0, size)),
                        point.Add(new Vec2d(-size, 0)),
                        point.Add(new Vec2d(0, -size)),
                        point.Add(new Vec2d(size, 0)),
                    }, true);
                break;
            }

            case WaveFigure.Plus:
            {
                wf.AddLines(new Vec2d[]
                    {
                        point.Add(new Vec2d(0, size)),
                        point.Add(new Vec2d(0, -size)),
                    }, false);
                wf.AddLines(new Vec2d[]
                    {
                        point.Add(new Vec2d(size, 0)),
                        point.Add(new Vec2d(-size, 0)),
                    }, false);
                break;
            }

            case WaveFigure.X:
            {
                wf.AddLines(new Vec2d[]
                    {
                        point.Add(new Vec2d(size, size)),
                        point.Add(new Vec2d(-size, -size)),
                    }, false);
                wf.AddLines(new Vec2d[]
                    {
                        point.Add(new Vec2d(-size, size)),
                        point.Add(new Vec2d(size, -size)),
                    }, false);
                break;
            }

            default:
            {
                throw new Exception();
            }
            }
            return(wf);
        }