public bool IsSelfInters(out InfoInters inters) { /* * RETURN VALUE: true if Self-Intersecting; false otherwise */ inters = null; Param parM; if (!IsSelfInters(out parM)) { return(false); } if (parM.Val == Param.Infinity) { inters = new IntersD1(0, null, 1, null, this, true); } else if (parM > 1) { Param paramStart = 1.0 / (2.0 * parM.Val - 1.0); BCurve curveInters = this.SubCurve(paramStart, 1); if (curveInters == null) { throw new ExceptionGMath("Bez2D", "IsSelfInters", ""); } inters = new IntersD1(paramStart, null, 1.0, null, curveInters, true); } else if (parM < 0) { Param paramEnd = (-2.0 * parM.Val) / (1.0 - 2.0 * parM.Val); BCurve curveInters = this.SubCurve(0, paramEnd); if (curveInters == null) { throw new ExceptionGMath("Bez2D", "IsSelfInters", ""); } inters = new IntersD1(0.0, null, paramEnd, null, curveInters, true); } return(true); }
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); }
public bool IsSelfInters(out InfoInters inters) { /* * RETURN VALUE: true if Self-Intersecting; false otherwise */ inters=null; Param parM; if (!IsSelfInters(out parM)) return false; if (parM.Val==Param.Infinity) { inters=new IntersD1(0,null,1,null,this,true); } else if (parM>1) { Param paramStart=1.0/(2.0*parM.Val-1.0); BCurve curveInters=this.SubCurve(paramStart,1); if (curveInters==null) { throw new ExceptionGMath("Bez2D","IsSelfInters",""); } inters=new IntersD1(paramStart,null,1.0,null,curveInters,true); } else if (parM<0) { Param paramEnd=(-2.0*parM.Val)/(1.0-2.0*parM.Val); BCurve curveInters=this.SubCurve(0,paramEnd); if (curveInters==null) { throw new ExceptionGMath("Bez2D","IsSelfInters",""); } inters=new IntersD1(0.0,null,paramEnd,null,curveInters,true); } return true; }
public static bool RefineIntersLLD1(LCurve lrsA, LCurve lrsB, out InfoInters inters) { inters = null; if ((lrsA is SegD) && (lrsB is SegD)) { BCurve curveA = lrsA as BCurve; BCurve curveB = lrsB as BCurve; return(Inters.RefineIntersBBD1(curveA, curveB, out inters)); } if (lrsA.LComplexity > lrsB.LComplexity) { bool res = Inters.RefineIntersLLD1(lrsB, lrsA, out inters); if (inters != null) { inters.ParamSwap(); } return(res); } VecD a0 = lrsA.Start; VecD a1 = lrsA.End; VecD b0 = lrsB.Start; VecD b1 = lrsB.End; Param paramBInvA0, paramBInvA1; bool isOn; if ((!a0.InverseOn(lrsB, out isOn, out paramBInvA0)) || (!isOn)) { return(false); } if ((!a1.InverseOn(lrsB, out isOn, out paramBInvA1)) || (!isOn)) { return(false); } Param paramAInvB0, paramAInvB1; if ((!b0.InverseOn(lrsA, out isOn, out paramAInvB0)) || (!isOn)) { return(false); } if ((!b1.InverseOn(lrsA, out isOn, out paramAInvB1)) || (!isOn)) { return(false); } bool areCoDirected = (paramBInvA1.Val >= paramBInvA0.Val); if (!areCoDirected) { if (lrsA is LineD) { if (lrsB is LineD) { paramAInvB0 = (areCoDirected)? -Param.Infinity: Param.Infinity; paramAInvB1 = (areCoDirected)? Param.Infinity: -Param.Infinity; inters = new IntersD1(paramAInvB0, -Param.Infinity, paramAInvB1, Param.Infinity, lrsB, false); return(true); } if (lrsB is RayD) { paramAInvB1 = (areCoDirected)? Param.Infinity: -Param.Infinity; inters = new IntersD1(paramAInvB0, 0, paramAInvB1, Param.Infinity, lrsB, false); return(true); } if (lrsB is SegD) { inters = new IntersD1(paramAInvB0, 0, paramAInvB1, 1, lrsB, false); return(true); } } if (lrsA is RayD) { if (lrsB is RayD) { if (areCoDirected) { if (paramAInvB0 > 0) { inters = new IntersD1(paramAInvB0, 0, Param.Infinity, Param.Infinity, lrsB, false); return(true); } else { inters = new IntersD1(0, paramBInvA0, Param.Infinity, Param.Infinity, lrsA, false); return(true); } } else { if (paramAInvB0 > 0) { inters = new IntersD1(0, paramBInvA0, paramAInvB0, 0, new SegD(a0, b0), false); return(true); } } } if (lrsB is SegD) { // intersection is known to have dimension D1 !!! if ((paramBInvA0 >= 1) || (paramBInvA0 <= 0)) { inters = new IntersD1(paramAInvB0, 0, paramAInvB1, 1, new SegD(b0, b1), false); return(true); } if ((0 < paramBInvA0) && (paramBInvA1 < 1)) { if (areCoDirected) { inters = new IntersD1(0, paramBInvA0, paramAInvB1, 1, new SegD(a0, b1), false); return(true); } else { inters = new IntersD1(0, paramBInvA0, paramAInvB0, 0, new SegD(a0, b0), false); return(true); } } } } } throw new ExceptionGMath("Intersect", "RefineIntersLLD1", null); //return false; }
/* * REFINE INTERSECTION D1 */ public static bool RefineIntersBBD1(BCurve curveA, BCurve curveB, out InfoInters inters) { /* * ASSUMPTIONS: * - curveA & curveB are MAXIMALLY REDUCED * - intersection is KNOWN to have dimension D1 * - does not work in case of SI beziers * => OR: both curveA & curveB are SEGMENTS * OR: both curveA & curveB are BEZIER */ inters = null; InfoInters selfinters; if (curveA.IsSelfInters(out selfinters) || curveB.IsSelfInters(out selfinters)) { throw new ExceptionGMath("Intersect", "RefineIntersBBD1", null); //return false; } VecD a0 = curveA.Start; VecD a1 = curveA.End; Param paramBInvA0, paramBInvA1; bool isOn; if (!a0.InverseOn(curveB, out isOn, out paramBInvA0) || (!isOn)) { return(false); } if (!a1.InverseOn(curveB, out isOn, out paramBInvA1) || (!isOn)) { return(false); } paramBInvA0.Round(0, 1); paramBInvA1.Round(0, 1); bool areCoDirected = (paramBInvA1 >= paramBInvA0); if (!areCoDirected) { BCurve revB = curveB.Reversed as BCurve; if (!Inters.RefineIntersBBD1(curveA, revB, out inters)) { return(false); } if (inters != null) { inters.ParamReverse(1, 1); } return(true); } VecD b0 = curveB.Start; VecD b1 = curveB.End; Param paramAInvB0, paramAInvB1; if (!b0.InverseOn(curveA, out isOn, out paramAInvB0) || (!isOn)) { return(false); } if (!b1.InverseOn(curveA, out isOn, out paramAInvB1) || (!isOn)) { return(false); } paramAInvB0.Round(0, 1); paramAInvB1.Round(0, 1); Param paramInA = null, paramInB = null, paramOutA = null, paramOutB = null; VecD pntIn = null, pntOut = null; if (paramBInvA0 <= 0) // before or start { paramInA = paramAInvB0; paramInB = 0; pntIn = b0; } else if (paramBInvA0 < 1) // inner { paramInA = 0; paramInB = paramBInvA0; pntIn = a0; } if ((paramBInvA1 >= 0) && (paramBInvA1 <= 1)) // inner or end { paramOutA = 1; paramOutB = paramBInvA1; pntOut = a1; } else if (paramBInvA1 > 1) // after { paramOutA = paramAInvB1; paramOutB = 1; pntOut = b1; } if ((pntIn == null) || (pntOut == null)) { throw new ExceptionGMath("Intersect", "RefineIntersBBD1", null); //return false; } Curve curveInters = curveA.SubCurve(paramInA, paramOutA); inters = new IntersD1(paramInA, paramInB, paramOutA, paramOutB, curveInters, false); return(true); }
/* * REFINE INTERSECTION D1 */ public static bool RefineIntersBBD1(BCurve curveA, BCurve curveB, out InfoInters inters) { /* * ASSUMPTIONS: * - curveA & curveB are MAXIMALLY REDUCED * - intersection is KNOWN to have dimension D1 * - does not work in case of SI beziers * => OR: both curveA & curveB are SEGMENTS * OR: both curveA & curveB are BEZIER */ inters=null; InfoInters selfinters; if (curveA.IsSelfInters(out selfinters)||curveB.IsSelfInters(out selfinters)) { throw new ExceptionGMath("Intersect","RefineIntersBBD1",null); //return false; } VecD a0=curveA.Start; VecD a1=curveA.End; Param paramBInvA0, paramBInvA1; bool isOn; if (!a0.InverseOn(curveB, out isOn, out paramBInvA0)||(!isOn)) return false; if (!a1.InverseOn(curveB, out isOn, out paramBInvA1)||(!isOn)) return false; paramBInvA0.Round(0,1); paramBInvA1.Round(0,1); bool areCoDirected=(paramBInvA1>=paramBInvA0); if (!areCoDirected) { BCurve revB=curveB.Reversed as BCurve; if (!Inters.RefineIntersBBD1(curveA,revB,out inters)) return false; if (inters!=null) { inters.ParamReverse(1,1); } return true; } VecD b0=curveB.Start; VecD b1=curveB.End; Param paramAInvB0, paramAInvB1; if (!b0.InverseOn(curveA, out isOn, out paramAInvB0)||(!isOn)) return false; if (!b1.InverseOn(curveA, out isOn, out paramAInvB1)||(!isOn)) return false; paramAInvB0.Round(0,1); paramAInvB1.Round(0,1); Param paramInA=null, paramInB=null, paramOutA=null, paramOutB=null; VecD pntIn=null, pntOut=null; if (paramBInvA0<=0) // before or start { paramInA=paramAInvB0; paramInB=0; pntIn=b0; } else if (paramBInvA0<1) // inner { paramInA=0; paramInB=paramBInvA0; pntIn=a0; } if ((paramBInvA1>=0)&&(paramBInvA1<=1)) // inner or end { paramOutA=1; paramOutB=paramBInvA1; pntOut=a1; } else if (paramBInvA1>1) // after { paramOutA=paramAInvB1; paramOutB=1; pntOut=b1; } if ((pntIn==null)||(pntOut==null)) { throw new ExceptionGMath("Intersect","RefineIntersBBD1",null); //return false; } Curve curveInters=curveA.SubCurve(paramInA,paramOutA); inters=new IntersD1(paramInA,paramInB, paramOutA,paramOutB,curveInters,false); return true; }
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; }
public static bool RefineIntersLLD1(LCurve lrsA, LCurve lrsB, out InfoInters inters) { inters=null; if ((lrsA is SegD) && (lrsB is SegD)) { BCurve curveA=lrsA as BCurve; BCurve curveB=lrsB as BCurve; return Inters.RefineIntersBBD1(curveA, curveB, out inters); } if (lrsA.LComplexity>lrsB.LComplexity) { bool res=Inters.RefineIntersLLD1(lrsB,lrsA,out inters); if (inters!=null) { inters.ParamSwap(); } return res; } VecD a0=lrsA.Start; VecD a1=lrsA.End; VecD b0=lrsB.Start; VecD b1=lrsB.End; Param paramBInvA0, paramBInvA1; bool isOn; if ((!a0.InverseOn(lrsB, out isOn, out paramBInvA0))||(!isOn)) return false; if ((!a1.InverseOn(lrsB, out isOn, out paramBInvA1))||(!isOn)) return false; Param paramAInvB0, paramAInvB1; if ((!b0.InverseOn(lrsA, out isOn, out paramAInvB0))||(!isOn)) return false; if ((!b1.InverseOn(lrsA, out isOn, out paramAInvB1))||(!isOn)) return false; bool areCoDirected=(paramBInvA1.Val>=paramBInvA0.Val); if (!areCoDirected) { if (lrsA is LineD) { if (lrsB is LineD) { paramAInvB0=(areCoDirected)? -Param.Infinity: Param.Infinity; paramAInvB1=(areCoDirected)? Param.Infinity: -Param.Infinity; inters=new IntersD1(paramAInvB0,-Param.Infinity, paramAInvB1,Param.Infinity,lrsB,false); return true; } if (lrsB is RayD) { paramAInvB1=(areCoDirected)? Param.Infinity: -Param.Infinity; inters=new IntersD1(paramAInvB0,0, paramAInvB1,Param.Infinity,lrsB,false); return true; } if (lrsB is SegD) { inters=new IntersD1(paramAInvB0,0, paramAInvB1,1,lrsB,false); return true; } } if (lrsA is RayD) { if (lrsB is RayD) { if (areCoDirected) { if (paramAInvB0>0) { inters=new IntersD1(paramAInvB0,0, Param.Infinity,Param.Infinity,lrsB,false); return true; } else { inters=new IntersD1(0,paramBInvA0, Param.Infinity,Param.Infinity,lrsA,false); return true; } } else { if (paramAInvB0>0) { inters=new IntersD1(0,paramBInvA0, paramAInvB0,0,new SegD(a0,b0),false); return true; } } } if (lrsB is SegD) { // intersection is known to have dimension D1 !!! if ((paramBInvA0>=1)||(paramBInvA0<=0)) { inters=new IntersD1(paramAInvB0,0, paramAInvB1,1,new SegD(b0,b1),false); return true; } if ((0<paramBInvA0)&&(paramBInvA1<1)) { if (areCoDirected) { inters=new IntersD1(0,paramBInvA0, paramAInvB1,1,new SegD(a0,b1),false); return true; } else { inters=new IntersD1(0,paramBInvA0, paramAInvB0,0,new SegD(a0,b0),false); return true; } } } } } throw new ExceptionGMath("Intersect","RefineIntersLLD1",null); //return false; }