public static bool _Is2dControlPointsOutOfFaceDomain(this NurbsCurve crv2d, Surface srf, out Percent maxOutsideDistPercent, out int outOfDomainCount) { Percent domainTolPercent = 0.01; var domainU = srf.Domain(0); var domainV = srf.Domain(1); var domainUTol = domainU.Length * domainTolPercent; //1% of domain length var domainVTol = domainV.Length * domainTolPercent; //1% of domain length outOfDomainCount = 0; var minU = domainU.T0 - domainUTol; var maxU = domainU.T1 + domainUTol; var minV = domainV.T0 - domainVTol; var maxV = domainV.T1 + domainVTol; maxOutsideDistPercent = 0; foreach (var p in crv2d.Points) { var u = p.Location.X; var v = p.Location.Y; if (u < minU || u > maxU || v < minV || v > maxV) { double dist = 0; if (u < minU) { dist = (domainU.T0 - u) / domainU.Length._GetNonZeroForDevisionOperation(); maxOutsideDistPercent = Math.Max(maxOutsideDistPercent, dist); } if (u > maxU) { dist = (u - domainU.T1) / domainU.Length._GetNonZeroForDevisionOperation(); maxOutsideDistPercent = Math.Max(maxOutsideDistPercent, dist); } if (v < minV) { dist = (domainV.T0 - v) / domainV.Length._GetNonZeroForDevisionOperation(); maxOutsideDistPercent = Math.Max(maxOutsideDistPercent, dist); } if (v > maxV) { dist = (v - domainV.T1) / domainV.Length._GetNonZeroForDevisionOperation(); maxOutsideDistPercent = Math.Max(maxOutsideDistPercent, dist); } outOfDomainCount++; } } return(outOfDomainCount > 0); }
public double T(Percent p) { p.MustBeInScope01(); double t; if (Crv.NormalizedLengthParameter(p, out t, 1E-08)) { return(t); } // very small curves are really hard to get some middle point - so dont bother - show a warning only for normal curves var len = Crv.PointAtStart._DistanceTo(Crv.PointAtEnd); if (len > 0.0001) { log.wrong("CurveNormalized.T(Percent p) cannot get value from method 'NormalizedLengthParameter'"); } // at least we can return approximated value return(Crv.Domain.T0 + Crv.Domain.Length * p); }
public static Percent _GetSizeDiffInPercent(this BoundingBox box, BoundingBox compareToBox, Percent minDiffInPercentAllowed) { Percent widthDiff = box._Width()._DiffInPercent(compareToBox._Width()); if (widthDiff < minDiffInPercentAllowed) { return(widthDiff); // speed optimization } Percent heightDiff = box._Height()._DiffInPercent(compareToBox._Height()); if (heightDiff < minDiffInPercentAllowed) { return(heightDiff); // speed optimization } //var boxCenter = box.Center; //var compareToBoxCenter = compareToBox.Center; //Percent Xdiff = 1- Math.Abs(boxCenter.X - compareToBoxCenter.X)._DiffInPercent(Math.Min(box._Width(), compareToBox._Width())); //if (widthDiff < minDiffInPercentAllowed) return widthDiff; // speed optimization //Percent Ydiff = 1 - Math.Abs(boxCenter.Y - compareToBoxCenter.Y)._DiffInPercent(Math.Min(box._Height(), compareToBox._Height())); //if (Ydiff < minDiffInPercentAllowed) return Ydiff; // speed optimization //Percent Zdiff = 1 - Math.Abs(boxCenter.Z - compareToBoxCenter.Z)._DiffInPercent(Math.Min(box._Deep(), compareToBox._Deep())); Percent diagonalDiff = box._Diagonal()._DiffInPercent(compareToBox._Diagonal()); Percent deepDiff = box._Deep()._DiffInPercent(compareToBox._Deep()); double minPercent = 1; foreach (var diff in new[] { diagonalDiff, widthDiff, heightDiff, deepDiff, }) // Xdiff, Ydiff, Zdiff { if (diff < minPercent) { minPercent = diff; } } return(new Percent(minPercent)); }
/// <summary> /// Remove portions of the curve outside the specified interval. /// </summary> /// <param name="p0"></param> /// <param name="p1"></param> /// <param name="failReason"></param> /// <returns></returns> public CurveNormalized Trim(Percent p0, Percent p1, out string failReason) { failReason = ""; Curve res = null; if (p0.is0percent() && p1.is100percent()) { res = Crv; } else { var t0 = T(p0); var t1 = T(p1); res = Crv.DuplicateCurve().Trim(t0, t1); } if (res == null) { failReason = "failed to trim crv"; return(null); } return(new CurveNormalized(res)); }
public static bool _Kinks_NewCurve_IsValid(Curve crv, Curve newCuve, List <CurveKinkData> kinks, out double deviation, out string failReason, double maxAllowedDeviation = 0.01) { failReason = ""; deviation = 0; Percent cutPercents = 1.0 / DIVBY_TEST; var divby = newCuve._GetDivBy(null, 0.01, DIVBY_TEST * 5); if (newCuve == null) { failReason = "newCuve == null"; return(false); } // // Validate crv for deviation (crv shouldn't have big distance from original curve in diapason outside kinks) // Point3d[] points; double[] ts; if (!crv._TryDivideByCount(divby, out points, out ts, out failReason)) { return(false); } Point3d[] pointsNewCuve; if (!newCuve._TryDivideByCount(divby, out pointsNewCuve, out failReason)) { return(false); } // get region outside kinks var tMin = crv.Domain.T0 - 1; var tMax = crv.Domain.T1 + 1; foreach (var kink in kinks) { switch (kink.CrvEnd) { case CurveEnd.Start: tMin = crv._TAtPercent(cutPercents); // cut 5% from start break; case CurveEnd.End: tMax = crv._TAtPercent(1 - cutPercents); // cut 5% from end break; } } for (int i = 0; i < points.Length; i++) { if (tMin <= ts[i] && ts[i] <= tMax) { var oldPoint = points[i]; var newPoint = pointsNewCuve[i]; deviation = Math.Max(deviation, oldPoint._DistanceTo(newPoint)); } } //log.temp("deviation = {0:0.00000}", deviation); // max dist must be reasonable - this is they key of fixing: 'correcting do not break' if (deviation > maxAllowedDeviation) { failReason = "deviation {0:0.00000} is max from allowed"._Format(deviation); //log.wrong("_Curve._TryRemoveKinks: " + failReason); return(false); } // // Validate crv for kinks (if we removing kinks - they should really be removed - otherwise fix failed) // if (DEBUG) { var oldKinks = crv._Kinks_Find(); // debug } var newKinks = newCuve._Kinks_Find(); if (newKinks != null) { failReason = "fixed curve has {0} kinks"._Format(newKinks.Count); //log.wrong("_Curve._TryRemoveKinks: " + failReason); - no need to write worng message here - we have 3 function that tries to fix - if one not succeed, another may - and only if 3 of them fail - we will write wrong message return(false); } var zigzags = newCuve._ZigZagDeformationsFind(); if (zigzags != null) { failReason = "fixed curve has {0} zigzags"._Format(zigzags.Length); //log.wrong("_Curve._TryRemoveKinks: " + failReason); return(false); } return(true); }
/// <summary> /// Remove kinks if possible. /// Works only for 3d curves. /// </summary> /// <param name="curve">3d curve</param> /// <param name="kinks">kinks provided by a method '_FindKinksAtEnds'</param> /// <param name="failReason">if a method failed - this string will have fail reason</param> /// <returns></returns> private static Curve _Kinks_TryRemove_Simple(Curve curve, List <CurveKinkData> kinks, int DIVBY_FIX, int DIVBY_MIN, out string failReason) { failReason = ""; Percent cutPercents = 1.0 / DIVBY_FIX; var crv = new CurveNormalized(curve); // Div crv by small segments var divby = curve._GetDivBy(null, 0.01, DIVBY_MIN); Point3d[] points; double[] ts; if (!curve._TryDivideByCount(divby, out points, out ts, out failReason)) { return(null); } // Construct copy indexes (we will remove 5% from start and end, where the kinks found) var tMin = crv.Domain.T0 - 1; var tMax = crv.Domain.T1 + 1; foreach (var kink in kinks) { switch (kink.CrvEnd) { case CurveEnd.Start: tMin = crv.T(0 + cutPercents); // cut 5% from start break; case CurveEnd.End: tMax = crv.T(1 - cutPercents); // cut 5% from end break; } } // Copy points excluding kink diapasons var iadded = new List <int>(); if (kinks.Exists(o => o.CrvEnd == CurveEnd.Start)) { iadded.Add(0); // add start point anyway, since we need it and it will be removed by condition 'tMin <= ts[i]' } for (int i = 0; i < points.Length; i++) { if (tMin <= ts[i] && ts[i] <= tMax) { iadded.Add(i); } } if (kinks.Exists(o => o.CrvEnd == CurveEnd.End)) { iadded.Add(points.Length - 1); // add end point anyway, since we need it and it will be removed by condition 'ts[i] <= tMax' } var validPoints = iadded.Select(o => points[o]).ToList(); // // Construct new curve // var newCuve = Curve.CreateControlPointCurve(validPoints, 3); //var newCuve = Curve.CreateInterpolatedCurve(validPoints, 3); - makes zigzag - so we cant use it here if (DEBUG) { Layers.Debug.AddCurve(newCuve); for (var i = 0; i < validPoints.Count; i++) { var p = validPoints[i]; Layers.Debug.AddPoint(p); // Layers.Debug.AddTextPoint("" + tsadded[i]._ToStringX(2), p); } } if (newCuve == null) { failReason = "failed to create curve from 3d points"; return(null); } newCuve = newCuve._Simplify(); //simplify crv after constructing if from many points return(newCuve); }
/// <summary> /// Remove kinks if possible. /// Works only for 3d curves. /// </summary> /// <param name="curve">3d curve</param> /// <param name="kinks">kinks provided by a method '_FindKinksAtEnds'</param> /// <param name="failReason">if a method failed - this string will have fail reason</param> /// <returns></returns> private static Curve _Kinks_TryRemove_Smooth(Curve curve, List <CurveKinkData> kinks, int DIVBY_FIX, int DIVBY_MIN, out string failReason) { failReason = ""; Percent cutPercents = 1.0 / DIVBY_FIX; var crv = new CurveNormalized(curve); // // Cut curve at kink ends // var crvCutted = new CurveNormalized(curve); var cutPointAtStart = Point3d.Origin; var cutPointAtEnd = Point3d.Origin; foreach (var kink in kinks) { switch (kink.CrvEnd) { case CurveEnd.Start: cutPointAtStart = crv.PointAt(0 + cutPercents); // cut 5% from start crvCutted = crvCutted.Trim(0 + cutPercents, 1, out failReason); // remove outside interval if (crvCutted == null) { return(null); } break; case CurveEnd.End: cutPointAtEnd = crv.PointAt(1 - cutPercents); // cut 5% from start crvCutted = crvCutted.Trim(0, 1 - cutPercents, out failReason); // remove outside interval if (crvCutted == null) { return(null); } break; } } //if(DEBUG) Layers.Debug.AddCurve(crvCutted); // // Extend cutted crv // var crvExtended = crvCutted.Crv; foreach (var kink in kinks) { switch (kink.CrvEnd) { case CurveEnd.Start: crvExtended = crvExtended._ExtendToPoint(CurveEnd.Start, curve.PointAtStart); if (crvExtended == null) { failReason = "failed to extend crv"; return(null); } break; case CurveEnd.End: crvExtended = crvExtended._ExtendToPoint(CurveEnd.End, curve.PointAtEnd); if (crvExtended == null) { failReason = "failed to extend crv"; return(null); } break; } } //if (DEBUG) Layers.Debug.AddCurve(crvExtended); // // Move ends of extended curve // var divby = crvExtended._GetDivBy(null, 0.01, DIVBY_MIN); Point3d[] pointsExtended; double[] tsExtended; if (!crvExtended._TryDivideByCount(divby, out pointsExtended, out tsExtended, out failReason)) { return(null); } foreach (var kink in kinks) { var end = kink.CrvEnd; var extendToPoint = curve._P(end); var direction = extendToPoint - crvExtended._P(end); var iStart = (end == CurveEnd.Start) // will be more close to middle of curve ? -Math.Abs(Array.BinarySearch(tsExtended, crvExtended._T(cutPointAtStart))) // negative value, like '-5' : Math.Abs(Array.BinarySearch(tsExtended, crvExtended._T(cutPointAtEnd))); var iEnd = (end == CurveEnd.Start) ? 0 : pointsExtended.Length - 1; // will be at ends of curve for (int ii = iStart; ii <= iEnd; ii++) { double shiftByPercent = (ii - iStart) / (double)(iEnd - iStart); // from 0 to 1 var i = Math.Abs(ii); if (DEBUG) { Layers.Debug.AddPoint(pointsExtended[i]); } pointsExtended[i] = pointsExtended[i] + direction * shiftByPercent; if (DEBUG) { Layers.Debug.AddPoint(pointsExtended[i]); } } } // // Construct new curve // var newCuve = Curve.CreateControlPointCurve(pointsExtended, 3); if (newCuve == null) { failReason = "failed to create curve from 3d points"; return(null); } if (DEBUG) { Layers.Debug.AddCurve(newCuve, "Smooth"); } newCuve = newCuve._Simplify(); //simplify crv after constructing if from many points return(newCuve); }
/// <summary> /// Remove kinks if possible. /// Works only for 3d curves. /// </summary> /// <param name="curve">3d curve</param> /// <param name="kinks">kinks provided by a method '_FindKinksAtEnds'</param> /// <param name="failReason">if a method failed - this string will have fail reason</param> /// <returns></returns> private static Curve _Kinks_TryRemove_Smooth_Iternal(Curve curve, List <CurveKinkData> kinks, int DIVBY_FIX, int DIVBY_MIN, out string failReason) { failReason = ""; Percent cutPercents = 1.0 / DIVBY_FIX; // // Cut curve at kink ends // var crvCutted = new CurveNormalized(curve); foreach (var kink in kinks) { switch (kink.CrvEnd) { case CurveEnd.Start: crvCutted = crvCutted.Trim(0 + cutPercents, 1, out failReason); // remove outside interval if (crvCutted == null) { return(null); } break; case CurveEnd.End: crvCutted = crvCutted.Trim(0, 1 - cutPercents, out failReason); // remove outside interval if (crvCutted == null) { return(null); } break; } } //if(DEBUG) Layers.Debug.AddCurve(crvCutted); // // Extend cutted crv // var crvExtended = crvCutted.Crv; foreach (var kink in kinks) { switch (kink.CrvEnd) { case CurveEnd.Start: crvExtended = crvExtended.Extend(CurveEnd.Start, CurveExtensionStyle.Arc, curve.PointAtStart); if (crvExtended == null) { failReason = "failed to extend crv"; return(null); } break; case CurveEnd.End: crvExtended = crvExtended.Extend(CurveEnd.End, CurveExtensionStyle.Arc, curve.PointAtEnd); if (crvExtended == null) { failReason = "failed to extend crv"; return(null); } break; } } if (DEBUG) { Layers.Debug.AddCurve(crvExtended, "Smooth_Iternal", Color.Bisque); } return(crvExtended); }
public static Percent _GetPositionDiffInPercent(this BoundingBox box, BoundingBox compareToBox, Percent minDiffInPercentAllowed) { return(box._GetSizeDiffInPercent(box._UnionFast(compareToBox), minDiffInPercentAllowed)); }
public Vector3d TangentAt(Percent p) { return(Crv.TangentAt(T(p))); }
public Point3d PointAt(Percent p) { return(Crv.PointAt(T(p))); }