protected virtual void FillXDerivations(KnotMatrix values) { for (var j = 0; j < values.Columns; j++) { FillXDerivations(j, values); } }
private static void OriginalKnots(KnotMatrix newKnots, KnotMatrix oldKnots) { for (var i = 0; i < oldKnots.Rows; i++) { for (var j = 0; j < oldKnots.Columns; j++) { newKnots[2*i, 2*j] = oldKnots[i, j]; } } }
public override KnotMatrix GenerateKnots( SurfaceDimension uDimension, SurfaceDimension vDimension) { var afvOld = _baseGenerator.GenerateKnots(uDimension/2, vDimension/2); var uCountNew = uDimension.KnotCount; var vCountNew = vDimension.KnotCount; var afvNew = new KnotMatrix(uCountNew, vCountNew); FillNewKnots(afvNew, afvOld); return afvNew; }
protected virtual void FillXYDerivations(int columnIndex, KnotMatrix values, double[] lowerDiagonal = null, double[] mainDiagonal = null, double[] upperDiagonal = null) { var unknownsCount = values.Rows - 2; if (unknownsCount == 0) return; Action<int, double> dset = (idx, value) => values[idx, columnIndex].Dxy = value; Func<int, double> rget = idx => values[idx, columnIndex].Dy; var h = values[1, 0].X - values[0, 0].X; var dlast = values[values.Rows - 1, columnIndex].Dxy; var dfirst = values[0, columnIndex].Dxy; SolveTridiagonal(rget, h, dfirst, dlast, unknownsCount, dset, lowerDiagonal, mainDiagonal, upperDiagonal); }
protected override void FillXYDerivations(KnotMatrix values) { base.FillXYDerivations(0, values, LowerDiagonal(values.Rows - 2), MainDiagonal(values.Rows - 2), UpperDiagonal(values.Rows - 2)); base.FillXYDerivations(values.Columns - 1, values, LowerDiagonal(values.Rows - 2), MainDiagonal(values.Rows - 2), UpperDiagonal(values.Rows - 2)); base.FillYXDerivations(0, values, LowerDiagonal(values.Columns - 2), MainDiagonal(values.Columns - 2), UpperDiagonal(values.Columns - 2)); base.FillYXDerivations(values.Rows - 1, values, LowerDiagonal(values.Columns - 2), MainDiagonal(values.Columns - 2), UpperDiagonal(values.Columns - 2)); }
internal IEnumerable<ISurface> CreateMesh(KnotMatrix knots) { var uCount_min_1 = knots.Rows - 1; var vCount_min_1 = knots.Columns - 1; var segments = new List<ISurface>(uCount_min_1*vCount_min_1); for (var i = 0; i < uCount_min_1; i++) { for (var j = 0; j < vCount_min_1; j++) { var segment = CreateSegment(i, j, knots); segments.Add(segment); } } return segments; }
protected override void FillXDerivations(KnotMatrix values) { var h = values[1, 0].X - values[0, 0].X; var oneDivH = 1/h; var threeDiv4H = 0.75*oneDivH; for (var j = 0; j < values.Columns; j++) { FillXDerivations(j, values); for (var i = 1; i < values.Rows - 1; i += 2) { values[i, j].Dx = threeDiv4H *(values[i + 1, j].Z - values[i - 1, j].Z) - 0.25 *(values[i + 1, j].Dx + values[i - 1, j].Dx); } } }
public override KnotMatrix GenerateKnots(SurfaceDimension uDimension, SurfaceDimension vDimension) { if (uDimension.KnotCount < 4 || vDimension.KnotCount < 4) { return new DirectKnotsGenerator(Function).GenerateKnots( uDimension, vDimension); } var values = new KnotMatrix(uDimension.KnotCount, vDimension.KnotCount); InitializeKnots(uDimension, vDimension, values); FillXDerivations(values); FillXYDerivations(values); FillYDerivations(values); FillYXDerivations(values); return values; }
protected override void FillYDerivations(KnotMatrix values) { var h = values[0, 1].Y - values[0, 0].Y; var oneDivH = 1/h; var threeDiv4H = 0.75*oneDivH; for (var i = 0; i < values.Rows; i++) { FillYDerivations(i, values); //for (var j = 1; j < values.Columns - 1; j += 2) //{ // values[i, j].Dy = threeDiv4H * (values[i, j + 1].Z - values[i, j - 1].Z) // - 0.25 * (values[i, j + 1].Dy + values[i, j - 1].Dy); //} } for (var i = 0; i < values.Rows; i++) { for (var j = 1; j < values.Columns - 1; j += 2) { values[i, j].Dy = threeDiv4H *(values[i, j + 1].Z - values[i, j - 1].Z) - 0.25 *(values[i, j + 1].Dy + values[i, j - 1].Dy); } } }
using System; using HermiteInterpolation.MathFunctions; using HermiteInterpolation.Numerics; using HermiteInterpolation.SplineKnots; using HermiteInterpolation.Utils; namespace HermiteInterpolation.Shapes.SplineInterpolation { public class BiquarticHermiteSurface : BicubicHermiteSurface { private class BiquarticKnotsGenerator : KnotsGenerator { private readonly KnotsGenerator _baseGenerator; public BiquarticKnotsGenerator(KnotsGenerator baseGenerator) : base(baseGenerator.Function) { _baseGenerator = baseGenerator; } public override KnotMatrix GenerateKnots(SurfaceDimension uDimension, SurfaceDimension vDimension) { var afvOld = _baseGenerator.GenerateKnots(uDimension/2, vDimension/2); var uCountNew = uDimension.KnotCount; var vCountNew = vDimension.KnotCount; var afvNew = new KnotMatrix(uCountNew, vCountNew); FillNewKnots(afvNew, afvOld); return afvNew; } private void FillNewKnots(KnotMatrix newKnots, KnotMatrix oldKnots) { // z, dx, dy, dxy initialization OriginalKnots(newKnots, oldKnots); // z, dx, deltay, deltaxy VerticalKnots(newKnots); // z, Dx, dy, Dxy HorizontalKnots(newKnots); // z, Dx, deltay, deltaxy InnerKnots(newKnots); } private void InnerKnots(KnotMatrix newKnots) { for (int i = 1; i < newKnots.Rows; i += 2) { for (int j = 1; j < newKnots.Columns; j += 2) { var u0v0 = newKnots[i - 1,j - 1]; var u1v0 = newKnots[i,j - 1]; var u2v0 = newKnots[i + 1,j - 1]; var u0v1 = newKnots[i - 1,j]; var u1v1 = new Knot(); var u2v1 = newKnots[i + 1,j]; var u0v2 = newKnots[i - 1,j + 1]; var u1v2 = newKnots[i,j + 1]; var u2v2 = newKnots[i + 1,j + 1]; var hx = Math.Abs(u2v0.X - u0v0.X) / 2; var hx4 = hx * 4; var hy = Math.Abs(u0v2.Y - u0v0.Y) / 2; var hy4 = hy * 4; var x = u0v1.X + hx; var y = u1v0.Y + hy; u1v1.X = x; u1v1.Y = y; u1v1.Z = Function.Z(x, y); u1v1.Dx = -(3 * (u0v1.Z - u2v1.Z) + hx * (u0v1.Dx + u2v1.Dx)) / hx4; u1v1.Dy = -(3 * (u1v0.Z - u1v2.Z) + hx * (u1v0.Dx + u1v2.Dx)) / hy4; u1v1.Dxy = (u0v0.Dxy + u2v0.Dxy + u0v2.Dxy + u2v2.Dxy + (3 * ((u0v0.Dy - u2v0.Dy + u0v2.Dy - u2v2.Dy) / hx + (u0v0.Dx + u2v0.Dx - u0v2.Dx - u2v2.Dx) / hy + (3 * (u0v0.Z - u2v0.Z - u0v2.Z + u2v2.Z)) / (hx * hy)))) / 16; newKnots[i,j] = u1v1; } } } private void HorizontalKnots(KnotMatrix newKnots) { for (int i = 1; i < newKnots.Rows; i += 2) { for (int j = 0; j < newKnots.Columns; j += 2) { var u0 = newKnots[i - 1,j]; var u1 = new Knot(); // finished var u2 = newKnots[i + 1,j]; var hx = Math.Abs(u2.X - u0.X) / 2; var hx4 = hx * 4; var x = u0.X + hx; var y = u0.Y; u1.X = x; u1.Y = y; u1.Z = Function.Z(x, y); u1.Dy = Function.Dy(x, y); u1.Dx = -(3 * (u0.Z - u2.Z) + hx * (u0.Dx + u2.Dx)) / hx4; u1.Dxy = -(3 * (u0.Dy - u2.Dy) + hx * (u0.Dxy + u2.Dxy)) / hx4; // finished newKnots[i,j] = u1; } } } private void VerticalKnots(KnotMatrix newKnots) { for (int i = 0; i < newKnots.Rows; i += 2) { for (int j = 1; j < newKnots.Columns; j += 2) { var v0 = newKnots[i,j - 1]; var v1 = new Knot(); // finished var v2 = newKnots[i,j + 1]; var hy = Math.Abs(v2.Y - v0.Y) / 2; var hy4 = hy * 4; var x = v0.X; var y = v0.Y + hy; v1.X = x; v1.Y = y; v1.Z = Function.Z(x, y); v1.Dx = Function.Dx(x, y); v1.Dy = -(3 * (v0.Z - v2.Z) + hy * (v0.Dy + v2.Dy)) / hy4; v1.Dxy = -(3 * (v0.Dx - v2.Dx) + hy * (v0.Dxy + v2.Dxy)) / hy4; // finished newKnots[i,j] = v1; } } } private static void OriginalKnots(KnotMatrix newKnots, KnotMatrix oldKnots) { for (var i = 0; i < oldKnots.Rows; i++) { for (var j = 0; j < oldKnots.Columns; j++) { newKnots[2 * i,2 * j] = oldKnots[i,j]; } } } } public BiquarticHermiteSurface(SurfaceDimension uDimension, SurfaceDimension vDimension, MathExpression mathExpression, Derivation derivation = Derivation.Zero) : this(uDimension, vDimension, InterpolativeMathFunction.FromExpression(mathExpression), derivation) { } public BiquarticHermiteSurface(SurfaceDimension uDimension, SurfaceDimension vDimension, InterpolativeMathFunction interpolativeMathFunction, Derivation derivation = Derivation.Zero) : this(uDimension, vDimension, new DirectKnotsGenerator(interpolativeMathFunction), derivation) { } public BiquarticHermiteSurface(SurfaceDimension uDimension, SurfaceDimension vDimension, KnotsGenerator knotsGenerator, Derivation derivation = Derivation.Zero) : base(uDimension, vDimension, new BiquarticKnotsGenerator(knotsGenerator), derivation) { } } }
private void VerticalKnots(KnotMatrix newKnots) { for (var i = 0; i < newKnots.Rows; i += 2) { for (var j = 1; j < newKnots.Columns; j += 2) { var v0 = newKnots[i, j - 1]; var v1 = new Knot(); // finished var v2 = newKnots[i, j + 1]; var hy = Math.Abs(v2.Y - v0.Y)/2; var hy4 = hy*4; var x = v0.X; var y = v0.Y + hy; v1.X = x; v1.Y = y; v1.Z = Function.Z(x, y); v1.Dx = Function.Dx(x, y); v1.Dy = -(3*(v0.Z - v2.Z) + hy*(v0.Dy + v2.Dy))/ hy4; v1.Dxy = -(3*(v0.Dx - v2.Dx) + hy*(v0.Dxy + v2.Dxy))/ hy4; // finished newKnots[i, j] = v1; } } }
protected virtual void FillXYDerivations(KnotMatrix values) { FillXYDerivations(0, values); FillXYDerivations(values.Columns - 1, values); }
private void FillNewKnots(KnotMatrix newKnots, KnotMatrix oldKnots) { // z, dx, dy, dxy initialization OriginalKnots(newKnots, oldKnots); // z, dx, deltay, deltaxy VerticalKnots(newKnots); // z, Dx, dy, Dxy HorizontalKnots(newKnots); // z, Dx, deltay, deltaxy InnerKnots(newKnots); }
protected virtual void InitializeKnots(SurfaceDimension uDimension, SurfaceDimension vDimension, KnotMatrix values) { var uSize = Math.Abs(uDimension.Max - uDimension.Min) /(uDimension.KnotCount - 1); var vSize = Math.Abs(vDimension.Max - vDimension.Min) /(vDimension.KnotCount - 1); var u = uDimension.Min; for (var i = 0; i < uDimension.KnotCount; i++, u += uSize) { var v = vDimension.Min; for (var j = 0; j < vDimension.KnotCount; j++, v += vSize) { var z = Function.Z.SafeCall(u, v); values[i, j] = new Knot(u, v, z); } } // Init Dx var uKnotCountMin1 = uDimension.KnotCount - 1; for (var j = 0; j < vDimension.KnotCount; j++) { values[0, j].Dx = Function.Dx.SafeCall(values[0, j].X, values[0, j].Y); values[uKnotCountMin1, j].Dx = Function.Dx.SafeCall(values[uKnotCountMin1, j].X, values[uKnotCountMin1, j].Y); } // Init Dy var vKnotCountMin1 = vDimension.KnotCount - 1; for (var i = 0; i < uDimension.KnotCount; i++) { values[i, 0].Dy = Function.Dy.SafeCall(values[i, 0].X, values[i, 0].Y); values[i, vKnotCountMin1].Dy = Function.Dy.SafeCall(values[i, vKnotCountMin1].X, values[i, vKnotCountMin1].Y); } // Init Dxy values[0, 0].Dxy = Function.Dxy.SafeCall(values[0, 0].X, values[0, 0].Y); values[uKnotCountMin1, 0].Dxy = Function.Dxy.SafeCall(values[uKnotCountMin1, 0].X, values[uKnotCountMin1, 0].Y); values[0, vKnotCountMin1].Dxy = Function.Dxy.SafeCall(values[0, vKnotCountMin1].X, values[0, vKnotCountMin1].Y); values[uKnotCountMin1, vKnotCountMin1].Dxy = Function.Dxy.SafeCall(values[uKnotCountMin1, vKnotCountMin1].X, values[uKnotCountMin1, vKnotCountMin1].Y); }
protected virtual void FillYXDerivations(int rowIndex, KnotMatrix values, double[] lowerDiagonal = null, double[] mainDiagonal = null, double[] upperDiagonal = null) { var unknownsCount = values.Columns - 2; if (unknownsCount == 0) return; Action<int, double> dset = (idx, value) => values[rowIndex, idx].Dxy = value; Func<int, double> rget = idx => values[rowIndex, idx].Dx; var h = values[0, 1].Y - values[0, 0].Y; var dfirst = values[rowIndex, 0].Dxy; var dlast = values[rowIndex, values.Columns - 1].Dxy; SolveTridiagonal(rget, h, dfirst, dlast, unknownsCount, dset, lowerDiagonal, mainDiagonal, upperDiagonal); }
protected virtual void FillYXDerivations(KnotMatrix values) { for (var i = 0; i < values.Rows; i++) { FillYXDerivations(i, values); } }
private void InnerKnots(KnotMatrix newKnots) { for (var i = 1; i < newKnots.Rows; i += 2) { for (var j = 1; j < newKnots.Columns; j += 2) { var u0v0 = newKnots[i - 1, j - 1]; var u1v0 = newKnots[i, j - 1]; var u2v0 = newKnots[i + 1, j - 1]; var u0v1 = newKnots[i - 1, j]; var u1v1 = new Knot(); var u2v1 = newKnots[i + 1, j]; var u0v2 = newKnots[i - 1, j + 1]; var u1v2 = newKnots[i, j + 1]; var u2v2 = newKnots[i + 1, j + 1]; var hx = Math.Abs(u2v0.X - u0v0.X)/2; var hx4 = hx*4; var hy = Math.Abs(u0v2.Y - u0v0.Y)/2; var hy4 = hy*4; var x = u0v1.X + hx; var y = u1v0.Y + hy; u1v1.X = x; u1v1.Y = y; u1v1.Z = Function.Z(x, y); u1v1.Dx = -(3*(u0v1.Z - u2v1.Z) + hx*(u0v1.Dx + u2v1.Dx))/ hx4; u1v1.Dy = -(3*(u1v0.Z - u1v2.Z) + hx*(u1v0.Dx + u1v2.Dx))/ hy4; u1v1.Dxy = (u0v0.Dxy + u2v0.Dxy + u0v2.Dxy + u2v2.Dxy + (3* ((u0v0.Dy - u2v0.Dy + u0v2.Dy - u2v2.Dy)/hx + (u0v0.Dx + u2v0.Dx - u0v2.Dx - u2v2.Dx)/hy + (3*(u0v0.Z - u2v0.Z - u0v2.Z + u2v2.Z)) /(hx*hy))))/ 16; newKnots[i, j] = u1v1; } } }
protected abstract ISurface CreateSegment(int uIdx, int vIdx, KnotMatrix knots);
private double[] RightSideCross(KnotMatrix knots, int i, double dfirst, double dlast, int unknownsCount) { var even = unknownsCount%2 == 0; var equationsCount = even ? unknownsCount/2 - 1 : unknownsCount/2; var eta = even ? -4 : 1; var rs = new double[equationsCount]; var oneDiv7 = 1/7; var hx = knots[1, 0].X - knots[0, 0].X; var hy = knots[0, 1].Y - knots[0, 0].Y; var oneDivHx = 1d/hx; var oneDivHy = 1d/hy; var threeDivHx = 3/hx; var threeDivHy = 3/hy; var threeDiv7hx = oneDiv7*threeDivHx; var threeDiv7hy = oneDiv7*threeDivHy; var threeDiv7hxhy = threeDiv7hy/hy; var columns = knots.Columns; var iMin1 = i - 1; var iMin2 = i - 2; for (int k = 0, j = 4; k < equationsCount - 1; k++, j += 2) { rs[k] = oneDiv7 *(knots[iMin2, j + 2].Dxy + knots[iMin2, j - 2].Dxy) - 2*knots[iMin1, j].Dxy + threeDiv7hx *(knots[iMin1, j + 2].Dy + knots[iMin1, j - 2].Dy) + threeDiv7hy *(-knots[iMin2, j + 2].X + knots[iMin2, j - 2].X) + 3*threeDivHx*(knots[i, j + 2].Dy + knots[i, j - 2].Dy) + 3*threeDiv7hxhy *(-knots[iMin2, j + 2].Z + knots[iMin2, j - 2].Z) + 4*threeDiv7hx *(-knots[iMin1, j + 2].Dy - knots[iMin1, j - 2].Dy) + 4*threeDiv7hy *(knots[iMin2, j + 1].X - knots[iMin2, j - 1].X) + threeDiv7hy*(knots[i, j + 2].Dx + knots[i, j - 2].Dx) + 9*threeDiv7hxhy*(-knots[i, j + 2].Z + knots[i, j - 2].Z) - 12*threeDiv7hxhy* (knots[iMin1, j + 2].Z - knots[iMin1, j - 2].Z + knots[iMin2, j + 1].Z - knots[iMin2, j - 1].Z) - 6*oneDivHx*knots[iMin2, j].Dy + 12*oneDivHy*(knots[i, j + 1].Dx + knots[i, j - 1].Dx) + 36*threeDiv7hxhy*(knots[i, j + 1].Z + knots[i, j - 1].Z) - 18*oneDivHx*knots[i, j].Dy + 48*threeDiv7hxhy *(-knots[iMin1, j + 1].Z + knots[iMin1, j - 1].Z) + 24*oneDivHx*knots[iMin1, j].Z; } rs[0] -= dfirst; rs[equationsCount - 1] = oneDiv7 *(knots[iMin2, columns - 1].Dxy + knots[iMin2, columns - 5].Dxy) - 2*knots[iMin1, columns - 3].Dxy + threeDiv7hx *(knots[iMin1, columns - 1].Dy + knots[iMin1, columns - 5].Dy) + threeDiv7hy *(-knots[iMin2, columns - 1].X + knots[iMin2, columns - 5].X) + 3*threeDivHx *(knots[i, columns - 1].Dy + knots[i, columns - 5].Dy) + 3*threeDiv7hxhy *(-knots[iMin2, columns - 1].Z + knots[iMin2, columns - 5].Z) + 4*threeDiv7hx *(-knots[iMin1, columns - 1].Dy - knots[iMin1, columns - 5].Dy) + 4*threeDiv7hy *(knots[iMin2, columns - 2].X - knots[iMin2, columns - 4].X) + threeDiv7hy *(knots[i, columns - 1].Dx + knots[i, columns - 5].Dx) + 9*threeDiv7hxhy *(-knots[i, columns - 1].Z + knots[i, columns - 5].Z) - 12*threeDiv7hxhy* (knots[iMin1, columns - 1].Z - knots[iMin1, columns - 5].Z + knots[iMin2, columns - 2].Z - knots[iMin2, columns - 4].Z) - 6*oneDivHx*knots[iMin2, columns - 3].Dy + 12*oneDivHy *(knots[i, columns - 2].Dx + knots[i, columns - 4].Dx) + 36*threeDiv7hxhy *(knots[i, columns - 2].Z + knots[i, columns - 4].Z) - 18*oneDivHx*knots[i, columns - 3].Dy + 48*threeDiv7hxhy *(-knots[iMin1, columns - 2].Z + knots[iMin1, columns - 4].Z) + 24*oneDivHx*knots[iMin1, columns - 3].Z - eta*dlast; return rs; }
protected override void FillYXDerivations(int rowIndex, KnotMatrix values, double[] lowerDiagonal = null, double[] mainDiagonal = null, double[] upperDiagonal = null) { var unknownsCount = values.Columns - 2; if (unknownsCount == 0) return; var h = values[0, 1].Y - values[0, 0].Y; var dfirst = values[rowIndex, 0].Dxy; var dlast = values[rowIndex, values.Columns - 1].Dxy; lowerDiagonal = lowerDiagonal ?? LowerDiagonal(unknownsCount); mainDiagonal = mainDiagonal ?? MainDiagonal(unknownsCount); upperDiagonal = upperDiagonal ?? UpperDiagonal(unknownsCount); var result = RightSideCross(values, rowIndex, dfirst, dlast, unknownsCount); LinearSystems.SolveTridiagonalSystem(lowerDiagonal, mainDiagonal, upperDiagonal, result); for (var i = 0; i < result.Length; i++) { values[rowIndex, 2*i + 1].Dxy = result[i]; } }
protected override void FillYXDerivations(KnotMatrix values) { for (var i = 2; i < values.Rows - 1; i += 2) { FillYXDerivations(i, values); } var oneDiv16 = 1d/16d; var threeDiv16 = oneDiv16*3; var hx = values[1, 0].X - values[0, 0].X; var hy = values[0, 1].Y - values[0, 0].Y; var oneDivHx = 1d/hx; var oneDivHy = 1d/hy; for (var i = 1; i < values.Rows - 1; i += 2) { for (var j = 1; j < values.Columns - 1; j += 2) { values[i, j].Dxy = oneDiv16* (values[i + 1, j + 1].Dxy + values[i + 1, j - 1].Dxy + values[i - 1, j + 1].Dxy + values[i - 1, j - 1].Dxy) - threeDiv16*oneDivHy* (values[i + 1, j + 1].Dx + values[i + 1, j - 1].Dx + values[i - 1, j + 1].Dx + values[i - 1, j - 1].Dx) - threeDiv16*oneDivHx* (values[i + 1, j + 1].Dy + values[i + 1, j - 1].Dy + values[i - 1, j + 1].Dy + values[i - 1, j - 1].Dy) + 3*threeDiv16*oneDivHx*oneDivHy* (values[i + 1, j + 1].Dy - values[i + 1, j - 1].Dy - values[i - 1, j + 1].Dy* values[i - 1, j - 1].Dy); } } for (var j = 2; j < values.Columns - 2; j += 2) { values[1, j].Dxy = 0.75*oneDivHy *(values[1, j + 1].Dx - values[1, j - 1].Dx) - 0.25 *(values[1, j + 1].Dxy - values[1, j - 1].Dxy); } for (var i = 2; i < values.Rows - 2; i += 2) { for (var j = 2; j < values.Columns - 2; j += 2) { values[i + 1, j].Dxy = 0.75*oneDivHy *(values[i + 1, j + 1].Dx - values[i + 1, j - 1].Dx) - 0.25 *(values[i + 1, j + 1].Dxy - values[i + 1, j - 1].Dxy); } for (var j = 1; j < values.Columns - 2; j += 2) { values[i, j].Dxy = 0.75*oneDivHy *(values[i, j + 1].Dx - values[i, j - 1].Dx) - 0.25 *(values[i, j + 1].Dxy - values[i, j - 1].Dxy); } } }
using System; using System.Collections.Generic; using HermiteInterpolation.MathFunctions; using HermiteInterpolation.Numerics; using HermiteInterpolation.Primitives; using HermiteInterpolation.SplineKnots; using MathNet.Numerics.LinearAlgebra; using Microsoft.Xna.Framework; namespace HermiteInterpolation.Shapes.SplineInterpolation { public class BicubicHermiteSurface :Spline { public BicubicHermiteSurface(SurfaceDimension uDimension, SurfaceDimension vDimension, MathExpression mathExpression, Derivation derivation = Derivation.Zero) : base(uDimension, vDimension, mathExpression, derivation) { } public BicubicHermiteSurface(SurfaceDimension uDimension, SurfaceDimension vDimension, InterpolativeMathFunction interpolativeMathFunction, Derivation derivation = Derivation.Zero) : base(uDimension, vDimension, interpolativeMathFunction, derivation) { } public BicubicHermiteSurface(SurfaceDimension uDimension, SurfaceDimension vDimension, KnotsGenerator knotsGenerator, Derivation derivation = Derivation.Zero) : base(uDimension, vDimension, knotsGenerator, derivation) { } protected delegate Vector<double> BasisVector(double t, double t0, double t1); /// <summary> /// /// </summary> /// <param name="uIdx"></param> /// <param name="vIdx"></param> /// <param name="knots"></param> /// <returns></returns> protected override ISurface CreateSegment(int uIdx, int vIdx, KnotMatrix knots) { var u0 = knots[uIdx,vIdx].X; var u1 = knots[uIdx+1,vIdx].X; var v0 = knots[uIdx,vIdx].Y; var v1 = knots[uIdx,vIdx+1].Y; var meshDensity = Constants.MeshDensity; var uKnotsDistance = Math.Abs(u1-u0); var xCount = Math.Ceiling(uKnotsDistance/meshDensity); var yKnotDistance = Math.Abs(v1 - v0); var yCount = Math.Ceiling(yKnotDistance / meshDensity); var verticesCount = (int)((++xCount) * (++yCount)); var segmentMeshVertices = new VertexPositionNormalColor[verticesCount]; var basisCalculator = new BicubicBasis(knots,Derivation);//BasisFactory.CreateBasis(Surface.Type); var phi = basisCalculator.Matrix(uIdx, vIdx); var k = 0; var x = (float) u0 ; for (var i = 0; i < xCount; i++,x += meshDensity) { x = x < u1 ? x : (float)u1; var lambda1 = basisCalculator.Vector(x, u0, u1); var basis = phi.LeftMultiply(lambda1); var y = (float) v0; for (var j = 0; j < yCount; j++,y += meshDensity) { y = y < v1 ? y : (float)v1; var lambda2 = basisCalculator.Vector(y, v0, v1); var zv = basis.PointwiseMultiply(lambda2); var z = (float) zv.Sum(); z = MathHelper.Clamp(z, -Constants.MaxSceneZDifference, Constants.MaxSceneZDifference); segmentMeshVertices[k++] = new VertexPositionNormalColor(new Vector3(x, y, z), DefaultNormal, DefaultColor); } } return new SimpleSurface(segmentMeshVertices, (int)xCount, (int)yCount); } } }
public BiquarticBasis(KnotMatrix knots, Derivation derivation) : base(knots, derivation) { }
private void HorizontalKnots(KnotMatrix newKnots) { for (var i = 1; i < newKnots.Rows; i += 2) { for (var j = 0; j < newKnots.Columns; j += 2) { var u0 = newKnots[i - 1, j]; var u1 = new Knot(); // finished var u2 = newKnots[i + 1, j]; var hx = Math.Abs(u2.X - u0.X)/2; var hx4 = hx*4; var x = u0.X + hx; var y = u0.Y; u1.X = x; u1.Y = y; u1.Z = Function.Z(x, y); u1.Dy = Function.Dy(x, y); u1.Dx = -(3*(u0.Z - u2.Z) + hx*(u0.Dx + u2.Dx))/ hx4; u1.Dxy = -(3*(u0.Dy - u2.Dy) + hx*(u0.Dxy + u2.Dxy))/ hx4; // finished newKnots[i, j] = u1; } } }