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); }
public bool Project(LCurve lcurve, out Param param, out VecD pnt) { /* * MEANING: the NEAREST point in the PARAMETRIC RANGE * of the curve * * ASSUMPTIONS: the curve may be not reduced */ param = null; pnt = null; if (lcurve.IsDegen) { SegD seg = lcurve as SegD; if (seg == null) { throw new ExceptionGMath("VecD", "Project", null); //return false; } param = new Param(Param.Degen); pnt = seg.Middle; return(true); } this.Perp(lcurve, out param); param.Clip(lcurve.ParamStart, lcurve.ParamEnd); pnt = lcurve.Evaluate(param); return(true); }
public static bool AuxIntersectBB(DegenD degen, SegD seg, InfoConnect icAB, InfoConnect icBA, ListInfoInters linters) { if (linters == null) { throw new ExceptionGMath("Intersect", "AuxIntersectBB(degen,seg)", "Null argument"); } // no reduction bool connectAB = ((icAB != null) && (icAB.IsConnect)); if (connectAB) { return(true); } Param param; VecD pnt; degen.Cp.Project(seg, out param, out pnt); if (degen.Cp.Dist(pnt) < MConsts.EPS_DEC) { IntersD0 inters = new IntersD0(Param.Degen, param, pnt, false); linters.Add(inters); } return(true); }
public bool IsSelfInters(out Param parM) { /* * RETURN VALUE: true if Self-Intersecting; false otherwise */ parM = null; if (this.IsDegen) { return(false); } Param parSeg; if (this.IsSeg(out parSeg)) { return(false); } SegD seg = new SegD(this.cp[0], this.cp[2]); if (seg.IsDegen) { parM = Param.Infinity; return(true); } LineD line = new LineD(seg); VecD pnt; this.cp[1].Project(line, out parM, out pnt); if (this.cp[1].Dist(pnt) > MConsts.EPS_DEC) { return(false); } return(true); }
public VecD DirTang(Param par) { if (this.IsDegen) { return(null); } Param parM; if (this.IsSeg(out parM)) { SegD seg = new SegD(this.cp[0], this.cp[2]); return((seg as LCurve).DirTang); } if (this.IsSelfInters(out parM)) { SegD support = this.SupportFlat(); return((support as LCurve).DirTang); } VecD tan = 2.0 * (1.0 - par.Val) * (this.cp[1] - this.cp[0]) + 2.0 * par.Val * (this.cp[2] - this.cp[1]); if (tan.Norm < MConsts.EPS_COMP) { return(null); } return((1.0 / tan.Norm) * tan); }
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); }
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 pnt = this.Evaluate(par); curveS = new SegD(this.cp[0], pnt); curveE = new SegD(pnt, this.cp[1]); }
/* * METHODS */ public bool IsSeg(out Param parM) { /* * MEANING: NON_DEGENERATED, PARAMETRIC segment * (implies, that the Bezier is not * self-intersecting) */ parM = null; if (this.IsDegen) { return(false); } if (this.cp[0] == this.cp[2]) { return(false); // S/I bezier } if (this.cp[0] == this.cp[1]) { parM = new Param(0); return(true); } if (this.cp[1] == this.cp[2]) { parM = new Param(1); return(true); } SegD seg = new SegD(this.cp[0], this.cp[2]); LineD line = new LineD(seg); VecD pnt; Param par; this.cp[1].Project(line, out par, out pnt); if (this.cp[1].Dist(pnt) > MConsts.EPS_DEC) { return(false); } if (!seg.IsEvaluableStrict(par)) { return(false); } parM = par; if (Math.Abs(parM.Val - 0.5) < MConsts.EPS_DEC) { parM.Val = 0.5; } return(true); }
/* * METHODS */ public bool IsSeg(out Param parM) { /* * MEANING: NON_DEGENERATED, PARAMETRIC segment * (implies, that the Bezier is not * self-intersecting) */ parM=null; if (this.IsDegen) return false; if (this.cp[0]==this.cp[2]) return false; // S/I bezier if (this.cp[0]==this.cp[1]) { parM=new Param(0); return true; } if (this.cp[1]==this.cp[2]) { parM=new Param(1); return true; } SegD seg=new SegD(this.cp[0], this.cp[2]); LineD line=new LineD(seg); VecD pnt; Param par; this.cp[1].Project(line,out par,out pnt); if (this.cp[1].Dist(pnt)>MConsts.EPS_DEC) return false; if (!seg.IsEvaluableStrict(par)) return false; parM=par; if (Math.Abs(parM.Val-0.5)<MConsts.EPS_DEC) { parM.Val=0.5; } return true; }
public static bool AuxIntersectBB(SegD segA, SegD segB, InfoConnect icAB, InfoConnect icBA, ListInfoInters linters) { bool connectAB = ((icAB != null) && (icAB.IsConnect)); bool connectBA = ((icBA != null) && (icBA.IsConnect)); bool connect = connectAB || connectBA; InfoInters inters; if (!Inters.IntersectLL(segA, segB, out inters)) { return(false); } if (inters != null) { if ((!connect) || ((connect) && (inters.Dim == InfoInters.TypeDim.Dim1))) { linters.Add(inters); } } return(true); }
public static bool AuxIntersectBB(DegenD degen, SegD seg, InfoConnect icAB, InfoConnect icBA, ListInfoInters linters) { if (linters==null) { throw new ExceptionGMath("Intersect","AuxIntersectBB(degen,seg)","Null argument"); } // no reduction bool connectAB = ((icAB!=null)&&(icAB.IsConnect)); if (connectAB) { return true; } Param param; VecD pnt; degen.Cp.Project(seg,out param, out pnt); if (degen.Cp.Dist(pnt)<MConsts.EPS_DEC) { IntersD0 inters=new IntersD0(Param.Degen,param,pnt,false); linters.Add(inters); } return true; }
public static bool AuxIntersectBL(SegD seg, LCurve lrs, ListInfoInters linters) { // segment is irreducable !!! if (linters == null) { throw new ExceptionGMath("Intersect", "AuxIntersectBL(seg,lrs)", "Null argument"); } if (lrs.IsDegen) { throw new ExceptionGMath("Intersect", "AuxIntersectBL(seg,lrs)", null); } InfoInters inters; if (!Inters.IntersectLL(seg, lrs, out inters)) { return(false); } if (inters != null) { linters.Add(inters); } return(true); }
/* * METHODS: I_DRAWABLE */ override public void Draw(I_Draw i_draw, DrawParam dp) { if (((object)this.bboxCP==null)||((object)this.bboxOutl==null)) return; double xMinCP=this.bboxCP.VecMin.X; double yMinCP=this.bboxCP.VecMin.Y; double xMaxCP=this.bboxCP.VecMax.X; double yMaxCP=this.bboxCP.VecMax.Y; double xMinOutl=this.bboxOutl.VecMin.X; double yMinOutl=this.bboxOutl.VecMin.Y; double xMaxOutl=this.bboxOutl.VecMax.X; double yMaxOutl=this.bboxOutl.VecMax.Y; SegD seg; DrawParamCurve dpCurve; if (xMinCP<xMinOutl) { seg=new SegD(new VecD(xMinOutl,yMinCP), new VecD(xMinOutl,yMaxCP)); dpCurve=new DrawParamCurve("Orange",1.5F,false,null); seg.Draw(i_draw,dpCurve); } if (yMinCP<yMinOutl) { seg=new SegD(new VecD(xMinCP,yMinOutl), new VecD(xMaxCP,yMinOutl)); dpCurve=new DrawParamCurve("Orange",1.5F,false,null); seg.Draw(i_draw,dpCurve); } if (xMaxCP>xMaxOutl) { seg=new SegD(new VecD(xMaxOutl,yMinCP), new VecD(xMaxOutl,yMaxCP)); dpCurve=new DrawParamCurve("Orange",1.5F,false,null); seg.Draw(i_draw,dpCurve); } if (yMaxCP>yMaxOutl) { seg=new SegD(new VecD(xMinCP,yMaxOutl), new VecD(xMaxCP,yMaxOutl)); dpCurve=new DrawParamCurve("Orange",1.5F,false,null); seg.Draw(i_draw,dpCurve); } }
public VecD DirTang(Param par) { if (this.IsDegen) return null; Param parM; if (this.IsSeg(out parM)) { SegD seg=new SegD(this.cp[0],this.cp[2]); return ((seg as LCurve).DirTang); } if (this.IsSelfInters(out parM)) { SegD support=this.SupportFlat(); return ((support as LCurve).DirTang); } VecD tan=2.0*(1.0-par.Val)*(this.cp[1]-this.cp[0])+ 2.0*par.Val*(this.cp[2]-this.cp[1]); if (tan.Norm<MConsts.EPS_COMP) return null; return ((1.0/tan.Norm)*tan); }
public bool IsSelfInters(out Param parM) { /* * RETURN VALUE: true if Self-Intersecting; false otherwise */ parM=null; if (this.IsDegen) return false; Param parSeg; if (this.IsSeg(out parSeg)) return false; SegD seg=new SegD(this.cp[0], this.cp[2]); if (seg.IsDegen) { parM=Param.Infinity; return true; } LineD line=new LineD(seg); VecD pnt; this.cp[1].Project(line,out parM,out pnt); if (this.cp[1].Dist(pnt)>MConsts.EPS_DEC) return false; return true; }
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); }
public static bool AuxIntersectBL(SegD seg, LCurve lrs, ListInfoInters linters) { // segment is irreducable !!! if (linters==null) { throw new ExceptionGMath("Intersect","AuxIntersectBL(seg,lrs)","Null argument"); } if (lrs.IsDegen) { throw new ExceptionGMath("Intersect","AuxIntersectBL(seg,lrs)",null); } InfoInters inters; if (!Inters.IntersectLL(seg, lrs, out inters)) return false; if (inters!=null) linters.Add(inters); 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 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); }
public SegD(SegD seg) : this() { this.cp[0]=new VecD(seg.Cp(0)); this.cp[1]=new VecD(seg.Cp(1)); }
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 pnt=this.Evaluate(par); curveS=new SegD(this.cp[0],pnt); curveE=new SegD(pnt,this.cp[1]); }
public SegD(SegD seg) : this() { this.cp[0] = new VecD(seg.Cp(0)); this.cp[1] = new VecD(seg.Cp(1)); }
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 AuxIntersectBB(SegD segA, SegD segB, InfoConnect icAB, InfoConnect icBA, ListInfoInters linters) { bool connectAB = ((icAB!=null)&&(icAB.IsConnect)); bool connectBA = ((icBA!=null)&&(icBA.IsConnect)); bool connect=connectAB||connectBA; InfoInters inters; if (!Inters.IntersectLL(segA,segB,out inters)) return false; if (inters!=null) { if ((!connect)|| ((connect)&&(inters.Dim==InfoInters.TypeDim.Dim1))) { linters.Add(inters); } } return true; }