Skip to content

Commit d3fe01d

Browse files
authored
Add plotting recipes (#284)
* update Project.toml for RecipesBase * add RotationsRecipesBaseExt * update plotting recipe for `Rotation{3}` * fix ext dependency * update for Julia v1.6 * add support recipe for `Rotation{2}` * add tests for plotting recipe * update axis color
1 parent 62da0eb commit d3fe01d

File tree

6 files changed

+127
-1
lines changed

6 files changed

+127
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
perf/benchmarkparams.json
55
Manifest.toml
66
docs/build
7+
/test/out_plot

Project.toml

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,25 @@ version = "1.6.2"
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
77
Quaternions = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0"
88
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
9+
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
910
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1011

12+
[weakdeps]
13+
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
14+
15+
[extensions]
16+
RotationsRecipesBaseExt = "RecipesBase"
17+
1118
[compat]
1219
Aqua = "0.8"
1320
BenchmarkTools = "1"
1421
ForwardDiff = "0.10"
1522
InteractiveUtils = "1"
1623
LinearAlgebra = "1"
24+
Plots = "1"
1725
Quaternions = "0.5.3, 0.6, 0.7"
1826
Random = "1"
27+
RecipesBase = "1"
1928
StaticArrays = "1.2.12"
2029
Test = "1"
2130
Unitful = "1"
@@ -27,11 +36,12 @@ BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
2736
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
2837
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
2938
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
39+
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
3040
Quaternions = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0"
3141
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
3242
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
3343
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
3444
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
3545

3646
[targets]
37-
test = ["Aqua", "BenchmarkTools", "ForwardDiff", "InteractiveUtils", "LinearAlgebra", "Quaternions", "Random", "StaticArrays", "Test", "Unitful"]
47+
test = ["Aqua", "BenchmarkTools", "ForwardDiff", "InteractiveUtils", "LinearAlgebra", "Plots", "Quaternions", "Random", "StaticArrays", "Test", "Unitful"]

ext/RotationsRecipesBaseExt.jl

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
module RotationsRecipesBaseExt
2+
3+
using RecipesBase
4+
using Rotations
5+
using StaticArrays
6+
7+
@recipe function f(R::Rotation{2}; origin=SVector(0,0), boxsize=0.2, axissize=1.0)
8+
l = boxsize
9+
L = axissize
10+
e₁ = R[:,1]
11+
e₂ = R[:,2]
12+
ox, oy = origin
13+
ps = vec([SVector(ox,oy)+R*SVector(x,y) for x in (-l,l), y in (-l,l)])
14+
xs = getindex.(ps,1)
15+
ys = getindex.(ps,2)
16+
@series begin
17+
primary := false
18+
color := :red1
19+
[e₁[1]*l+ox,e₁[1]*L+ox],[e₁[2]*l+oy,e₁[2]*L+oy]
20+
end
21+
@series begin
22+
primary := false
23+
color := :green1
24+
[e₂[1]*l+ox,e₂[1]*L+ox],[e₂[2]*l+oy,e₂[2]*L+oy]
25+
end
26+
fill := true
27+
delete!(plotattributes, :origin)
28+
delete!(plotattributes, :boxsize)
29+
delete!(plotattributes, :axissize)
30+
xs[[1,3,4,2,1]], ys[[1,3,4,2,1]]
31+
end
32+
33+
@recipe function f(R::Rotation{3}; origin=SVector(0,0,0), boxsize=0.2, axissize=1.0)
34+
l = boxsize
35+
L = axissize
36+
e₁ = R[:,1]
37+
e₂ = R[:,2]
38+
e₃ = R[:,3]
39+
ox, oy, oz = origin
40+
ps = vec([SVector(ox,oy,oz)+R*SVector(x,y,z) for x in (-l,l), y in (-l,l), z in (-l,l)])
41+
xs = getindex.(ps,1)
42+
ys = getindex.(ps,2)
43+
zs = getindex.(ps,3)
44+
@series begin
45+
primary := false
46+
color := :red1
47+
[e₁[1]*l+ox,e₁[1]*L+ox],[e₁[2]*l+oy,e₁[2]*L+oy],[e₁[3]*l+oz,e₁[3]*L+oz]
48+
end
49+
@series begin
50+
primary := false
51+
color := :green1
52+
[e₂[1]*l+ox,e₂[1]*L+ox],[e₂[2]*l+oy,e₂[2]*L+oy],[e₂[3]*l+oz,e₂[3]*L+oz]
53+
end
54+
@series begin
55+
primary := false
56+
color := :blue1
57+
[e₃[1]*l+ox,e₃[1]*L+ox],[e₃[2]*l+oy,e₃[2]*L+oy],[e₃[3]*l+oz,e₃[3]*L+oz]
58+
end
59+
seriestype := :mesh3d
60+
connections := (
61+
# Somehow 0-based indexing
62+
# https://docs.juliaplots.org/latest/gallery/gr/generated/gr-ref047/
63+
[1-1,1-1,1-1,1-1,1-1,1-1,8-1,8-1,8-1,8-1,8-1,8-1,],
64+
[2-1,6-1,4-1,3-1,7-1,5-1,4-1,3-1,7-1,5-1,6-1,2-1,],
65+
[6-1,5-1,2-1,4-1,3-1,7-1,3-1,7-1,5-1,6-1,2-1,4-1,],
66+
)
67+
# This connections can be 1-based indexing, but this throws an error on PythonPlot.
68+
# https://discourse.julialang.org/t/how-to-plot-a-cube-in-3d-in-plots-jl/86919/2?u=hyrodium
69+
# connections := [(1,2,6),(1,6,5),(1,4,2),(1,3,4),(1,7,3),(1,5,7),(8,4,3),(8,3,7),(8,7,5),(8,5,6),(8,6,2),(8,2,4)]
70+
delete!(plotattributes, :origin)
71+
delete!(plotattributes, :boxsize)
72+
delete!(plotattributes, :axissize)
73+
xs,ys,zs
74+
end
75+
76+
end

src/Rotations.jl

+4
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,8 @@ export
7878
# derivatives (names clash with ForwarDiff?)
7979
#jacobian, hessian
8080

81+
if !isdefined(Base, :get_extension)
82+
include("../ext/RotationsRecipesBaseExt.jl")
83+
end
84+
8185
end # module

test/plots.jl

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
@testset "plot" begin
2+
dir_out = joinpath(@__DIR__, "out_plot")
3+
rm(dir_out; force=true, recursive=true)
4+
mkpath(dir_out)
5+
6+
@testset "2d" begin
7+
pl = plot(Angle2d(0.2); aspectratio=1)
8+
plot!(pl, Angle2d(0.3); aspectratio=1)
9+
10+
path_img = joinpath(dir_out, "2d.png")
11+
@test !isfile(path_img)
12+
savefig(pl, path_img)
13+
@test isfile(path_img)
14+
end
15+
16+
@testset "3d" begin
17+
N = 12
18+
Random.seed!(42)
19+
R1 = rand(QuatRotation)
20+
R2 = rand(QuatRotation)
21+
pl = plot(R1; linewidth=3, label="R1")
22+
plot!(pl, R2; linewidth=3, label="R2", origin=(1,0,0))
23+
for i in 2:N-1
24+
t = i/N
25+
plot!(pl, slerp(R1,R2,t); linewidth=3, label=nothing, origin=(t,0,0), boxsize=0.0, axissize=3/4)
26+
end
27+
28+
path_img = joinpath(dir_out, "3d.png")
29+
@test !isfile(path_img)
30+
savefig(pl, path_img)
31+
@test isfile(path_img)
32+
end
33+
end

test/runtests.jl

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ using StaticArrays
55
using InteractiveUtils: subtypes
66
using Quaternions
77
using Aqua
8+
using Plots
89
import Unitful
910
import Random
1011

@@ -25,5 +26,6 @@ include("nearest_rotation.jl")
2526
include("rotation_generator.jl")
2627
include("elementary_functions.jl")
2728
include("deprecated.jl")
29+
include("plots.jl")
2830

2931
include(joinpath(@__DIR__, "..", "perf", "runbenchmarks.jl"))

0 commit comments

Comments
 (0)