예제 #1
0
 public Bez2D(Bez2D bez) 
     : this()
 {
     this.cp[0]=new VecD(bez.Cp(0));
     this.cp[1]=new VecD(bez.Cp(1));
     this.cp[2]=new VecD(bez.Cp(2));
 }
예제 #2
0
 public Bez2D(Bez2D bez)
     : this()
 {
     this.cp[0] = new VecD(bez.Cp(0));
     this.cp[1] = new VecD(bez.Cp(1));
     this.cp[2] = new VecD(bez.Cp(2));
 }
예제 #3
0
        public SegD SupportFlat()
        {
            Param parM;

            if ((this.IsDegen) || (this.IsSeg(out parM)))
            {
                return(new SegD(this.Start, this.End));
            }
            if (this.IsSelfInters(out parM))
            {
                double valM = parM.Val;
                if (valM == Param.Infinity)
                {
                    return(new SegD(this.Start, 0.5 * (this.Start + this.Cp(1))));
                }
                if (valM > 1)
                {
                    return(new SegD(this.Start, this.Start + ((valM * valM) / (2 * valM - 1)) * (this.End - this.Start)));
                }
                if (parM.Val < 0)
                {
                    Bez2D bezRev     = this.Reversed as Bez2D;
                    SegD  supportRev = bezRev.SupportFlat();
                    return(supportRev.Reversed as SegD);
                }
            }
            return(null);
        }
예제 #4
0
        public bool Project(Bez2D bez, out Param par, out VecD pnt)
        {
            /*
             *        MEANING:    the NEAREST point in the RANGE [0,1]
             *        ASSUMPTION:    -    bezier can be non-reduced
             *                    -    bezier is NOT self-intersecting
             */
            par = null;
            pnt = null;
            Param parM;

            if (bez.IsSelfInters(out parM))
            {
                throw new ExceptionGMath("VecD", "Project(bez)", null);
                //return false;
            }
            if (bez.IsDegen)
            {
                par = new Param(Param.Degen);
                pnt = bez.Middle;
                return(true);
            }
            if (bez.IsSeg(out parM))
            {
                SegD seg = bez.Reduced as SegD;
                this.Project(seg, out par, out pnt);
                bez.ParamFromSeg(par);
                return(true);
            }
            // case of non-flat Bezier
            Param[] parsPerp;
            if (!this.Perp(bez, out parsPerp))
            {
                return(false);
            }
            double distS   = this.Dist(bez.Start);
            double distE   = this.Dist(bez.End);
            double distMin = Math.Min(distS, distE);
            double parMin  = (distS <= distE)? 0.0: 1.0;

            if (parsPerp != null)
            {
                for (int iPerp = 0; iPerp < parsPerp.Length; iPerp++)
                {
                    if (bez.IsEvaluableStrict(parsPerp[iPerp]))
                    {
                        double distPerp = this.Dist(bez.Evaluate(parsPerp[iPerp]));
                        if (distPerp < distMin)
                        {
                            distMin = distPerp;
                            parMin  = parsPerp[iPerp];
                        }
                    }
                }
            }
            par = parMin;
            pnt = bez.Evaluate(parMin);
            return(true);
        }
예제 #5
0
        public bool Inverse(Bez2D bez, out Param par)
        {
            /*
             *        MEANING:
             *            -    Parameter of the nearest point in range
             *                [-Infinity, Infinity]
             *        ASSUMPTIONS:
             *            -    Bezier is REDUCED
             *            -    Works for any bezier if the nearest point belongs
             *                to support
             *            -    Works for non S/I bezier if the nearest point lies
             *                without the support
             */
            par = null;

            Param parM;

            if (!bez.IsSelfInters(out parM))
            {
                Param[] parsPerp;
                if (!this.Perp(bez, out parsPerp))
                {
                    return(false);
                }
                double distMin = MConsts.Infinity;
                for (int iPar = 0; iPar < parsPerp.Length; iPar++)
                {
                    double distCur = this.Dist(bez.Evaluate(parsPerp[iPar]));
                    if (distCur < distMin)
                    {
                        distMin = distCur;
                        par     = parsPerp[iPar];
                    }
                }
                return(true);
            }
            // bezier is s/i
            Param[] parsProj;
            VecD    pnt;

            if (!this.ProjectGeneral(bez, out parsProj, out pnt))
            {
                return(false);
            }
            if (this.Dist(pnt) > MConsts.EPS_DEC)
            {
                throw new ExceptionGMath("VecD", "Inverse(bez)", null);
                //return false;
            }
            par = parsProj[0];
            return(true);
        }
