示例#1
0
        /// <summary>
        /// Creates a interpolated curve through a set of points.<br/>
        /// <em>Refer to Algorithm A9.1 on The NURBS Book, pp.369-370 for details.</em>
        /// </summary>
        /// <param name="pts">The set of points to interpolate.</param>
        /// <param name="degree">The Curve degree.</param>
        /// <param name="startTangent">The tangent vector for the first point.</param>
        /// <param name="endTangent">The tangent vector for the last point.</param>
        /// <param name="centripetal">True use the chord as per knot spacing, false use the squared chord.</param>
        /// <returns>A the interpolated curve.</returns>
        public static NurbsBase Interpolated(List <Point3> pts, int degree, Vector3?startTangent = null,
                                             Vector3?endTangent = null, bool centripetal = false)
        {
            if (pts.Count < degree + 1)
            {
                throw new Exception($"You must supply at least degree + 1 points. You supplied {pts.Count} pts.");
            }

            // Gets uk parameters.
            List <double> uk = CurveHelpers.Parametrization(pts, centripetal);

            // Compute knot vectors.
            bool       hasTangents = startTangent != null && endTangent != null;
            KnotVector knots       = ComputeKnotsForInterpolation(uk, degree, hasTangents);

            // Global interpolation.
            // Build matrix of basis function coefficients.
            Matrix coeffMatrix = BuildCoefficientsMatrix(pts, degree, hasTangents, uk, knots);
            // Solve for each points.
            List <Point4> ctrlPts = (hasTangents)
                ? SolveCtrlPtsWithTangents(knots, pts, coeffMatrix, degree, new Vector3(startTangent.Value), new Vector3(endTangent.Value))
                : SolveCtrlPts(pts, coeffMatrix);

            return(new NurbsCurve(degree, knots, ctrlPts));
        }
示例#2
0
        public static PolyCurve Join(IList <NurbsBase> curves)
        {
            if (curves == null)
            {
                throw new Exception("The set of curves is empty.");
            }

            if (curves.Count <= 1)
            {
                throw new Exception("Insufficient curves for join operation.");
            }

            List <NurbsBase> sortedCurves = CurveHelpers.QuickSortCurve(curves);

            for (int i = 0; i < sortedCurves.Count - 1; i++)
            {
                if (sortedCurves[i].IsClosed)
                {
                    throw new Exception($"Curve at {i} is closed.");
                }
                if (sortedCurves[i].ControlPoints.Last().DistanceTo(sortedCurves[i + 1].ControlPoints[0]) > GSharkMath.MinTolerance)
                {
                    throw new Exception($"Curve at {i} don't touch curve at {i + 1}.");
                }
            }

            PolyCurve polyCurve = new PolyCurve(sortedCurves);

            return(polyCurve);
        }
 private void Action_FlipY(object context)
 {
     if (context is SerializedProperty property)
     {
         AnimationCurve curve = property.animationCurveValue;
         CurveHelpers.FlipY(curve);
         property.animationCurveValue = curve;
         property.serializedObject.ApplyModifiedProperties();
     }
 }
示例#4
0
        /// <summary>
        /// Constructs a ruled surface between two curves.
        /// <em>Follows the algorithm at page 337 of The NURBS Book by Piegl and Tiller.</em>
        /// </summary>
        /// <param name="curveA">The first curve.</param>
        /// <param name="curveB">The second curve.</param>
        /// <returns>A ruled surface.</returns>
        public static NurbsSurface Ruled(NurbsBase curveA, NurbsBase curveB)
        {
            IList <NurbsBase> curves = new[] { curveA, curveB };

            curves = CurveHelpers.NormalizedDegree(curves);
            curves = CurveHelpers.NormalizedKnots(curves);

            return(new NurbsSurface(1, curves[0].Degree, new KnotVector(1, 2), curves[0].Knots,
                                    new List <List <Point4> > {
                curves[0].ControlPoints, curves[1].ControlPoints
            }));
        }
