Skip to content

Commit

Permalink
Merge pull request #6 from HolyLab/as/docs_with_glmakie
Browse files Browse the repository at this point in the history
More Makie integration
  • Loading branch information
asinghvi17 authored May 29, 2024
2 parents 4f34f37 + 432b8c0 commit 86e6140
Show file tree
Hide file tree
Showing 12 changed files with 549 additions and 36 deletions.
47 changes: 25 additions & 22 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,36 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
docs:
name: Documentation
name: Build and deploy documentation
runs-on: ubuntu-latest
permissions:
actions: write # needed to allow julia-actions/cache to proactively delete old caches that it has created
contents: write
statuses: write
steps:
- name: Install binary dependencies
run: sudo apt-get update && sudo apt-get install -y xorg-dev mesa-utils xvfb libgl1 freeglut3-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
- name: Download all workflow run artifacts
uses: actions/download-artifact@v4
- uses: julia-actions/setup-julia@latest
with:
version: '1'
- uses: julia-actions/cache@v2
- name: Configure doc environment
shell: julia --project=docs --color=yes {0}
- name: Install documentation dependencies
run: |
using Pkg
Pkg.develop(PackageSpec(path=pwd()))
Pkg.instantiate()
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-docdeploy@v1
xvfb-run -s '-screen 0 1024x768x24' julia --project=docs -e '
using Pkg
Pkg.develop(PackageSpec(path=pwd()))
Pkg.add(name = "DocumenterVitepress", rev = "master")
Pkg.instantiate()'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
- name: Run doctests
shell: julia --project=docs --color=yes {0}
run: |
using Documenter: DocMeta, doctest
using FlyThroughPaths
DocMeta.setdocmeta!(FlyThroughPaths, :DocTestSetup, :(using FlyThroughPaths); recursive=true)
doctest(FlyThroughPaths)
DISPLAY: ':0'
- name: Build and deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # If authenticating with SSH deploy key
DISPLAY: ':0'
run: xvfb-run -s '-screen 0 1024x768x24' julia --project=docs/ docs/make.jl deploy
- name: Run doctests
run: julia --project=docs -e '
using Documenter;
using FlyThroughPaths;
Documenter.DocMeta.setdocmeta!(FlyThroughPaths, :DocTestSetup, :(using FlyThroughPaths); recursive=true);
Documenter.doctest(FlyThroughPaths);'
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,22 +139,22 @@ You need to load the visualization package, e.g., `using GLMakie`, in your sessi

This can be handy for constructing a path, for example you can interactively set the approximate position and view parameters and then query them for use by the tools above.

```
```julia
state = capture_view(scene)
```

`state` is a `ViewState` object.

### Setting the current view state

```
```julia
oldstate = set_view!(camera, path, t)
```

This updates the current `camera` settings from `path` at time `t`.

### Displaying the path

```
```julia
plot(path)
```
4 changes: 4 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
FlyThroughPaths = "c11bb9a7-2755-425a-88f3-ebe93bbdb91f"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
MakieCore = "20f20a25-4f0e-4fdf-b5d1-57303727442b"
4 changes: 4 additions & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ makedocs(;
),
pages=[
"Home" => "index.md",
"Makie integration" => "makie.md",
"Developer documentation" => "devdocs.md"
],
warnonly=true,
)

deploydocs(;
repo="github.com/HolyLab/FlyThroughPaths.jl",
devbranch="main",
push_preview=true,
)
16 changes: 16 additions & 0 deletions docs/src/devdocs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Developer documentation

## Implementing support for FlyThroughPaths

FlyThroughPaths operates on the [`ViewState`](@ref) model. In order to implement support for this in a plotting package, you must implement dispatches for the following two functions:
- `capture_view(obj)::ViewState`: extract the current `ViewState`, i.e., camera settings, from `obj`.
- `set_view!(obj, viewstate::ViewState)`: set the camera to the given `ViewState`.

Integration is already implemented for Makie; you can see that in `ext/FlyThroughPathsMakieExt.jl`. The first ~20 lines are the most instructive, beyond which lie utility functions and visualization specializations.

## The `PathChange` interface

```@docs
PathChange
duration
```
140 changes: 137 additions & 3 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,143 @@ CurrentModule = FlyThroughPaths

Documentation for [FlyThroughPaths](https://github.com/HolyLab/FlyThroughPaths.jl).

```@index

All of the examples below assume you've loaded the package with `using FlyThroughPaths`.

# Quick start

## Generic tools

