diff --git a/.github/workflows/Docs.yml b/.github/workflows/Docs.yml index 2bf1836..a35b5a7 100644 --- a/.github/workflows/Docs.yml +++ b/.github/workflows/Docs.yml @@ -40,6 +40,7 @@ jobs: julia --project=docs -e ' using Pkg Pkg.develop(PackageSpec(path=pwd())) + Pkg.develop("PDFIO") Pkg.instantiate()' - name: Run doctest run: | diff --git a/Project.toml b/Project.toml index 285bd2f..91a1d19 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ThesisArt" uuid = "6184abd9-1539-47ca-b742-6ec6f8d46641" authors = ["Benedikt V. Ehinger"] -version = "0.2.0" +version = "0.3.0" [deps] BSplineKit = "093aae92-e908-43d7-9660-e50ee39d5a0a" @@ -14,7 +14,7 @@ RollingFunctions = "b0e4dd01-7b14-53d8-9b45-175a3e362653" Makie = "0.21" MakieCore = "0.8" BSplineKit = "0.17" -PDFIO = "0.1" +PDFIO = "0.1.14" RollingFunctions = "0.8" julia = "1" diff --git a/docs/Project.toml b/docs/Project.toml index 56b4933..c1d226c 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -3,6 +3,7 @@ CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589" +PDFIO = "4d0d745f-9d9a-592e-8d18-1ad8a0f42b92" ThesisArt = "6184abd9-1539-47ca-b742-6ec6f8d46641" [compat] diff --git a/docs/src/02-textonpath.md b/docs/src/02-textonpath.md index 6805cc4..fb81142 100644 --- a/docs/src/02-textonpath.md +++ b/docs/src/02-textonpath.md @@ -1,4 +1,4 @@ -# [TextOnPath](@id init_example) +# [TextOnPath](@id textonpath) ## TextOnPath diff --git a/docs/src/03-interpolation.md b/docs/src/03-interpolation.md new file mode 100644 index 0000000..018f294 --- /dev/null +++ b/docs/src/03-interpolation.md @@ -0,0 +1,75 @@ +# [Interpolation](@id interpolate) + +## Interpolation + +```@example main +using ThesisArt +using CairoMakie +using Random +nothing #hide +``` + +Let's define a (random) shape first + +```@example main +my_points = 400 .* (rand(MersenneTwister(1),Point2f,20).-Point2f(0.5,0.5)) +nothing #hide +``` + +```@example main +scatterlines(my_points) +``` + +The lines are not that nice. Let's interpolate them + +## order setting + +```@example ax_main +my_xy_interpolated_2 =ThesisArt.rolling_interpolation(my_points;order=2) +my_xy_interpolated_4 =ThesisArt.rolling_interpolation(my_points;order=4) # default +``` + +```@example main +f = Figure() +scatterlines(f[1,1],my_xy_interpolated_2,axis=(;title="Order 2")) +scatter!(my_points,color=:red) +scatterlines(f[1,2],my_xy_interpolated_4,axis=(;title="Order 4")) +scatter!(my_points,color=:red) +f +``` + +We see left linear interpolation, right cubic interpolation. + +## subsample + +```@example main +my_xy_interpolated_20 =ThesisArt.rolling_interpolation(my_points;subsample=20) +my_xy_interpolated_5 =ThesisArt.rolling_interpolation(my_points;subsample=5) # +``` + +```@example main +f = Figure() +scatterlines(f[1,1],my_xy_interpolated_5,axis=(;title="subsample 5")) +scatter!(my_points,color=:red) +scatterlines(f[1,2],my_xy_interpolated_20,axis=(;title="subsample 20")) +scatter!(my_points,color=:red) +f +``` + +## Equalize distance + +```@example main +my_xy_interpolated_100 =ThesisArt.rolling_interpolation(my_points;subsample=100) + +my_xy_equ_10 = equalize_distance(my_xy_interpolated_100,min_dist=10) +my_xy_equ_50 = equalize_distance(my_xy_interpolated_100,min_dist=50) +``` + +```@example main +f = Figure() +scatterlines(f[1,1],my_xy_equ_10,axis=(;title="mindist 10")) +scatter!(my_points,color=:red) +scatterlines(f[1,2],my_xy_equ_50,axis=(;title="mindist 50")) +scatter!(my_points,color=:red) +f +``` diff --git a/src/ThesisArt.jl b/src/ThesisArt.jl index 894ed6a..fbf6efc 100644 --- a/src/ThesisArt.jl +++ b/src/ThesisArt.jl @@ -13,7 +13,7 @@ include("fontOnCurve.jl") export import_pdf export get_rotation -export rolling_inter2d +export rolling_interpolation, equalize_distance export add_spacer!, add_title!, newfigure export TextOnPath end diff --git a/src/interpolateCurve.jl b/src/interpolateCurve.jl index 91b8e7e..350e33a 100644 --- a/src/interpolateCurve.jl +++ b/src/interpolateCurve.jl @@ -2,22 +2,36 @@ # returns interpolator -function interp_spline(z; order = 2) +function interpolate_spline(z; order = 4) t = range(0, 1, length = length(z)) return interpolate(t, z, BSplineOrder(order), Natural()) end # returns k x more points, interpolated x/y -function interp_curve(k, x; kwargs...) - it = interp_spline(collect(x); kwargs...) +function interpolate_curve(k, x; kwargs...) + it = interpolate_spline(collect(x); kwargs...) r = range(0, 1, length = k * length(x)) r = range(0.5 - 1 / (length(x) * 2 - 2), 0.5 + 1 / (length(x) * 2 - 2), length = k) return it.(r) end -function rolling_interp(x; times = 5, winsize = 4, kwargs...) + +""" + +Interpolates in 1D or 2D using BSplineOrder(order=4) the x/y path. + +# arguments +x: Vector of Numeric, or vector of Point2f +[y: if x/y pairs are provided, will call the function on both axes individually] + +# keyword +`winsize=4`: Over how many samples the interpolation function should run. For order =4, needs to be at least 4. For higher orders you need to increase this - you might get better interpolation by raising this, but i'm not sure. +`subsample=5`: How many points to evaluate the spline on, effectively how many intermediate points to return. +`order=4` the order of the BSPline. 4 is default, 2 is linear. +""" +function rolling_interpolation(x; subsample = 5, winsize = 4, kwargs...) if length(x) == 2 - return range(x[1], x[2], length = times) + return range(x[1], x[2], length = subsample) end #if length(x)==3 #winsize =3 @@ -26,23 +40,31 @@ function rolling_interp(x; times = 5, winsize = 4, kwargs...) - return vcat(rolling(x -> interp_curve(times, x; kwargs...), x, winsize)..., x[end]) + return vcat( + rolling(x -> interpolate_curve(subsample, x; kwargs...), x, winsize)..., + x[end], + ) end -function rolling_inter2d(x, y; minDist = 1, kwargs...) - x = rolling_interp(x; kwargs...) - y = rolling_interp(y; kwargs...) +rolling_interpolation(x::Vector{Point2f}; kwargs...) = + Point2f.(rolling_interpolation(first.(x), last.(x); kwargs...)...) + +function rolling_interpolation(x, y; kwargs...) + x = rolling_interpolation(x; kwargs...) + y = rolling_interpolation(y; kwargs...) + - #ix = 1:length(x) - return equalize_distance(x, y; minDist = minDist) + return x, y end -function equalize_distance(x, y; minDist = 1) +equalize_distance(p::Vector{Point2f}; kwargs...) = + Point2f.(equalize_distance(first.(p), last.(p); kwargs...)...) +function equalize_distance(x, y; min_dist = 1) dist = rolling(dist2, x, y, 2) sumdist = cumsum(dist) - ix = vcat(0, findall(diff(floor.(sumdist ./ minDist)) .> 0), length(x) - 1) .+ 1 - return (; :x => x[ix], :y => y[ix]) + ix = vcat(0, findall(diff(floor.(sumdist ./ min_dist)) .> 0), length(x) - 1) .+ 1 + return x[ix], y[ix] end function dist2(x, y) return sqrt((x[1] - x[2])^2 + (y[1] - y[2])^2)