| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- /**
- * AUTO-GENERATED FILE. DO NOT MODIFY.
- */
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- import { getPrecision, round, nice, quantityExponent, mathPow, mathMax, mathRound, mathLog, mathAbs, mathFloor, mathCeil } from '../util/number.js';
- import { isValidNumberForExtent } from '../util/model.js';
- import { getScaleExtentForTickUnsafe } from './scaleMapper.js';
- /**
- * See also method `nice` in `src/util/number.ts`.
- */
- // export function isValueNice(val: number) {
- // const exp10 = Math.pow(10, quantityExponent(Math.abs(val)));
- // const f = Math.abs(round(val / exp10, 0));
- // return f === 0
- // || f === 1
- // || f === 2
- // || f === 3
- // || f === 5;
- // }
- export function isIntervalOrLogScale(scale) {
- return isIntervalScale(scale) || isLogScale(scale);
- }
- export function isIntervalOrTimeScale(scale) {
- return isIntervalScale(scale) || isTimeScale(scale);
- }
- export function isIntervalScale(scale) {
- return scale.type === 'interval';
- }
- export function isTimeScale(scale) {
- return scale.type === 'time';
- }
- export function isLogScale(scale) {
- return scale.type === 'log';
- }
- export function isOrdinalScale(scale) {
- return scale.type === 'ordinal';
- }
- /**
- * @param extent Both extent[0] and extent[1] should be valid number.
- * Should be extent[0] < extent[1].
- * @param splitNumber splitNumber should be >= 1.
- */
- export function intervalScaleNiceTicks(extent, spanWithBreaks, splitNumber, minInterval, maxInterval) {
- var result = {};
- var interval = result.interval = nice(spanWithBreaks / splitNumber, true);
- if (minInterval != null && interval < minInterval) {
- interval = result.interval = minInterval;
- }
- if (maxInterval != null && interval > maxInterval) {
- interval = result.interval = maxInterval;
- }
- var precision = result.intervalPrecision = getIntervalPrecision(interval);
- // Niced extent inside original extent
- result.niceTickExtent = [round(mathCeil(extent[0] / interval) * interval, precision), round(mathFloor(extent[1] / interval) * interval, precision)];
- return result;
- }
- /**
- * The input `niceInterval` should be generated
- * from `nice` method in `src/util/number.ts`, or
- * from `increaseInterval` itself.
- */
- export function increaseInterval(niceInterval) {
- var exponent = quantityExponent(niceInterval);
- // No rounding error in Math.pow(10, integer).
- var exp10 = mathPow(10, exponent);
- // Fix IEEE 754 float rounding error
- var f = mathRound(niceInterval / exp10);
- if (!f) {
- f = 1;
- } else if (f === 2) {
- f = 3;
- } else if (f === 3) {
- f = 5;
- } else {
- // f is 1 or 5
- f *= 2;
- }
- // Fix IEEE 754 float rounding error
- return round(f * exp10, -exponent);
- }
- export function getIntervalPrecision(niceInterval) {
- // Tow more digital for tick.
- // NOTE: `2` was introduced in commit `af2a2a9f6303081d7c3b52f0a38add07b4c6e0c7`;
- // it works on "nice" interval, but seems not necessarily mathematically required.
- return getPrecision(niceInterval) + 2;
- }
- /**
- * NOTE:
- * - If `val` is `NaN`, return `NaN`.
- * - If `val` is `0`, return `-Infinity`.
- * - If `val` is negative, return `NaN`.
- *
- * @see {DataStore#getDataExtent} It handles non-positive values for logarithm scale.
- */
- export function logScaleLogTick(val, base) {
- // NOTE:
- // - rounding error may happen above, typically expecting `log10(1000)` but actually
- // getting `2.9999999999999996`, but generally it does not matter since they are not
- // used to display.
- // - Consider backward compatibility and other log bases, do not use `Math.log10`.
- return mathLog(val) / mathLog(base);
- }
- /**
- * Cumulative rounding errors cause the logarithm operation to become non-invertible by simply exponentiation.
- * - `Math.pow(10, integer)` itself has no rounding error. But,
- * - If `linearTickVal` is generated internally by `calcNiceTicks`, it may be still "not nice" (not an integer)
- * when it is `extent[i]`.
- * - If `linearTickVal` is generated outside (e.g., by `scaleCalcAlign`) and set by `setExtent`,
- * `logScaleLogTick` may already have introduced rounding errors even for "nice" values.
- * But invertible is required when the original `extent[i]` need to be respected, or "nice" ticks need to be
- * displayed instead of something like `5.999999999999999`, which is addressed in this function.
- * See also `#4158`.
- *
- * [CAUTION]:
- * Monotonicity may be broken on extent ends - callers must make sure it does not matter.
- */
- export function logScalePowTick(
- // `tickVal` should be in the linear space.
- linearTickVal, base, opt) {
- var lookup = opt && opt.lookup;
- if (lookup) {
- for (var i = 0; i < lookup.from.length; i++) {
- if (linearTickVal === lookup.from[i]) {
- return lookup.to[i];
- }
- }
- }
- return mathPow(base, linearTickVal);
- }
- /**
- * For `IntervalScale`, convert `rawExtent` to:
- * - Be no non-finite number.
- * - Be `extent[0] < extent[1]`- no equal; otherwise, additional handling is required
- * in "nice" and "align" ticks.
- */
- export function intervalScaleEnsureValidExtent(rawExtent, fixMinMax, rawExtentResult) {
- var extent = rawExtent.slice();
- // PENDING:
- // This implementation is not rigorous, but has long been in use.
- // If extent start and end are same, expand them
- if (extent[0] === extent[1]) {
- // If `containShape`, the extent must be evenly distributed to both sides;
- // otherwise, shape (e.g., bars) may be overflow and clipped.
- var containShapeRequired = rawExtentResult && rawExtentResult.ctnShp;
- if (extent[0] !== 0) {
- // Expand extent
- // Note that extents can be both negative. See #13154
- var expandSize = mathAbs(extent[0]);
- // In the fowllowing case
- // Axis has been fixed max 100
- // Plus data are all 100 and axis extent are [100, 100].
- // Extend to the both side will cause expanded max is larger than fixed max.
- // So only expand to the smaller side.
- if (!fixMinMax[1]) {
- extent[1] += expandSize / 2;
- extent[0] -= expandSize / 2;
- } else {
- extent[0] -= expandSize / 2;
- }
- } else {
- if (containShapeRequired) {
- extent[0] = -1;
- extent[1] = 1;
- } else {
- extent[1] = 1;
- }
- }
- }
- // For example, if there are no series data, extent may be `[Infinity, -Infinity]` here.
- if (!isValidNumberForExtent(extent[0]) || !isValidNumberForExtent(extent[1])) {
- extent[0] = 0;
- extent[1] = 1;
- }
- if (extent[1] < extent[0]) {
- extent.reverse();
- }
- return extent;
- }
- export function extentDiffers(extent1, extent2) {
- return [extent1[0] !== extent2[0], extent1[1] !== extent2[1]];
- }
- export function ensureValidSplitNumber(rawSplitNumber, defaultSplitNumber) {
- rawSplitNumber = rawSplitNumber || defaultSplitNumber;
- return mathRound(mathMax(rawSplitNumber, 1));
- }
- /**
- * NOTE: The result can have only one item, e.g., when `extent[0] === extent[1]`
- * and `categoryInterval === 0`.
- */
- export function ordinalScaleCreateTicks(ordinalScale,
- // `categoryInterval` is the number part of `CategoryTickLabelSplitIntervalOption`.
- categoryInterval, addItem) {
- var extent = getScaleExtentForTickUnsafe(ordinalScale);
- var startTick = extent[0];
- var tickCount = ordinalScale.count();
- var step = Math.max((categoryInterval || 0) + 1, 1);
- // Calculate start tick based on zero if possible to keep label consistent
- // while zooming and moving while interval > 0. Otherwise the selection
- // of displayable ticks and symbols probably keep changing.
- if (startTick !== 0 && step > 1 && tickCount / step > 2) {
- startTick = Math.round(Math.ceil(startTick / step) * step);
- }
- // min max labels may be excluded if `startTick > 0`, but they should be always
- // included and the label display strategy is adopted uniformly later in `AxisBuilder`.
- if (startTick !== extent[0]) {
- addItemInternally(extent[0], true, true);
- }
- var tickValue = startTick;
- for (; tickValue <= extent[1]; tickValue += step) {
- addItemInternally(tickValue, false, tickValue === extent[0] || tickValue === extent[1]);
- }
- if (tickValue - step !== extent[1]) {
- addItemInternally(extent[1], true, true);
- }
- function addItemInternally(tickValue, offInterval, isExtentBoundary) {
- addItem({
- value: tickValue,
- offInterval: offInterval
- }, isExtentBoundary);
- }
- }
|