Esempio n. 1
0
        /*
         *        INTERSECT: (LCurve, LCurve)
         *                - both curves are supposed to be NON-DEGENERATED
         */

        public static bool IntersectLL(LCurve lrsA, LCurve lrsB,
                                       out InfoInters inters)
        {
            inters = null;
            if ((lrsA.IsDegen) || (lrsB.IsDegen))
            {
                throw new ExceptionGMath("Intersect", "IntersectLL(lrs,lrs)", null);
            }

            VecD   a0   = lrsA.Start;
            VecD   a1   = lrsA.End;
            VecD   b0   = lrsB.Start;
            VecD   b1   = lrsB.End;
            VecD   dirA = lrsA.DirTang;
            VecD   dirB = lrsB.DirTang;
            double det  = dirA.Cross(dirB);

            // lrsA and lrsB are not parallel
            if (Math.Abs(det) > MConsts.EPS_DEC)
            {
                double lenA = (a1 - a0).Norm;
                double lenB = (b1 - b0).Norm;
                VecD   diff = b0 - a0;
                Param  parA = (diff.Cross(dirB)) / (det * lenA);
                Param  parB = (diff.Cross(dirA)) / (det * lenB);
                if (lrsA.IsEvaluableStrict(parA) && lrsB.IsEvaluableStrict(parB))
                {
                    VecD pnt = 0.5 * (lrsA.Evaluate(parA) + lrsB.Evaluate(parB));
                    inters = new IntersD0(parA, parB, pnt, false);
                }
                return(true);
            }

            // lrsA and lrsB are parallel
            LineD lineB = new LineD(lrsB);
            Param paramBInvA0, paramBInvA1;
            VecD  pntProjA0, pntProjA1;

            a0.Project(lineB, out paramBInvA0, out pntProjA0);
            a1.Project(lineB, out paramBInvA1, out pntProjA1);
            double distA0 = a0.Dist(pntProjA0);
            double distA1 = a1.Dist(pntProjA1);

            if ((distA0 < MConsts.EPS_DEC) || (distA1 < MConsts.EPS_DEC))
            {
                // lrsA and lrsB are colinear
                Param.TypeParam typeA0 = lrsB.ParamClassify(paramBInvA0);
                Param.TypeParam typeA1 = lrsB.ParamClassify(paramBInvA1);
                int             mult   = (int)typeA0 * (int)typeA1;

                if (mult == 4)
                {
                    return(true);
                }
                else if (mult == 1)
                {
                    throw new ExceptionGMath("Intersect", "IntersectLL(lrs,lrs)", null); // lrsA is degenerated
                    //return false;
                }
                else if (mult == 2)
                {
                    if ((typeA0 == Param.TypeParam.Start) &&
                        (typeA1 == Param.TypeParam.Before))
                    {
                        inters = new IntersD0(0, 0, a0, false);
                    }
                    if ((typeA0 == Param.TypeParam.Before) &&
                        (typeA1 == Param.TypeParam.Start))
                    {
                        inters = new IntersD0(1, 0, a1, false);
                    }
                    if ((typeA0 == Param.TypeParam.End) &&
                        (typeA1 == Param.TypeParam.After))
                    {
                        inters = new IntersD0(0, 1, a0, false);
                    }
                    if ((typeA0 == Param.TypeParam.After) &&
                        (typeA1 == Param.TypeParam.End))
                    {
                        inters = new IntersD0(1, 1, a1, false);
                    }
                    return(true);
                }
                else if (mult <= 0)
                {
                    return(Inters.RefineIntersLLD1(lrsA, lrsB, out inters));
                }
            }

            return(true);
        }
Esempio n. 2
0
        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);
        }