예제 #6
0
        public BCurve SubCurve(Param parA, Param parB)
        {
            if ((!this.IsEvaluableStrict(parA)) || (!this.IsEvaluableStrict(parB)))
            {
                return(null);
            }

            Bez2D  bezWork = new Bez2D(this);
            double valA    = parA.Val;
            double valB    = parB.Val;

            if (valA > valB)
            {
                bezWork.Reverse();
                valA = 1 - valA;
                valB = 1 - valB;
            }

            /*
             * if ((valS==0)&&(valE==1))
             *  return new Bez2D(bezWork);
             * CurveD curveS, curveE;
             * if (valS==0)
             * {
             *  bezWork.Subdivide(valB,out curveS, out curveE);
             *  return curveS;
             * }
             * if (valE==1)
             * {
             *  bezWork.Subdivide(valA,out curveS, out curveE);
             *  return curveE;
             * }
             */
            VecD a01, a12, b01, b12;

            a01 = (1 - valA) * bezWork.Cp(0) + valA * bezWork.Cp(1);
            a12 = (1 - valA) * bezWork.Cp(1) + valA * bezWork.Cp(2);
            b01 = (1 - valB) * bezWork.Cp(0) + valB * bezWork.Cp(1);
            b12 = (1 - valB) * bezWork.Cp(1) + valB * bezWork.Cp(2);

            VecD start, mid, end;

            start = (1 - valA) * a01 + valA * a12;
            end   = (1 - valB) * b01 + valB * b12;
            mid   = (1 - valB) * a01 + valB * a12;
            // mid=(1-valA)*(1-valB)*bezWork.Cp(0)+valA*valB*bezWork.Cp(2)+
            //        ((1-valB)*valA+(1-valA)*valB))*bezWork.Cp(1);

            return(new Bez2D(start, mid, end));
        }
예제 #7
0
        public void Subdivide(Param par, out BCurve curveS, out BCurve curveE)
        {
            /*
             *        ASSUMPTION: par should be in the range [0,1]
             */
            curveS = null;
            curveE = null;
            if (!this.IsEvaluableStrict(par))
            {
                return;
            }
            VecD pnt01 = (1 - par.Val) * this.cp[0] + par.Val * this.cp[1];
            VecD pnt12 = (1 - par.Val) * this.cp[1] + par.Val * this.cp[2];
            VecD pnt   = (1 - par.Val) * pnt01 + par.Val * pnt12;

            curveS = new Bez2D(this.cp[0], pnt01, pnt);
            curveE = new Bez2D(pnt, pnt12, this.cp[2]);
        }
예제 #8
0
        public static bool AuxIntersectBB(DegenD degen, Bez2D bez,
                                          InfoConnect icAB, InfoConnect icBA, ListInfoInters linters)
        {
            if (linters == null)
            {
                throw new ExceptionGMath("Intersect", "AuxIntersectBB(degen,bez)", "Null argument");
            }

            // no reduction !!

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

            if (connect)
            {
                return(true);
            }

            // bbox check
            if (!bez.BBox.Contains(degen.Cp))
            {
                return(true);
            }

            Param[] pars;
            VecD    pnt;

            if (!degen.Cp.ProjectGeneral(bez, out pars, out pnt))
            {
                return(false);
            }
            if (degen.Cp.Dist(pnt) < MConsts.EPS_DEC)
            {
                Param parM;
                bool  isSelfInters = bez.IsSelfInters(out parM);
                for (int iPar = 0; iPar < pars.Length; iPar++)
                {
                    IntersD0 inters = new IntersD0(Param.Degen, pars[iPar], pnt, isSelfInters);
                    linters.Add(inters);
                }
            }
            return(true);
        }
