Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add vertical orientation option to Toggle #4445

Closed
wants to merge 1 commit into from

Conversation

bjarthur
Copy link
Contributor

@bjarthur bjarthur commented Oct 3, 2024

Description

Fixes #4378 by adding an orientation kwarg to Toggle that defaults to :horizontal and accepts :vertical too.

Type of change

  • New feature (non-breaking change which adds functionality)

Checklist

  • Added an entry in CHANGELOG.md (for new features and breaking changes)
  • Added or changed relevant sections in the documentation
  • Added unit tests for new algorithms, conversion methods, etc.
  • Added reference image tests for new plotting functions, recipes, visual options, etc.

@bjarthur
Copy link
Contributor Author

bjarthur commented Oct 3, 2024

i think so long as the attributes section on this page of the docs get automatically updated then no further change is necessary. but happy to add more if others disagree.

@bjarthur
Copy link
Contributor Author

bjarthur commented Oct 3, 2024

ready for review!

Screenshot 2024-10-03 at 5 19 42 PM

@EdsterG
Copy link
Contributor

EdsterG commented Oct 4, 2024

I can see a world where one would want to vertical direction to be flipped. It would be cool if orientation can also be specified as an arbitrary rotation, e.g. π/2, -π/2, or even π/5 if someone really wanted. Though I suspect there is a good bit of code specialize for the horizontal case so it might be too much work to support an arbitrary rotation.

@bjarthur
Copy link
Contributor Author

bjarthur commented Oct 9, 2024

that's a great suggestion @EdsterG. thanks!

using rotate! would achieve arbitrary rotations most easly, but i can't figure out how to specify the origin about which to rotate. if i use a quaternion of 0,0,1, it rotates about the right axis, but the origin seems to be off the edge of the figure:

julia> using GLMakie

julia> f = Figure()

julia> t1 = Toggle(f[1,1])
Toggle()

julia> t2 = Toggle(f[1,1])
Toggle()

julia> rotate!(t2.blockscene, qrotation(Vec3f(0,0,1), 0.25pi))
0.9238795 + 0.0im + 0.0jm + 0.38268343km
Screenshot 2024-10-09 at 10 12 58 AM

@jkrumbiegel
Copy link
Member

I think the origin is (0, 0), you can probably translate by the negative midpoint first, then rotate, then translate back.

@bjarthur
Copy link
Contributor Author

bjarthur commented Oct 9, 2024

sorry, i should've mentioned i tried that. this

julia> bbox = t2.layoutobservables.computedbbox[]
GeometryBasics.HyperRectangle{2, Float32}(Float32[284.0, 216.0], Float32[32.0, 18.0])

julia> translate!(t2.blockscene, -bbox.origin[1]+bbox.widths[1]/2, -bbox.origin[2]+bbox.widths[2]/2)
3-element Vec{3, Float64} with indices SOneTo(3):
 -268.0
 -207.0
    0.0

results in this:

Screenshot 2024-10-09 at 1 01 29 PM

and then this makes it disappear out of the figure:

rotate!(t2.blockscene, qrotation(Vec3f(0,0,1), 0.5pi))

[EDIT: similar story even when i subtract the widths]

@asinghvi17
Copy link
Member

Ah I think you need to rotate!(Accum, ...)

@bjarthur
Copy link
Contributor Author

bjarthur commented Oct 9, 2024

nope. neither rotating with Accum with or without translating to 0,0 works.

@bjarthur
Copy link
Contributor Author

bjarthur commented Oct 9, 2024

have figured out in this one particular example how to translate the toggle after the rotation back to where it was. wish i could figure out where these numbers (525,-75) come from so i can calculate them for the general case:

julia> using GLMakie

julia> f = Figure()

julia> t1 = Toggle(f[1,1])
Toggle()

julia> t2 = Toggle(f[1,1])
Toggle()

julia> rotate!(t2.blockscene, qrotation(Vec3f(0,0,1), 0.5pi))
0.70710677 + 0.0im + 0.0jm + 0.70710677km

julia> translate!(t2.blockscene, 525, -75)
3-element Vec{3, Float64} with indices SOneTo(3):
 525.0
 -75.0
   0.0
Screenshot 2024-10-09 at 5 51 47 PM

@asinghvi17
Copy link
Member

asinghvi17 commented Oct 9, 2024

I figure it's something like this:

  • compute centerpoint of toggle in screen space (maybe just use the centroid of toggle.layoutobservables.computedbbox)
  • rotate that (manually, by multiplying with rotation matrix) by theta around (0, 0), let's call this positive_offset
  • rotate your actual toggle
  • translate!(toggle, -positive_offset...)

This approach is very fragile though, and I'm not sure if it will scale. This is the perfect example of where a full Mat4f would come in handy to indicate a model, since you can stack transformations on that.

@EdsterG
Copy link
Contributor

EdsterG commented Oct 10, 2024

This is the perfect example of where a full Mat4f would come in handy to indicate a model, since you can stack transformations on that.

+1 to this if it's not yet implemented

@ffreyer
Copy link
Collaborator

ffreyer commented Oct 10, 2024

I figure it's something like this:

* compute centerpoint of toggle in screen space (maybe just use the centroid of `toggle.layoutobservables.computedbbox`)

* rotate that (manually, by multiplying with rotation matrix) by theta around (0, 0), let's call this positive_offset

* rotate your actual toggle

* translate!(toggle, -positive_offset...)

