Skip to content

Commit 8fbc3ba

Browse files
committed
cosmetic i need to stop
1 parent 6fe650f commit 8fbc3ba

File tree

1 file changed

+47
-61
lines changed

1 file changed

+47
-61
lines changed

examples/NDLPwriteup.jl

Lines changed: 47 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ The most common alternative is to construct a re-parameterization for the curve
2424
2525
In this notebook we propose Normal-Deviation–Limited Parameterization (NDLP) which embeds a pointwise geometric deviation bound in the parameterization using the curve's normal acceleration. The resulting segmentation has smoothly varying density and exhibits a maximum deviation from the curve which is tightly bound to a prescribed tolerance, enforcing the bound while minimizing the number of segments. This is achieved without iteration or heuristic tuning - a true one-shot method.
2626
27-
All results below are fully reproducible. Click the "Download as Pluto notebook" button at the top right to run locally.
27+
> All results below are fully reproducible. Click the `Edit or run this notebook` button at the top right.
2828
2929
## Key idea
3030
@@ -62,7 +62,7 @@ These are deliberately chosen to expose both strengths and failure modes of the
6262
begin
6363
cx = CubicSpline([0, 0, 2, 2, 1/6, 0],range(0,1,6))
6464
cy = CubicSpline([0, 1/2, -2/3, 3/4, -1/3, 0],range(0,1,6))
65-
r_spline(u) = SA[cx(u), cy(u)]
65+
fish_spline(u) = SA[cx(u), cy(u)]
6666

6767
test_curves = [
6868
# C∞ smooth, constant curvature
@@ -74,7 +74,7 @@ begin
7474
notes="Smoothly varying κ"),
7575

7676
# cubic spline fish
77-
(;name="Spline fish", r=r_spline, range=(0, 1),
77+
(;name="Spline fish", r=fish_spline, range=(0, 1),
7878
notes="Highly uneven curvature and spacing distribution. Delicious"),
7979

8080
# 3D helix with varying pitch & radius
@@ -85,13 +85,11 @@ begin
8585
(;name="V-shape", r=u->u<1 ? SA[u, u] : SA[u, 2-u], range=(0, 2.25),
8686
notes="Corner at u=1, violates smoothness assumption")
8787
]
88+
plot(); for (name,r,range,_) in test_curves
89+
plot!(t->r(t)[1],t->r(t)[2],range...,label=name)
90+
end; plot!(aspect_ratio=:equal,xlabel="x",ylabel="y")
8891
end
8992

90-
# ╔═╡ 957d0951-2070-4d64-8fc9-58b5121bdfc1
91-
plot(); for (name,r,range,_) in test_curves
92-
plot!(t->r(t)[1],t->r(t)[2],range...,label=name)
93-
end; plot!(aspect_ratio=:equal,xlabel="x",ylabel="y")
94-
9593
# ╔═╡ 10b2e0b0-f373-4a02-b6dc-fd1085b1f34a
9694
md"""
9795
## Segmentation methods
@@ -132,27 +130,28 @@ Note that while the deviation estimate that is the basis of this parameterizatio
132130

133131
# ╔═╡ 219826fb-5362-46f2-bf51-84465e614269
134132
md"""
135-
### Results
133+
## Method evaluation results
136134
137135
We evaluate each method on the test curves defined above, using a maximum segment length of $\Delta s=L/33$ and a deviation limit of $d_n=1/100$. The results are summarized in the tables below, reporting the following metrics:
138136
- `δ∞`=$\max(\delta)/(d_n\Delta s)$: the scaled normal deviation (target is 1),
139137
- `σ`=$N\Delta s/L-1$: the scaled number of extra segments needed to hit the deviation limit (lower is better),
140138
- `Rₜᵥ`=$\sum(R)/L$ where $R_i=|Δl_{i+1}-Δl_i|$: the scaled total variation of segment lengths (lower is better),
141139
- `R∞`=$\max(R)/\Delta s$: the scaled maximum variation of segment lengths (lower is better).
142140
143-
The NDLP segmentation consistently produces a max deviation which is tight to the prescribed limit, resulting in minimal excess segments, outperforming both adaptive subdivision and curvature-weighted sampling. In particular the deviation from NDLP sampling is within 4% of the deviation limit, while the curvature weighted method has a ±20% variation **even after tuning**, and the subdivision method can be up to 50% oversampled. Adjacent segment lengths under NDLP sampling differ by at most $O(\Delta s)$, indicating Lipschitz-continuous spacing adaptation with respect to arclength.
141+
The NDLP segmentation consistently produces a max deviation which is tight to the prescribed limit, resulting in minimal excess segments, outperforming both adaptive subdivision and curvature-weighted sampling. In particular the deviation from NDLP sampling is within 4% of the deviation limit, while the curvature weighted method has a ±20% variation **even after tuning**, and the subdivision method can be up to 50% oversampled. Adjacent segment lengths under NDLP sampling differ by at most $O(\Delta s)$, indicating Lipschitz-continuous spacing adaptation with respect to arclength.
144142
"""
145143

146144
# ╔═╡ b38c2b1c-a48c-4f1f-954b-95faaba680d7
147-
begin # sample `r` using `method`, and report metrics
145+
begin
148146
function metrics(method, r, u₀, u₁, Δs, dₙ)
149-
L = quadgk(arcspeed(r), u₀, u₁)[1]; Δs *= L
150-
u = method(r, u₀, u₁, Δs, dₙ)
151-
dl,δ = seg_len(r,u),seg_dev(r,u)
152-
(;δ∞ = maximum(δ)/(Δs*dₙ), # scaled max deviation, should => 1!
153-
σ = length(δ)*Δs/L-1, # extra segments needed to hit dₙ
154-
Rₜᵥ = sum(abs,diff(dl))/L, # total variation of segment length
155-
R∞ = maximum(abs,diff(dl))/Δs) # max variation of segment length
147+
L = seg_len(r, u₀, u₁) # total length of curve `r`
148+
Δs *= L # scale by L to compare across curves
149+
u = method(r, u₀, u₁, Δs, dₙ) # sample points using `method`
150+
dl,δ = seg_len(r,u),seg_dev(r,u) # segment lengths and deviations
151+
return (;δ∞ = maximum(δ)/(Δs*dₙ), # scaled max deviation, should => 1!
152+
σ = length(δ)*Δs/L-1, # extra segments needed to hit dₙ
153+
Rₜᵥ = sum(abs, diff(dl))/L, # total variation of segment length
154+
R∞ = maximum(abs, diff(dl))/Δs) # max variation of segment length
156155
end
157156

158157
# segment metrics
@@ -210,31 +209,26 @@ end
210209
211210
# ╔═╡ 60fc45b3-8cea-4cae-83f4-9c05011b1dee
212211
plot(); let
213-
c = test_curves[3]; x(u) = c.r(u)[1]; y(u) = c.r(u)[2]
214-
for f in (κ_weighted,subdivision,NDLP)
215-
u = f(c.r,c.range...,1/4,0.09)
216-
δ = maximum(seg_dev(c.r,u))
217-
plot!(x.(u),y.(u),label="$f, N=$(length(u)), max dev=$(round(δ,sigdigits=2))",marker=:circle)
212+
x(u) = fish_spline(u)[1]; y(u) = fish_spline(u)[2]; range=(0,1)
213+
Δs = 1/4; dₙ = 0.09
214+
for method in (subdivision,κ_weighted,NDLP)
215+
u = method(fish_spline,range...,Δs,dₙ)
216+
δ = maximum(seg_dev(fish_spline,u))
217+
plot!(x.(u),y.(u),label="$method, N=$(length(u)-1), max dev=$(round(δ,sigdigits=2))",marker=:circle)
218218
end
219219
end; plot!(aspect_ratio=:equal,xlabel="x",ylabel="y")
220220
221-
# ╔═╡ 0394397a-1198-444b-9340-b3b737e1b638
222-
Δs = 1/33; dₙ = 1/100;
223-
224221
# ╔═╡ f7a8cdf1-2cdb-4d6b-a10f-3f2d980c836e
225-
map(test_curves) do (name, r, range, _)
226-
(;name,metrics(subdivision,r,range...,Δs,dₙ)...)
227-
end |> Table |> display
228-
229-
# ╔═╡ 11a078e6-0eca-49c2-84d6-829b4b9351f8
230-
map(test_curves) do (name, r, range, _)
231-
(;name,metrics(κ_weighted,r,range...,Δs,dₙ)...)
232-
end |> Table |> display
233-
234-
# ╔═╡ 30dbf23a-1ac7-47f3-9a8f-11fb1712366c
235-
map(test_curves) do (name, r, range, _)
236-
(;name,metrics(NDLP,r,range...,Δs,dₙ)...)
237-
end |> Table |> display
222+
let
223+
invΔs = 33; dₙ = 1/100; # held constant for all methods/test_curves
224+
println("Metrics using Δs = L/$invΔs and dₙ=$dₙ")
225+
for method in (subdivision,κ_weighted,NDLP)
226+
println("\nMethod: $method")
227+
map(test_curves) do (name, r, range, _)
228+
(;name,metrics(method,r,range...,1/invΔs,dₙ)...)
229+
end |> Table |> display
230+
end
231+
end
238232
239233
# ╔═╡ 561a1373-57a4-4b67-be5a-9d94c9496360
240234
md"""
@@ -247,19 +241,18 @@ Holding $d_n=1\%$ constant and *reducing* $\Delta s$ shows two distance phases.
247241
- In the second phase the deviation limit is no longer active, so $\max(\delta)$ goes to zero without any additional segments or any length variation.
248242
"""
249243
250-
# ╔═╡ 1273c8c7-20b9-42c0-9b0d-d9bb8db57ec2
251-
convergeΔs = map(logrange(1e-1,1e-4,70)) do Δs
252-
(;Δs,metrics(NDLP,test_curves[3].r,test_curves[3].range...,Δs,1e-2)...)
253-
end |> Table;
254-
255244
# ╔═╡ dcb68886-2771-4b37-91b6-9c983e118728
256-
begin
245+
let
246+
dₙ = 1e-2
247+
convergeΔs = map(logrange(1e-1,1e-4,70)) do Δs
248+
(;Δs,metrics(NDLP,fish_spline,0,1,Δs,dₙ)...)
249+
end |> Table
257250
plot(convergeΔs.Δs,convergeΔs.δ∞,label="max(δ)/dₙΔs")
258251
plot!(convergeΔs.Δs,convergeΔs.σ,label="NΔs/L-1")
259252
plot!(convergeΔs.Δs,convergeΔs.Rₜᵥ,label="sum(R)/L")
260253
plot!(convergeΔs.Δs,convergeΔs.R∞,label="max(R)/Δs")
261254
plot!(ylabel="scaled metrics",xlabel="Δs",xscale=:log10,xflip=true)
262-
plot!(title="NDLP segmentation metrics with fixed dₙ=1%")
255+
plot!(title="NDLP segmentation metrics with fixed dₙ=$dₙ")
263256
end
264257
265258
# ╔═╡ 67eba604-640b-4388-bc08-928f4e5e62ca
@@ -269,19 +262,18 @@ Holding $\Delta s=L/100$ and _increasing_ $d_n$ shows a similar trend.
269262
- In the second phase, the $d_n$ limit deactivates, letting $\max(\delta)$ scaled by $d_n$ and $\max(R)$ both drop to zero as the sampling becomes uniformly spaced.
270263
"""
271264
272-
# ╔═╡ 260406ec-97ff-49fc-bb17-4f28fe12b8b6
273-
convergedₙ = map(logrange(1,5e-4,100)) do dₙ
274-
(;dₙ,metrics(NDLP,test_curves[3].r,test_curves[3].range...,1e-2,dₙ)...)
275-
end |> Table;
276-
277265
# ╔═╡ f67fc432-8031-4230-899b-b24fcb7b44f4
278-
begin
266+
let
267+
invΔs = 100
268+
convergedₙ = map(logrange(1,5e-4,100)) do dₙ
269+
(;dₙ,metrics(NDLP,fish_spline,0,1,1/invΔs,dₙ)...)
270+
end |> Table
279271
plot(convergedₙ.dₙ,convergedₙ.δ∞,label="max(δ)/dₙΔs")
280272
plot!(convergedₙ.dₙ,convergedₙ.σ,label="NΔs/L-1")
281273
plot!(convergedₙ.dₙ,convergedₙ.Rₜᵥ,label="sum(R)/L")
282274
plot!(convergedₙ.dₙ,convergedₙ.R∞,label="max(R)/Δs")
283275
plot!(ylabel="scaled metrics",xlabel="dₙ",xscale=:log10)
284-
plot!(title="NDLP segmentation metrics with fixed Δs=L/100")
276+
plot!(title="NDLP segmentation metrics with fixed Δs=L/$invΔs")
285277
end
286278
287279
# ╔═╡ 6094d19e-e64a-4434-b6db-e5647fd71e78
@@ -1789,20 +1781,14 @@ version = "1.13.0+0"
17891781
# ╟─60fc45b3-8cea-4cae-83f4-9c05011b1dee
17901782
# ╟─e1bc7e76-a497-41db-8f91-b8912e359e0e
17911783
# ╟─28abbec4-f1ea-4edb-8bd7-bcdc63c7cd82
1792-
# ╟─957d0951-2070-4d64-8fc9-58b5121bdfc1
17931784
# ╟─10b2e0b0-f373-4a02-b6dc-fd1085b1f34a
1794-
# ╟─cc1fa09e-21da-425d-bb6c-a8c906a65e98
1785+
# ╠═cc1fa09e-21da-425d-bb6c-a8c906a65e98
17951786
# ╟─219826fb-5362-46f2-bf51-84465e614269
17961787
# ╠═b38c2b1c-a48c-4f1f-954b-95faaba680d7
1797-
# ╠═0394397a-1198-444b-9340-b3b737e1b638
1798-
# ╠═f7a8cdf1-2cdb-4d6b-a10f-3f2d980c836e
1799-
# ╠═11a078e6-0eca-49c2-84d6-829b4b9351f8
1800-
# ╠═30dbf23a-1ac7-47f3-9a8f-11fb1712366c
1788+
# ╟─f7a8cdf1-2cdb-4d6b-a10f-3f2d980c836e
18011789
# ╟─561a1373-57a4-4b67-be5a-9d94c9496360
1802-
# ╠═1273c8c7-20b9-42c0-9b0d-d9bb8db57ec2
18031790
# ╟─dcb68886-2771-4b37-91b6-9c983e118728
18041791
# ╟─67eba604-640b-4388-bc08-928f4e5e62ca
1805-
# ╠═260406ec-97ff-49fc-bb17-4f28fe12b8b6
18061792
# ╟─f67fc432-8031-4230-899b-b24fcb7b44f4
18071793
# ╟─6094d19e-e64a-4434-b6db-e5647fd71e78
18081794
# ╟─00000000-0000-0000-0000-000000000001

0 commit comments

Comments
 (0)