Surfaces

Surfaces can be refined, splitted, knots can be removed, and the degree can be manipulated.


Refining a Surface

Based on the principles of knot insertion, several knots can be inserted into a surface (without changing the points the surface describes) by the refine function.

BSurfaceRef = refine(BSurface; U=[0.5, 0.5, 0.72], V=[0.2, 0.42])

plotPatches([BSurfaceRef], enforceRatio=false, plotControlPoints=true)
Note

Refining a surface does not change the points in space described by the surface. Effectively, in the plots it can be seen that the number of control points is increased. However, also underlying properties such as the differentiability are changed.


Splitting a Surface

To split a surface into multiple separate surfaces the function split is provided which returns an array of surfaces.

sVec = split(BSurface, U=[0.5,0.75], V=[0.6])

plotPatches(sVec, enforceRatio=false, plotControlPoints=false)

To equally split a surface into $n$ times $m$ surfaces as second and third argument an integer can be provided:

sVec = split(BSurface, 3, 2) # split into 3 x 2 surfaces
6-element Vector{BsplineSurface{Float64}}:
 BsplineSurface{Float64}(Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.6000000000000001, 1.0, 1.0, 1.0]), Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.4, 0.8, 1.0, 1.0, 1.0]), StaticArraysCore.SVector{3, Float64}[[0.0, 0.0, 3.0] [0.0, 1.0, 3.0] … [0.0, 2.75, 2.0] [0.0, 3.0, 2.0]; [1.0, 0.0, 3.0] [1.0, 1.0, 3.0] … [1.0, 2.75, 2.0] [1.0, 3.0, 2.0]; [1.8333333333333333, 0.0, 2.166666666666667] [1.8333333333333333, 1.0, 2.166666666666667] … [1.8333333333333333, 2.75, 1.1666666666666667] [1.8333333333333333, 3.0, 1.1666666666666665]; [2.166666666666666, 0.0, 2.055555555555556] [2.166666666666666, 1.0, 2.055555555555556] … [2.166666666666666, 2.75, 1.0555555555555556] [2.166666666666666, 3.0, 1.0555555555555556]])
 BsplineSurface{Float64}(Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.6000000000000001, 1.0, 1.0, 1.0]), Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.19999999999999996, 0.6000000000000001, 1.0, 1.0, 1.0]), StaticArraysCore.SVector{3, Float64}[[0.0, 3.0, 2.0] [0.0, 3.25, 2.0] … [0.0, 5.0, 2.0] [0.0, 6.0, 2.0]; [1.0, 3.0, 2.0] [1.0, 3.25, 2.0] … [1.0, 5.0, 2.0] [1.0, 6.0, 2.0]; [1.8333333333333333, 3.0, 1.1666666666666665] [1.8333333333333333, 3.25, 1.1666666666666665] … [1.8333333333333333, 5.0, 1.1666666666666667] [1.8333333333333333, 6.0, 1.1666666666666667]; [2.166666666666666, 3.0, 1.0555555555555556] [2.166666666666666, 3.25, 1.0555555555555556] … [2.166666666666666, 5.0, 0.8333333333333335] [2.166666666666666, 6.222222222222222, 0.8333333333333335]])
 BsplineSurface{Float64}(Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.20000000000000012, 0.8, 1.0, 1.0, 1.0]), Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.4, 0.8, 1.0, 1.0, 1.0]), StaticArraysCore.SVector{3, Float64}[[2.166666666666666, 0.0, 2.055555555555556] [2.166666666666666, 1.0, 2.055555555555556] … [2.166666666666666, 2.75, 1.0555555555555556] [2.166666666666666, 3.0, 1.0555555555555556]; [2.333333333333333, 0.0, 2.0] [2.333333333333333, 1.0, 2.0] … [2.333333333333333, 2.75, 1.0] [2.333333333333333, 3.0, 1.0]; … ; [3.6666666666666665, 0.0, 1.3333333333333335] [3.6666666666666665, 1.0, 1.3333333333333335] … [3.6666666666666665, 2.75, 0.3333333333333335] [3.6666666666666665, 3.0, 0.41666666666666674]; [3.833333333333333, 0.0, 1.2222222222222223] [3.833333333333333, 1.0, 1.2222222222222223] … [3.833333333333333, 2.75, 0.22222222222222238] [3.833333333333333, 3.0, 0.3125000000000001]])
 BsplineSurface{Float64}(Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.20000000000000012, 0.8, 1.0, 1.0, 1.0]), Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.19999999999999996, 0.6000000000000001, 1.0, 1.0, 1.0]), StaticArraysCore.SVector{3, Float64}[[2.166666666666666, 3.0, 1.0555555555555556] [2.166666666666666, 3.25, 1.0555555555555556] … [2.166666666666666, 5.0, 0.8333333333333335] [2.166666666666666, 6.222222222222222, 0.8333333333333335]; [2.333333333333333, 3.0, 1.0] [2.333333333333333, 3.25, 1.0] … [2.333333333333333, 5.0, 0.6666666666666667] [2.333333333333333, 6.333333333333333, 0.6666666666666667]; … ; [3.6666666666666665, 3.0, 0.41666666666666674] [3.6666666666666665, 3.25, 0.5] … [3.6666666666666665, 5.0, 0.0] [3.6666666666666665, 6.333333333333334, 0.0]; [3.833333333333333, 3.0, 0.3125000000000001] [3.833333333333333, 3.25, 0.40277777777777785] … [3.833333333333333, 5.0, 0.0] [3.833333333333333, 6.222222222222223, 0.0]])
 BsplineSurface{Float64}(Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.4000000000000002, 1.0, 1.0, 1.0]), Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.4, 0.8, 1.0, 1.0, 1.0]), StaticArraysCore.SVector{3, Float64}[[3.833333333333333, 0.0, 1.2222222222222223] [3.833333333333333, 1.0, 1.2222222222222223] … [3.833333333333333, 2.75, 0.22222222222222238] [3.833333333333333, 3.0, 0.3125000000000001]; [4.166666666666667, 0.0, 1.0] [4.166666666666667, 1.0, 1.0] … [4.166666666666667, 2.75, 0.0] [4.166666666666666, 3.0, 0.10416666666666664]; [5.0, 0.0, 1.0] [5.0, 1.0, 1.0] … [5.0, 2.75, 0.0] [5.0, 3.0, 0.0]; [6.0, 0.0, 1.0] [6.0, 1.0, 1.0] … [6.0, 2.75, 0.0] [6.0, 3.0, 0.0]])
 BsplineSurface{Float64}(Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.4000000000000002, 1.0, 1.0, 1.0]), Bspline{Float64}(2, [0.0, 0.0, 0.0, 0.19999999999999996, 0.6000000000000001, 1.0, 1.0, 1.0]), StaticArraysCore.SVector{3, Float64}[[3.833333333333333, 3.0, 0.3125000000000001] [3.833333333333333, 3.25, 0.40277777777777785] … [3.833333333333333, 5.0, 0.0] [3.833333333333333, 6.222222222222223, 0.0]; [4.166666666666666, 3.0, 0.10416666666666664] [4.166666666666666, 3.25, 0.2083333333333333] … [4.166666666666667, 5.0, 0.0] [4.166666666666667, 6.0, 0.0]; [5.0, 3.0, 0.0] [5.0, 3.25, 0.0] … [5.0, 5.0, 0.0] [5.0, 6.0, 0.0]; [6.0, 3.0, 0.0] [6.0, 3.25, 0.0] … [6.0, 5.0, 0.0] [6.0, 6.0, 0.0]])