This approach is very fragile though, and I'm not sure if it will scale. This is the perfect example of where a full Mat4f would come in handy to indicate a model, since you can stack transformations on that.

I disagree, this is an example of our transformation interface being incomplete. You can rewrite a translate-rotate-translate operation with how our transformations are defined, there is just no convenience function for it. Example:

p = rand(Point2f)
rect = Rect2f(p .- 0.1, Vec2f(0.2))

fig = Figure()
sl = Slider(fig[1, 1], range = range(0, 2pi, length=101))
ax = Axis(fig[2, 1], aspect = DataAspect())
p1 = poly!(ax, rect, color = :orange)
p2 = lines!(ax, rect, color = :red)
xlims!(ax, -1.5, 1.5)
ylims!(ax, -1.1, 1.1)

on(sl.value) do angle
    center = to_ndim(Vec3f, p, 0)

    R = Makie.rotationmatrix_z(angle)
    T = Makie.translationmatrix(-center)
    Tinv = Makie.translationmatrix(center)
    p1.transformation.model[] = Tinv * R * T # Did we break setting plot.model?
    
    R = Makie.rotationmatrix_z(angle)
    t = Point3f(R * to_ndim(Point4f, -center, 1))
    translate!(p2, center + t)
    rotate!(p2, angle)
end

fig
$$T(t) R(\phi) T(-t) p = T(t) R(\phi) (p - t) = T(t) (R(\phi) p - R(\phi) t) = T(t) T(-R(\phi) t) R p = T(t - R(\phi) t) R(\phi) p$$

@bjarthur
Copy link
Contributor Author

YES! thanks so much @ffreyer . you are my HERO!!

julia> using GLMakie

julia> f = Figure()

julia> t1 = Toggle(f[1,1])
Toggle()

julia> t2 = Toggle(f[1,1])
Toggle()

julia> bbox = t2.layoutobservables.computedbbox[]
GeometryBasics.HyperRectangle{2, Float32}(Float32[284.0, 216.0], Float32[32.0, 18.0])

julia> center = Vec3f(bbox.origin[1]+bbox.widths[1]/2, bbox.origin[2]+bbox.widths[2]/2, 0)
3-element Vec{3, Float32} with indices SOneTo(3):
 300.0
 225.0
   0.0

julia> angle = 0.5pi
1.5707963267948966

julia> R = Makie.rotationmatrix_z(angle)
4×4 StaticArraysCore.SMatrix{4, 4, Float64, 16} with indices SOneTo(4)×SOneTo(4):
 6.12323e-17  -1.0          0.0  0.0
 1.0           6.12323e-17  0.0  0.0
 0.0           0.0          1.0  0.0
 0.0           0.0          0.0  1.0

julia> T = Makie.translationmatrix(-center)
4×4 StaticArraysCore.SMatrix{4, 4, Float32, 16} with indices SOneTo(4)×SOneTo(4):
 1.0  0.0  0.0  -300.0
 0.0  1.0  0.0  -225.0
 0.0  0.0  1.0    -0.0
 0.0  0.0  0.0     1.0

julia> Tinv = Makie.translationmatrix(center)
4×4 StaticArraysCore.SMatrix{4, 4, Float32, 16} with indices SOneTo(4)×SOneTo(4):
 1.0  0.0  0.0  300.0
 0.0  1.0  0.0  225.0
 0.0  0.0  1.0    0.0
 0.0  0.0  0.0    1.0

julia> t2.blockscene.transformation.model[] = Tinv * R * T
4×4 StaticArraysCore.SMatrix{4, 4, Float64, 16} with indices SOneTo(4)×SOneTo(4):
 6.12323e-17  -1.0          0.0  525.0
 1.0           6.12323e-17  0.0  -75.0
 0.0           0.0          1.0    0.0
 0.0           0.0          0.0    1.0
Screenshot 2024-10-10 at 5 00 42 PM

that being said, a convenience function sure would be convenient :)

@bjarthur bjarthur mentioned this pull request Oct 10, 2024
5 tasks
@asinghvi17
Copy link
Member

Right - I should have sent a code example with that :D. But agreed that the interface could use some love.

Do we actually have tests for arbitrary model matrices? Would be nice to know when that fails at least. I don't personally depend on it but I imagine there might be people who do.

@bjarthur
Copy link
Contributor Author

superseded by #4471

@bjarthur bjarthur closed this Oct 10, 2024
@bjarthur bjarthur deleted the bja/togglevertical branch October 10, 2024 21:50
@ffreyer
Copy link
Collaborator

ffreyer commented Oct 10, 2024

Right - I should have sent a code example with that :D. But agreed that the interface could use some love.

Do we actually have tests for arbitrary model matrices? Would be nice to know when that fails at least. I don't personally depend on it but I imagine there might be people who do.

Probably not? I think passing a model matrix directly wasn't really supposed to be a feature. You were/are supposed to rely on translate/rotate/scale, let Transformation build your model matrix and plot.model was just supposed to be an easy passthrough to the backend. That way we always know the translation, rotation, scale that the model matrix represents and we can be sure about the matrix properties it has. I always get frustrated when I need to work with plot.model and can't simplify calculations because it could technically be any kind of Mat4f instead of the semi-unitary matrix it almost always is.

@ffreyer ffreyer mentioned this pull request Oct 10, 2024
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Closed
Development

Successfully merging this pull request may close these issues.

vertical toggle
5 participants