コード例 #1
0
ファイル: VecD.cs プロジェクト: sjvudp/Font-Validator
        bool Perp(Bez2D bez, out Param[] pars)
        {
            /*
             *        MEANING:    perpendicular to the parametric range
             *                    [-Infinity, Infinity] for NON-DEGENERATED,
             *                    NON-FLAT bezier
             */
            pars = null;
            Param parM;

            if (bez.IsDegen)
            {
                throw new ExceptionGMath("VecD", "Perp", null);
                //return false;
            }
            if (bez.IsSeg(out parM) || bez.IsSelfInters(out parM))
            {
                throw new ExceptionGMath("VecD", "Perp", null);
                //return false;
            }
            VecD[] pcf;
            bez.PowerCoeff(out pcf);
            double a = 2 * (pcf[2].Dot(pcf[2]));
            double b = 3 * (pcf[2].Dot(pcf[1]));
            double c = pcf[1].Dot(pcf[1]) + 2 * ((pcf[0] - (this)).Dot(pcf[2]));
            double d = (pcf[0] - (this)).Dot(pcf[1]);
            int    numRootReal;

            double[] root;
            Equation.RootsReal(a, b, c, d, out numRootReal, out root);
            pars = new Param[root.Length];
            for (int iRoot = 0; iRoot < root.Length; iRoot++)
            {
                pars[iRoot] = new Param(root[iRoot]);
            }
            return(true);
        }
コード例 #2
0
        // deg 4
        public static void RootsReal(double a, double b, double c, double d, double e,
                                     out int numRootReal, out double[] root)
        {
            /*
             *  Catch EXACT TANGENTS when they are not obvious
             *    from the control points specification
             */

            double rootToAdd      = -1.0; // asign an invalid parametric value
            int    numRootRealRed = -1;   // roots after reduction

            double[] rootRed = null;
            if (Equation.Evaluate(0.0, a, b, c, d, e) == 0.0)
            {
                rootToAdd = 0.0;
                Equation.RootsReal(a, b, c, d,
                                   out numRootRealRed, out rootRed);
            }
            if (Equation.Evaluate(1.0, a, b, c, d, e) == 0.0)
            {
                rootToAdd = 1.0;
                Equation.RootsReal(a, a + b, a + b + c, a + b + c + d,
                                   out numRootRealRed, out rootRed);
            }
            if (rootToAdd != -1.0)
            {
                root        = new double[numRootRealRed + 1];
                numRootReal = numRootRealRed + 1;
                int indToInsert = 0;
                for (indToInsert = 0; indToInsert < numRootRealRed; indToInsert++)
                {
                    if (rootToAdd <= rootRed[indToInsert])
                    {
                        break;
                    }
                }
                for (int iRoot = 0; iRoot < indToInsert; iRoot++)
                {
                    root[iRoot] = rootRed[iRoot];
                }
                root[indToInsert] = rootToAdd;
                for (int iRoot = indToInsert; iRoot < numRootRealRed; iRoot++)
                {
                    root[iRoot + 1] = rootRed[iRoot];
                }
                return; // end - catch EXACT TANGENT
            }


            if (Math.Abs(a) < MConsts.EPS_DEC)
            {
                Equation.RootsReal(b, c, d, e, out numRootReal, out root);
            }
            else
            {
                numRootReal = 0;
                root        = null;
                double bb, cc, dd, ee, pp, qq, rr;
                bb = b / a; cc = c / a; dd = d / a; ee = e / a;
                // substitution: x = z - bb/4

                pp = Equation.Evaluate(bb / 4.0, -6.0, 0, cc);
                qq = Equation.Evaluate(bb / 4.0, 8.0, 0, -2.0 * cc, dd);
                rr = Equation.Evaluate(bb / 4.0, -3.0, 0, cc, -dd, ee);

                // solve C(ubic) R(esolvent) equation (1, 2pp, pp^2-4rr, -q^2)
                int    numRealRootCR, numRootCR;
                CNum[] rootCR;

                // the cubic equation is non-degenerated,=> numRootCR = 3
                Equation.RootsAll(1.0, 2.0 * pp, pp * pp - 4.0 * rr, -qq * qq,
                                  out numRootCR, out numRealRootCR, out rootCR);
                if (numRootCR == Equation.NumRootInfinite)
                {
                    throw new ExceptionGMath("Equation", "RootsReal", "Degree 4");
                }

                if (numRealRootCR == 3)    // 3 real (not necessarily different) roots of CR
                {
                    if (rootCR[0].Re >= 0) // 3 real roots of CR; all roots are positive
                    {
                        numRootReal = 4;
                        double sqrt0 = Math.Sqrt(rootCR[0].Re);
                        double sqrt1 = Math.Sqrt(rootCR[1].Re);
                        double sqrt2 = (Math.Sign(qq) != 0) ?
                                       Math.Sign(qq) * Math.Sqrt(rootCR[2].Re) :
                                       Math.Sqrt(rootCR[2].Re);

                        ArrayList arr = new ArrayList();
                        arr.Add(-bb / 4.0 + 0.5 * (sqrt0 + sqrt1 - sqrt2));
                        arr.Add(-bb / 4.0 + 0.5 * (-sqrt0 + sqrt1 + sqrt2));
                        arr.Add(-bb / 4.0 + 0.5 * (sqrt0 - sqrt1 + sqrt2));
                        arr.Add(-bb / 4.0 + 0.5 * (-sqrt0 - sqrt1 - sqrt2));
                        arr.Sort();

                        root = new double[4];
                        for (int i = 0; i < 4; i++)
                        {
                            root[i] = (double)arr[i];
                        }
                    }

                    if ((rootCR[1].Re < 0) && (rootCR[2].Re >= 0)) // 3 real roots of CR; 1 root is positive
                    {
                        if (Math.Abs(rootCR[0].Re - rootCR[1].Re) < MConsts.EPS_DEC)
                        {
                            numRootReal = 2; // double-root
                            root        = new double[2];
                            root[0]     = root[1] = -bb / 4.0 - 0.5 * Math.Sqrt(rootCR[2].Re) * Math.Sign(qq);
                        }
                    }
                }
                if ((numRealRootCR == 1) && (rootCR[0].Re >= 0)) // 1 real root of CR; the root is positive
                {
                    numRootReal = 2;
                    double sqrt0 = Math.Sign(qq) * Math.Sqrt(rootCR[0].Re);
                    double sqrt1 = rootCR[1].PrimeRoot(2).Re;
                    root    = new double[2];
                    root[0] = -bb / 4.0 - 0.5 * sqrt0 - sqrt1;
                    root[1] = -bb / 4.0 - 0.5 * sqrt0 + sqrt1;
                }
            }
        }
