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

projection: Add orthographic projection utilities #504

Merged
merged 4 commits into from
Mar 16, 2024
Merged

Conversation

johannes-wolf
Copy link
Member

@johannes-wolf johannes-wolf commented Feb 13, 2024

This PR adds some helper functions for setting up orthographic projection.

Three functions for drawing on different planes got added: on-xy, on-xz and on-yz.
These allow elements which do not allow to be used with different z-coordinates to be drawn in 3D space without having to use rotations etc.

The new ortho function sets-up an isometric projection by default:
grafik

There is no z-sorting (yet?).

Code
#import "src/lib.typ" as cetz
#set page(width: auto, height: auto)

#cetz.canvas({
import cetz.draw: *

let cube() = {
  set-style(
    line: (mark: (end: ">", scale: .3)))

  scale(3)
  line((-1,0,0), (1,0,0))
  line((0,-1,0), (0,1,0))
  line((0,0,-1), (0,0,1))

  set-style(
    stroke: (paint: black, thickness: 1pt, join: "round"),
    fill: rgb(0,0,255,50))

  scale(.35)
  on-xy(z: -1, rect((-1,-1), (1,1)))
  on-xy(z: +1, rect((-1,-1), (1,1)))
  on-xz(y: -1, rect((-1,-1), (1,1)))
  on-xz(y: +1, rect((-1,-1), (1,1)))
  on-yz(x: -1, rect((-1,-1), (1,1)))
  on-yz(x: +1, rect((-1,-1), (1,1)))
}

ortho(name: "ortho", {
  cube()
})

set-origin("ortho.east")
group(name: "ortho", anchor: "west", ortho(x: 20deg, {
  cube()
}))

set-origin("ortho.east")
group(name: "ortho", anchor: "west", ortho(y: 20deg, {
  cube()
}))
})

#cetz.canvas({
import cetz.draw: *

ortho({
  scale(2)
  on-xy(z: -1.1, {
    rect((-1,-1), (1,1))
    translate((-.9, -.9))
    cetz.plot.plot(size: (1.8, 1.8), x-tick-step: none, y-tick-step: none, x-label: none, y-label: none, {
      cetz.plot.add(domain: (-2, 2), x => x * x * x)
      cetz.plot.add-contour(
        (x, y) => 2 - (x - 1) * (y - 1),
        fill: true,
        x-domain: (-2, 2),
        y-domain: (-10, 11))
    })
  })
  on-xz(y: -1.1, {
    rect((-1,-1), (1,1))
    grid((-.9, -.9), (.9, .9), step: .2)
  })
  group(name: "g3", {
    on-yz(x: -1.1, {
      rect((-1,-1), (1,1))
      for r in range(1, 10) {
        circle((0,0), radius: .1 * r)
      }
    })
  })
}, name: "gO")
})

@KronosTheLate
Copy link

That looks neat! Would it be possible to allow helper-functions/krwargs to make ticks and axis-labels? E.g. ortho(content, axis-labels=true) for default label style and position, and ortho(content, axis-labels=(x, y, z)), with x y z being either strongs or content. And similarly a kwarg tick-spacing which is a number applied to all axis, or a vector of number for finer control.

This looks nice though. Easy to use and rotate round any axis. However, would this be much different from defining your object, and rhen rotating the entire thing? I am not sure what ortho adds that is not east enough already.

@johannes-wolf
Copy link
Member Author

johannes-wolf commented Feb 14, 2024

That looks neat! Would it be possible to allow helper-functions/krwargs to make ticks and axis-labels? E.g. ortho(content, axis-labels=true) for default label style and position, and ortho(content, axis-labels=(x, y, z)), with x y z being either strongs or content. And similarly a kwarg tick-spacing which is a number applied to all axis, or a vector of number for finer control.

Adding axes with ticks should be a separate Element.

This looks nice though. Easy to use and rotate round any axis. However, would this be much different from defining your object, and rhen rotating the entire thing? I am not sure what ortho adds that is not east enough already.

  • It gives an environment for 3D, we could even sort by camera z-order insides ortho.
  • I do not really like the default z-shearing transformation, we could remove it
  • Ortho outputs "flat" coordinates with no z-value (outsides the environment), which is useful with anchors and other elements.

@johannes-wolf johannes-wolf marked this pull request as ready for review February 14, 2024 17:09
@KronosTheLate
Copy link

Alright, I can see how on-xy and friends, plus ortho would be useful. I am unable to really check the pros and cons of this implementation in my mind, but like it, and do not immediately have any reservations about it ^_^ I would also say that tagging breaking releases in quick succession due to trying things out if not a big problem as I see it, given the maturity of both Typst and all its packages. So I feel like it makes sense to give this a go, and to not be afraid to change it if usage reveals issues.

@fenjalien fenjalien added this to the 0.3.0 milestone Feb 15, 2024
Copy link
Member

@fenjalien fenjalien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really cool.

Standard extra stuff, manual, changelog, tests are still needed

src/draw/projection.typ Outdated Show resolved Hide resolved
src/draw/projection.typ Show resolved Hide resolved
src/draw/projection.typ Outdated Show resolved Hide resolved
src/draw/projection.typ Outdated Show resolved Hide resolved
Copy link
Member

@fenjalien fenjalien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update changelog first

@johannes-wolf
Copy link
Member Author

@fenjalien Do we want to add this to 0.2.2? This is a non-breaking change.

@fenjalien
Copy link
Member

I don't see why not :)

@johannes-wolf johannes-wolf modified the milestones: 0.3.0, 0.2.2 Mar 16, 2024
@johannes-wolf johannes-wolf merged commit 28bcc96 into master Mar 16, 2024
1 check passed
@johannes-wolf johannes-wolf deleted the cetz-3d branch March 16, 2024 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants