I would really like to make a parabola. I am not sure if I have figured it out, yet.
Something that looks basically right is a path
as follows:
#let w = 100mm
#let start = (0mm, 0mm)
#let end = (0mm, w)
#let apex-x = w / 2
#let apex-y = w / 2
// Control point for quadratic Bezier curve.
#let control-x = w
#let control-y = w / 2
// Cubic control points
#let c1-x = w / 2
#let c1-y = w / 4
#let c2-x = w / 2
#let c2-y = 3 * w / 4
#let parabola = [
#path(
start,
(
(apex-x, apex-y),
(c1-x - apex-x, c1-y - apex-y),
(c2-x - apex-x, c2-y - apex-y),
),
end,
)
]
At the end of the document, please find a fuller program that creates the following diagram:
In blue, we have the control polygon of a quadratic Bezier curve. This is translated to a cubic Bezier curve, the control polygon of which is in green. (In Typst, there is a Bezier curve type – path
– which supports only cubic curves.) It certainly does look like a parabola, but the control points that make it look like this don’t make a whole lot of sense to me.
A parabola can be easily represented with a quadratic Bezier curve (as far as I can tell, the control point is the point on the directrix opposite the focus) and there is a way to translate quadratic Bezier curves to cubic Bezier curves. Per “Degree Elevation” on Wikipedia, we learn that “A Bézier curve of degree n can be converted into a Bézier curve of degree n + 1 with the same shape.”.
According to the formula given by Wikipedia (and other sources), the cubic control points should be:
#let c1-x = (2 * control-x / 3) + (start.first() / 3)
#let c1-y = (2 * control-y / 3) + (start.last() / 3)
#let c2-x = (2 * control-x / 3) + (end.first() / 3)
#let c2-y = (2 * control-y / 3) + (end.last() / 3)
However, this results in a lobed curve:
Now I am just not sure if I really made a parabola or not, since I really just eyeballed it.
Here is the code for the full diagram:
#set page(paper: "a4")
#let w = 100mm
#let start = (0mm, 0mm)
#let end = (0mm, w)
#let apex-x = w / 2
#let apex-y = w / 2
// Control point for quadratic Bezier curve.
#let control-x = w
#let control-y = w / 2
// Cubic control points
#let c1-x = w / 2
#let c1-y = w / 4
#let c2-x = w / 2
#let c2-y = 3 * w / 4
// #let c1-x = (2 * control-x / 3) + (start.first() / 3)
// #let c1-y = (2 * control-y / 3) + (start.last() / 3)
// #let c2-x = (2 * control-x / 3) + (end.first() / 3)
// #let c2-y = (2 * control-y / 3) + (end.last() / 3)
#let parabola = [
#path(
start,
(
(apex-x, apex-y),
(c1-x - apex-x, c1-y - apex-y),
(c2-x - apex-x, c2-y - apex-y),
),
end,
stroke: black + 1mm,
)
]
#let grid = {
let steps = 10
let step = w / steps
let cell = rect(width: step, height: step, stroke: gray + 0.1mm)
for i in array.range(0, steps) {
for j in array.range(0, steps) {
place(dx: i * step, dy: j * step, cell)
}
}
place(
dx: 0mm,
dy: 0mm,
polygon(start, (control-x, control-y), end,
stroke: blue.transparentize(25%) + 1mm)
)
place(
dx: 0mm,
dy: 0mm,
polygon(start, (c1-x, c1-y), (c2-x, c2-y), end,
stroke: green.transparentize(50%) + 0.5mm)
)
}
#place(dx: 0mm, dy: 0mm, parabola)
#place(dx: 0mm, dy: 0mm, grid)