コード例 #3
0
        // deg3
        public static void RootsAll(double a, double b, double c, double d,
                                    out int numRoot, out int numRootReal, out CNum[] root)
        {
            //    output:
            //    case of 3 real roots =>
            //            the roots are sorted in increasing order
            //    case of 1 real root  => real, complex-, complex+
            //
            //    multiply real roots referred as different roots

            /*
             *  Catch EXACT TANGENTS when they are not obvious
             *    from the control points specification
             */

            double rootToAdd = -1.0;                     // asign an invalid parametric value
            int    numRootRed = -1, numRootRealRed = -1; // roots after reduction

            CNum[] rootRed = null;
            if (Equation.Evaluate(0.0, a, b, c, d) == 0.0)
            {
                rootToAdd = 0.0;
                Equation.RootsAll(a, b, c,
                                  out numRootRed, out numRootRealRed, out rootRed);
            }
            if (Equation.Evaluate(1.0, a, b, c, d) == 0.0)
            {
                rootToAdd = 1.0;
                Equation.RootsAll(a, a + b, a + b + c,
                                  out numRootRed, out numRootRealRed, out rootRed);
            }
            if (rootToAdd != -1.0)
            {
                root        = new CNum[numRootRed + 1];
                numRoot     = numRootRed + 1;
                numRootReal = numRootRealRed + 1;
                //
                //  two complex roots of the reduced (quadratic) equation
                //
                if ((numRootRed - numRootRealRed) == 2)
                {
                    root[0] = new CNum(rootToAdd, 0.0);
                    root[1] = new CNum(rootRed[0]);
                    root[2] = new CNum(rootRed[1]);
                    return;
                }
                //
                //  all roots of the reduced equation are real
                //
                CNum rootNew = new CNum(rootToAdd, 0.0);
                // adjust multiplicities
                for (int iRootRed = 0; iRootRed < numRootRed; iRootRed++)
                {
                    if (rootToAdd == rootRed[iRootRed].Re)
                    {
                        rootNew.Multiplicity           += 1;
                        rootRed[iRootRed].Multiplicity += 1;
                    }
                }
                if (numRootRed == 0)
                {
                    root[0] = new CNum(rootNew);
                    return;
                }
                if (numRootRed == 1)
                {
                    if (rootToAdd <= rootRed[0].Re)
                    {
                        root[0] = new CNum(rootNew);
                        root[1] = new CNum(rootRed[0]);
                    }
                    else
                    {
                        root[0] = new CNum(rootRed[0]);
                        root[1] = new CNum(rootNew);
                    }
                }
                if (numRootRed == 2)
                {
                    if (rootToAdd <= rootRed[0].Re)
                    {
                        root[0] = new CNum(rootNew);
                        root[1] = new CNum(rootRed[0]);
                        root[2] = new CNum(rootRed[1]);
                    }
                    else if (rootToAdd <= rootRed[1].Re)
                    {
                        root[0] = new CNum(rootRed[0]);
                        root[1] = new CNum(rootNew);
                        root[2] = new CNum(rootRed[1]);
                    }
                    else
                    {
                        root[0] = new CNum(rootRed[0]);
                        root[1] = new CNum(rootRed[1]);
                        root[2] = new CNum(rootNew);
                    }
                }
                return; // end - catch EXACT TANGENTS
            }

            if (Math.Abs(a) < MConsts.EPS_DEC)
            {
                Equation.RootsAll(b, c, d, out numRoot, out numRootReal, out root);
            }
            else
            {
                numRoot = 3;
                root    = new CNum[3];

                double bb, cc, dd, pp, qq, D;
                bb = b / a;
                cc = c / a;
                dd = d / a;
                pp = -(bb * bb / 3.0) + cc;
                qq = (2.0 * bb * bb * bb / 27.0) - (bb * cc / 3.0) + dd;

                // solve quadratic equation (1,qq,-pp^3/27)
                D = qq * qq + (4.0 * pp * pp * pp / 27.0);
                D = (Math.Abs(D) < MConsts.EPS_DEC * MConsts.EPS_DEC) ? 0.0 : D; //tolerancing for double roots

                if (D > 0)                                                       //D>0, => 1 real & 2 complex roots
                {
                    numRootReal = 1;
                    double zp = 0.5 * (-qq + Math.Sqrt(D));   // two real roots of the quadratic equation
                    double zm = 0.5 * (-qq - Math.Sqrt(D));

                    double zpRoot3  = Math.Sign(zp) * Math.Pow(Math.Abs(zp), (double)(1.0 / 3.0));
                    double zmRoot3  = Math.Sign(zm) * Math.Pow(Math.Abs(zm), (double)(1.0 / 3.0));
                    double sumRoots = zpRoot3 + zmRoot3;
                    double difRoots = zpRoot3 - zmRoot3;
                    root[0] = new CNum(-bb / 3.0 + sumRoots, 0);
                    root[1] = new CNum(-bb / 3.0 - 0.5 * sumRoots, -0.5 * Math.Sqrt(3.0) * difRoots);
                    root[2] = new CNum(-bb / 3.0 - 0.5 * sumRoots, 0.5 * Math.Sqrt(3.0) * difRoots);
                }
                else    //D<=0, => 3 real roots
                {
                    numRootReal = 3;
                    ArrayList arr = new ArrayList();  // roots of the depressed equation, root = y-bb/3
                    int       i;
                    if (D < 0)
                    {
                        CNum z = new CNum(-0.5 * qq, 0.5 * Math.Sqrt(-D)); // root of the quartatic equation
                        if (z.IsZero)
                        {
                            throw new ExceptionGMath("Equation", "RootsAll", "Degree 3");
                        }
                        double zRadius      = z.Radius;
                        double zAngle       = z.Angle;
                        double zRadiusRoot3 = Math.Pow(zRadius, 1.0 / 3.0);
                        for (i = 0; i <= 2; i++)
                        {
                            arr.Add(2.0 * zRadiusRoot3 * Math.Cos((zAngle + 2.0 * i * Math.PI) / 3.0));
                        }
                        arr.Sort();            // TODO: check
                        for (i = 0; i <= 2; i++)
                        {
                            root[i] = new CNum(-bb / 3.0 + (double)arr[i], 0);
                        }
                    }
                    if (D == 0)                    // case of the multiply roots
                    {
                        double z      = -0.5 * qq; // double real root of the quadratic equation
                        double zRoot3 = Math.Sign(z) * Math.Pow(Math.Abs(z), 1.0 / 3.0);
                        arr.Add(2.0 * zRoot3);
                        arr.Add(-zRoot3);
                        arr.Add(-zRoot3);
                        if (qq > 0)
                        {
                            root[0] = new CNum(-bb / 3.0 + (double)arr[0], 0, 1);
                            root[1] = new CNum(-bb / 3.0 + (double)arr[1], 0, 2);
                            root[2] = new CNum(root[1]);
                        }
                        else if (qq == 0)
                        {
                            root[0] = new CNum(-bb / 3.0, 0, 3);
                            root[1] = new CNum(root[0]);
                            root[2] = new CNum(root[0]);
                        }
                        else
                        {
                            root[0] = new CNum(-bb / 3.0 + (double)arr[1], 0, 2);
                            root[1] = new CNum(root[0]);
                            root[2] = new CNum(-bb / 3.0 + (double)arr[0], 0, 2);
                        }
                    }
                }
            }
        }
