Is there any fundamental difference between using rotations and ortho projection?
Is
ortho(x:-90deg, y:-90deg, z:60deg) { ... }
the same as
rotate(x: -90deg)
rotate(y: -90deg)
rotate(z: 60deg)
?
Also, are the rotations in the ortho projection alwas applied in that order, starting from x to z?
Y.D.X
January 17, 2025, 10:24am
2
I have never used ortho
before, but I think the source code agrees with your conjecture.
#let ortho(x: 35.264deg, y: 45deg, z: 0deg, sorted: true, cull-face: none, reset-transform: false, body, name: none) = group(name: name, ctx => {
_projection(body, ortho-matrix(x, y, z), ortho-projection-matrix,
// Get an orthographic view matrix for 3 angles
#let ortho-matrix(x, y, z) = matrix.mul-mat(
matrix.ident(),
matrix.transform-rotate-x(x),
matrix.transform-rotate-y(y),
matrix.transform-rotate-z(z),
)
/// rect((-1,-1), (1,1))
/// // Rotate on y-axis
/// rotate(y: 80deg)
/// circle((0,0))
/// ```
///
/// - ..angles (angle): A single angle as a positional argument to rotate on the z-axis by.
/// Named arguments of `x`, `y` or `z` can be given to rotate on their respective axis.
/// You can give named arguments of `yaw`, `pitch` or `roll`, too.
/// - origin (none,coordinate): Origin to rotate around, or (0, 0, 0) if set to `none`.
#let rotate(..angles, origin: none) = {
assert(angles.pos().len() == 1 or angles.named().len() > 0,
message: "Rotate takes a single z-angle or angles " +
"(x, y, z or yaw, pitch, roll) as named arguments, got: " + repr(angles))
let named = angles.named()
let names = named.keys()
let mat = if angles.pos().len() == 1 {
matrix.transform-rotate-z(angles.pos().at(0))
} else if names.all(n => n in ("x", "y", "z")) {
matrix.transform-rotate-xyz(named.at("x", default: 0deg),
named.at("y", default: 0deg),
named.at("z", default: 0deg))
/// Returns a $4 \times 4$ rotation matrix - euler angles
///
/// Calculates the product of the three rotation matrices
/// $R = Rz(z) Ry(y) Rx(x)$
///
/// - x (angle): Rotation about x
/// - y (angle): Rotation about y
/// - z (angle): Rotation about z
/// -> matrix
#let transform-rotate-xyz(x, y, z) = {
((cos(y)*cos(z), sin(x)*sin(y)*cos(z) - cos(x)*sin(z), cos(x)*sin(y)*cos(z) + sin(x)*sin(z), 0),
(cos(y)*sin(z), sin(x)*sin(y)*sin(z) + cos(x)*cos(z), cos(x)*sin(y)*sin(z) - sin(x)*cos(z), 0),
(-sin(y), sin(x)*cos(y), cos(x)*cos(y), 0),
(0,0,0,1))
}
Thanks @Y.D.X .
Yes, the rotations are applied consecutively but assuming x=0deg, y=0deg and z=0deg as the initial state, different to the default state where the projection of the z axis is visible for points with z coordinate.
Other thing I noticed is that transform-shape:false
for markers is ignored inside ortho
:(
To this point, I am not seeing any particular advantage of using ortho
.