Skip to content

Commit 5fa00fe

Browse files
committed
Implement efficient sampling of curves.
1 parent 24874b4 commit 5fa00fe

15 files changed

+68
-7
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Curve Interface:
3131
* `startpoint(C)`
3232
* `endpoint(C)`
3333
* `dpoint(C, s)`
34+
* `samples(C, e)`
3435

3536
All derivatives are given in respect to the parameter `s`.
3637

docs/src/api.md

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ PolyCurve
3333
[`dcurvature`](@ref)\
3434
[`tangentangle`](@ref)\
3535
[`radialangle`](@ref)\
36+
[`samples`](@ref)\
3637

3738
```@docs
3839
smax
@@ -46,6 +47,7 @@ curvature
4647
dcurvature
4748
tangentangle
4849
radialangle
50+
samples
4951
```
5052

5153
## Curve specific functions

docs/src/curve.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@
1515
[`curvature`](@ref)\
1616
[`dcurvature`](@ref)\
1717
[`tangentangle`](@ref)\
18-
[`radialangle`](@ref)
18+
[`radialangle`](@ref)\
19+
[`samples`](@ref)

docs/src/index.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ and the possibility to chain them together as [PolyCurve](@ref). All curves impl
2020
[`curvature`](@ref)\
2121
[`dcurvature`](@ref)\
2222
[`tangentangle`](@ref)\
23-
[`radialangle`](@ref)
23+
[`radialangle`](@ref)\
24+
[`samples`](@ref)
2425

2526
Additionally, [Construction](@ref) methods which generate smooth curves from given polygon paths are provided.
2627

src/SmoothCurves.jl

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export Curve, Pose, LineSegment, ArcSegment, Clothoid, PolyCurve,
99
curvature_unchecked, dcurvature_unchecked,
1010
point, dpoint, startpoint, endpoint,
1111
point_unchecked, dpoint_unchecked,
12+
samples,
1213
direction,
1314
frenet,
1415
construction

src/arcsegment.jl

+5
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,8 @@ function dpoint_unchecked(C::ArcSegment, Δϕ::Real)
4848
ϕ = radialangle(C, Δϕ)
4949
C.radius*sign(C)*SVector(-sin(ϕ), cos(ϕ))
5050
end
51+
52+
function samples(C::ArcSegment, e::Real)
53+
n = max(1, ceil(Int, abs(C.angle1 - C.angle0)/e)) + 2
54+
return collect(range(0, stop=abs(C.angle1-C.angle0), length=n))
55+
end

src/clothoid.jl

+18
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,21 @@ function dpoint_unchecked(C::Clothoid, s::Real)
126126
dy = sin(C.λ*l_^2)
127127
return rotate2d(C.rotation, dx, dy)
128128
end
129+
130+
function samples(C::Clothoid, e::Real)
131+
if C.l0==0
132+
θmax = C.λ*standardlength(C, smax(C))^2
133+
n = ceil(Int, max(2, abs(θmax/e))) + 1
134+
θvec = range(0, stop=θmax, length=n)
135+
lvec = sqrt.(abs.(θvec/C.λ))
136+
return lvec
137+
elseif C.l1==0
138+
θmax = C.λ*standardlength(C, 0)^2
139+
n = ceil(Int, max(2, abs(θmax/e))) + 1
140+
θvec = range(θmax, stop=0, length=n)
141+
lvec = sqrt.(abs.(θvec/C.λ))
142+
return -lvec .- C.l0
143+
else
144+
error("Not implemented")
145+
end
146+
end

src/curve.jl