コード例 #4
0
ファイル: Intersect.cs プロジェクト: sjvudp/Font-Validator
        public static bool AuxIntersectBL(Bez2D bez, LCurve lrs, ListInfoInters linters)
        {
            // bezier is irreducable !!!
            if (linters == null)
            {
                throw new ExceptionGMath("Intersect", "AuxIntersectBL(bez,lrs)", "Null argument");
            }
            if (lrs.IsDegen)
            {
                throw new ExceptionGMath("Intersect", "AuxIntersectBL(bez,lrs)", null);
            }

            Param parM;

            if (bez.IsSelfInters(out parM))
            {
                if (parM.Val < 0)
                {
                    Bez2D bezRev          = bez.Reversed as Bez2D;
                    int   numIntersBefore = linters.Count;
                    if (!Inters.AuxIntersectBL(bezRev, lrs, linters))
                    {
                        return(false);
                    }
                    linters.ParamReverse(1, 0, numIntersBefore);
                    return(true);
                }
                SegD       support = bez.SupportFlat();
                InfoInters intersSup;
                if (!Inters.IntersectLL(support, lrs, out intersSup))
                {
                    return(false);
                }
                if (intersSup == null)
                {
                    return(true);
                }

                /*
                 *  convert parameters from support to Bezier
                 */
                // invalidate in case of D1 intersection
                if (intersSup.Dim == InfoInters.TypeDim.Dim1)
                {
                    (intersSup as IntersD1).ParamInvalidateBezSI();
                    linters.Add(intersSup);
                    return(true);
                }

                // write as 1 or 2 intersections with different parameters
                // in case of D0 intersections
                InfoInters[] intersBez;
                if (!bez.IntersFromSupport(intersSup, 0, out intersBez))
                {
                    return(false);
                }
                for (int iIntersBez = 0; iIntersBez < intersBez.Length; iIntersBez++)
                {
                    linters.Add(intersBez[iIntersBez]);
                }
                return(true);
            }

            // bezier is NOT self/intersecting
            VecD[] cfLrs, cfBez;
            lrs.PowerCoeff(out cfLrs);
            bez.PowerCoeff(out cfBez);
            VecD norm = lrs.DirNorm;
            VecD tang = lrs.DirTang;

            double[] roots;
            int      numRootBez;

            Equation.RootsReal(cfBez[2].Dot(norm),
                               cfBez[1].Dot(norm), (cfBez[0] - cfLrs[0]).Dot(norm),
                               out numRootBez, out roots);
            if (numRootBez == Equation.NumRootInfinite)
            {
                // bezier is irreducable,=> only D0 intersections are possible
                throw new ExceptionGMath("Intersect", "AuxIntersectBL(bez,lrs)", null);
                //return false;
            }
            for (int iRoot = 0; iRoot < numRootBez; iRoot++)
            {
                Param parBez = roots[iRoot];
                if (bez.IsEvaluableStrict(parBez))
                {
                    Param parLrs = Equation.Evaluate(parBez.Val,
                                                     cfBez[2].Dot(tang), cfBez[1].Dot(tang),
                                                     (cfBez[0] - cfLrs[0]).Dot(tang)) / (cfLrs[1].Dot(tang));
                    if (lrs.IsEvaluableStrict(parLrs))
                    {
                        IntersD0 inters = new IntersD0(parBez, parLrs,
                                                       0.5 * (lrs.Evaluate(parLrs.Val) + bez.Evaluate(parBez.Val)),
                                                       false);
                        linters.Add(inters);
                    }
                }
            }
            return(true);
        }