예제 #9
0
 public void FromReduced(BCurve bcurve)
 {
     // parameter of the (reduced)curve may be invalidated if
     // the curve intersects the self-intersecting Bezier
     if (this.val == Param.Invalid)
     {
         return;
     }
     if (bcurve.IsDegen)
     {
         return;
     }
     if (bcurve is Bez2D)
     {
         Bez2D bez = bcurve as Bez2D;
         Param parM;
         if (bez.IsSeg(out parM))
         {
             bez.ParamFromSeg(this);
         }
     }
 }
예제 #10
0
        public static bool AuxIntersectBB(DegenD degen, Bez2D bez,
            InfoConnect icAB, InfoConnect icBA, ListInfoInters linters)
        {
            if (linters==null)
            {
                throw new ExceptionGMath("Intersect","AuxIntersectBB(degen,bez)","Null argument");
            }
            
            // no reduction !!
            
            bool connectAB = ((icAB!=null)&&(icAB.IsConnect));
            bool connectBA = ((icBA!=null)&&(icBA.IsConnect));
            bool connect=connectAB||connectBA;
            if (connect)
            {
                return true;
            }

            // bbox check
            if (!bez.BBox.Contains(degen.Cp))
                return true;

            Param[] pars;
            VecD pnt;
            if (!degen.Cp.ProjectGeneral(bez,out pars, out pnt))
                return false;
            if (degen.Cp.Dist(pnt)<MConsts.EPS_DEC)
            {
                Param parM;
                bool isSelfInters=bez.IsSelfInters(out parM);
                for (int iPar=0; iPar<pars.Length; iPar++)
                {
                    IntersD0 inters=new IntersD0(Param.Degen,pars[iPar],pnt,isSelfInters);
                    linters.Add(inters);
                }
            }
            return true;
        }
예제 #11
0
        bool InverseOn(Bez2D bez, out bool isOn, out Param par)
        {
            /*
             *        MEANING:    inverse point which is known to lie on the
             *                    bezier in range [-Infinity, Infinity]
             *
             *        ASSUMPTIONS:    bez is IRREDUCABLE && NOT S/I
             *
             */

            isOn = false;
            par  = null;

            Param parM;

            if ((bez.IsDegen) || (bez.IsSeg(out parM)) || (bez.IsSelfInters(out parM)))
            {
                throw new ExceptionGMath("VecD", "InverseOn(bez)", null);
                //return false;
            }

            VecD[] cfBez;
            bez.PowerCoeff(out cfBez);

            double dev = (cfBez[2].Cross(this - cfBez[0])) *
                         (cfBez[2].Cross(this - cfBez[0])) -
                         (cfBez[2].Cross(cfBez[1])) *
                         ((this - cfBez[0]).Cross(cfBez[1]));

            if (Math.Abs(dev) < MConsts.EPS_DEC)
            {
                isOn = true;
                par  = (cfBez[2].Cross(this - cfBez[0])) / (cfBez[2].Cross(cfBez[1]));
            }

            return(true);
        }
예제 #12
0
        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);
        }
