|
232 | 232 | format: "float" |
233 | 233 | ), |
234 | 234 | mode: auto, base: auto) = ( |
235 | | - min: min, max: max, ticks: ticks, label: label, inset: (0, 0), show-break: false, mode: mode, base: base |
| 235 | + min: min, max: max, ticks: ticks, label: label, inset: (0, 0), show-break: false, mode: mode, base: base, |
| 236 | + kind: "cartesian", |
236 | 237 | ) |
237 | 238 |
|
238 | 239 | // Format a tick value |
|
509 | 510 | return axis |
510 | 511 | } |
511 | 512 |
|
| 513 | +// Transform a single value along a cartesian axis |
| 514 | +#let transform-cartesian(axis, v) = { |
| 515 | + let a = axis.origin |
| 516 | + let b = axis.target |
| 517 | + |
| 518 | + let length = vector.dist(a, b) - axis.inset.sum() |
| 519 | + let offset = axis.inset.at(0) |
| 520 | + |
| 521 | + let transform-func(n) = if axis.mode == "log" { |
| 522 | + calc.log(calc.max(n, util.float-epsilon), base: axis.base) |
| 523 | + } else { |
| 524 | + n |
| 525 | + } |
| 526 | + |
| 527 | + let factor = length / (transform-func(axis.max) - transform-func(axis.min)) |
| 528 | + return vector.scale( |
| 529 | + vector.norm(vector.sub(b, a)), |
| 530 | + (transform-func(v) - transform-func(axis.min)) * factor + offset) |
| 531 | +} |
| 532 | + |
512 | 533 | // Transform a single vector along a x, y and z axis |
513 | 534 | // |
514 | | -// - size (vector): Coordinate system size |
515 | | -// - x-axis (axis): X axis |
516 | | -// - y-axis (axis): Y axis |
517 | | -// - z-axis (axis): Z axis |
| 535 | +// - axes (list): List of axes |
518 | 536 | // - vec (vector): Input vector to transform |
519 | 537 | // -> vector |
520 | | -#let transform-vec(size, x-axis, y-axis, z-axis, vec) = { |
521 | | - let axes = (x-axis, y-axis) |
522 | | - |
523 | | - let (x, y,) = for (dim, axis) in axes.enumerate() { |
524 | | - let s = size.at(dim) - axis.inset.sum() |
525 | | - let o = axis.inset.at(0) |
| 538 | +#let transform-vec(axes, vec) = { |
| 539 | + let res = (0, 0, 0) |
| 540 | + for (dim, axis) in axes.enumerate() { |
| 541 | + let v = vec.at(dim, default: 0) |
526 | 542 |
|
527 | | - let transform-func(n) = if axis.mode == "log" { |
528 | | - calc.log(calc.max(n, util.float-epsilon), base: axis.base) |
| 543 | + if axis.kind == "cartesian" { |
| 544 | + res = vector.add(res, transform-cartesian(axis, v)) |
529 | 545 | } else { |
530 | | - n |
| 546 | + panic("Unknown axit type " + repr(axis.kind)) |
531 | 547 | } |
532 | | - |
533 | | - let range = transform-func(axis.max) - transform-func(axis.min) |
534 | | - |
535 | | - let f = s / range |
536 | | - ((transform-func(vec.at(dim)) - transform-func(axis.min)) * f + o,) |
537 | 548 | } |
538 | | - |
539 | | - return (x, y, 0) |
| 549 | + return res |
540 | 550 | } |
541 | 551 |
|
542 | 552 | // Draw inside viewport coordinates of two axes |
543 | 553 | // |
544 | | -// - size (vector): Axis canvas size (relative to origin) |
545 | | -// - x (axis): Horizontal axis |
546 | | -// - y (axis): Vertical axis |
547 | | -// - z (axis): Z axis |
| 554 | +// - axes (list): List of axes |
548 | 555 | // - name (string,none): Group name |
549 | | -#let axis-viewport(size, x, y, z, body, name: none) = { |
| 556 | +#let axis-viewport(axes, body, name: none) = { |
550 | 557 | draw.group(name: name, (ctx => { |
551 | 558 | let transform = ctx.transform |
552 | 559 |
|
|
559 | 566 | if "segments" in d { |
560 | 567 | d.segments = d.segments.map(((kind, ..pts)) => { |
561 | 568 | (kind, ..pts.map(pt => { |
562 | | - transform-vec(size, x, y, none, pt) |
| 569 | + transform-vec(axes, pt) |
563 | 570 | })) |
564 | 571 | }) |
565 | 572 | } |
566 | 573 | if "pos" in d { |
567 | | - d.pos = transform-vec(size, x, y, none, d.pos) |
| 574 | + d.pos = transform-vec(axes, d.pos) |
568 | 575 | } |
569 | 576 | return d |
570 | 577 | }) |
|
0 commit comments