示例#5
0
        public static NurbsBase Approximate(List <Point3> pts, int degree, bool centripetal = false)
        {
            int numberCpts = pts.Count - 1;

            // Gets the parameters curve uk.
            List <double> uk = CurveHelpers.Parametrization(pts, centripetal);

            // Computes knot vectors.
            KnotVector knots = ComputeKnotsForCurveApproximation(uk, degree, numberCpts, pts.Count);

            // Compute matrix N
            Matrix matrixN = new Matrix();

            for (int i = 1; i < pts.Count - 1; i++)
            {
                List <double> tempRow = new List <double>();
                for (int j = 1; j < numberCpts - 1; j++)
                {
                    tempRow.Add(Evaluate.Curve.OneBasisFunction(degree, knots, j, uk[i]));
                }
                matrixN.Add(tempRow);
            }

            // Compute NT matrix.
            Matrix matrixNt = matrixN.Transpose();
            // Compute NTN matrix.
            Matrix matrixNtN = matrixNt * matrixN;

            // Computes Rk - Eqn 9.63.
            List <Point3> Rk = ComputesValuesRk(knots, uk, degree, pts, numberCpts);

            // Compute R - Eqn 9.67.
            var vectorR = ComputeValuesR(knots, uk, Rk, degree, numberCpts);

            // Computes control points, fixing the first and last point from the input points.
            List <Point4> ctrlPts = new List <Point4> {
                pts[0]
            };

            ctrlPts.AddRange(SolveCtrlPts(vectorR, matrixNtN));
            ctrlPts.Add(pts[pts.Count - 1]);

            return(new NurbsCurve(degree, knots, ctrlPts));
        }
示例#6
0
        /// <summary>
        /// Constructs a NURBS surface from a set of NURBS curves.<br/>
        /// </summary>
        /// <param name="curves">Set of a minimum of two curves to create the surface.</param>
        /// <param name="loftType">Enum to choose the type of loft generation.</param>
        /// <returns>A NURBS surface.</returns>
        public static NurbsSurface FromLoft(IList <NurbsBase> curves, LoftType loftType = LoftType.Normal)
        {
            if (curves == null)
            {
                throw new ArgumentException("An invalid number of curves to perform the loft.");
            }

            if (curves.Count < 2)
            {
                throw new ArgumentException("An invalid number of curves to perform the loft.");
            }

            if (curves.Any(x => x == null))
            {
                throw new ArgumentException("The input set contains null curves.");
            }

            bool isClosed = curves[0].IsClosed;

            foreach (NurbsBase c in curves.Skip(1))
            {
                if (isClosed != c.IsClosed)
                {
                    throw new ArgumentException("Loft only works if all curves are open, or all curves are closed.");
                }
            }

            // Copy curves for possible operation of homogenization.
            IList <NurbsBase> copyCurves = new List <NurbsBase>(curves);

            // Clamp curves if periodic.
            if (copyCurves[0].IsPeriodic)
            {
                for (int i = 0; i < copyCurves.Count; i++)
                {
                    copyCurves[i] = copyCurves[i].ClampEnds();
                }
            }

            // If necessary, the curves can be brought to a common degree and knots, as we do for the ruled surface.
            // In fact, the ruled surface is a special case of a skinned surface.
            if (copyCurves.Any(c => c.Degree != copyCurves[0].Degree))
            {
                copyCurves = CurveHelpers.NormalizedDegree(copyCurves);
                copyCurves = CurveHelpers.NormalizedKnots(copyCurves);
            }

            int                   degreeV              = copyCurves[0].Degree;
            int                   degreeU              = 3;
            KnotVector            knotVectorU          = new KnotVector();
            KnotVector            knotVectorV          = copyCurves[0].Knots;
            List <List <Point4> > surfaceControlPoints = new List <List <Point4> >();

            switch (loftType)
            {
            case LoftType.Normal:
                List <List <Point4> > tempPts = new List <List <Point4> >();
                for (int n = 0; n < copyCurves[0].ControlPointLocations.Count; n++)
                {
                    List <Point3> pts = copyCurves.Select(c => c.ControlPointLocations[n]).ToList();
                    NurbsBase     crv = Fitting.Curve.Interpolated(pts, degreeU);
                    tempPts.Add(crv.ControlPoints);
                    knotVectorU = crv.Knots;
                }
                surfaceControlPoints = CollectionHelpers.Transpose2DArray(tempPts);
                break;

            case LoftType.Loose:
                surfaceControlPoints = copyCurves.Select(c => c.ControlPoints).ToList();
                knotVectorU          = new KnotVector(degreeU, copyCurves.Count);
                break;
            }
            return(new NurbsSurface(degreeU, degreeV, knotVectorU, knotVectorV, surfaceControlPoints));
        }