예제 #13
0
        public bool ParamFromSupport(Param parSupport, out Param[] parsBez)
        {
            parsBez = null;
            parSupport.Round(0, 1);
            if ((parSupport.Val < 0) || (parSupport.Val > 1))
            {
                throw new ExceptionGMath("Bez2D", "ParamFromSupport", "Outside [0,1]");
                //return false;
            }

            Param parM;

            if (!this.IsSelfInters(out parM))
            {
                parsBez    = new Param[1];
                parsBez[0] = parSupport.Copy();
                this.ParamFromSeg(parsBez[0]);
                return(true);
            }

            // self-intersecting Bezier
            double valM = parM.Val;

            if (valM == Param.Infinity)
            {
                double tau = 0.5 * parSupport.Val; // parameter with respect to [Cp(0),Cp(1)]
                parsBez    = new Param[2];
                parsBez[0] = new Param(0.5 * (1 - Math.Sqrt(1 - 2 * tau)));
                parsBez[1] = new Param(0.5 * (1 + Math.Sqrt(1 - 2 * tau)));
                return(true);
            }
            else if (valM > 1)
            {
                double tau = ((valM * valM) / (1 - 2 * valM)) * parSupport.Val;
                double D   = valM * valM + tau * (1 - 2 * valM);
                if (Math.Abs(D) < MConsts.EPS_DEC)
                {
                    D = 0;
                }
                if (D < 0)
                {
                    throw new ExceptionGMath("BezD", "ParamFromSegGeneral", null);
                    //return false;
                }
                if (tau < 1)
                {
                    parsBez    = new Param[1];
                    parsBez[0] = new Param((valM - Math.Sqrt(D)) / (1 - 2 * valM));
                }
                else // 1<=tau<=(valM*valM)/(1-2*valM)
                {
                    parsBez    = new Param[2];
                    parsBez[0] = new Param((valM - Math.Sqrt(D)) / (1 - 2 * valM));
                    parsBez[1] = new Param((valM + Math.Sqrt(D)) / (1 - 2 * valM));
                }
                return(true);
            }
            else
            {
                // valM<=1
                Bez2D bezRev = this.Reversed as Bez2D;
                if (!bezRev.ParamFromSupport(1 - parSupport.Val, out parsBez))
                {
                    return(false);
                }
                if (parsBez == null)
                {
                    return(true);
                }
                for (int iParBez = 0; iParBez < parsBez.Length; iParBez++)
                {
                    parsBez[iParBez].Reverse(1);
                }
                return(true);
            }
            throw new ExceptionGMath("Bez2D", "ParamFromSupport", "NOT IMPLEMENTED");
            //return false;
        }
예제 #14
0
        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;
        }
예제 #15
0
        public BCurve SubCurve(Param parA, Param parB)
        {
            if ((!this.IsEvaluableStrict(parA))||(!this.IsEvaluableStrict(parB)))
                return null;

            Bez2D bezWork=new Bez2D(this);
            double valA=parA.Val;
            double valB=parB.Val;
            if (valA>valB)
            {
                bezWork.Reverse();
                valA=1-valA;
                valB=1-valB;
            }
            /*
            if ((valS==0)&&(valE==1))
                return new Bez2D(bezWork);
            CurveD curveS, curveE;
            if (valS==0)
            {
                bezWork.Subdivide(valB,out curveS, out curveE);
                return curveS;
            }
            if (valE==1)
            {
                bezWork.Subdivide(valA,out curveS, out curveE);
                return curveE;
            }
            */
            VecD a01,a12,b01,b12;
            a01=(1-valA)*bezWork.Cp(0)+valA*bezWork.Cp(1);
            a12=(1-valA)*bezWork.Cp(1)+valA*bezWork.Cp(2);
            b01=(1-valB)*bezWork.Cp(0)+valB*bezWork.Cp(1);
            b12=(1-valB)*bezWork.Cp(1)+valB*bezWork.Cp(2);

            VecD start, mid, end;
            start=(1-valA)*a01+valA*a12;
            end=(1-valB)*b01+valB*b12;
            mid=(1-valB)*a01+valB*a12; 
            // mid=(1-valA)*(1-valB)*bezWork.Cp(0)+valA*valB*bezWork.Cp(2)+
            //        ((1-valB)*valA+(1-valA)*valB))*bezWork.Cp(1);

            return new Bez2D(start,mid,end);
        }