コード例 #5
0
ファイル: Intersect.cs プロジェクト: sjvudp/Font-Validator
        public static bool AuxIntersectBB(Bez2D bezA, Bez2D bezB,
                                          InfoConnect icAB, InfoConnect icBA, ListInfoInters linters)
        {
            // bezA and bezB are irreducable !!!

            bool connectAB = ((icAB != null) && (icAB.IsConnect));
            bool connectBA = ((icBA != null) && (icBA.IsConnect));

            if ((connectBA) && (!connectAB))
            {
                throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
            }
            bool connect = connectAB || connectBA;

            Param parM;
            bool  isSelfIntersA = bezA.IsSelfInters(out parM);
            bool  isSelfIntersB = bezB.IsSelfInters(out parM);

            if (isSelfIntersA || isSelfIntersB)
            {
                BCurve curveA = bezA;
                if (isSelfIntersA)
                {
                    curveA = bezA.SupportFlat();
                }
                BCurve curveB = bezB;
                if (isSelfIntersB)
                {
                    curveB = bezB.SupportFlat();
                }
                int numIntersBefore = linters.Count;
                Inters.IntersectBB(curveA, curveB, null, null, linters);

                /*
                 *    CLEAN END-POINT if the curve does not return to it
                 */
                if ((connectAB) && (!connectBA))
                {
                    bool coversA1 = false;
                    bool coversB0 = false;
                    if (isSelfIntersA)
                    {
                        coversA1 = bezA.CoversEndPoint(false);
                    }
                    if (isSelfIntersB)
                    {
                        coversB0 = bezB.CoversEndPoint(true);
                    }
                    if ((!coversA1) && (!coversB0))
                    {
                        linters.CleanEndPointBezSI(bezA.End, numIntersBefore);
                    }
                }
                linters.ParamInvalidateBezSI(numIntersBefore);
                return(true);
            }

            // test for 1-dimensional intersection of supports
            bool  isB0OnA, isB2OnA;
            Param paramAInvB0, paramAInvB2;

            if (!bezB.Cp(0).InverseOn(bezA, out isB0OnA, out paramAInvB0))
            {
                return(false);
            }
            if (!bezB.Cp(2).InverseOn(bezA, out isB2OnA, out paramAInvB2))
            {
                return(false);
            }
            if ((isB0OnA) && (isB2OnA))
            {
                bool  areCoincide = true;
                Param par;
                for (int i = 1; i <= 3; i++)
                {
                    //    evaluate bezB at paramaters 1/4, 1/2, 3/4 and check
                    //    whether the points lie on bezA [-Infinity,Infinity]
                    VecD pnt = bezB.Evaluate(0.25 * i);
                    if (!pnt.InverseOn(bezA, out areCoincide, out par))
                    {
                        return(false);
                    }
                    if (!areCoincide)
                    {
                        break;
                    }
                }
                if (areCoincide)
                {
                    Param.TypeParam typeB0 = bezA.ParamClassify(paramAInvB0);
                    Param.TypeParam typeB2 = bezA.ParamClassify(paramAInvB2);
                    int             mult   = (int)typeB0 * (int)typeB2;

                    if (mult == 4)
                    {
                        return(true); // no intersections
                    }
                    else if (mult == 1)
                    {
                        // bezB is degenerated
                        throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                        //return false;
                    }
                    else if (mult == 2)
                    {
                        // 0-dimentional connection at the end point
                        if ((typeB0 == Param.TypeParam.Start) &&
                            (typeB2 == Param.TypeParam.Before))
                        {
                            if (connect)
                            {
                                throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                                //return false;
                            }
                            IntersD0 inters = new IntersD0(0, 0, bezB.Start, false);
                            linters.Add(inters);
                            return(true);
                        }
                        if ((typeB0 == Param.TypeParam.Before) &&
                            (typeB2 == Param.TypeParam.Start))
                        {
                            if (connect)
                            {
                                throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                                //return false;
                            }
                            IntersD0 inters = new IntersD0(1, 0, bezB.End, false);
                            linters.Add(inters);
                            return(true);
                        }
                        if ((typeB0 == Param.TypeParam.End) &&
                            (typeB2 == Param.TypeParam.After))
                        {
                            if (!connect)
                            {
                                IntersD0 inters = new IntersD0(0, 1, bezB.Start, false);
                                linters.Add(inters);
                                return(true);
                            }
                            return(true);
                        }
                        if ((typeB0 == Param.TypeParam.After) &&
                            (typeB2 == Param.TypeParam.End))
                        {
                            if (connect)
                            {
                                throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                                //return false;
                            }
                            IntersD0 inters = new IntersD0(1, 1, bezB.End, false);
                            linters.Add(inters);
                            return(true);
                        }
                    }
                    else if (mult <= 0)
                    {
                        InfoInters inters;
                        Inters.RefineIntersBBD1(bezA, bezB, out inters);
                        linters.Add(inters);
                        return(true);
                    }
                    throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                    //return false;
                }
            }

            /*
             *        INTERSECTION IS 0-DIMENTIONAL AT MOST
             */
            VecD[] cfA, cfB;
            bezA.PowerCoeff(out cfA);
            bezB.PowerCoeff(out cfB);

            Param parA, parB;
            int   numRootB;

            double[] rootsB;
            double   kappa = cfA[2].Cross(cfA[1]);

            // bezA and bezB are non-degenerated and consequent
            if (connectAB)
            {
                if (bezA.End != bezB.Start)
                {
                    throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                    //return false;
                }

                if (connectBA)
                {
                    // both ends are connected
                    if (bezA.Start != bezB.End)
                    {
                        throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                        //return false;
                    }

                    if (icAB.IsTangent || icBA.IsTangent)
                    {
                        // tangent connection - no additional intersections
                        return(true);
                    }

                    double   crossA2B2 = cfA[2].Cross(cfB[2]);
                    double[] cfEqn     = { kappa *(kappa + 2 * crossA2B2 + cfA[1].Cross(cfB[2])),
                                           -crossA2B2 * (2 * kappa + crossA2B2),
                                           crossA2B2 *crossA2B2 };
                    Equation.RootsReal(cfEqn[2], cfEqn[1], cfEqn[0],
                                       out numRootB, out rootsB);
                    if (numRootB == Equation.NumRootInfinite)
                    {
                        throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                        //return false;
                    }
                    if (rootsB != null)
                    {
                        for (int iRoot = 0; iRoot < numRootB; iRoot++)
                        {
                            parB = rootsB[iRoot];
                            if (bezB.IsEvaluableStrict(parB))
                            {
                                parA = 1.0 +
                                       parB.Val * (cfA[2].Cross(cfB[2]) * parB.Val +
                                                   cfA[2].Cross(cfB[1])) / kappa;
                                if (bezA.IsEvaluableStrict(parA) /*&& (parA!=1.)*/)
                                {
                                    IntersD0 inters = new IntersD0(parA, parB,
                                                                   0.5 * (bezA.Evaluate(parA) + bezB.Evaluate(parB)),
                                                                   false);
                                    linters.Add(inters);
                                }
                            }
                        }
                    }

                    return(true);
                }

                // consequent Bezier with one connection
                if (icAB.IsTangent)
                {
                    // tangent connection - at most 2 additional intersections
                    double[] cfEqn = { kappa *(kappa - cfB[2].Cross(cfB[1])),
                                       2 * cfA[2].Cross(cfB[2]) * kappa,
                                       cfA[2].Cross(cfB[2]) * cfA[2].Cross(cfB[2]) };
                    Equation.RootsReal(cfEqn[2], cfEqn[1], cfEqn[0],
                                       out numRootB, out rootsB);
                    if (numRootB == Equation.NumRootInfinite)
                    {
                        throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                        //return false;
                    }
                    if (rootsB != null)
                    {
                        for (int iRoot = 0; iRoot < numRootB; iRoot++)
                        {
                            parB = rootsB[iRoot];
                            if (bezB.IsEvaluableStrict(parB))
                            {
                                parA = 1 +
                                       parB.Val * (cfA[2].Cross(cfB[2]) * parB.Val +
                                                   cfA[2].Cross(cfB[1])) / kappa;
                                if (bezA.IsEvaluableStrict(parA) /*&&(parA!=1)*/)
                                {
                                    IntersD0 inters = new IntersD0(parA, parB,
                                                                   0.5 * (bezA.Evaluate(parA) + bezB.Evaluate(parB)),
                                                                   false);
                                    linters.Add(inters);
                                }
                            }
                        }
                    }
                    return(true);
                }
                else
                {
                    // non-tangent connection - at most 3 additional intersections
                    double[] cfEqn = { kappa *(2 * cfA[2].Cross(cfB[1]) + cfA[1].Cross(cfB[1])),
                                       cfA[2].Cross(cfB[1]) * cfA[2].Cross(cfB[1]) +
                                       kappa * (2 * cfA[2].Cross(cfB[2]) + cfA[1].Cross(cfB[2])),
                                       2 * cfA[2].Cross(cfB[2]) * cfA[2].Cross(cfB[1]),
                                       cfA[2].Cross(cfB[2]) * cfA[2].Cross(cfB[2]) };
                    Equation.RootsReal(cfEqn[3], cfEqn[2], cfEqn[1], cfEqn[0],
                                       out numRootB, out rootsB);
                    if (numRootB == Equation.NumRootInfinite)
                    {
                        throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                        //return false;
                    }
                    if (rootsB != null)
                    {
                        for (int iRoot = 0; iRoot < numRootB; iRoot++)
                        {
                            parB = rootsB[iRoot];
                            if (bezB.IsEvaluableStrict(parB))
                            {
                                parA = 1 +
                                       parB.Val * (cfA[2].Cross(cfB[2]) * parB +
                                                   cfA[2].Cross(cfB[1])) / kappa;
                                if (bezA.IsEvaluableStrict(parA) /*&&(parA!=1)*/)
                                {
                                    IntersD0 inters = new IntersD0(parA, parB,
                                                                   0.5 * (bezA.Evaluate(parA) + bezB.Evaluate(parB)),
                                                                   false);
                                    linters.Add(inters);
                                }
                            }
                        }
                    }
                    return(true);
                }
            }

            // bezA and bezB are non-degenerated, non-consequent curves
            bool isSwappedAB = false;

            if (Math.Abs(cfA[2].Cross(cfA[1])) < Math.Abs(cfB[2].Cross(cfB[1])))
            {
                kappa       = cfB[2].Cross(cfB[1]);
                isSwappedAB = true;
                VecD tmp;
                for (int i = 0; i < 3; i++)
                {
                    tmp = cfA[i]; cfA[i] = cfB[i]; cfB[i] = tmp;
                }
            }
            double[] e = { cfA[2].Cross(cfB[0] - cfA[0]),
                           cfA[2].Cross(cfB[1]),
                           cfA[2].Cross(cfB[2]) };
            double[] f = { (cfB[0] - cfA[0]).Cross(cfA[1]),
                           cfB[1].Cross(cfA[1]),
                           cfB[2].Cross(cfA[1]) };
            Equation.RootsReal(e[2] * e[2],
                               2 * e[2] * e[1],
                               e[1] * e[1] + 2 * e[2] * e[0] - kappa * f[2],
                               2 * e[1] * e[0] - kappa * f[1],
                               e[0] * e[0] - kappa * f[0],
                               out numRootB, out rootsB);

            if (numRootB == Equation.NumRootInfinite)
            {
                throw new ExceptionGMath("Intersect", "AuxIntersectBB(bez,bez)", null);
                //return false;
            }
            if (rootsB != null)
            {
                for (int iRoot = 0; iRoot < numRootB; iRoot++)
                {
                    parB = rootsB[iRoot];
                    parA = Equation.Evaluate(parB.Val, e[2], e[1], e[0]) / kappa;
                    if (isSwappedAB)
                    {
                        Param parTmp;
                        parTmp = parA;
                        parA   = parB;
                        parB   = parTmp;
                    }
                    if (bezA.IsEvaluableStrict(parA) && bezB.IsEvaluableStrict(parB))
                    {
                        IntersD0 inters = new IntersD0(parA, parB,
                                                       0.5 * (bezA.Evaluate(parA) + bezB.Evaluate(parB)),
                                                       false);
                        linters.Add(inters);
                    }
                }
            }
            return(true);
        }
