scichart
Version:
Fast WebGL JavaScript Charting Library and Framework
260 lines (259 loc) • 12.9 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogarithmicTickProvider = exports.ELogarithmicMajorTickMode = exports.ELogarithmicMinorTickMode = void 0;
var Guard_1 = require("../../../Core/Guard");
var NumberRange_1 = require("../../../Core/NumberRange");
var isRealNumber_1 = require("../../../utils/isRealNumber");
var TickProvider_1 = require("./TickProvider");
var ELogarithmicMinorTickMode;
(function (ELogarithmicMinorTickMode) {
ELogarithmicMinorTickMode["Linear"] = "Linear";
ELogarithmicMinorTickMode["Logarithmic"] = "Logarithmic";
ELogarithmicMinorTickMode["Auto"] = "Auto";
})(ELogarithmicMinorTickMode = exports.ELogarithmicMinorTickMode || (exports.ELogarithmicMinorTickMode = {}));
var ELogarithmicMajorTickMode;
(function (ELogarithmicMajorTickMode) {
ELogarithmicMajorTickMode["EqualSpacing"] = "EqualSpacing";
ELogarithmicMajorTickMode["RoundNumbers"] = "RoundNumbers";
})(ELogarithmicMajorTickMode = exports.ELogarithmicMajorTickMode || (exports.ELogarithmicMajorTickMode = {}));
/**
* @summary The LogarithmicTickProvider is a {@link TickProvider} implementation for Logarithmic 2D or 3D Axis.
* @description TickProviders are responsible for calculating the interval between major and minor gridlines, ticks and labels.
*
* * The method {@link getMajorTicks} returns an array of major ticks (data-values values where SciChart will place labels and major gridlines.
* * The method {@link getMinorTicks} returns an array of minor ticks (data-values values where SciChart will place minor gridlines.
* * The method {@link calculateTicks} performs the actual calculation
*
* Override these methods to create custom implementations of Tick intervals in SciChart
* @remarks
* See also {@link TickProvider} for the base implementation.
*/
var LogarithmicTickProvider = /** @class */ (function (_super) {
__extends(LogarithmicTickProvider, _super);
function LogarithmicTickProvider(wasmContext) {
var _this = _super.call(this) || this;
_this.logarithmicBase = 10;
_this.isHighPrecisionTicks = true;
_this.majorTickModeProperty = ELogarithmicMajorTickMode.EqualSpacing;
_this.minorTickModeProperty = ELogarithmicMinorTickMode.Linear;
_this.wasmContext = wasmContext;
return _this;
}
Object.defineProperty(LogarithmicTickProvider.prototype, "majorTickMode", {
/**
* Gets or sets the mode for Major ticks using {@link ELogarithmicMajorTickMode}
* Equally spaced (best for large ranges) or
* Round numbers (better for small ranges)
*/
get: function () {
return this.majorTickModeProperty;
},
/**
* Gets or sets the mode for Major ticks using {@link ELogarithmicMajorTickMode}
* Equally spaced (best for large ranges) or
* Round numbers (better for small ranges)
*/
set: function (mode) {
var _a;
this.majorTickModeProperty = mode;
if ((_a = this.parentAxis) === null || _a === void 0 ? void 0 : _a.invalidateParentCallback) {
this.parentAxis.invalidateParentCallback();
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(LogarithmicTickProvider.prototype, "minorTickMode", {
/**
* Gets or sets the mode for minor ticks using {@link ELogarithmicMinorTickMode},
* Linear (default, best for smaller ranges),
* Logarithmic (better for very large ranges) or
* Auto (switches from linear to Logarithmic when the visible range is such that
* the first linear minor tick would be more than 70% of the major tick)
*/
get: function () {
return this.minorTickModeProperty;
},
/**
* Gets or sets the mode for minor ticks using {@link ELogarithmicMinorTickMode},
* Linear (default, best for smaller ranges),
* Logarithmic (better for very large ranges) or
* Auto (switches from linear to Logarithmic when the visible range is such that
* the first linear minor tick would be more than 70% of the major tick)
*/
set: function (mode) {
var _a;
this.minorTickModeProperty = mode;
if ((_a = this.parentAxis) === null || _a === void 0 ? void 0 : _a.invalidateParentCallback) {
this.parentAxis.invalidateParentCallback();
}
},
enumerable: false,
configurable: true
});
LogarithmicTickProvider.prototype.getMajorTicks = function (minorDelta, majorDelta, visibleRange) {
var deltaRange = new NumberRange_1.NumberRange(minorDelta, majorDelta);
var logAxis = this.parentAxis;
var adj = 1;
if ((logAxis === null || logAxis === void 0 ? void 0 : logAxis.isNegative) && visibleRange.min < 0) {
adj = -1;
visibleRange = new NumberRange_1.NumberRange(Math.abs(visibleRange.max), Math.abs(visibleRange.min));
}
if (!this.isParamsValid(visibleRange, deltaRange)) {
return [];
}
if (this.majorTickMode === ELogarithmicMajorTickMode.RoundNumbers) {
return this.getRoundNumberMajorTicks(minorDelta, majorDelta, visibleRange);
}
else {
var results = [];
if (this.logarithmicBase === 0)
return results;
var current = visibleRange.min;
var min = visibleRange.min;
var max = visibleRange.max;
var numberUtil = this.wasmContext.NumberUtil;
if (!this.isHighPrecisionTicks &&
!numberUtil.IsPowerOf(current, this.logarithmicBase, this.logarithmicBase)) {
current = numberUtil.RoundDownPower(current, this.logarithmicBase, this.logarithmicBase);
}
var start = numberUtil.Log(current, this.logarithmicBase);
start = numberUtil.RoundToDigits(start, 10);
if (!numberUtil.IsDivisibleBy(start, majorDelta)) {
start = numberUtil.RoundUp(start, majorDelta);
}
var exp = start;
current = Math.pow(this.logarithmicBase, exp);
var tickCount = 0;
while (current <= max) {
// If major ticks are calculated, the exponent of current should be divisible by MajorDelta
if (numberUtil.IsDivisibleBy(exp, majorDelta)) {
results.push(adj * current);
}
exp = start + ++tickCount * majorDelta;
current = Math.pow(this.logarithmicBase, exp);
}
//console.log(majorDelta, minorDelta, results);
if (adj === -1) {
return results.reverse();
}
else {
return results;
}
}
};
LogarithmicTickProvider.prototype.getRoundNumberMajorTicks = function (minorDelta, majorDelta, visibleRange) {
var results = [];
var current = visibleRange.min;
var min = visibleRange.min;
var max = visibleRange.max;
var diff = Math.pow(this.logarithmicBase, majorDelta);
var minDiff = this.roundNum(min * (diff - 1));
current = this.roundNum(current, minDiff);
results.push(current);
while (current <= max) {
var nextDiff = current * (diff - 1);
var next = this.roundNum(current * diff, nextDiff);
var working = next;
while (next === current) {
working = working * diff;
next = this.roundNum(working, nextDiff);
}
current = next;
results.push(current);
}
return results;
};
LogarithmicTickProvider.prototype.roundNum = function (value, difference) {
if (value === 0)
return 0;
var exponent = Math.floor(Math.log10(value));
if (difference) {
exponent = Math.min(exponent, Math.round(Math.log10(difference)));
}
// Fractional part of range
var figures = this.wasmContext.NumberUtil.RoundToDigits(value / Math.pow(10, exponent), 1);
var base = Math.floor(figures);
var fraction = figures - base;
var niceFraction = NaN;
if (fraction < 0.3) {
niceFraction = 0;
}
else if (fraction < 0.7) {
niceFraction = 0.5;
}
else {
niceFraction = 1;
}
return (base + niceFraction) * Math.pow(10, exponent);
};
LogarithmicTickProvider.prototype.getMinorTicks = function (minorDelta, majorDelta, visibleRange) {
var logAxis = this.parentAxis;
var adj = 1;
if (logAxis === null || logAxis === void 0 ? void 0 : logAxis.isNegative) {
adj = -1;
visibleRange = new NumberRange_1.NumberRange(Math.abs(visibleRange.max), Math.abs(visibleRange.min));
}
var firstIncrement = visibleRange.min * minorDelta;
var partMajor = visibleRange.min * Math.pow(this.logarithmicBase, majorDelta * 0.7);
var minorsToMajors = (Math.pow(this.logarithmicBase, majorDelta) - 1) / minorDelta;
var minorLogMode = this.minorTickMode === ELogarithmicMinorTickMode.Logarithmic ||
(this.minorTickMode === ELogarithmicMinorTickMode.Auto && partMajor < firstIncrement);
var results = [];
var majorTicks = this.getMajorTicks(minorDelta, majorDelta, visibleRange);
var count = majorTicks.length;
var logDiff = Math.pow(this.logarithmicBase, majorDelta);
if (count > 0) {
for (var index = 0; index <= count; index++) {
var upper = index < count ? majorTicks[index] : majorTicks[index - 1] * logDiff;
var prev = Math.max(upper / logDiff, visibleRange.min);
var increment = prev * minorDelta;
if (minorLogMode) {
var ticks = this.getMajorTicks(1, majorDelta / minorsToMajors, new NumberRange_1.NumberRange(prev, upper));
ticks.forEach(function (t) { return results.push(adj * t); });
}
else {
var current = prev + increment;
while (current < upper && increment > 0) {
results.push(adj * current);
current += increment;
}
}
}
}
return results;
};
/**
* @summary Performs sanity checks to see if parameters are valid.
* @description If this method returns false, then we should not process or compute major/minor gridlines, but instead should
* return empty array ```[]``` in {@link getMajorTicks} / {@link getMinorTicks}
* @param visibleRange The current {@link AxisCore.visibleRange} which is the minimum / maximum range visible on the Axis.
* @param deltaRange The current {@link AxisCore.minorDelta} and {@link AxisCore.majorDelta} which is the difference between minor
* and major gridlines requested by the {@link AxisCore | Axis}
*/
LogarithmicTickProvider.prototype.isParamsValid = function (visibleRange, deltaRange) {
Guard_1.Guard.notNull(visibleRange, "visibleRange");
Guard_1.Guard.notNull(deltaRange, "deltaRange");
return ((0, isRealNumber_1.isRealNumber)(visibleRange.min) &&
(0, isRealNumber_1.isRealNumber)(visibleRange.max) &&
(0, isRealNumber_1.isRealNumber)(deltaRange.min) &&
(0, isRealNumber_1.isRealNumber)(deltaRange.max));
};
return LogarithmicTickProvider;
}(TickProvider_1.TickProvider));
exports.LogarithmicTickProvider = LogarithmicTickProvider;