Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"

[extensions]
RotationsMakieExt = "Makie"
RotationsRecipesBaseExt = "RecipesBase"

[compat]
Expand All @@ -21,6 +22,7 @@ BenchmarkTools = "1"
ForwardDiff = "0.10"
InteractiveUtils = "1"
LinearAlgebra = "1"
Makie = "0.24"
Plots = "1"
Quaternions = "0.5.3, 0.6, 0.7"
Random = "1"
Expand All @@ -36,6 +38,7 @@ BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Quaternions = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Expand Down
130 changes: 130 additions & 0 deletions ext/RotationsMakieExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
module RotationsMakieExt

using Rotations
using Makie
using StaticArrays

Makie.plottype(::Rotation{2}) = Rotation2Plot
Makie.plottype(::Rotation{3}) = Rotation3Plot

@recipe Rotation2Plot (rot::Rotation{2},) begin
begin
arrows_attributes = Makie.documented_attributes(Arrows2D)
filter!(a -> a.first ∉ [:color], arrows_attributes.d)
arrows_attributes
end...
"Origin point for the 2D rotation visualization"
origin = SVector(0, 0)
"Size of the reference square"
boxsize = 0.2
"Length of the axis lines"
axissize = 1.0
"Colours for the two axes (x, y)"
axiscolors = [:red, :green]
"Colour of the reference square"
boxcolor = :gray
end

function Makie.plot!(p::Rotation2Plot{<:Tuple{<:Rotation{2}}})
# Use ComputationPipeline for dynamic updates
map!(p.attributes, [:rot, :origin, :boxsize, :axissize], [:arrows_origin, :arrows1_end, :arrows2_end, :box_points]) do rot, origin, l, L
e₁ = rot[:, 1]
e₂ = rot[:, 2]
ox, oy = origin

# Compute box corners
box_points = [Point2f(ox, oy) + rot * Point2f(x, y) for x in (-l, l) for y in (-l, l)][[1, 2, 4, 3]]

return (Point2f(ox, oy), Point2f(ox + L * e₁[1], oy + L * e₁[2]), Point2f(ox + L * e₂[1], oy + L * e₂[2]), box_points)
end

map!(p.attributes, [:axiscolors], [:arrows1_color, :arrows2_color]) do axiscolors
(axiscolors[1], axiscolors[2])
end

arrows2d!(p, p.attributes, p.arrows_origin, p.arrows1_end; color=p.arrows1_color)
arrows2d!(p, p.attributes, p.arrows_origin, p.arrows2_end; color=p.arrows2_color)
poly!(p, p.attributes, p.box_points; color=p.boxcolor)

return p
end

@recipe Rotation3Plot (rot::Rotation{3},) begin
begin
arrows_attributes = Makie.documented_attributes(Arrows3D)
filter!(a -> a.first ∉ [:color], arrows_attributes.d)
arrows_attributes
end...
"Origin point for the 3D rotation visualization"
origin = SVector(0, 0, 0)
"Size of the reference cube"
boxsize = 0.2
"Length of the axis lines"
axissize = 1.0
"Colours for the three axes (x, y, z)"
axiscolors = [:red, :green, :blue]
"Colour of the reference cube faces"
boxcolor = :gray
"Colour of cube edges"
edgecolor = :black
end

function Makie.plot!(p::Rotation3Plot{<:Tuple{<:Rotation{3}}})
# Use ComputationPipeline for dynamic updates
map!(p.attributes, [:rot, :origin, :boxsize, :axissize], [:arrows_origin, :arrows1_end, :arrows2_end, :arrows3_end, :cube_points, :cube_faces, :cube_edges]) do rot, origin, l, L
e₁ = rot[:, 1]
e₂ = rot[:, 2]
e₃ = rot[:, 3]
ox, oy, oz = origin

# Compute cube vertices
cube_points = [Point3f(ox, oy, oz) + rot * Point3f(x, y, z) for x in (-l, l) for y in (-l, l) for z in (-l, l)]

# Define cube faces (triangulated)
cube_faces = [
1, 2, 4, 4, 3, 1, # bottom
5, 6, 8, 8, 7, 5, # top
1, 2, 6, 6, 5, 1, # front
3, 4, 8, 8, 7, 3, # back
1, 3, 7, 7, 5, 1, # left
2, 4, 8, 8, 6, 2 # right
]

# Define cube edges for wireframe
cube_edges = [
# Bottom face edges
cube_points[1], cube_points[2], cube_points[2], cube_points[4],
cube_points[4], cube_points[3], cube_points[3], cube_points[1],
# Top face edges
cube_points[5], cube_points[6], cube_points[6], cube_points[8],
cube_points[8], cube_points[7], cube_points[7], cube_points[5],
# Vertical edges
cube_points[1], cube_points[5], cube_points[2], cube_points[6],
cube_points[3], cube_points[7], cube_points[4], cube_points[8]
]

return (
Point3f(ox, oy, oz),
Point3f(ox + L * e₁[1], oy + L * e₁[2], oz + L * e₁[3]),
Point3f(ox + L * e₂[1], oy + L * e₂[2], oz + L * e₂[3]),
Point3f(ox + L * e₃[1], oy + L * e₃[2], oz + L * e₃[3]),
cube_points, cube_faces, cube_edges
)
end

map!(p.attributes, [:axiscolors], [:arrows1_color, :arrows2_color, :arrows3_color]) do axiscolors
(axiscolors[1], axiscolors[2], axiscolors[3])
end

arrows3d!(p, p.attributes, p.arrows_origin, p.arrows1_end, color=p.arrows1_color)
arrows3d!(p, p.attributes, p.arrows_origin, p.arrows2_end, color=p.arrows2_color)
arrows3d!(p, p.attributes, p.arrows_origin, p.arrows3_end, color=p.arrows3_color)
mesh!(p, p.attributes, p.cube_points, p.cube_faces; color=p.boxcolor)
linesegments!(p, p.attributes, p.cube_edges; color=p.edgecolor)

return p
end

Makie.preferred_axis_type(::Rotation3Plot) = Makie.Axis3

end