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

chart: Pie Chart #342

Merged
merged 5 commits into from
Dec 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ CeTZ 0.2.0 requires Typst 0.10.0
- Axis orientation can be changed, enabling rotation of plots
- Plots now support legends!

### Chart
- Added `piechart` for drawing pie- and donut charts
- Added `boxwhisker` for drawing boxwhisker charts

# 0.1.2
CeTZ requires Typst 0.8.0.

Expand Down
Binary file modified gallery/pie-chart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 26 additions & 51 deletions gallery/pie-chart.typ
Original file line number Diff line number Diff line change
@@ -1,58 +1,33 @@
#import "@preview/cetz:0.2.0"

#set page(width: auto, height: auto, margin: .5cm)

#let data = (
([Belgium], 24),
([Germany], 31),
([Greece], 18),
([Spain], 21),
([France], 23),
([Hungary], 18),
([Netherlands], 27),
([Romania], 17),
([Finland], 26),
([Turkey], 13),
)

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

let chart(..values, name: none) = {
let values = values.pos()

let offset = 0
let total = values.fold(0, (s, v) => s + v.at(0))

let segment(from, to) = {
merge-path(close: true, {
line((0, 0), (rel: (360deg * from, 1)))
arc((), start: from * 360deg, stop: to * 360deg, radius: 1)
})
}

group(name: name, {
stroke((paint: black, join: "round"))

let i = 0
for v in values {
fill(v.at(1))
let value = v.at(0) / total

// Draw the segment
segment(offset, offset + value)

// Place an anchor for each segment
anchor(v.at(2), (offset * 360deg + value * 180deg, .75))

offset += value
}
})
}

// Draw the chart
chart((10, red, "red"),
(3, blue, "blue"),
(1, green, "green"),
name: "chart")

set-style(mark: (fill: white, start: "o", stroke: black),
content: (padding: .1))

// Draw annotations
line("chart.red", ((), "-|", (2, 0)))
content((), [Red], anchor: "west")

line("chart.blue", (1, -1), ((), "-|", (2,0)))
content((), [Blue], anchor: "west")

line("chart.green", ((), "-|", (2,0)))
content((), [Green], anchor: "west")
let colors = gradient.linear(red, blue, green, yellow)

chart.piechart(
data,
value-key: 1,
label-key: 0,
radius: 4,
slice-style: colors,
inner-radius: 1,
outset: 3,
inner-label: (content: (value, label) => [#text(white, str(value))], radius: 110%),
outer-label: (content: "%", radius: 110%))
})
9 changes: 1 addition & 8 deletions manual.typ
Original file line number Diff line number Diff line change
Expand Up @@ -647,16 +647,9 @@ Axis names to be used for styling:

With the `chart` library it is easy to draw charts.

Supported charts are:
- `barchart(..)` and `columnchart(..)`: A chart with horizontal/vertical growing bars
- `mode: "basic"`: (default): One bar per data row
- `mode: "clustered"`: Multiple grouped bars per data row
- `mode: "stacked"`: Multiple stacked bars per data row
- `mode: "stacked100"`: Multiple stacked bars relative to the sum of a data row
- `boxwhisker(..)`: A box-plot chart

#doc-style.parse-show-module("/src/lib/chart/barchart.typ")
#doc-style.parse-show-module("/src/lib/chart/columnchart.typ")
#doc-style.parse-show-module("/src/lib/chart/piechart.typ")
#doc-style.parse-show-module("/src/lib/chart/boxwhisker.typ")

=== Examples -- Bar Chart <barchart-examples>
Expand Down
5 changes: 3 additions & 2 deletions src/intersection.typ
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
/// - b (vector): Line 1 point 2
/// - c (vector): Line 2 point 1
/// - d (vector): Line 2 point 2
/// - ray (bool): treat both lines as infinite
/// -> (vector,none)
#let line-line(a, b, c, d) = {
#let line-line(a, b, c, d, ray: false) = {
let lli8(x1, y1, x2, y2, x3, y3, x4, y4) = {
let nx = (x1*y2 - y1*x2)*(x3 - x4)-(x1 - x2)*(x3*y4 - y3*x4)
let ny = (x1*y2 - y1*x2)*(y3 - y4)-(y1 - y2)*(x3*y4 - y3*x4)
Expand All @@ -30,7 +31,7 @@
let My = calc.max(a.at(1), b.at(1)) + epsilon
return mx <= x and Mx >= x and my <= y and My >= y
}
if on-line(pt, a, b) and on-line(pt, c, d) {
if ray or (on-line(pt, a, b) and on-line(pt, c, d)) {
return pt
}
}
Expand Down
1 change: 1 addition & 0 deletions src/lib/chart.typ
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
#import "chart/boxwhisker.typ": boxwhisker, boxwhisker-default-style
#import "chart/barchart.typ": barchart, barchart-default-style
#import "chart/columnchart.typ": columnchart, columnchart-default-style
#import "chart/piechart.typ": piechart
Loading