Bezier Patches and Surface Curvatures

profileSubi
6f743034e4f7615f50fc04db435f39ac_cec877e5b0c50fddc645b3a46e5d537d_81.pdf

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_] := SumBernsteinBasis[deg, i, t] * bptsi + 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 = Tablecurvebpts, Length[bpts] - 1, t, t, 0, 1, 1.0 / 10.0;

(* Noisy line *)

dataNoisyLine = Tablet, 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 = Tablecurvebpts, 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 = Tablecurvebpts, Length[bpts] - 1, t, t, 0, 1, 1.0 / 3.0;

(* This is a data set to simulate an outlier *)

dataOutlier = Tablet, Sin[t], t, 0, Pi, 1.0 / 10.0;

dataOutlier〚17, 2〛 = dataOutlier〚17, 2〛 - 0.5;

(* semicircle *)

dataSemiCircle = TableCos[t], Sin[t] // N, t, 0, Pi, Pi  10.0;

(* spiral with noise *)

dataSpiral =

Tablet * 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 = Table1  (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_] := Moduledistances, totalLength, params,

(*Calculate distances between consecutive points*)

distances = TableEuclideanDistancedatai, datai + 1, i, 1, Length[data] - 1; (*Calculate total length of the curve*)totalLength = Total[distances];

(*Calculate chord length parameters*)

params = AccumulatePrependdistances  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]:=

approxn_, params_, data_ := Module pre, ps = params, T, sol, dat = data, bez,

pre = TableBernsteinBasisn, i, psj, j, 1, Length@ps, i, 0, n;

T = KroneckerProduct{1, 0}, {0, 1}, pre;

sol = LinearSolveTranspose[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_] :=

Moduleerrors, totalError, averageError, minError, maxError, errors = TableNormcurvebez, deg, paramsi - datai, 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]:=

setMinMaxbez_, 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〛 = Minbezmin〚1〛, datamin〚1〛;

plotmm〚1, 2〛 = Minbezmin〚2〛, datamin〚2〛;

plotmm〚2, 1〛 = Maxbezmax〚1〛, datamax〚1〛;

plotmm〚2, 2〛 = Maxbezmax〚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 = ListPlotdata, PlotStyle → Black, PointSize[Medium];

(* Graphics entity for Bezier points and Bezier curve *)

points = GraphicsRGBColor[0.5, 0.79, 0.81], PointSize[Large], Point[bez]; bplot = ListLinePlot[bez, PlotStyle → RGBColor[0.5, 0.79, 0.81]];

cplot = GraphicsThick, Blue, BezierCurvebez, 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 = approxapproxdeg, params, data;

uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;

setMinMaxbez, approxdeg, data, data // Length;

createGraphics[approxdeg];

uniformgraphics = Showcplot, 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 = chordlengthparamsdata, data // Length;

bez = approxapproxdeg, params, data;

chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;

createGraphics[approxdeg];

chordgraphics = Showcplot, 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" ";

PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;

PrintStyle"Each approximate is degree = ", FontSize → 15,

Style[approxdeg, FontSize → 15];

PrintStyle" Errors ", FontSize → 15;

(* Load stats for table display *)

results =

TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,

ScientificFormchordErrorsi, ndigit, i, 0, 4;

TableFormresults, TableDirections → Row,

TableHeadings → "dataUniformline Data ", "Total ",

"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"

8

Print

Style"Left: uniform parametrization Right: chord length parametrization",

FontSize → 15;

GraphicsRowuniformgraphics, 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 = approxapproxdeg, params, data;

uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;

setMinMaxbez, approxdeg, data, data // Length;

createGraphics[approxdeg];

uniformgraphics = Showcplot, 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 = chordlengthparamsdata, data // Length;

bez = approxapproxdeg, params, data;

chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;

createGraphics[approxdeg];

chordgraphics = Showcplot, 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" ";

PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;

PrintStyle"Each approximate is degree = ", FontSize → 15,

Style[approxdeg, FontSize → 15];

PrintStyle" Errors ", FontSize → 15;

(* Load stats for table display *)

results =

TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,

ScientificFormchordErrorsi, ndigit, i, 0, 4;

10

TableFormresults, TableDirections → Row,

TableHeadings → "dataNoisyLine Data ", "Total ",

"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"

Print

Style"Left: uniform parametrization Right: chord length parametrization",

FontSize → 15;

GraphicsRowuniformgraphics, 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 = approxapproxdeg, params, data;

uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;

setMinMaxbez, approxdeg, data, data // Length;

createGraphics[approxdeg];

uniformgraphics = Showcplot, 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 = chordlengthparamsdata, data // Length;

bez = approxapproxdeg, params, data;

chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;

createGraphics[approxdeg];

chordgraphics = Showcplot, 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" ";

PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;

PrintStyle"Each approximate is degree = ", FontSize → 15,

Style[approxdeg, FontSize → 15];

PrintStyle" Errors ", FontSize → 15;

(* Load stats for table display *)

results =

TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,

ScientificFormchordErrorsi, ndigit, i, 0, 4;

TableFormresults, TableDirections → Row,

TableHeadings → "dataGF Data ", "Total ", "Ave ", "Min ", "Max ",

"Uniform", "Chord lgth"

Print

Style"Left: uniform parametrization Right: chord length parametrization",

FontSize → 15;

GraphicsRowuniformgraphics, 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 = approxapproxdeg, params, data;

uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;

setMinMaxbez, approxdeg, data, data // Length;

createGraphics[approxdeg];

uniformgraphics = Showcplot, 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 = chordlengthparamsdata, data // Length;

bez = approxapproxdeg, params, data;

chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;

