Beispiel #1
0
        public override Vector2d Tangent(Point2d where)
        {
            Transform2d tr = Transform2d.Rotate(-rotation); // ToStandardPosition;

            where = where.GetTransformed(tr);
            Point2d stdvertex = vertex.GetTransformed(tr);

            double slope = 2 * a * (where.X - stdvertex.X); ///(4*FocalDistance); //from diffrentiation

            //TODO: reverse vector if wrong direction
            return(Vector2d.FromSlope(slope).GetTransformed(tr.Inversed));
        }
Beispiel #2
0
        public override Point2d PointAt(double t)
        {
            double  f   = FocalDistance;
            Point2d res = new Point2d(t, a * t * t);

            //TODO: need to be optimized!!
            return(res.GetTransformed(Transform2d.Rotate(rotation) * Transform2d.Translate(vertex.X, vertex.Y)));
        }
Beispiel #3
0
        public override Vector2d Tangent(Point2d pnt)
        {
            double a = majoraxis.Length;
            double b = MinorAxis.Length;


            pnt = pnt.GetTransformed(ToStandardPosition);

            double slope = -(sigratio * sigratio * pnt.X) / (pnt.Y);

            return(Vector2d.FromAngle(Math.Atan(slope) + (pnt.Y < 0.0 ? 0.0:MathUtil.PI))); //TODO: not correct slope, inverted sometimes
        }
Beispiel #4
0
        public override bool Transform(Transform2d t)
        {
            if (t.IsUniform)
            {
                return(false);
            }

            start = start.GetTransformed(t);
            end   = end.GetTransformed(t);

            if (t.Determinant < 0.0)
            {
                bulge = -bulge; //mirror
            }
            return(true);
        }
Beispiel #5
0
        public override bool Transform(Transform2d t)
        {
            //transform hyperbola centered at origin, because it's more stable general conic
            Hyperbola2d hyp = new Hyperbola2d(this);

            hyp.center = Point2d.Origo;
            var gencon = hyp.ToGeneralConic();

            if (!gencon.Transform(new Transform2d(t.AX, t.AY, t.BX, t.BY, 0.0, 0.0)))
            {
                return(false);
            }

            hyp = gencon.Reduce() as Hyperbola2d;
            if (hyp == null)
            {
                return(false);
            }

            //now transform centerpoint separately,
            //and write bac to this
            center    = center.GetTransformed(t);
            ratio     = hyp.ratio;
            majoraxis = hyp.majoraxis;

            return(true);


            /* double majax = majoraxis.Length;
             * double minax = -majax * ratio;
             * double rot = Rotation;
             * bool reverse;
             * Hyperbola_Transform(ref majax, ref minax, ref rot, ref center, t, out reverse);
             *
             * majoraxis = Vector2d.FromAngleAndLength(rot, majax);
             * ratio = minax / majax;
             *
             * return true;*/
        }
Beispiel #6
0
        public Point2d Eval(double t)
        {
            //see http://en.wikipedia.org/wiki/Superellipse

            //t must be between 0 and pi/2
            double xsign, ysign;

            // t = MathUtil.NormalizeAngle(t);
            if (t > MathUtil.Deg270)
            {
                xsign = 1.0;
                ysign = -1.0;
            }
            else if (t > MathUtil.Deg180)
            {
                xsign = -1;
                ysign = -1;
            }
            else if (t > MathUtil.Deg90)
            {
                xsign = -1.0;
                ysign = 1.0;
            }
            else
            {
                xsign = 1.0;
                ysign = 1.0;
            }

            //evaluate in standard position and transform
            double  p2 = 2.0 / power;
            Point2d pt = new Point2d(
                Math.Pow(Math.Abs(Math.Cos(t)), p2) * xsign,
                Math.Pow(Math.Abs(Math.Sin(t)), p2) * ratio * ysign
                );

            return(pt.GetTransformed(FromStandardPosition));
        }