Removing Knots from a Surface

Based on the principles of knot removal, an interior knot can potentially be removed multiple times from a surface (without changing the points the surface describes) by the removeKnotU and the removeKnotV functions.

# --- surface with removable knots
p = 3
kVec = Float64[0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2]

P1 = SVector(0.0, 0.0, 0.0)
P2 = SVector(0.0, 2.0, 0.0)
P3 = SVector(1.5, 3.0, 0.0)
P4 = SVector(3.0, 3.0, 0.0)
P5 = SVector(4.5, 3.0, 0.0)
P6 = SVector(6.0, 2.0, 0.0)
P7 = SVector(6.0, 0.0, 0.0)

cP = [P1 , P2 , P3 , P4 , P5 , P6 , P7 ]

P1 = SVector(0.0, 0.0, 2.0)
P2 = SVector(0.0, 2.0, 2.0)
P3 = SVector(1.5, 3.0, 2.0)
P4 = SVector(3.0, 3.0, 2.0)
P5 = SVector(4.5, 3.0, 2.0)
P6 = SVector(6.0, 2.0, 2.0)
P7 = SVector(6.0, 0.0, 2.0)

cP2 = [P1 , P2 , P3 , P4 , P5 , P6 , P7 ]

controlPoints = [[cP, cP2][j][i] for i in 1:7, j in 1:2]

BS1 = BsplineSurface(Bspline(p, kVec), Bspline(1, [0.0,0.0,1.0,1.0]), controlPoints)


# --- remove knot
BS2 = removeKnotU(BS1, 0.5, 1) # remove knot once


# --- plot before and after
t1 = plotPatches([BS1], enforceRatio=true, plotControlPoints=true)
t2 = plotPatches([BS2], enforceRatio=true, plotControlPoints=true)

uEval = vEval = collect(0:0.005:1.0)

S1 = BS1(uEval, vEval)
S2 = BS2(uEval, vEval)

x, t1 = plotSurface(S1, controlPoints=BS1.controlPoints, returnTrace=true)
x, t2 = plotSurface(S2, controlPoints=BS2.controlPoints, returnTrace=true)

fig = make_subplots(
    rows=1, cols=2,
    specs=fill(Spec(kind="scene"), 1, 2)
)

for i in eachindex(t1)
    add_trace!(fig, t1[i], row=1, col=1)
end
for i in eachindex(t2)
    add_trace!(fig, t2[i], row=1, col=2)
end

fig
[ Info: The knot vector is being modified (normalized).
Note

Removing a knot from a surface is only possible when the continuity of the surface is sufficient at the knot. A central part of the removeKnot functions is to verify if the knot can actually be removed. If not, warnings are generated, indicating the encountered limitations.


Degree Manipulation

To be done.