Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Equally spaced points along spline #362

Closed
tomerarnon opened this issue Dec 22, 2023 · 2 comments
Closed

Equally spaced points along spline #362

tomerarnon opened this issue Dec 22, 2023 · 2 comments

Comments

@tomerarnon
Copy link

tomerarnon commented Dec 22, 2023

Screenshot 2023-12-22 at 11 36 28 AM

In the above image, sampling the shown spline at equal intervals produces unequally spaced points. Is there a simple way to produce equally spaced points along a spline?

@hyrodium
Copy link
Owner

Thanks for the question!

BasicBSpline.jl does not provide API for that, but equally spaced points can be obtained using Newton's method:

using BasicBSpline
using Plots
using StaticArrays
using ForwardDiff
using LinearAlgebra
using FastGaussQuadrature
using Random

# Define B-spline curve
Random.seed!(2)
k = UniformKnotVector(1:12)
P = BSplineSpace{3}(k)
a = [rand(SVector{2}) for _ in 1:dim(P)]
C = BSplineManifold(a,P)

# Plot non-equally spaced points on the curve
N = 20
ps = C.(range(domain(P),length=N))
xs = [p[1] for p in ps]
ys = [p[2] for p in ps]
plot(C, aspectratio=:equal)
scatter!(xs, ys)

# Speed of the curve
speed(t) = norm(ForwardDiff.derivative(C,(t)))
# Parameter points on the curve
ts = collect(range(domain(P),length=N))
# Length between parameter points
ls = zeros(N-1)
# Update ts with iterations
for _ in 1:5
    for i in 1:N-1
        a, b = ts[i], ts[i+1]
        nodes, weights = gausslegendre(20)
        ls[i] = sum(speed.((nodes .+ 1) ./ 2 .* (b-a) .+ a).*weights)*(b-a)/2
    end
    L = sum(ls)
    for i in 2:N-1
        d = sum(view(ls, 1:i-1)) - range(0,L,length=20)[i]
        ts[i] -= d/speed(ts[i])
    end
end

# Check lengths are equal
ls

# Plot the equally spaced points
ps = C.(ts)
xs = [p[1] for p in ps]
ys = [p[2] for p in ps]
plot(C, aspectratio=:equal)
scatter!(xs, ys)

First plot
non-equally-spaced-points

Second plot
equally-spaced-points

@tomerarnon
Copy link
Author

Thanks for the info!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants