Skip to content

Commit d43d7fb

Browse files
committed
polar: Support polar grid
1 parent 755df34 commit d43d7fb

File tree

2 files changed

+102
-11
lines changed

2 files changed

+102
-11
lines changed

src/spine.typ

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@
331331
draw.line(r-start, (rel: (0, radius + r-padding)), stroke: distal-style.stroke)
332332
if "computed-ticks" in distal {
333333
// TODO
334-
//ticks.draw-cartesian-grid(min-y, max-y, 1, y, y.computed-ticks, min-x, max-x, y-style)
334+
ticks.draw-distal-grid(proj, distal.computed-ticks, distal-style)
335335
ticks.draw-cartesian(r-start, r-end, distal.computed-ticks, distal-style)
336336
}
337337

@@ -351,6 +351,7 @@
351351
mode: "PIE")
352352
}
353353
if "computed-ticks" in angular {
354+
ticks.draw-angular-grid(proj, angular.computed-ticks, angular-style)
354355
// TODO
355356
}
356357
},

src/ticks.typ

Lines changed: 100 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,22 @@
33

44
#import "/src/plot/formats.typ"
55

6+
#let _get-grid-mode(mode) = {
7+
return if mode in (true, "major") {
8+
1
9+
} else if mode == "minor" {
10+
2
11+
} else if mode == "both" {
12+
3
13+
} else {
14+
0
15+
}
16+
}
17+
18+
#let _draw-grid(mode, is-major) = {
19+
return mode >= 3 or (is-major and mode == 1) or mode == 2
20+
}
21+
622
// Format a tick value
723
#let format-tick-value(value, tic-options) = {
824
// Without it we get negative zero in conversion
@@ -306,16 +322,7 @@
306322
// - high (vector): End position of a grid-line at tick 0
307323
// - style (style): Style
308324
#let draw-cartesian-grid(start, stop, component, axis, ticks, low, high, style) = {
309-
let kind = if axis.grid in (true, "major") {
310-
1
311-
} else if axis.grid == "minor" {
312-
2
313-
} else if axis.grid == "both" {
314-
3
315-
} else {
316-
0
317-
}
318-
325+
let kind = _get-grid-mode(axis.grid)
319326
if kind > 0 {
320327
draw.on-layer(style.grid-layer, {
321328
for (distance, label, is-major) in ticks {
@@ -338,3 +345,86 @@
338345
})
339346
}
340347
}
348+
349+
/// Draw angular polar grid
350+
#let draw-angular-grid(projection, ticks, style) = {
351+
let (angular, distal, ..) = projection.axes
352+
let mode = _get-grid-mode(distal.grid)
353+
if mode == 0 {
354+
return
355+
}
356+
357+
let (origin,) = (projection.transform)(
358+
(angular.min, distal.min),
359+
)
360+
361+
let padding = style.padding.first()
362+
let range = angular.max - angular.min
363+
364+
draw.on-layer(style.grid-layer, {
365+
for (pos, _, is-major) in ticks {
366+
if not _draw-grid(mode, is-major) {
367+
continue
368+
}
369+
370+
let (pos,) = (projection.transform)(
371+
(angular.min + pos * range, distal.max),
372+
)
373+
374+
pos = vector.add(pos, vector.scale(vector.norm(vector.sub(pos, origin)), padding))
375+
376+
draw.line(origin, pos,
377+
stroke: if is-major { style.grid.stroke } else { style.grid.minor-stroke })
378+
}
379+
})
380+
}
381+
382+
/// Draw distal polar grid
383+
#let draw-distal-grid(projection, ticks, style) = {
384+
let (angular, distal, ..) = projection.axes
385+
let mode = _get-grid-mode(distal.grid)
386+
if mode == 0 {
387+
return
388+
}
389+
390+
let (origin, start, stop) = (projection.transform)(
391+
(angular.min, distal.min),
392+
(angular.min, distal.max),
393+
(angular.max, distal.max),
394+
).map(v => v.map(calc.round.with(digits: 6)))
395+
396+
let is-arc = start != stop
397+
let radius = vector.dist(origin, start)
398+
let range = distal.max - distal.min
399+
400+
let draw-ring = (position, stroke) => {
401+
let v = distal.min + position * range
402+
if distal.min < v and v < distal.max {
403+
if not is-arc {
404+
draw.circle(origin, radius: radius / range * v,
405+
stroke: stroke,
406+
fill: none)
407+
} else {
408+
let (start, mid, stop) = (projection.transform)(
409+
(angular.min, v),
410+
((angular.min + angular.max) / 2, v),
411+
(angular.max, v)
412+
)
413+
414+
draw.arc-through(start, mid, stop,
415+
stroke: stroke,
416+
fill: none)
417+
}
418+
}
419+
}
420+
421+
draw.on-layer(style.grid-layer, {
422+
for (pos, _, is-major) in ticks {
423+
if not _draw-grid(mode, is-major) {
424+
continue
425+
}
426+
427+
draw-ring(pos, if is-major { style.grid.stroke } else { style.grid.minor-stroke })
428+
}
429+
})
430+
}

0 commit comments

Comments
 (0)