Esempio n. 1
0
        public Point2d[] Perpendicular(Point2d from)
        {
            double      i, j; //i,j is from-point in standard space
            Transform2d tr = ToStandardPosition;

            tr.Apply(from.X, from.Y, out i, out j, true);

            //cubic coefficients gotten from langarnge multiplier minimizing distance from i,j to curve
            double[] xs = RealPolynomial.SolveCubic2(-1, 0.0, j - 0.25, 0.25 * i);
            if (xs == null)
            {
                return(null);
            }

            Point2d[] res = new Point2d[xs.Length];
            tr = tr.Inversed;
            int respos = 0;

            foreach (double x in xs)
            {
                tr.Apply(x, x * x, out i, out j, true);
                res[respos++] = new Point2d(i, j);
            }

            return(res);
        }
Esempio n. 2
0
        public static Point2d[] ConicConic(GeneralConic2d tcon1, GeneralConic2d tcon2)
        {
            // uses the beautiful solution to find the multiplier λ, so that Conic11+λ*Conic2 is
            // a degenerate conic, that is a conic of lines (the 'pencil'). The lines in this conic
            // intersects each of the conics in their common intersection points, thus the problem
            // has been reduced to a Conic-Line intersection problem.
            // This technique is described in book Graphics Gems V, of which we are inspired although
            // this code differs a somewhat from the one in the book.

            // work in standard space for conic 1, gives a more stable computation and speeds up
            // the multiple line-conic intersections later on.
            GeneralConic2d con1 = new GeneralConic2d(tcon1);
            GeneralConic2d con2 = new GeneralConic2d(tcon2);



            //TODO: does not work properly, probably because line extractor does not work correctly in some cases


            //convert conic coefficients to their matrix form
            double a = con1.A, b = con1.B * 0.5, c = con1.C, d = con1.D * 0.5, e = con1.E * 0.5, f = con1.F;
            double A = con2.A, B = con2.B * 0.5, C = con2.C, D = con2.D * 0.5, E = con2.E * 0.5, F = con2.F;


            //TODO: since conic 1 is in standard position, thoose can be simplified: b,d,e terms are always zero
            double c3 = (A * C - B * B) * F - A * E * E + 2 * B * D * E - C * D * D;
            double c2 = (a * C - 2 * b * B + c * A) * F - a * E * E + (2 * b * D + 2 * d * B - 2 * e * A) * E - c * D * D + (2 * e * B - 2 * d * C) * D + f * A * C - f * B * B;
            double c1 = (a * c - b * b) * F + (2 * b * d - 2 * a * e) * E + (2 * b * e - 2 * c * d) * D + (a * f - d * d) * C + (2 * d * e - 2 * b * f) * B + (c * f - e * e) * A;
            double c0 = (a * c - b * b) * f - a * e * e + 2 * b * d * e - c * d * d;

            double[] lambdas2 = RealPolynomial.SolveCubic2(c3, c2, c1, c0); //up to three coefficients that will turn conic sum to degenerate lines
            double[] lambdas  = GetRealRoots(c3, c2, c1, c0);



            if (lambdas == null)
            {
                return(null); //this can never happen on a 3d degree equation but we check it anyway
            }
            Point2dSet res = new Point2dSet();

            foreach (double lambda in lambdas)
            {
                GeneralConic2d pencil = new GeneralConic2d(
                    a + lambda * A,
                    (b + lambda * B) * 2,
                    c + lambda * C,
                    (d + lambda * D) * 2,
                    (e + lambda * E) * 2,
                    f + lambda * F);

                Line2d[] lines = pencil.ToLines();

                if (lines != null)
                {
                    foreach (Line2d lin in lines)
                    { //max 2 lines
                        Point2d[] intpts = ConicLine(con1, lin);
                        if (intpts == null)
                        {
                            continue;
                        }

                        //validate each point satisfying the conic equations (they can be out of range for finite conics such as ellipses)
                        foreach (Point2d pt in intpts)
                        {
                            double x    = pt.X;
                            double y    = pt.Y;
                            double err1 = con1.A * x * x + con1.B * x * y + con1.C * y * y + con1.D * x + con1.E * y + con1.F;
                            if (MathUtil.IsZero(err1, 5.0))
                            {
                                double err2 = con2.A * x * x + con2.B * x * y + con2.C * y * y + con2.D * x + con2.E * y + con2.F;
                                if (MathUtil.IsZero(err2, 5.0))
                                {
                                    res.Add(pt);
                                }
                            }
                        }
                    }
                }
            }

            //res.Transform(tr.Inversed);
            return(res.ToArray());
        }