public static NurbsPoint DeBoorSurface( List <List <NurbsPoint> > controlNet, decimal u, decimal[] knotU, decimal v, decimal[] knotV) { var cPointsU = controlNet.First(); var cPointsV = controlNet.Transpose().First(); var p = knotU.Length - cPointsU.Count - 1; var q = knotV.Length - cPointsV.Count - 1; u = Math.Round(u, 21); v = Math.Round(v, 21); var magic = 0; switch (u) { case 0: magic += 1; break; case 1: magic += 3; break; default: magic += 2; break; } switch (v) { case 0: magic += 0; break; case 1: magic += 6; break; default: magic += 3; break; } switch (magic) { case 1: return(controlNet.First().First()); case 2: return(NurbsLogic.DeBoor(p, controlNet.First(), u, knotU)); case 3: return(controlNet.First().Last()); case 4: return(NurbsLogic.DeBoor(q, controlNet.Transpose().First(), v, knotV)); case 5: break; case 6: return(NurbsLogic.DeBoor(q, controlNet.Transpose().Last(), v, knotV)); case 7: return(controlNet.Last().First()); case 8: return(NurbsLogic.DeBoor(p, controlNet.Last(), u, knotU)); case 9: return(controlNet.Last().Last()); default: break; } var c = NurbsLogic.FindSpan(u, knotU); var d = NurbsLogic.FindSpan(v, knotV); var s = NurbsLogic.CheckMultiplicity(knotU, u); var t = NurbsLogic.CheckMultiplicity(knotV, v); NurbsPoint point; if (u.GreaterThanOrEqualTo(knotU[c]) && u.LessThan(knotU[c + 1]) && v.GreaterThanOrEqualTo(knotV[d]) && v.LessThan(knotV[d + 1])) { var P = new NurbsPoint[c - s + 1, d - t + 1]; var Q = new NurbsPoint[c - s + 1]; for (var i = 0; i < P.GetLength(0); i++) { for (var j = 0; j < P.GetLength(1); j++) { P[i, j] = controlNet[j][i]; } } for (var i = 0; i < P.GetLength(0); i++) { var Pi = new List <NurbsPoint>(); for (var j = 0; j < P.GetLength(1); j++) { Pi.Add(P[i, j]); } Q[i] = NurbsLogic.DeBoor(q, Pi, v, knotV); } point = NurbsLogic.DeBoor(p, Q.ToList(), u, knotU); } else { // ReSharper disable once UnthrowableException throw new IndexOutOfRangeException("u not in [u_c, u_c+1) or v not in [u_d, u_d+1)"); } return(point); }
public static NurbsPoint DeBoor(int p, List <NurbsPoint> controlPoints, decimal u, decimal[] knotVector) { if (u.AlmostEquals(0M)) { return(controlPoints.First()); } if (u.AlmostEquals(1M)) { return(controlPoints.Last()); } var k = FindSpan(u, knotVector); var s = NurbsLogic.CheckMultiplicity(knotVector, u); NurbsPoint point; if (u.GreaterThanOrEqualTo(knotVector[k]) && u.LessThan(knotVector[k + 1])) { var h = p - s; if (h == 0) { return(controlPoints[k - s]); } var points = new List <Point4D> [h + 1]; points[0] = controlPoints.ToPoint4DList(); for (var r = 1; r <= h; r++) { /*points[r] = new List<Point4D>(k - s + 1); * for (var i = 0; i <= k - s + 1; i++) * { * points[r].Add(new Point4D(-1, -1, -1, -1)); * }*/ points[r] = controlPoints.ToPoint4DList(); for (var i = k - p + r; i <= k - s; i++) { if (points[r - 1][i - 1] == null || points[r - 1][i] == null) { continue; } // ReSharper disable once InconsistentNaming var a_ir = (double)((u - knotVector[i]) / (knotVector[i + p - r + 1] - knotVector[i])); var x = ((1 - a_ir) * points[r - 1][i - 1].X) + (a_ir * points[r - 1][i].X); var y = ((1 - a_ir) * points[r - 1][i - 1].Y) + (a_ir * points[r - 1][i].Y); var z = ((1 - a_ir) * points[r - 1][i - 1].Z) + (a_ir * points[r - 1][i].Z); var weight = ((1 - a_ir) * points[r - 1][i - 1].Weight) + (a_ir * points[r - 1][i].Weight); points[r][i] = new Point4D(x, y, z, weight); } } point = points[h][k - s].ToNurbsPoint(); } else { // ReSharper disable once UnthrowableException throw new IndexOutOfRangeException("u not in [u_k, u_k+1)"); } return(point); }