예제 #16
0
 public void Subdivide(Param par, out BCurve curveS, out BCurve curveE)
 {
     /*
      *        ASSUMPTION: par should be in the range [0,1]
      */
     curveS=null;
     curveE=null;
     if (!this.IsEvaluableStrict(par))
         return;
     VecD pnt01=(1-par.Val)*this.cp[0]+par.Val*this.cp[1];
     VecD pnt12=(1-par.Val)*this.cp[1]+par.Val*this.cp[2];
     VecD pnt = (1-par.Val)*pnt01+par.Val*pnt12;
     curveS=new Bez2D(this.cp[0],pnt01,pnt);
     curveE=new Bez2D(pnt,pnt12,this.cp[2]);
 }
예제 #17
0
 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;
 }
예제 #18
0
        public bool ProjectGeneral(Bez2D bez, out Param[] pars, out VecD pnt)
        {
            /*
             *        MEANING:    parameter (or parameters) of the nearest point
             *                    in range [0,1]
             *
             *        ASSUMPTIONS:    bezier can be non-reduced
             *                        bezier can be self-intersecting
             *
             */


            pars = null;
            pnt  = null;
            Param parM;

            if (!bez.IsSelfInters(out parM))
            {
                Param par;
                if (!this.Project(bez, out par, out pnt))
                {
                    return(false);
                }
                if (par != null)
                {
                    pars    = new Param[1];
                    pars[0] = par;
                }
                return(true);
            }

            double valM = parM.Val;

            if (parM < 0)
            {
                Bez2D bezRev = new Bez2D(bez);
                bezRev.Reverse();
                if (!this.ProjectGeneral(bezRev, out pars, out pnt))
                {
                    return(false);
                }
                if (pars != null)
                {
                    for (int iPar = 0; iPar < pars.Length; iPar++)
                    {
                        pars[iPar].Reverse(1);
                    }
                }
                return(true);
            }
            SegD  support = bez.SupportFlat();
            Param parSupport;

            if (!this.Project(support, out parSupport, out pnt))
            {
                return(false);
            }
            if (!bez.ParamFromSupport(parSupport, out pars))
            {
                return(false);
            }
            return(true);
        }
예제 #19
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);
        }
예제 #20
0
        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);
        }
예제 #21
0
 public bool Inverse(Bez2D bez, out Param par)
 {
     /*
      *        MEANING:
      *            -    Parameter of the nearest point in range 
      *                [-Infinity, Infinity]
      *        ASSUMPTIONS:
      *            -    Bezier is REDUCED
      *            -    Works for any bezier if the nearest point belongs
      *                to support
      *            -    Works for non S/I bezier if the nearest point lies
      *                without the support  
      */
     par=null;
     
     Param parM;
     if (!bez.IsSelfInters(out parM))
     {    
         Param[] parsPerp;
         if (!this.Perp(bez, out parsPerp))
             return false;
         double distMin=MConsts.Infinity;
         for (int iPar=0; iPar<parsPerp.Length; iPar++)
         {
             double distCur=this.Dist(bez.Evaluate(parsPerp[iPar]));
             if (distCur<distMin)
             {
                 distMin=distCur;
                 par=parsPerp[iPar];
             }
         }
         return true;
     }
     // bezier is s/i
     Param[] parsProj;
     VecD pnt;
     if (!this.ProjectGeneral(bez, out parsProj, out pnt))
         return false;
     if (this.Dist(pnt)>MConsts.EPS_DEC)
     {
         throw new ExceptionGMath("VecD","Inverse(bez)",null);
         //return false;
     }
     par=parsProj[0];
     return true;
 }
예제 #22
0
        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;
        }