+7
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,13 @@ Return the last point ``C(s_\\mathrm{max}`` of the curve.
127127
"""
128128
endpoint(C::Curve) = point_unchecked(C, smax(C))
129129

130+
"""
131+
samples(C::Curve, e::Real)
132+
133+
Distribute values between 0 and smax in order to generate a "smooth" polygon.
134+
"""
135+
samples(C::Curve, e::Real) = error("Not Implemented")
136+
130137

131138
struct Pose
132139
x::Float64

src/linesegment.jl

+2
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,5 @@ dpoint_unchecked(C::LineSegment, s::Real) = direction(C)
5151

5252
startpoint(C::LineSegment) = C.p0
5353
endpoint(C::LineSegment) = C.p1
54+
55+
samples(C::LineSegment, e::Real) = Float64[0., smax(C)]

src/plotrecipes.jl

+6-4
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ import .Pose
2121
end
2222
end
2323

24-
@recipe function f(curve::Curve; spacing=0.1)
24+
@recipe function f(curve::Curve; e=0.01)
2525
aspect_ratio --> :equal
2626
label --> ""
2727

28-
n = round(Int, length(curve)/spacing, RoundUp)
29-
svec = range(0., stop=smax(curve), length=n)
30-
points = point.(curve, svec)
28+
# n = round(Int, length(curve)/spacing, RoundUp)
29+
# svec = range(0., stop=smax(curve), length=n)
30+
# points = point.(curve, svec)
31+
32+
points = point.(curve, samples(curve, e))
3133
[p[1] for p in points], [p[2] for p in points]
3234
end

src/polycurve.jl

+8
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,11 @@ curvature_unchecked(C::PolyCurve, s::Real) = dispatch(curvature_unchecked, C, s)
7676
dcurvature_unchecked(C::PolyCurve, s::Real) = dispatch(dcurvature_unchecked, C, s)
7777
startpoint(C::PolyCurve) = startpoint(C.curves[1])
7878
endpoint(C::PolyCurve) = endpoint(C.curves[end])
79+
80+
function samples(C::PolyCurve, e::Real)
81+
svec = samples(C.curves[1], e)
82+
for i=2:length(C.curves)
83+
append!(svec, samples(C.curves[i], e)[2:end] .+ C.cum_smax[i-1])
84+
end
85+
svec
86+
end

test/curvefunctions_testsuite.jl

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using Test
22
import SmoothCurves
33

4-
using LinearAlgebra: norm, dot
4+
using LinearAlgebra: norm, normalize, dot
55

66
using ForwardDiff
77

@@ -57,4 +57,13 @@ function test_curvefunctions(C::SmoothCurves.Curve)
5757
# Test dcurvature
5858
@test dcurvature(s) d_ds(curvature, s) atol=1e-13
5959
end
60+
61+
for maxangle=0.1:0.1:1
62+
svec = samples(C, maxangle)
63+
for i=1:Base.length(svec)-1
64+
v0 = dpoint(svec[i])
65+
v1 = dpoint(svec[i+1])
66+
@test dot(normalize(v0), normalize(v1)) >= cos(maxangle)
67+
end
68+
end
6069
end

test/test_curve.jl

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ s = 0.25
3333
@test_throws ErrorException dpoint(C, s)
3434
@test_throws ErrorException startpoint(C)
3535
@test_throws ErrorException endpoint(C)
36+
@test_throws ErrorException samples(C, 0.1)
3637

3738
s = 0.75
3839
@test_throws ArgumentError length(C, s)

test/test_linesegment.jl

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ l = LineSegment([1, 2], [4, 6])
66
@test point(l, 0) == [1, 2]
77
@test point(l, smax(l)) == [4, 6]
88
@test length(l) 5
9+
@test samples(l, 0.1) [0., smax(l)]
910
end
1011

1112
include("curvefunctions_testsuite.jl")

test/test_polycurve.jl

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ C = PolyCurve(C_l0, C_l1, C_l2)
2525
@test smax(C) == smax(C_l0) + smax(C_l1) + smax(C_l2)
2626
@test length(C) == length(C_l0) + length(C_l1) + length(C_l2)
2727
@test length(C, smax(C)) == length(C)
28+
29+
@test samples(C, 0.01) == [0, smax(C_l0), smax(C_l0)+smax(C_l1), smax(C)]
2830
end
2931

3032
C_arc = ArcSegment([1, 3], 2., 0., π)

0 commit comments

Comments
 (0)