Skip to content

Commit

Permalink
feat(nurbs): Working basic nurbs curve class.
Browse files Browse the repository at this point in the history
  • Loading branch information
AlanRynne committed Oct 31, 2020
1 parent 197166a commit e26d245
Show file tree
Hide file tree
Showing 8 changed files with 371 additions and 24 deletions.
8 changes: 8 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -366,14 +366,20 @@ dotnet_naming_rule.parameters_rule.style=camel_case_style
dotnet_naming_rule.parameters_rule.severity=warning

# Microsoft .NET properties
csharp_new_line_between_query_expression_clauses=true
csharp_prefer_braces=false:none
csharp_space_after_keywords_in_control_flow_statements=true
csharp_space_between_method_call_parameter_list_parentheses=false
csharp_space_between_method_declaration_parameter_list_parentheses=false
csharp_space_between_parentheses=false

# ReSharper properties
resharper_align_multiline_argument=true
resharper_align_multiline_calls_chain=true
resharper_braces_redundant=true
resharper_csharp_outdent_dots=true
resharper_csharp_wrap_after_declaration_lpar=true
resharper_csharp_wrap_parameters_style=chop_if_long
resharper_empty_block_style=together_same_line
resharper_local_function_body=expression_body
resharper_space_within_catch_parentheses=false
Expand All @@ -385,6 +391,8 @@ resharper_space_within_parentheses=false
resharper_space_within_switch_parentheses=false
resharper_space_within_using_parentheses=false
resharper_space_within_while_parentheses=false
resharper_wrap_before_linq_expression=true
resharper_wrap_linq_expressions=chop_always

##########################################
# License
Expand Down
150 changes: 129 additions & 21 deletions src/Geometry/3D/Nurbs/NurbsCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,18 @@ public static class NurbsCalculator
/// </summary>
/// <param name="controlPointCount">Ammount of control points in the curve.</param>
/// <param name="degree">Degree of the curve.</param>
/// <exception cref="Exception">Throws an error if degree is bigger than controlPoints+1</exception>
/// <returns></returns>
public static double[] CreateUnitKnotVector(int controlPointCount, int degree)
{
if (degree > controlPointCount)
throw new Exception("Degree cannot be bigger than 'ControlPoints - 1'");
var knotVector = new double[controlPointCount + degree + 2];
var knotVector = new double[controlPointCount + degree + 1];
for (var i = 0; i <= degree; i++)
knotVector[i] = 0.0;
for (var i = degree + 1; i < controlPointCount + 1; i++)
knotVector[i] = ((double)i - degree) / ((controlPointCount - degree) + 1);
for (var i = controlPointCount + 1; i < controlPointCount + degree + 2; i++)
for (var i = degree + 1; i < controlPointCount; i++)
knotVector[i] = ((double)i - degree) / (controlPointCount - degree);
for (var i = controlPointCount; i < controlPointCount + degree + 1; i++)
knotVector[i] = 1.0;
return knotVector;
}
Expand Down Expand Up @@ -61,8 +62,10 @@ public static double Bernstein(int index, int degree, double t)

var u1 = 1.0 - t;
for (var k = 1; k <= degree; k++)
for (var j = degree; j >= k; j--)
temp[j] = (u1 * temp[j]) + (t * temp[j - 1]);
{
for (var j = degree; j >= k; j--)
temp[j] = (u1 * temp[j]) + (t * temp[j - 1]);
}