예제 #23
0
 public bool Project(Bez2D bez, out Param par, out VecD pnt)
 {
     /*
      *        MEANING:    the NEAREST point in the RANGE [0,1]
      *        ASSUMPTION:    -    bezier can be non-reduced
      *                    -    bezier is NOT self-intersecting
      */
     par=null;
     pnt=null;
     Param parM;
     if (bez.IsSelfInters(out parM))
     {
         throw new ExceptionGMath("VecD","Project(bez)",null);
         //return false;
     }
     if (bez.IsDegen)
     {
         par=new Param(Param.Degen);
         pnt=bez.Middle;
         return true;
     }
     if (bez.IsSeg(out parM))
     {
         SegD seg=bez.Reduced as SegD;
         this.Project(seg,out par,out pnt);
         bez.ParamFromSeg(par);
         return true;
     }
     // case of non-flat Bezier
     Param[] parsPerp;
     if (!this.Perp(bez, out parsPerp))
         return false;
     double distS=this.Dist(bez.Start);
     double distE=this.Dist(bez.End);
     double distMin=Math.Min(distS,distE);
     double parMin=(distS<=distE)? 0.0: 1.0;
     if (parsPerp!=null)
     {
         for (int iPerp=0; iPerp<parsPerp.Length; iPerp++)
         {
             if (bez.IsEvaluableStrict(parsPerp[iPerp]))
             {
                 double distPerp=this.Dist(bez.Evaluate(parsPerp[iPerp]));
                 if (distPerp<distMin)
                 {
                     distMin=distPerp;
                     parMin=parsPerp[iPerp];
                 }
             }
         }
     }
     par=parMin;
     pnt=bez.Evaluate(parMin);
     return true;
 }
예제 #24
0
        public bool ProjectGeneral(Bez2D bez, out Param[] pars, out VecD pnt)
        {
            /*
             *        MEANING:    parameter (or parameters) of the nearest point
             *                    in range [0,1]
             * 
             *        ASSUMPTIONS:    bezier can be non-reduced
             *                        bezier can be self-intersecting
             * 
             */


            pars=null;
            pnt=null;
            Param parM;
            if (!bez.IsSelfInters(out parM))
            {
                Param par;
                if (!this.Project(bez,out par,out  pnt))
                    return false;
                if (par!=null)
                {
                    pars=new Param[1];
                    pars[0]=par;
                }
                return true;
            }

            double valM=parM.Val;
            if (parM<0)
            {
                Bez2D bezRev=new Bez2D(bez);
                bezRev.Reverse();
                if (!this.ProjectGeneral(bezRev,out pars,out pnt))
                    return false;
                if (pars!=null)
                {
                    for (int iPar=0; iPar<pars.Length; iPar++)
                    {
                        pars[iPar].Reverse(1);
                    }
                }
                return true;
            }
            SegD support=bez.SupportFlat();
            Param parSupport;
            if (!this.Project(support,out parSupport, out pnt))
                return false;
            if (!bez.ParamFromSupport(parSupport,out pars))
                return false;
            return true;
        }
예제 #25
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;
        }
예제 #26
0
        bool InverseOn(Bez2D bez, out bool isOn, out Param par)
        {
            /*
             *        MEANING:    inverse point which is known to lie on the
             *                    bezier in range [-Infinity, Infinity]
             * 
             *        ASSUMPTIONS:    bez is IRREDUCABLE && NOT S/I 
             * 
             */    
        
            isOn=false;
            par=null;

            Param parM;
            if ((bez.IsDegen)||(bez.IsSeg(out parM))||(bez.IsSelfInters(out parM)))
            {
                throw new ExceptionGMath("VecD","InverseOn(bez)",null);
                //return false;
            }

            VecD[] cfBez;
            bez.PowerCoeff(out cfBez);

            double dev=(cfBez[2].Cross(this-cfBez[0]))*
                (cfBez[2].Cross(this-cfBez[0]))-
                (cfBez[2].Cross(cfBez[1]))*
                ((this-cfBez[0]).Cross(cfBez[1]));

            if (Math.Abs(dev)<MConsts.EPS_DEC)
            {
                isOn=true;
                par=(cfBez[2].Cross(this-cfBez[0]))/(cfBez[2].Cross(cfBez[1]));
            }

            return true;
        }
예제 #27
0
        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);
        }