### Representation of paths and view state

Paths are parametrized by time `t`, represented in units of seconds. All paths implicitly start at `t=0`.

The representation of view state is independent of any particular plotting package, although our parametrization is inspired by [Makie's 3D camera](https://docs.makie.org/stable/explanations/cameras/#3d_camera):

- `eyeposition`: the 3d coordinates of the camera
- `lookat`: the 3d coordinates of the point of the camera's "focus" (center of gaze)
- `upvector`: the 3d direction that will correspond to the top of the view. Any component of this vector in the direction of `lookat - eyeposition` is ignored/discarded.
- `fov`: the angle (in degrees) of the cone centered on `lookat - eyeposition` that should be captured.

Set these as follows:

```@repl main
using FlyThroughPaths
state = ViewState(eyeposition=[-10, 0, 0], lookat=[0, 0, 0], upvector=[0, 0, 1], fov=45)
```

You can set just a subset of these:
```@repl main
newstate = ViewState(eyeposition=[-5, 0, 0])
```

This syntax is often used for updating a previous view; for the unspecified settings, the previous value is left intact.


### Initializing a path

```@repl main
path = Path(state)
```

The path starts at `state` at time `t=0`.

### Evaluating at a particular time

Once you have a path, you can get the current `ViewState` with `path(t)`:

```@repl main
path(0)
path(10)
```

So far, nothing much is happening. Things get more interesting when we add movements.

### Holding steady

The simplest thing you can do is insert a pause:

```@repl main
path2 = path * Pause(5)
```

The view will hold steady for 5 seconds. Typically you add `Pause` when you also plan to add other movements later.

### Moving the camera, option 1: constrained movements

This option is typically used for things like rotations around a center point.

```@repl main
path2 = path * ConstrainedMove(5, newstate; constraint=:none, speed=:constant)
```

```@autodocs
Modules = [FlyThroughPaths]
This indicates that over a 5-second period, the camera state gradually adopts any values specified in `newstate`.

```@repl main
path2(0)
path2(5)
path2(2.5)
```

Keyword options include:

- `constraint` (`:none` or `:rotation`): specify a value to keep constant during motion. `:rotation` performs a rotation around `lookat`. Note that if the separation between `eyeposition` and `lookat` is not constant, then the trajectory will be elliptical rather than circular.
- `speed` controls how the change is made across time:
- `:constant`: speed is instantaneously set to a new constant value that will arrive at the endpoint at the specified time
- `:sinusoidal`: speed will initially increase (starting at a speed of 0), achieve a maximum at the midpoint, and then decrease back to 0.


### Moving the camera, option 2: Bezier movements

With this option, you can approximately simulate the feeling of flight, preserving momentum:

```
path2 = path * BezierMove(Δt::Real, P1::ViewState, P2::ViewState...)
```

where a `bezier` path is specified as indicated in this diagram:

![bezier diagram](https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/Bezier_curve.svg/640px-Bezier_curve.svg.png)

The starting state, `P0` in the diagram, is taken from the endpoint of `path`. Over the next `Δt` seconds, one then moves towards the last `ViewState` argument of `bezier`, orienting successively towards any prior arguments. Probably the most robust option is to use `bezier(Δt, P1, P2, P3)`, which can be interpreted as "depart `P0` traveling towards `P1`, and arrive at `P3` as if you had come from `P2`." The view does not actually pass through `P1` and `P2`, but these set the initial and final tangents of the curve.

To see this in action, let's create a move that "rotates" around the origin but moves outward (to a more distant orbit) on its way there:

```@repl main
move = BezierMove(5, ViewState(eyeposition=[0, 10, 0]), [ViewState(eyeposition=[-20, 20, 0])])
path2 = path * move;
path2(2.5)
```

## Backend-specific tools

These require interaction with a plotting package supported by one of the extensions. Currently supported:

- [Makie](https://docs.makie.org/stable/)

You need to load the visualization package, e.g., `using GLMakie`, in your session before any of the commands below will work.

### Capturing the current view state

This can be handy for constructing a path, for example you can interactively set the approximate position and view parameters and then query them for use by the tools above.

```julia
state = capture_view(scenelike::Union{Scene, LScene})
```

`state` is a `ViewState` object.

### Setting the current view state

```julia
oldstate = set_view!(scenelike, path, t)
```

This updates the current `camera` settings from `path` at time `t`.

### Displaying the path

```julia
plot(path)
```
Loading

0 comments on commit 86e6140

Please sign in to comment.