Bezier Patches and Surface Curvatures
In[1116]:=
Clear["Global`*"]
CSE 477
Instructor: Dianne Hansford
Homework 2:
Exploring Least Squares Approximation with Bezier Curves
The purpose of this homework is to explore least squares approximation with Bezier curves. The
program flow is as follows.1) Input data points to be approximated 2) Uniform or chord length
parameters are created for the data.3) Input the degree n of the approximation4) Approximate the
data with a degree n Bezier curve
This program finds the approximation with both sets of parameter values so they may be
displayed together.5) Measure error between the Bezier curve and the input data.6) Display the
input, approximation, errors7) Document your observations. Details for each of these steps are
given below in the blue sections. You must complete the code when instructed to do so. I have
supplied some code and graphics for you.See the Observations section for instructions for the final
report: running the data sets and reporting.Instructions on how to get started will be given in class.
Guidelines:
Turn in via Canvas
Name your file lastname_HW2.nb
Below each problem description, add your MM code
Comment your notebook
Work independently
Bezier Curve Evaluator
(You do not need to change this routine.)
In[1117]:=
curve[bpts_, deg_, t_] := SumBernsteinBasis[deg, i, t] * bptsi + 1, i, 0, deg;
Data Sets
Below are some sample data sets
Create numdata = number of data to be approximated
Create data (x,y) or (x,y,z) points to be approximated
Load one data set into “data”
In[1118]:=
(* uniformly sampled line *)
bpts = {0, 0}, {1, 1}, {2, 2}, {3, 3};
dataUniformline = Tablecurvebpts, Length[bpts] - 1, t, t, 0, 1, 1.0 / 10.0;
(* Noisy line *)
dataNoisyLine = Tablet, t + 0.2 * RandomReal[], t, 0, 1, 1.0 / 30.0;
(* nice curve: classic car fender sillouette *)
bpts = {0, 0}, {0, 1}, {0, 2}, {20, 3};
dataGF = Tablecurvebpts, Length[bpts] - 1, t, t, 0, 1, 1.0 / 20.0;
(* This data set has a gap in the data --
suppose some part was occluded or data lost *)
dataGFgap = {0, 0}, 0.0025000000000000005`, 0.15000000000000002`, 0.020000000000000004`, 0.30000000000000004`, 0.06750000000000003`, 0.45000000000000007`, 0.16000000000000003`, 0.6000000000000002`,
0.3125`, 0.75`, 0.5400000000000003`, 0.9000000000000001`, 0.8575000000000002`, 1.05`, 1.2800000000000002`, 1.2000000000000002`, 1.8225000000000002`, 1.3500000000000003`, 5.4925000000000015`, 1.95`, 6.860000000000001`, 2.1`, 8.4375`, 2.25`, 10.240000000000002`, 2.4000000000000004`, 12.282500000000002`, 2.5500000000000003`,
14.580000000000002`, 2.7`, 17.1475`, 2.8499999999999996`, {20, 3};
(* four points *)
bpts = {0, 0}, 0.0, 1.0, 2.0, 1.0, 2.0, 0.0;
dataFour = Tablecurvebpts, Length[bpts] - 1, t, t, 0, 1, 1.0 / 3.0;
(* This is a data set to simulate an outlier *)
dataOutlier = Tablet, Sin[t], t, 0, Pi, 1.0 / 10.0;
dataOutlier〚17, 2〛 = dataOutlier〚17, 2〛 - 0.5;
(* semicircle *)
dataSemiCircle = TableCos[t], Sin[t] // N, t, 0, Pi, Pi 10.0;
(* spiral with noise *)
dataSpiral =
Tablet * Cos[t] + 0.2 * RandomReal[], t * Sin[t] + 0.2 * RandomReal[], t, 0, 6, 0.2;
(* spiral reverse *)
dataSpiralRev = Table
(6 - t) * Cos[(6 - t)] + 0.2 * RandomReal[], (6 - t) * Sin[(6 - t)] + 0.2 * RandomReal[], t, 0, 6, 0.2;
2
(* ********************************* *)
(* ********************************* *)
(* Select one data set and load into data *)
data = dataUniformline ;
numdata = Length[data];
Print"Input numdata =", numdata;
(* Print"Data = ",MatrixForm[data]; *)
Input numdata =11
In[1134]:=
Uniform parameter values
Input:
numdata: number of data
params: parameter values data structure
Output:
params: uniform parameter values associated with each data
Note: params[[1]] = 0.0 and params[[numdata]] = 1.0
You must write this routine
In[1135]:=
uniformparams[numdata_] := Module{params},
params = Table1 (numdata - 1) i, i, 0, numdata - 1;
Print"Uniform paramters = ", params // N;
params
;
Chord length parameters
Input:
data (x,y) or (x,y,z) points
numdata: number of data
params: parameter values data structure
Output:
params: chord length parameter values associated with each data
Note: params[[1]] = 0.0 and params[[numdata]] = 1.0
You must write this routine.
3
In[1136]:=
chordlengthparams[data_, numdata_] := Moduledistances, totalLength, params,
(*Calculate distances between consecutive points*)
distances = TableEuclideanDistancedatai, datai + 1, i, 1, Length[data] - 1; (*Calculate total length of the curve*)totalLength = Total[distances];
(*Calculate chord length parameters*)
params = AccumulatePrependdistances totalLength, 0; (*Please leave this print stmt.Uncomment when function completed*)
Print"chordlength parameters = ", params // N;
(*Return the params data structure*)params;
Least squares approximation with Bezier curve
Input:
n: degree of approximation
data: (x,y) or (x,y,z) points to approximate
numdata: number of data points
params: parameter value for each data point
Output:
Bezier points bez
Note:
You must set up the normal equations yourself, but you can use LinearSolve to solve the normal
equations.
Matrix multiplication in MM is with a “.”: mat1.mat2
You must write this routine.
In[1137]:=
approxn_, params_, data_ := Module pre, ps = params, T, sol, dat = data, bez,
pre = TableBernsteinBasisn, i, psj, j, 1, Length@ps, i, 0, n;
T = KroneckerProduct{1, 0}, {0, 1}, pre;
sol = LinearSolveTranspose[T].T, Transpose[T].(dat // Transpose // Flatten);
bez = sol // Partition#, Length[sol] 2 & // Transpose
(*
Print" solution = ",MatrixForm[bez]," Bezier points";
*)
Least squares error reporting
Input:
4
data: data points
numdata: number of data points
params: parameters assigned to each data
bez: bezier curve approximating data
deg: degree of Bezier curve
Return as a vector
{total error, average error, min error, and max error}
You must write this routine.
In[1138]:=
lsqerror[data_, numdata_, params_, bez_, deg_] :=
Moduleerrors, totalError, averageError, minError, maxError, errors = TableNormcurvebez, deg, paramsi - datai, i, 1, data // Length; totalError = Total[errors];
averageError = Mean[errors];
minError = Min[errors];
maxError = Max[errors];
totalError, averageError, minError, maxError
5
Establish minmax box for control points and data points
This mmbox is used for the display of the uniform and chord lgth curves, so they are displayed at
the same scale.
Input:
bez, deg : Bezier curve and degree
data, numdata : data points and number of them
Output:
plotmm holding {min corner, max corner}
No changes to this routine.
In[1139]:=
setMinMaxbez_, deg_, data_, numdata_ :=
(* data structure to hold mmbox *)
plotmm = {{0, 0}, {0, 0}};
(* work on x coordinate *)
bezmin = Min /@ Transpose[bez];
bezmax = Max /@ Transpose[bez];
datamin = Min /@ Transpose[data];
datamax = Max /@ Transpose[data];
plotmm〚1, 1〛 = Minbezmin〚1〛, datamin〚1〛;
plotmm〚1, 2〛 = Minbezmin〚2〛, datamin〚2〛;
plotmm〚2, 1〛 = Maxbezmax〚1〛, datamax〚1〛;
plotmm〚2, 2〛 = Maxbezmax〚2〛, datamax〚2〛;
(* make the mmbox a little bigger taht the data *)
pbigger = 0.05;
deltax = plotmm〚2, 1〛 - plotmm〚1, 1〛; deltay = plotmm〚2, 2〛 - plotmm〚1, 2〛; offx = deltax * pbigger;
offy = deltay * pbigger;
plotmm〚1, 1〛 = plotmm〚1, 1〛 - offx;
plotmm〚1, 2〛 = plotmm〚1, 2〛 - offy;
plotmm〚2, 1〛 = plotmm〚2, 1〛 + offx;
plotmm〚2, 2〛 = plotmm〚2, 2〛 + offy;
(* Print"plotmm = ",plotmm; *)
;
Create graphics entities
data points, Bezier control points, Bezier control polygon, Bezier curve
6
No changes to this routine.
In[1140]:=
createGraphics[deg_] :=
(* Create graphics entities for input data *)
dplot = ListPlotdata, PlotStyle → Black, PointSize[Medium];
(* Graphics entity for Bezier points and Bezier curve *)
points = GraphicsRGBColor[0.5, 0.79, 0.81], PointSize[Large], Point[bez]; bplot = ListLinePlot[bez, PlotStyle → RGBColor[0.5, 0.79, 0.81]];
cplot = GraphicsThick, Blue, BezierCurvebez, SplineDegree → deg;
;
“Main” routine
Create the approximating Bezier curve based on the input knot selection method
Here you set the degree as described in the observations section.
In[1141]:=
Observations
Run each of the data sets that I have supplied for degree 5.
-- Select the parameters inputs, results, and graphics cells and merge the cells.
-- Cut and paste the resulting cell below.
-- Add the data set name at the top of the cell pasted below.
(I have put an example below -- delete it and replace it with your own.)
Examine the graphics display and errors for the approximations.
For each data set, just below the output, comment on the behavior of the approximation based
on the degree and parameters. Anything interesting/special?
Share any general observations you have regarding the two parameter generation methods and
the approximation degree.
Your observations must be formatted text.
dataUniformline
In[1142]:=
(* Choose degree of approximation *)
7
approxdeg = 5;
data = dataUniformline;
numdata = data // Length;
(* Create data structure for paramters *)
params = uniformparams[data // Length];
(* Create the approximate with uniform parameters *)
bez = approxapproxdeg, params, data;
uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;
setMinMaxbez, approxdeg, data, data // Length;
createGraphics[approxdeg];
uniformgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* Create the approximate with chordlength parameter *)
params = chordlengthparamsdata, data // Length;
bez = approxapproxdeg, params, data;
chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;
createGraphics[approxdeg];
chordgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* number of digits to report error *)
ndigit = 5;
Print" ";
PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;
PrintStyle"Each approximate is degree = ", FontSize → 15,
Style[approxdeg, FontSize → 15];
PrintStyle" Errors ", FontSize → 15;
(* Load stats for table display *)
results =
TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,
ScientificFormchordErrorsi, ndigit, i, 0, 4;
TableFormresults, TableDirections → Row,
TableHeadings → "dataUniformline Data ", "Total ",
"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"
8
Print
Style"Left: uniform parametrization Right: chord length parametrization",
FontSize → 15;
GraphicsRowuniformgraphics, chordgraphics
Uniform paramters = {0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.}
chordlength parameters = {0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.}
RESULTS:
Each approximate is degree = 5
Errors
Out[1162]//TableForm=
dataUniformline Data Total Ave Min Max
Uniform 11 1.7229 × 10-14 1.5662 × 10-15 0. 3.7682 × 10-15
Chord lgth 11 1.2902 × 10-14 1.1729 × 10-15 0. 2.4576 × 10-15
Left: uniform parametrization
Right: chord length parametrization
Out[1164]=
In the case of a straight line and evenly distributed data points, it can be observed that both uniform
and chord length parameterizations yield identical results. Furthermore, the fitted curves closely
match the actual data points.
9
dataNoisyLine
In[1165]:=
(* Choose degree of approximation *)
approxdeg = 5;
data = dataNoisyLine;
numdata = data // Length;
(* Create data structure for paramters *)
params = uniformparams[data // Length];
(* Create the approximate with uniform parameters *)
bez = approxapproxdeg, params, data;
uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;
setMinMaxbez, approxdeg, data, data // Length;
createGraphics[approxdeg];
uniformgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* Create the approximate with chordlength parameter *)
params = chordlengthparamsdata, data // Length;
bez = approxapproxdeg, params, data;
chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;
createGraphics[approxdeg];
chordgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* number of digits to report error *)
ndigit = 5;
Print" ";
PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;
PrintStyle"Each approximate is degree = ", FontSize → 15,
Style[approxdeg, FontSize → 15];
PrintStyle" Errors ", FontSize → 15;
(* Load stats for table display *)
results =
TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,
ScientificFormchordErrorsi, ndigit, i, 0, 4;
10
TableFormresults, TableDirections → Row,
TableHeadings → "dataNoisyLine Data ", "Total ",
"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"
Print
Style"Left: uniform parametrization Right: chord length parametrization",
FontSize → 15;
GraphicsRowuniformgraphics, chordgraphics
Uniform paramters =
{0., 0.0333333, 0.0666667, 0.1, 0.133333, 0.166667, 0.2, 0.233333, 0.266667, 0.3,
0.333333, 0.366667, 0.4, 0.433333, 0.466667, 0.5, 0.533333, 0.566667, 0.6, 0.633333,
0.666667, 0.7, 0.733333, 0.766667, 0.8, 0.833333, 0.866667, 0.9, 0.933333, 0.966667, 1.}
chordlength parameters =
{0., 0.0709861, 0.125597, 0.19213, 0.20885, 0.223693, 0.264389, 0.288052,
0.327548, 0.359572, 0.380051, 0.391421, 0.403354, 0.455302, 0.472053, 0.48365,
0.533029, 0.584676, 0.640015, 0.658842, 0.672953, 0.695411, 0.723414,
0.772076, 0.784331, 0.817835, 0.881856, 0.90308, 0.948126, 0.986731, 1.}
RESULTS:
Each approximate is degree = 5
Errors
Out[1185]//TableForm=
dataNoisyLine Data Total Ave Min Max
Uniform 31 1.7176 5.5407 × 10-2 1.8257 × 10-3 1.0546 × 10-1
Chord lgth 31 1.7033 5.4945 × 10-2 7.5086 × 10-3 1.1917 × 10-1
Left: uniform parametrization
Right: chord length parametrization
11
Out[1187]=
In the presence of noise interference, the fitted curves still approximate the data points reasonably
well, indicating that both parameterizations can provide effective fitting. However, it is noticeable
that the linearity of the Bezier points derived from the chord length parameterization method is
slightly weaker.
dataGF
In[1188]:=
(* Choose degree of approximation *)
approxdeg = 5;
data = dataGF;
numdata = data // Length;
(* Create data structure for paramters *)
params = uniformparams[data // Length];
(* Create the approximate with uniform parameters *)
bez = approxapproxdeg, params, data;
uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;
setMinMaxbez, approxdeg, data, data // Length;
createGraphics[approxdeg];
uniformgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* Create the approximate with chordlength parameter *)
12
params = chordlengthparamsdata, data // Length;
bez = approxapproxdeg, params, data;
chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;
createGraphics[approxdeg];
chordgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* number of digits to report error *)
ndigit = 5;
Print" ";
PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;
PrintStyle"Each approximate is degree = ", FontSize → 15,
Style[approxdeg, FontSize → 15];
PrintStyle" Errors ", FontSize → 15;
(* Load stats for table display *)
results =
TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,
ScientificFormchordErrorsi, ndigit, i, 0, 4;
TableFormresults, TableDirections → Row,
TableHeadings → "dataGF Data ", "Total ", "Ave ", "Min ", "Max ",
"Uniform", "Chord lgth"
Print
Style"Left: uniform parametrization Right: chord length parametrization",
FontSize → 15;
GraphicsRowuniformgraphics, chordgraphics
Uniform paramters = {0., 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35,
0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.}
chordlength parameters = {0., 0.00722928, 0.0145066, 0.0220886, 0.0305808, 0.0408886,
0.05402, 0.0709414, 0.0925461, 0.119669, 0.153108, 0.193633, 0.242004,
0.298965, 0.365258, 0.441618, 0.528778, 0.627469, 0.738417, 0.862352, 1.}
RESULTS:
Each approximate is degree = 5
13
Errors Out[1208]//TableForm=
dataGF Data Total Ave Min Max
Uniform 21 6.4729 × 10-14 3.0823 × 10-15 0. 7.1193 × 10-15
Chord lgth 21 1.3543 6.449 × 10-2 1.297 × 10-2 1.6677 × 10-1
Left: uniform parametrization
Right: chord length parametrization
Out[1210]=
In the case of the ‘dataGF’ dataset, both parameterizations yield curves that almost perfectly match
the data. However, the uniform parameterization method produces a superior fit. This is attributed to
the fact that the data points themselves were generated using uniform parameterization.
dataGFgap
In[1211]:=
(* Choose degree of approximation *)
approxdeg = 5;
data = dataGFgap;
numdata = data // Length;
(* Create data structure for paramters *)
params = uniformparams[data // Length];
(* Create the approximate with uniform parameters *)
bez = approxapproxdeg, params, data;
uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;
setMinMaxbez, approxdeg, data, data // Length;
createGraphics[approxdeg];
uniformgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* Create the approximate with chordlength parameter *)
params = chordlengthparamsdata, data // Length;
bez = approxapproxdeg, params, data;
chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;
createGraphics[approxdeg];
chordgraphics = Showcplot, points, bplot, dplot, Axes → False,
14
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* number of digits to report error *)
ndigit = 5;
Print" ";
PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;
PrintStyle"Each approximate is degree = ", FontSize → 15,
Style[approxdeg, FontSize → 15];
PrintStyle" Errors ", FontSize → 15;
(* Load stats for table display *)
results =
TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,
ScientificFormchordErrorsi, ndigit, i, 0, 4;
TableFormresults, TableDirections → Row,
TableHeadings → "dataGFgap Data ", "Total ", "Ave ", "Min ", "Max ",
"Uniform", "Chord lgth"
Print
Style"Left: uniform parametrization Right: chord length parametrization",
FontSize → 15;
GraphicsRowuniformgraphics, chordgraphics
Uniform paramters =
{0., 0.0588235, 0.117647, 0.176471, 0.235294, 0.294118, 0.352941, 0.411765, 0.470588,
0.529412, 0.588235, 0.647059, 0.705882, 0.764706, 0.823529, 0.882353, 0.941176, 1.}
chordlength parameters = {0., 0.00722998, 0.014508, 0.0220907,
0.0305837, 0.0408926, 0.0540252, 0.0709482, 0.092555, 0.119681,
0.298898, 0.365197, 0.441565, 0.528733, 0.627433, 0.738392, 0.862339, 1.}
RESULTS:
Each approximate is degree = 5
Errors
15
Out[1231]//TableForm=
dataGFgap Data Total Ave Min Max
Uniform 18 5.6092 3.1162 × 10-1 1.3551 × 10-2 1.2783
Chord lgth 18 1.0587 5.8816 × 10-2 1.2302 × 10-2 1.4259 × 10-1
Left: uniform parametrization
Right: chord length parametrization
Out[1233]=
When there are gaps in the data, the data points are not uniformly parameterized. Consequently, the
fitting quality is slightly compromised for the uniform parameterization method. Nonetheless, both
methods manage to approximate the overall shape of the curve effectively.
dataFour
In[1234]:=
(* Choose degree of approximation *)
approxdeg = 3;
data = dataFour;
numdata = data // Length;
(* Create data structure for paramters *)
params = uniformparams[data // Length];
(* Create the approximate with uniform parameters *)
bez = approxapproxdeg, params, data;
uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;
setMinMaxbez, approxdeg, data, data // Length;
createGraphics[approxdeg];
uniformgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* Create the approximate with chordlength parameter *)
params = chordlengthparamsdata, data // Length;
bez = approxapproxdeg, params, data;
chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;
createGraphics[approxdeg];
chordgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
16
(* number of digits to report error *)
ndigit = 5;
Print" ";
PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;
PrintStyle"Each approximate is degree = ", FontSize → 15,
Style[approxdeg, FontSize → 15];
PrintStyle" Errors ", FontSize → 15;
(* Load stats for table display *)
results =
TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,
ScientificFormchordErrorsi, ndigit, i, 0, 4;
TableFormresults, TableDirections → Row,
TableHeadings → "dataFour Data ", "Total ", "Ave ", "Min ", "Max ",
"Uniform", "Chord lgth"
Print
Style"Left: uniform parametrization Right: chord length parametrization",
FontSize → 15;
GraphicsRowuniformgraphics, chordgraphics
Uniform paramters = {0., 0.333333, 0.666667, 1.}
chordlength parameters = {0., 0.318454, 0.681546, 1.}
RESULTS:
Each approximate is degree = 3
Errors Out[1254]//TableForm=
dataFour Data Total Ave Min Max
Uniform 4 4.1507 × 10-16 1.0377 × 10-16 0. 2.2649 × 10-16
Chord lgth 4 2.6452 × 10-16 6.613 × 10-17 0. 2.2384 × 10-16
Left: uniform parametrization
Right: chord length parametrization
17
Out[1256]=
For the ‘dataFour’ dataset, both algorithms yield excellent fitting results.
dataOutlier
In[1257]:=
(* Choose degree of approximation *)
approxdeg = 3;
data = dataOutlier;
numdata = data // Length;
(* Create data structure for paramters *)
params = uniformparams[data // Length];
(* Create the approximate with uniform parameters *)
bez = approxapproxdeg, params, data;
uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;
setMinMaxbez, approxdeg, data, data // Length;
createGraphics[approxdeg];
uniformgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* Create the approximate with chordlength parameter *)
params = chordlengthparamsdata, data // Length;
bez = approxapproxdeg, params, data;
chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;
createGraphics[approxdeg];
chordgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* number of digits to report error *)
ndigit = 5;
Print" ";
PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;
18
PrintStyle"Each approximate is degree = ", FontSize → 15,
Style[approxdeg, FontSize → 15];
PrintStyle" Errors ", FontSize → 15;
(* Load stats for table display *)
results =
TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,
ScientificFormchordErrorsi, ndigit, i, 0, 4;
TableFormresults, TableDirections → Row,
TableHeadings → "dataOutlier Data ", "Total ",
"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"
Print
Style"Left: uniform parametrization Right: chord length parametrization",
FontSize → 15;
GraphicsRowuniformgraphics, chordgraphics
Uniform paramters = {0., 0.0322581, 0.0645161, 0.0967742, 0.129032, 0.16129, 0.193548,
0.225806, 0.258065, 0.290323, 0.322581, 0.354839, 0.387097, 0.419355, 0.451613,
0.483871, 0.516129, 0.548387, 0.580645, 0.612903, 0.645161, 0.677419, 0.709677,
0.741935, 0.774194, 0.806452, 0.83871, 0.870968, 0.903226, 0.935484, 0.967742, 1.}
chordlength parameters =
{0., 0.030916, 0.0616782, 0.0921367, 0.122149, 0.151586, 0.180331, 0.208292,
0.235399, 0.26161, 0.286919, 0.311355, 0.334988, 0.357928, 0.380325, 0.402362,
0.513479, 0.623344, 0.645568, 0.668262, 0.691591, 0.715682, 0.740622, 0.766457,
0.793194, 0.820806, 0.849236, 0.878398, 0.908186, 0.938476, 0.969129, 1.}
RESULTS:
Each approximate is degree = 3
Errors
Out[1277]//TableForm=
dataOutlier Data Total Ave Min Max
Uniform 32 1.1491 3.5911 × 10-2 1.5804 × 10-4 4.4373 × 10-1
Chord lgth 32 2.6052 8.1413 × 10-2 1.682 × 10-2 4.9443 × 10-1
19
Left: uniform parametrization
Right: chord length parametrization
Out[1279]=
In the ‘dataOutliner’ dataset, both parameterizations manage to capture the curve’s shape effec-
tively. Experimentally, the uniform parameterization method exhibits smaller errors. However,
visually, both methods perform exceptionally well.
dataSemiCircle
In[1280]:=
(* Choose degree of approximation *)
approxdeg = 3;
data = dataSemiCircle;
numdata = data // Length;
(* Create data structure for paramters *)
params = uniformparams[data // Length];
(* Create the approximate with uniform parameters *)
bez = approxapproxdeg, params, data;
uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;
setMinMaxbez, approxdeg, data, data // Length;
createGraphics[approxdeg];
uniformgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* Create the approximate with chordlength parameter *)
params = chordlengthparamsdata, data // Length;
bez = approxapproxdeg, params, data;
chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;
createGraphics[approxdeg];
chordgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* number of digits to report error *)
20
ndigit = 5;
Print" ";
PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;
PrintStyle"Each approximate is degree = ", FontSize → 15,
Style[approxdeg, FontSize → 15];
PrintStyle" Errors ", FontSize → 15;
(* Load stats for table display *)
results =
TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,
ScientificFormchordErrorsi, ndigit, i, 0, 4;
TableFormresults, TableDirections → Row,
TableHeadings → "dataSemiCircle Data ", "Total ",
"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"
Print
Style"Left: uniform parametrization Right: chord length parametrization",
FontSize → 15;
GraphicsRowuniformgraphics, chordgraphics
Uniform paramters = {0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.}
chordlength parameters = {0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.}
RESULTS:
Each approximate is degree = 3
Errors
Out[1300]//TableForm=
dataSemiCircle Data Total Ave Min Max
Uniform 11 2.2916 × 10-1 2.0833 × 10-2 6.0398 × 10-3 2.6319 × 10-2
Chord lgth 11 2.2916 × 10-1 2.0833 × 10-2 6.0398 × 10-3 2.6319 × 10-2
Left: uniform parametrization
Right: chord length parametrization
21
Out[1302]=
For the ‘dataSemiCircle’ dataset, both parameterizations achieve satisfactory fitting results.
dataSpiral
In[1303]:=
(* Choose degree of approximation *)
approxdeg = 5;
data = dataSpiral;
numdata = data // Length;
(* Create data structure for paramters *)
params = uniformparams[data // Length];
(* Create the approximate with uniform parameters *)
bez = approxapproxdeg, params, data;
uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;
setMinMaxbez, approxdeg, data, data // Length;
createGraphics[approxdeg];
uniformgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* Create the approximate with chordlength parameter *)
params = chordlengthparamsdata, data // Length;
bez = approxapproxdeg, params, data;
chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;
createGraphics[approxdeg];
chordgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* number of digits to report error *)
ndigit = 5;
Print" ";
22
PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;
PrintStyle"Each approximate is degree = ", FontSize → 15,
Style[approxdeg, FontSize → 15];
PrintStyle" Errors ", FontSize → 15;
(* Load stats for table display *)
results =
TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,
ScientificFormchordErrorsi, ndigit, i, 0, 4;
TableFormresults, TableDirections → Row,
TableHeadings → "dataSpiral Data ", "Total ",
"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"
Print
Style"Left: uniform parametrization Right: chord length parametrization",
FontSize → 15;
GraphicsRowuniformgraphics, chordgraphics
Uniform paramters =
{0., 0.0333333, 0.0666667, 0.1, 0.133333, 0.166667, 0.2, 0.233333, 0.266667, 0.3,
0.333333, 0.366667, 0.4, 0.433333, 0.466667, 0.5, 0.533333, 0.566667, 0.6, 0.633333,
0.666667, 0.7, 0.733333, 0.766667, 0.8, 0.833333, 0.866667, 0.9, 0.933333, 0.966667, 1.}
chordlength parameters =
{0., 0.0165587, 0.0288641, 0.0408079, 0.0526653, 0.0710228, 0.0856536, 0.099847,
0.125872, 0.136201, 0.164845, 0.19125, 0.210271, 0.238697, 0.272028, 0.302158,
0.332215, 0.364215, 0.408718, 0.443125, 0.484808, 0.530053, 0.575403,
0.618206, 0.665753, 0.716402, 0.771092, 0.821731, 0.879113, 0.942405, 1.}
RESULTS:
Each approximate is degree = 5
Errors
Out[1323]//TableForm=
dataSpiral Data Total Ave Min Max
Uniform 31 3.2256 1.0405 × 10-1 3.0533 × 10-2 2.2594 × 10-1
Chord lgth 31 4.7265 1.5247 × 10-1 3.7717 × 10-3 5.1609 × 10-1
23
Left: uniform parametrization
Right: chord length parametrization
Out[1325]=
In the case of the ‘dataSpiral’ dataset, both methods provide good fitting results. The uniform parame-
terization method incurs slightly larger fitting errors.
dataSpiralRev
In[1326]:=
(* Choose degree of approximation *)
approxdeg = 5;
data = dataSpiralRev;
numdata = data // Length;
(* Create data structure for paramters *)
params = uniformparams[data // Length];
(* Create the approximate with uniform parameters *)
bez = approxapproxdeg, params, data;
uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;
setMinMaxbez, approxdeg, data, data // Length;
createGraphics[approxdeg];
uniformgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* Create the approximate with chordlength parameter *)
params = chordlengthparamsdata, data // Length;
bez = approxapproxdeg, params, data;
24
chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;
createGraphics[approxdeg];
chordgraphics = Showcplot, points, bplot, dplot, Axes → False,
PlotRange → {{plotmm〚1, 1〛, plotmm〚2, 1〛}, {plotmm〚1, 2〛, plotmm〚2, 2〛}};
(* number of digits to report error *)
ndigit = 5;
Print" ";
PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;
PrintStyle"Each approximate is degree = ", FontSize → 15,
Style[approxdeg, FontSize → 15];
PrintStyle" Errors ", FontSize → 15;
(* Load stats for table display *)
results =
TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,
ScientificFormchordErrorsi, ndigit, i, 0, 4;
TableFormresults, TableDirections → Row,
TableHeadings → "dataSpiralRev Data ", "Total ",
"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"
Print
Style"Left: uniform parametrization Right: chord length parametrization",
FontSize → 15;
GraphicsRowuniformgraphics, chordgraphics
Uniform paramters =
{0., 0.0333333, 0.0666667, 0.1, 0.133333, 0.166667, 0.2, 0.233333, 0.266667, 0.3,
0.333333, 0.366667, 0.4, 0.433333, 0.466667, 0.5, 0.533333, 0.566667, 0.6, 0.633333,
0.666667, 0.7, 0.733333, 0.766667, 0.8, 0.833333, 0.866667, 0.9, 0.933333, 0.966667, 1.}
chordlength parameters =
{0., 0.0551113, 0.108233, 0.173553, 0.224785, 0.277305, 0.330263, 0.376479,
0.42994, 0.466892, 0.518171, 0.553055, 0.601952, 0.638039, 0.672442,
0.702587, 0.736292, 0.766808, 0.799122, 0.82294, 0.84686, 0.868957, 0.891585,
0.905908, 0.927978, 0.943184, 0.957608, 0.967122, 0.982282, 0.988754, 1.}
RESULTS:
25
Each approximate is degree = 5
Errors
Out[1346]//TableForm=
dataSpiralRev Data Total Ave Min Max
Uniform 31 4.002 1.291 × 10-1 2.8713 × 10-2 2.5079 × 10-1
Chord lgth 31 4.4036 1.4205 × 10-1 1.3426 × 10-2 3.7033 × 10-1
Left: uniform parametrization
Right: chord length parametrization
Out[1348]=
For the ‘dataSpiralRev’ dataset, both parameterizations yield impressive fitting results, particularly in
sparse data regions, where the errors are minimal.
26