createGraphics[approxdeg];

chordgraphics = Showcplot, 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" ";

PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;

PrintStyle"Each approximate is degree = ", FontSize → 15,

Style[approxdeg, FontSize → 15];

PrintStyle" Errors ", FontSize → 15;

(* Load stats for table display *)

results =

TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,

ScientificFormchordErrorsi, ndigit, i, 0, 4;

TableFormresults, TableDirections → Row,

TableHeadings → "dataGFgap Data ", "Total ", "Ave ", "Min ", "Max ",

"Uniform", "Chord lgth"

Print

Style"Left: uniform parametrization Right: chord length parametrization",

FontSize → 15;

GraphicsRowuniformgraphics, 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 = approxapproxdeg, params, data;

uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;

setMinMaxbez, approxdeg, data, data // Length;

createGraphics[approxdeg];

uniformgraphics = Showcplot, 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 = chordlengthparamsdata, data // Length;

bez = approxapproxdeg, params, data;

chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;

createGraphics[approxdeg];

chordgraphics = Showcplot, 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" ";

PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;

PrintStyle"Each approximate is degree = ", FontSize → 15,

Style[approxdeg, FontSize → 15];

PrintStyle" Errors ", FontSize → 15;

(* Load stats for table display *)

results =

TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,

ScientificFormchordErrorsi, ndigit, i, 0, 4;

TableFormresults, TableDirections → Row,

TableHeadings → "dataFour Data ", "Total ", "Ave ", "Min ", "Max ",

"Uniform", "Chord lgth"

Print

Style"Left: uniform parametrization Right: chord length parametrization",

FontSize → 15;

GraphicsRowuniformgraphics, 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 = approxapproxdeg, params, data;

uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;

setMinMaxbez, approxdeg, data, data // Length;

createGraphics[approxdeg];

uniformgraphics = Showcplot, 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 = chordlengthparamsdata, data // Length;

bez = approxapproxdeg, params, data;

chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;

createGraphics[approxdeg];

chordgraphics = Showcplot, 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" ";

PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;

18

PrintStyle"Each approximate is degree = ", FontSize → 15,

Style[approxdeg, FontSize → 15];

PrintStyle" Errors ", FontSize → 15;

(* Load stats for table display *)

results =

TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,

ScientificFormchordErrorsi, ndigit, i, 0, 4;

TableFormresults, TableDirections → Row,

TableHeadings → "dataOutlier Data ", "Total ",

"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"

Print

Style"Left: uniform parametrization Right: chord length parametrization",

FontSize → 15;

GraphicsRowuniformgraphics, 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 = approxapproxdeg, params, data;

uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;

setMinMaxbez, approxdeg, data, data // Length;

createGraphics[approxdeg];

uniformgraphics = Showcplot, 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 = chordlengthparamsdata, data // Length;

bez = approxapproxdeg, params, data;

chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;

createGraphics[approxdeg];

chordgraphics = Showcplot, 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" ";

PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;

PrintStyle"Each approximate is degree = ", FontSize → 15,

Style[approxdeg, FontSize → 15];

PrintStyle" Errors ", FontSize → 15;

(* Load stats for table display *)

results =

TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,

ScientificFormchordErrorsi, ndigit, i, 0, 4;

TableFormresults, TableDirections → Row,

TableHeadings → "dataSemiCircle Data ", "Total ",

"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"

Print

Style"Left: uniform parametrization Right: chord length parametrization",

FontSize → 15;

GraphicsRowuniformgraphics, 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 = approxapproxdeg, params, data;

uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;

setMinMaxbez, approxdeg, data, data // Length;

createGraphics[approxdeg];

uniformgraphics = Showcplot, 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 = chordlengthparamsdata, data // Length;

bez = approxapproxdeg, params, data;

chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;

createGraphics[approxdeg];

chordgraphics = Showcplot, 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

PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;

PrintStyle"Each approximate is degree = ", FontSize → 15,

Style[approxdeg, FontSize → 15];

PrintStyle" Errors ", FontSize → 15;

(* Load stats for table display *)

results =

TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,

ScientificFormchordErrorsi, ndigit, i, 0, 4;

TableFormresults, TableDirections → Row,

TableHeadings → "dataSpiral Data ", "Total ",

"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"

Print

Style"Left: uniform parametrization Right: chord length parametrization",

FontSize → 15;

GraphicsRowuniformgraphics, 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 = approxapproxdeg, params, data;

uniformErrors = lsqerrordata, data // Length, params, bez, approxdeg;

setMinMaxbez, approxdeg, data, data // Length;

createGraphics[approxdeg];

uniformgraphics = Showcplot, 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 = chordlengthparamsdata, data // Length;

bez = approxapproxdeg, params, data;

24

chordErrors = lsqerrordata, data // Length, params, bez, approxdeg;

createGraphics[approxdeg];

chordgraphics = Showcplot, 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" ";

PrintStyle"RESULTS: ", FontSize → 15, FontWeight → Bold;

PrintStyle"Each approximate is degree = ", FontSize → 15,

Style[approxdeg, FontSize → 15];

PrintStyle" Errors ", FontSize → 15;

(* Load stats for table display *)

results =

TableIfi ⩵ 0, {data // Length, data // Length}, ScientificFormuniformErrorsi, ndigit,

ScientificFormchordErrorsi, ndigit, i, 0, 4;

TableFormresults, TableDirections → Row,

TableHeadings → "dataSpiralRev Data ", "Total ",

"Ave ", "Min ", "Max ", "Uniform", "Chord lgth"

Print

Style"Left: uniform parametrization Right: chord length parametrization",

FontSize → 15;

GraphicsRowuniformgraphics, 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