return temp[degree];
}
Expand Down Expand Up @@ -184,7 +187,7 @@ public static Point3d DeCasteljau2(Matrix<Point3d> controlPoints, int degreeU, i
/// <returns>The knot span index.</returns>
public static int FindSpan(int n, int degree, double t, IList<double> knotVector)
{
if (t == knotVector[n + 1])
if (Math.Abs(t - knotVector[n + 1]) < Settings.Tolerance)
return n;

var low = degree;
Expand Down Expand Up @@ -215,8 +218,10 @@ public static int FindSpan(int n, int degree, double t, IList<double> knotVector
{
var n = new double[degree + 1, degree + 1];
for (var i = 0; i <= degree; i++)
for (var j = 0; j <= i; j++)
n[j, i] = OneBasisFun(degree, knotVector.Count - 1, knotVector, (span - i) + j, param);
{
for (var j = 0; j <= i; j++)
n[j, i] = OneBasisFun(degree, knotVector.Count - 1, knotVector, (span - i) + j, param);
}

return n;
}
Expand Down Expand Up @@ -264,7 +269,7 @@ public static double[] BasisFuns(int span, double param, int degree, IList<doubl
/// <returns>Multidimensional array holding the basis functions and their derivatives for that parameter.</returns>
public static Matrix<double> DersBasisFuns(int span, double param, int degree, int n, IList<double> knotVector)
{
var ders = new Matrix<double>(n, degree);
var ders = new Matrix<double>(n + 1, degree + 1);
var ndu = new double[degree + 1, degree + 1];
var a = new double[2, degree + 1];
var left = new double[degree + 1];
Expand Down Expand Up @@ -361,14 +366,18 @@ public static double OneBasisFun(int degree, int m, IList<double> knotVector, in
// Initialize zeroth-degree functions
var n = new double[degree + 1];
for (var j = 0; j <= degree; j++)
{
if (param >= knotVector[span + j] && param < knotVector[span + j + 1])
n[j] = 1.0;
else
n[j] = 0.0;
}

for (var k = 1; k <= degree; k++)
{
var saved = n[0] == 0.0 ? 0.0 : ((param - knotVector[span]) * n[0]) / (knotVector[span + k] - knotVector[span]);
var saved = n[0] == 0.0
? 0.0
: ((param - knotVector[span]) * n[0]) / (knotVector[span + k] - knotVector[span]);
for (var j = 0; j < (degree - k) + 1; j++)
{
var uLeft = knotVector[span + j + 1];
Expand Down Expand Up @@ -413,8 +422,10 @@ public static double[] DersOneBasisFun(int p, int m, IList<double> knotVector, i

var tmpN = new double[p + 1, p + 1];
for (var j = 0; j <= p; j++)
{
if (u >= knotVector[i + j] && u < knotVector[i + j + 1])
tmpN[j, 0] = 1.0;
}

for (var k = 1; k <= p; k++)
{
Expand Down Expand Up @@ -481,6 +492,15 @@ public static double[] DersOneBasisFun(int p, int m, IList<double> knotVector, i
return ders;
}

/// <summary>
/// Computes a point on a nurbs curve.
/// </summary>
/// <param name="n"></param>
/// <param name="p"></param>
/// <param name="knotVector"></param>
/// <param name="controlPoints"></param>
/// <param name="u"></param>
/// <returns></returns>
public static Point3d CurvePoint(int n, int p, IList<double> knotVector, IList<Point3d> controlPoints, double u)
{
var span = FindSpan(n, p, u, knotVector);
Expand All @@ -491,7 +511,13 @@ public static Point3d CurvePoint(int n, int p, IList<double> knotVector, IList<P
return c;
}

public static Vector3d[] CurveDerivsAlg1(int n, int p, IList<double> knotVector, IList<Point3d> controlPoints, double u, int d)
public static Vector3d[] CurveDerivsAlg1(
int n,
int p,
IList<double> knotVector,
IList<Point3d> controlPoints,
double u,
int d)
{
var ck = new Vector3d[d + 1];
var du = Math.Min(d, p);
Expand All @@ -509,23 +535,40 @@ public static Vector3d[] CurveDerivsAlg1(int n, int p, IList<double> knotVector,
return ck;
}

public static Point3d[,] CurveDerivCpts(int n, int p, IList<double> knotVector, IList<Point3d> controlPoints, int d, int r1, int r2)
public static Point3d[,] CurveDerivCpts(
int n,
int p,
IList<double> knotVector,
IList<Point3d> controlPoints,
int d,
int r1,
int r2)
{
var r = r2 - r1;
var pk = new Point3d[d + 1, r];
for (var i = 0; i <= r; i++)
pk[0, i] = controlPoints[r1 + i];

for (var k = 1; k <= d; k++)
{
var tmp = (p - k) + 1;
for (var i = 0; i <= r - k; i++)
pk[k, i] = (tmp * (Point3d)(pk[k - 1, i + 1] - pk[k - 1, i])) / (knotVector[r1 + i + p + 1] - knotVector[r1 + i + k]);
{
pk[k, i] = (tmp * (Point3d)(pk[k - 1, i + 1] - pk[k - 1, i])) /
(knotVector[r1 + i + p + 1] - knotVector[r1 + i + k]);
}
}

return pk;
}

public static Vector3d[] CurveDerivsAlg2(int n, int p, IList<double> knotVector, IList<Point3d> controlPoints, double u, int d)
public static Vector3d[] CurveDerivsAlg2(
int n,
int p,
IList<double> knotVector,
IList<Point3d> controlPoints,
double u,
int d)
{
var du = Math.Min(d, p);
var ck = new Vector3d[d + 1];
Expand All @@ -545,7 +588,30 @@ public static Vector3d[] CurveDerivsAlg2(int n, int p, IList<double> knotVector,
}

// B-Spline Surfaces
public static Point3d SurfacePoint(int n, int p, IList<double> knotVectorU, int m, int q, IList<double> knotVectorV, Matrix<Point3d> controlPoints, double u, double v)

/// <summary>
/// Computes a point on a nurbs surface.
/// </summary>
/// <param name="n"></param>
/// <param name="p"></param>
/// <param name="knotVectorU"></param>
/// <param name="m"></param>
/// <param name="q"></param>
/// <param name="knotVectorV"></param>
/// <param name="controlPoints"></param>
/// <param name="u"></param>
/// <param name="v"></param>
/// <returns></returns>
public static Point3d SurfacePoint(
int n,
int p,
IList<double> knotVectorU,
int m,
int q,
IList<double> knotVectorV,
Matrix<Point3d> controlPoints,
double u,
double v)
{
var uspan = FindSpan(n, p, u, knotVectorU);
var nU = BasisFuns(uspan, u, p, knotVectorU);
Expand All @@ -565,7 +631,17 @@ public static Point3d SurfacePoint(int n, int p, IList<double> knotVectorU, int
return surfPt;
}

public static Point3d[,] SurfaceDerivsAlg1(int n, int p, IList<double> knotVectorU, int m, int q, IList<double> knotVectorV, Matrix<Point3d> controlPoints, double u, double v, int derivCount)
public static Point3d[,] SurfaceDerivsAlg1(
int n,
int p,
IList<double> knotVectorU,
int m,
int q,
IList<double> knotVectorV,
Matrix<Point3d> controlPoints,
double u,
double v,
int derivCount)
{
var sKL = new Point3d[derivCount + 1, derivCount + 1];
var du = Math.Min(derivCount, p);
Expand Down Expand Up @@ -608,7 +684,19 @@ public static Point3d SurfacePoint(int n, int p, IList<double> knotVectorU, int
return sKL;
}

public static Point3d[][][][] SurfaceDerivCpts(int n, int p, IList<double> knotVectorU, int m, int q, IList<double> knotVectorV, Matrix<Point3d> controlPoints, int d, int r1, int r2, int s1, int s2)
public static Point3d[][][][] SurfaceDerivCpts(
int n,
int p,
IList<double> knotVectorU,
int m,
int q,
IList<double> knotVectorV,
Matrix<Point3d> controlPoints,
int d,
int r1,
int r2,
int s1,
int s2)
{
var pkl = new Point3d[d][][][];

Expand Down Expand Up @@ -638,7 +726,17 @@ public static Point3d[][][][] SurfaceDerivCpts(int n, int p, IList<double> knotV
return pkl;
}

public static Point3d[,] SurfaceDerivsAlg2(int n, int p, IList<double> knotVectorU, int m, int q, IList<double> knotVectorV, Matrix<Point3d> controlPoints, double u, double v, int d)
public static Point3d[,] SurfaceDerivsAlg2(
int n,
int p,
IList<double> knotVectorU,
int m,
int q,
IList<double> knotVectorV,
Matrix<Point3d> controlPoints,
double u,
double v,
int d)
{
var skl = new Point3d[d + 1, d + 1];

Expand All @@ -656,7 +754,8 @@ public static Point3d[][][][] SurfaceDerivCpts(int n, int p, IList<double> knotV
var nV = AllBasisFuns(uSpan, u, p, knotVectorU);
var vSpan = FindSpan(m, q, v, knotVectorV);
var nU = AllBasisFuns(vSpan, v, q, knotVectorV);
var pkl = SurfaceDerivCpts(n, p, knotVectorU, m, q, knotVectorV, controlPoints, d, uSpan - p, uSpan, vSpan - q, vSpan);
var pkl = SurfaceDerivCpts(n, p, knotVectorU, m, q, knotVectorV, controlPoints, d, uSpan - p, uSpan,
vSpan - q, vSpan);

for (var k = 0; k <= du; k++)
{
Expand Down Expand Up @@ -725,7 +824,16 @@ public static Vector3d[] RatCurveDerivs(IList<Vector3d> aDers, IList<double> wDe
/// <param name="u"></param>
/// <param name="v"></param>
/// <returns></returns>
public static Point3d SurfacePoint(int n, int p, IList<double> knotVectorU, int m, int q, IList<double> knotVectorV, Matrix<Point4d> controlPoints, double u, double v)
public static Point3d SurfacePoint(
int n,
int p,
IList<double> knotVectorU,
int m,
int q,
IList<double> knotVectorV,
Matrix<Point4d> controlPoints,
double u,
double v)
{
var uspan = FindSpan(n, p, u, knotVectorU);
var nU = BasisFuns(uspan, u, p, knotVectorU);
Expand Down
Loading

0 comments on commit e26d245

Please sign in to comment.