Beispiel #7
0
        internal static void Ellipse_Transform(ref double a_rh, ref double a_rv, ref double a_offsetrot, ref Point2d endpoint, Transform2d a_mat, out bool a_ReverseWinding)
        {
            double rh, rv, rot;

            double[] m = new double[4]; // matrix representation of transformed ellipse
            double   s, c;              // sin and cos helpers (the former offset rotation)
            double   A, B, C;           // ellipse implicit equation:
            double   ac, A2, C2;        // helpers for angle and halfaxis-extraction.

            rh  = a_rh;
            rv  = a_rv;
            rot = a_offsetrot;

            s = Math.Sin(rot);
            c = Math.Cos(rot);

            // build ellipse representation matrix (unit circle transformation).
            // the 2x2 matrix multiplication with the upper 2x2 of a_mat is inlined.
            m[0] = a_mat.AX * +rh * c + a_mat.BX * rh * s;
            m[1] = a_mat.AY * +rh * c + a_mat.BY * rh * s;
            m[2] = a_mat.AX * -rv * s + a_mat.BX * rv * c;
            m[3] = a_mat.AY * -rv * s + a_mat.BY * rv * c;

            // to implict equation (centered)
            A = (m[0] * m[0]) + (m[2] * m[2]);
            C = (m[1] * m[1]) + (m[3] * m[3]);
            B = (m[0] * m[1] + m[2] * m[3]) * 2.0f;

            // precalculate distance A to C
            ac = A - C;

            // convert implicit equation to angle and halfaxis:
            if (MathUtil.IsZero(B)) //=not tilted
            {
                if (MathUtil.IsZero(ac) || A > C)
                {
                    a_offsetrot = 0;
                }
                else
                {
                    a_offsetrot = MathUtil.Deg90;
                }



                A2 = A;
                C2 = C;
            }
            else
            {
                if (MathUtil.IsZero(ac))
                {
                    A2          = A + B * 0.5f;
                    C2          = A - B * 0.5f;
                    a_offsetrot = MathUtil.PI / 4.0f;
                }
                else
                {
                    // Precalculate radical:
                    double K = 1 + B * B / (ac * ac);

                    // Clamp (precision issues might need this.. not likely, but better safe than sorry)
                    if (K < 0)
                    {
                        K = 0;
                    }
                    else
                    {
                        K = Math.Sqrt(K);
                    }

                    A2          = 0.5f * (A + C + K * ac);
                    C2          = 0.5f * (A + C - K * ac);
                    a_offsetrot = 0.5f * Math.Atan2(B, ac);
                }
            }

            // This can get slightly below zero due to rounding issues.
            // it's save to clamp to zero in this case (this yields a zero length halfaxis)
            if (A2 < 0)
            {
                A2 = 0;
            }
            else
            {
                A2 = Math.Sqrt(A2);
            }
            if (C2 < 0)
            {
                C2 = 0;
            }
            else
            {
                C2 = Math.Sqrt(C2);
            }

            // now A2 and C2 are half-axis:
            if (ac <= 0)
            {
                a_rv = A2;
                a_rh = C2;
            }
            else
            {
                a_rv = C2;
                a_rh = A2;
            }

            // The transformation matrix might contain a mirror-component, and the
            // winding order of the ellise needs to be changed.
            // check the sign of the upper 2x2 submatrix determinant to find out..
            a_ReverseWinding = ((a_mat.AX * a_mat.BY) - (a_mat.AY * a_mat.BX)) < 0 ? true : false;

            // finally, transform ellipse endpoint. This takes care about the
            // translational part which we ignored at the whole math-showdown above.
            endpoint = endpoint.GetTransformed(a_mat);
        }
Beispiel #8
0
        /// <summary>
        /// Returns all the perpendicular points on the ellipse from a given point 'from'
        /// </summary>
        public Point2d[] Perpendicular(Point2d from)
        {
            // Solved by Robert.P. in december 2012
            // Note on solutions:
            // Quartic coefficients gotten from applying lagrange multiplier to minimize (x-i)^2+(y-j)^2
            // with x^2/a^2+y^2/b^2-1=0 as constraint (a=1 because we work in standard position).
            // This gives a system of three equations F_x,F_y,F_lambda, which were solved with
            // resultant theory using 'eliminate' in maxima

            //work in standard position, retranslate solutions last
            Transform2d tostd = ToStandardPosition;

            from = from.GetTransformed(tostd);

            double b = sigratio, b2 = b * b, b4 = b2 * b2;
            double i = from.X, i2 = i * i;
            double j = from.Y, j2 = j * j;


            double x4 = b4 - 2 * b2 + 1;
            double x3 = 2 * b2 * i - 2 * i;
            double x2 = b2 * j2 + i2 - b4 + 2 * b2 - 1;
            double x1 = 2 * i - 2 * b2 * i;
            double x0 = -i2;

            double[] sols = RealPolynomial.SolveQuartic2(x4, x3, x2, x1, x0, 1e-16);

            if (sols == null)
            {
                return(null);
            }

            Point2dSet respts = new Point2dSet();

            foreach (double x in sols)
            {
                double y = (1 - x * x) * b2;
                if (y < 0.0)
                {
                    continue;
                }
                y = Math.Sqrt(y);


                for (int l = 0; l < 2; l++)
                {
                    //both posetive and negative y:s can be solutions. Check with each possible
                    //point that its perpendicular to ellipse (subtracting the inverse ellipse slope (=normal slope) with the slope from 'from' point)
                    double err;
                    err = y * (from.X - x) - x * b2 * (from.Y - y);
                    if (Math.Abs(err) < 1e-6)
                    {
                        respts.Add(new Point2d(x, y));
                    }

                    y = -y; //test negative solution as well
                }
            }

            respts.Transform(tostd.Inversed);
            return(respts.ToArray());
        }
Beispiel #9
0
 public override bool Transform(Transform2d t)
 {
     start = start.GetTransformed(t);
     end   = end.GetTransformed(t);
     return(true);    //a line can always be transformed
 }