Beispiel #1
0
        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);
        }
Beispiel #3
0
        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));
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        /// <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);
        }
Beispiel #8
0
        /// <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);
        }
Beispiel #9
0
 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)));
 }