|
| 1 | +/* eslint-disable header/header, no-param-reassign */ |
| 2 | + |
| 3 | +/** |
| 4 | + * @notice |
| 5 | + * This product includes code that is adapted from d3-array@3.0.4 and d3-scale@4.0.2, |
| 6 | + * which are both available under a "ISC" license. |
| 7 | + * |
| 8 | + * ISC License |
| 9 | + * |
| 10 | + * Copyright 2010-2021 Mike Bostock |
| 11 | + * Permission to use, copy, modify, and/or distribute this software for any purpose |
| 12 | + * with or without fee is hereby granted, provided that the above copyright notice |
| 13 | + * and this permission notice appear in all copies. |
| 14 | +
|
| 15 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH |
| 16 | + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| 17 | + * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, |
| 18 | + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS |
| 19 | + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| 20 | + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF |
| 21 | + * THIS SOFTWARE. |
| 22 | + */ |
| 23 | + |
| 24 | +import { ScaleContinuousNumeric } from 'd3-scale'; |
| 25 | + |
| 26 | +import { PrimitiveValue } from '../../partition_chart/layout/utils/group_by_rollup'; |
| 27 | + |
| 28 | +const e10 = Math.sqrt(50); |
| 29 | +const e5 = Math.sqrt(10); |
| 30 | +const e2 = Math.sqrt(2); |
| 31 | + |
| 32 | +/** @internal */ |
| 33 | +export function getLinearTicks(start: number, stop: number, count: number, base: number = 2) { |
| 34 | + let reverse, |
| 35 | + i = -1, |
| 36 | + n, |
| 37 | + ticks, |
| 38 | + step; |
| 39 | + |
| 40 | + stop = +stop; |
| 41 | + start = +start; |
| 42 | + count = +count; |
| 43 | + if (start === stop && count > 0) return [start]; |
| 44 | + if ((reverse = stop < start)) { |
| 45 | + n = start; |
| 46 | + start = stop; |
| 47 | + stop = n; |
| 48 | + } |
| 49 | + if ((step = tickIncrement(start, stop, count, base)) === 0 || !isFinite(step)) return []; |
| 50 | + |
| 51 | + if (step > 0) { |
| 52 | + let r0 = Math.round(start / step), |
| 53 | + r1 = Math.round(stop / step); |
| 54 | + if (r0 * step < start) ++r0; |
| 55 | + if (r1 * step > stop) --r1; |
| 56 | + ticks = new Array((n = r1 - r0 + 1)); |
| 57 | + while (++i < n) ticks[i] = (r0 + i) * step; |
| 58 | + } else { |
| 59 | + step = -step; |
| 60 | + let r0 = Math.round(start * step), |
| 61 | + r1 = Math.round(stop * step); |
| 62 | + if (r0 / step < start) ++r0; |
| 63 | + if (r1 / step > stop) --r1; |
| 64 | + ticks = new Array((n = r1 - r0 + 1)); |
| 65 | + while (++i < n) ticks[i] = (r0 + i) / step; |
| 66 | + } |
| 67 | + |
| 68 | + if (reverse) ticks.reverse(); |
| 69 | + |
| 70 | + return ticks; |
| 71 | +} |
| 72 | + |
| 73 | +function tickIncrement(start: number, stop: number, count: number, base: number = 10) { |
| 74 | + const step = (stop - start) / Math.max(0, count); |
| 75 | + const power = Math.floor(Math.log(step) / Math.log(base) + Number.EPSILON); |
| 76 | + const error = step / Math.pow(base, power); |
| 77 | + return power >= 0 |
| 78 | + ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(base, power) |
| 79 | + : -Math.pow(base, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); |
| 80 | +} |
| 81 | + |
| 82 | +/** @internal */ |
| 83 | +export function getNiceLinearTicks( |
| 84 | + scale: ScaleContinuousNumeric<PrimitiveValue, number>, |
| 85 | + count: number = 10, |
| 86 | + base = 10, |
| 87 | +) { |
| 88 | + const d = scale.domain(); |
| 89 | + let i0 = 0; |
| 90 | + let i1 = d.length - 1; |
| 91 | + let start = d[i0]; |
| 92 | + let stop = d[i1]; |
| 93 | + let prestep; |
| 94 | + let step; |
| 95 | + let maxIter = 10; |
| 96 | + |
| 97 | + if (stop < start) { |
| 98 | + step = start; |
| 99 | + start = stop; |
| 100 | + stop = step; |
| 101 | + |
| 102 | + step = i0; |
| 103 | + i0 = i1; |
| 104 | + i1 = step; |
| 105 | + } |
| 106 | + |
| 107 | + while (maxIter-- > 0) { |
| 108 | + step = tickIncrement(start, stop, count, base); |
| 109 | + if (step === prestep) { |
| 110 | + d[i0] = start; |
| 111 | + d[i1] = stop; |
| 112 | + return scale.domain(d); |
| 113 | + } else if (step > 0) { |
| 114 | + start = Math.floor(start / step) * step; |
| 115 | + stop = Math.ceil(stop / step) * step; |
| 116 | + } else if (step < 0) { |
| 117 | + start = Math.ceil(start * step) / step; |
| 118 | + stop = Math.floor(stop * step) / step; |
| 119 | + } else { |
| 120 | + break; |
| 121 | + } |
| 122 | + prestep = step; |
| 123 | + } |
| 124 | + |
| 125 | + return scale; |
| 126 | +} |
| 127 | + |
| 128 | +/* eslint-enable header/header, no-param-reassign */ |
0 commit comments