Derivatives example

The code below shows an example of how derivatives can be used to compute the normal vectors of a surface.

Defining the surface

using SplineGrids

# Spline Grid Parameters
n_control_points = (5, 5)
degree = (2, 2)
n_sample_points = (100, 100)
Nout = 3
max_derivative_order = 1

# Define the spline grid
spline_dimensions = SplineDimension.(
    n_control_points, degree, n_sample_points; max_derivative_order)
spline_grid = SplineGrid(spline_dimensions, Nout)
for i in 1:n_control_points[1]
    for j in 1:n_control_points[2]
        spline_grid.control_points[i, j, 3] = exp(-((i - 3)^2 + (j - 3)^2))
    end
end

Inspecting the basis functions

Let's look at the basis functions for the first dimension:

using Plots

plot(spline_dimensions[1])
Example block output

and the derivatives of these basis functions:

using Plots

plot(spline_dimensions[1]; derivative_order = 1)
Example block output

Evaluating the surface

The data is copied because spline_grid.eval will be overwritten below when computing the partial derivatives.

evaluate!(spline_grid)
spline_grid_data = copy(spline_grid.eval)
nothing

Computing the partial derivatives

# Derivatives of the surface with respect to the first dimension parameter
evaluate!(spline_grid; derivative_order = (1, 0))
∂₁spline_grid_data = copy(spline_grid.eval)

# Derivatives of the surface with respect to the second dimension parameter
evaluate!(spline_grid; derivative_order = (0, 1))
∂₂spline_grid_data = spline_grid.eval
nothing

Computing the normal vectors

using LinearAlgebra

normal_vectors = similar(spline_grid_data)
for i in 1:n_sample_points[1]
    for j in 1:n_sample_points[2]
        normal_vectors[i, j, :] .= cross(
            view(∂₁spline_grid_data, i, j, :),
            view(∂₂spline_grid_data, i, j, :)
        )
        normal_vectors[i, j, :] ./= 10 * norm(view(normal_vectors, i, j, :))
    end
end

Plotting

using CairoMakie

# Plotting the surface
f = Figure()
ax = Axis3(f[1, 1])
CairoMakie.surface!(ax, eachslice(spline_grid_data, dims = 3)...)

# Plotting a subset of the normal vectors
spline_grid_data_reshaped = reshape(spline_grid_data, (prod(n_sample_points), 3))
normal_vectors_reshaped = reshape(normal_vectors, (prod(n_sample_points), 3))

CairoMakie.quiver!(
    ax,
    eachslice(view(spline_grid_data_reshaped, 1:192:prod(n_sample_points), :), dims = 2)...,
    eachslice(view(normal_vectors_reshaped, 1:192:prod(n_sample_points), :), dims = 2)...,
    arrowsize = 0.03
)

CairoMakie.xlims!(0, 1)
CairoMakie.ylims!(0, 1)

f
Example block output