Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

determineDataLimits optimizations #6695

Merged
merged 10 commits into from
Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/controllers/controller.bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ module.exports = DatasetController.extend({
value = custom.barStart;
length = custom.barEnd - custom.barStart;
// bars crossing origin are not stacked
if (value !== 0 && Math.sign(value) !== Math.sign(custom.barEnd)) {
if (value !== 0 && helpers.sign(value) !== helpers.sign(custom.barEnd)) {
start = 0;
}
start += value;
Expand Down
4 changes: 4 additions & 0 deletions src/core/core.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,10 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {
scales[scale.id] = scale;
}

// parse min/max value, so we can properly determine min/max for other scales
scale._userMin = scale._parse(scale.options.ticks.min);
benmccann marked this conversation as resolved.
Show resolved Hide resolved
scale._userMax = scale._parse(scale.options.ticks.max);

// TODO(SB): I think we should be able to remove this custom case (options.scale)
// and consider it as a regular scale part of the "scales"" map only! This would
// make the logic easier and remove some useless? custom code.
Expand Down
26 changes: 23 additions & 3 deletions src/core/core.datasetController.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ function applyStack(stack, value, dsIndex, allOther) {
break;
}
otherValue = stack.values[datasetIndex];
if (!isNaN(otherValue) && (value === 0 || Math.sign(value) === Math.sign(otherValue))) {
if (!isNaN(otherValue) && (value === 0 || helpers.sign(value) === helpers.sign(otherValue))) {
value += otherValue;
}
}
Expand Down Expand Up @@ -185,6 +185,13 @@ function getFirstScaleId(chart, axis) {
return (scalesOpts && scalesOpts[prop] && scalesOpts[prop].length && scalesOpts[prop][0].id) || scaleId;
}

function getUserBounds(scale) {
var {min, max, minDefined, maxDefined} = scale._getUserBounds();
return {
min: minDefined ? min : Number.NEGATIVE_INFINITY,
max: maxDefined ? max : Number.POSITIVE_INFINITY
};
}
// Base class for all dataset controllers (line, bar, etc)
var DatasetController = function(chart, datasetIndex) {
this.initialize(chart, datasetIndex);
Expand Down Expand Up @@ -298,6 +305,15 @@ helpers.extend(DatasetController.prototype, {
return this.getScaleForId(this._getIndexScaleId());
},

/**
* @private
*/
_getOtherScale: function(scale) {
return scale.id === this._getIndexScaleId()
? this._getValueScale()
: this._getIndexScale();
},

reset: function() {
this._update(true);
},
Expand Down Expand Up @@ -615,15 +631,19 @@ helpers.extend(DatasetController.prototype, {
var max = Number.NEGATIVE_INFINITY;
var stacked = canStack && meta._stacked;
var indices = getSortedDatasetIndices(chart, true);
var i, item, value, parsed, stack, min, minPositive;
var otherScale = this._getOtherScale(scale);
var {min: otherMin, max: otherMax} = getUserBounds(otherScale);
var i, item, value, parsed, stack, min, minPositive, otherValue;

min = minPositive = Number.POSITIVE_INFINITY;

for (i = 0; i < ilen; ++i) {
item = metaData[i];
parsed = item._parsed;
value = parsed[scale.id];
if (item.hidden || isNaN(value)) {
otherValue = parsed[otherScale.id];
if (item.hidden || isNaN(value) ||
otherMin > otherValue || otherMax < otherValue) {
continue;
}
if (stacked) {
Expand Down
46 changes: 35 additions & 11 deletions src/core/core.scale.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const helpers = require('../helpers/index');
const Ticks = require('./core.ticks');

const isArray = helpers.isArray;
const isFinite = helpers.isFinite;
const isNullOrUndef = helpers.isNullOrUndef;
const valueOrDefault = helpers.valueOrDefault;
const resolve = helpers.options.resolve;
Expand Down Expand Up @@ -347,26 +348,49 @@ class Scale extends Element {
return null;
}

/**
* @private
* @since 3.0
*/
_getUserBounds() {
var min = this._userMin;
var max = this._userMax;
if (isNullOrUndef(min) || isNaN(min)) {
min = Number.POSITIVE_INFINITY;
}
if (isNullOrUndef(max) || isNaN(max)) {
max = Number.NEGATIVE_INFINITY;
}
return {min, max, minDefined: isFinite(min), maxDefined: isFinite(max)};
}

/**
* @private
* @since 3.0
*/
_getMinMax(canStack) {
var me = this;
var metas = me._getMatchingVisibleMetas();
var min = Number.POSITIVE_INFINITY;
var max = Number.NEGATIVE_INFINITY;
var {min, max, minDefined, maxDefined} = me._getUserBounds();
var minPositive = Number.POSITIVE_INFINITY;
var i, ilen, minmax;
var i, ilen, metas, minmax;

if (minDefined && maxDefined) {
return {min, max};
}

metas = me._getMatchingVisibleMetas();
for (i = 0, ilen = metas.length; i < ilen; ++i) {
minmax = metas[i].controller._getMinMax(me, canStack);
min = Math.min(min, minmax.min);
max = Math.max(max, minmax.max);
if (!minDefined) {
kurkle marked this conversation as resolved.
Show resolved Hide resolved
min = Math.min(min, minmax.min);
}
if (!maxDefined) {
max = Math.max(max, minmax.max);
}
minPositive = Math.min(minPositive, minmax.minPositive);
}

return {
min: min,
max: max,
minPositive: minPositive
};
return {min, max, minPositive};
}

_invalidateCaches() {}
Expand Down
40 changes: 8 additions & 32 deletions src/scales/scale.category.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,44 +24,20 @@ module.exports = Scale.extend({

determineDataLimits: function() {
var me = this;
var labels = me._getLabels();
var ticksOpts = me.options.ticks;
var min = ticksOpts.min;
var max = ticksOpts.max;
var minIndex = 0;
var maxIndex = labels.length - 1;
var findIndex;

if (min !== undefined) {
// user specified min value
findIndex = labels.indexOf(min);
if (findIndex >= 0) {
minIndex = findIndex;
}
}

if (max !== undefined) {
// user specified max value
findIndex = labels.indexOf(max);
if (findIndex >= 0) {
maxIndex = findIndex;
}
}
var max = me._getLabels().length - 1;

me.minIndex = minIndex;
me.maxIndex = maxIndex;
me.min = labels[minIndex];
me.max = labels[maxIndex];
me.min = Math.max(me._userMin || 0, 0);
me.max = Math.min(me._userMax || max, max);
},

buildTicks: function() {
var me = this;
var labels = me._getLabels();
var minIndex = me.minIndex;
var maxIndex = me.maxIndex;
var min = me.min;
var max = me.max;

// If we are viewing some subset of labels, slice the original array
labels = (minIndex === 0 && maxIndex === labels.length - 1) ? labels : labels.slice(minIndex, maxIndex + 1);
labels = (min === 0 && max === labels.length - 1) ? labels : labels.slice(min, max + 1);
return labels.map(function(l) {
return {value: l};
});
Expand Down Expand Up @@ -93,7 +69,7 @@ module.exports = Scale.extend({
return;
}

me._startValue = me.minIndex - (offset ? 0.5 : 0);
me._startValue = me.min - (offset ? 0.5 : 0);
me._valueRange = Math.max(ticks.length - (offset ? 0 : 1), 1);
},

Expand All @@ -112,7 +88,7 @@ module.exports = Scale.extend({
var ticks = this.ticks;
return index < 0 || index > ticks.length - 1
? null
: this.getPixelForValue(index + this.minIndex);
: this.getPixelForValue(index + this.min);
},

getValueForPixel: function(pixel) {
Expand Down
2 changes: 1 addition & 1 deletion src/scales/scale.linearbase.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function generateTicks(generationOptions, dataRange) {
}

module.exports = Scale.extend({
_parse: function(raw) {
_parse: function(raw, index) { // eslint-disable-line no-unused-vars
if (helpers.isNullOrUndef(raw)) {
return NaN;
}
Expand Down
52 changes: 25 additions & 27 deletions src/scales/scale.logarithmic.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,11 @@ var defaultConfig = {
}
};

// TODO(v3): change this to positiveOrDefault
function nonNegativeOrDefault(value, defaultValue) {
return helpers.isFinite(value) && value >= 0 ? value : defaultValue;
}

module.exports = Scale.extend({
_parse: LinearScaleBase.prototype._parse,
_parse: function(raw, index) { // eslint-disable-line no-unused-vars
const value = LinearScaleBase.prototype._parse.apply(this, arguments);
return helpers.isFinite(value) && value >= 0 ? value : undefined;
},

determineDataLimits: function() {
var me = this;
Expand All @@ -88,39 +86,39 @@ module.exports = Scale.extend({

handleTickRangeOptions: function() {
var me = this;
var tickOpts = me.options.ticks;
var DEFAULT_MIN = 1;
var DEFAULT_MAX = 10;
var min = me.min;
var max = me.max;

me.min = nonNegativeOrDefault(tickOpts.min, me.min);
me.max = nonNegativeOrDefault(tickOpts.max, me.max);

if (me.min === me.max) {
if (me.min !== 0 && me.min !== null) {
me.min = Math.pow(10, Math.floor(log10(me.min)) - 1);
me.max = Math.pow(10, Math.floor(log10(me.max)) + 1);
if (min === max) {
if (min !== 0 && min !== null) {
min = Math.pow(10, Math.floor(log10(min)) - 1);
max = Math.pow(10, Math.floor(log10(max)) + 1);
} else {
me.min = DEFAULT_MIN;
me.max = DEFAULT_MAX;
min = DEFAULT_MIN;
max = DEFAULT_MAX;
}
}
if (me.min === null) {
me.min = Math.pow(10, Math.floor(log10(me.max)) - 1);
if (min === null) {
min = Math.pow(10, Math.floor(log10(max)) - 1);
}
if (me.max === null) {
me.max = me.min !== 0
? Math.pow(10, Math.floor(log10(me.min)) + 1)
if (max === null) {
max = min !== 0
? Math.pow(10, Math.floor(log10(min)) + 1)
: DEFAULT_MAX;
}
if (me.minNotZero === null) {
if (me.min > 0) {
me.minNotZero = me.min;
} else if (me.max < 1) {
me.minNotZero = Math.pow(10, Math.floor(log10(me.max)));
if (min > 0) {
me.minNotZero = min;
} else if (max < 1) {
me.minNotZero = Math.pow(10, Math.floor(log10(max)));
} else {
me.minNotZero = DEFAULT_MIN;
}
}
me.min = min;
me.max = max;
},

buildTicks: function() {
Expand All @@ -129,8 +127,8 @@ module.exports = Scale.extend({
var reverse = !me.isHorizontal();

var generationOptions = {
min: nonNegativeOrDefault(tickOpts.min),
max: nonNegativeOrDefault(tickOpts.max)
min: me._userMin,
max: me._userMax
};
var ticks = generateTicks(generationOptions, me);

Expand Down
Loading