コード例 #6
0
ファイル: Intersect.cs プロジェクト: sjvudp/Font-Validator
        public static bool AuxIntersectBB(SegD seg, Bez2D bez,
                                          InfoConnect icAB, InfoConnect icBA, ListInfoInters linters)
        {
            // both seg & bez are irreducable !!!
            if (linters == null)
            {
                throw new ExceptionGMath("Intersect", "AuxIntersectBB(seg,bez)", "Null argument");
            }

            bool connectAB = ((icAB != null) && (icAB.IsConnect));
            bool connectBA = ((icBA != null) && (icBA.IsConnect));

            if ((connectBA) && (!connectAB))
            {
                throw new ExceptionGMath("Intersect", "AuxIntersectBB(seg,bez)", null);
                //return false;
            }
            bool connect = connectAB || connectBA;

            if (!connect)
            {
                int numIntersBefore = linters.Count;
                if (!Inters.AuxIntersectBL(bez, seg, linters))
                {
                    return(false);
                }
                linters.ParamSwap(numIntersBefore);
                return(true);
            }

            // bez and seg are connected, => connectAB=true
            Param parM;

            if (bez.IsSelfInters(out parM))
            {
                if (connectBA) // both ends are connected
                {
                    // parM!=Infinity - otherwise the seg is degenerated
                    double   valM = parM.Val;
                    IntersD1 inters;
                    if (valM > 1)
                    {
                        inters = new IntersD1(0, 1,
                                              1, 1 / (2 * valM - 1), seg, true);
                    }
                    else
                    {
                        inters = new IntersD1(0, 1,
                                              1, (2 * valM) / (2 * valM - 1), seg, true);
                    }
                    linters.Add(inters);
                    return(true);
                }
                if (icAB.IsTangent)
                {
                    return(true); // no additional intersections
                }
                else
                {
                    SegD       segSupp = bez.SupportFlat();
                    InfoInters inters;
                    if (!Inters.IntersectLL(seg, segSupp, out inters))
                    {
                        return(false);
                    }
                    if (inters == null)
                    {
                        return(true);
                    }
                    inters.ParamInvalidateBezSI();
                    int numIntersBefore = linters.Count;
                    linters.Add(inters);

                    /*
                     *    CLEAN END-POINT if the Bezier does not return to it
                     */
                    bool coversBezStart = bez.CoversEndPoint(true);
                    if (!coversBezStart)
                    {
                        linters.CleanEndPointBezSI(bez.Start, numIntersBefore);
                    }
                    return(true);
                }
            }

            //    bezier is NOT self-intersecting
            if (connectBA)
            {
                return(true);    // no additional intersections
            }
            if (icAB.IsTangent)
            {
                return(true);    // no additional intersections
            }
            //    seg & bez are connected and not-tangent,=>
            //    at most one additional point of intersection
            VecD[] cfSeg, cfBez;
            seg.PowerCoeff(out cfSeg);
            bez.PowerCoeff(out cfBez);
            VecD tang = (seg as LCurve).DirTang;
            VecD norm = (seg as LCurve).DirNorm;

            // connected but not-tangent: one
            double[] rootsBez;
            int      numRootBez;

            Equation.RootsReal(cfBez[2].Dot(norm), cfBez[1].Dot(norm),
                               out numRootBez, out rootsBez);
            if (numRootBez == Equation.NumRootInfinite)
            {
                throw new ExceptionGMath("Intersect", "AuxIntersectBB(seg,bez)", null);
                //return false;
            }
            if (rootsBez == null)
            {
                return(true);
            }
            Param parBez = rootsBez[0];

            if (bez.IsEvaluableStrict(parBez))
            {
                double valBez = parBez.Val;
                Param  parSeg = 1 + valBez * (cfBez[2].Dot(tang) * valBez + cfBez[1].Dot(tang)) / cfSeg[1].Dot(tang);
                if (seg.IsEvaluableStrict(parSeg)) // ??? && (parSeg!=1)
                {
                    IntersD0 inters = new IntersD0(parSeg, parBez,
                                                   0.5 * (seg.Evaluate(parSeg) + bez.Evaluate(parBez)), false);
                    linters.Add(inters);
                }
            }
            return(true);
        }