mirror of
https://github.com/nasa/openmct.git
synced 2025-02-22 18:12:57 +00:00
[Code Style] Continue refactor of Plot bundle
Continue refactoring Plot bundle to use prototypes, WTD-1482
This commit is contained in:
parent
18bc7d3637
commit
aefad6fdd3
@ -83,7 +83,7 @@ define(
|
|||||||
* that some pan-zoom state is always available.)
|
* that some pan-zoom state is always available.)
|
||||||
*/
|
*/
|
||||||
PlotPanZoomStack.prototype.popPanZoom = function popPanZoom() {
|
PlotPanZoomStack.prototype.popPanZoom = function popPanZoom() {
|
||||||
if (stack.length > 1) {
|
if (this.stack.length > 1) {
|
||||||
this.stack.pop();
|
this.stack.pop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -38,15 +38,13 @@ define(
|
|||||||
* group
|
* group
|
||||||
*/
|
*/
|
||||||
function PlotPanZoomStackGroup(count) {
|
function PlotPanZoomStackGroup(count) {
|
||||||
var stacks = [],
|
var self = this;
|
||||||
decoratedStacks = [],
|
|
||||||
i;
|
|
||||||
|
|
||||||
// Push a pan-zoom state; the index argument identifies
|
// Push a pan-zoom state; the index argument identifies
|
||||||
// which stack originated the request (all other stacks
|
// which stack originated the request (all other stacks
|
||||||
// will ignore the range part of the change.)
|
// will ignore the range part of the change.)
|
||||||
function pushPanZoom(origin, dimensions, index) {
|
function pushPanZoom(origin, dimensions, index) {
|
||||||
stacks.forEach(function (stack, i) {
|
self.stacks.forEach(function (stack, i) {
|
||||||
if (i === index) {
|
if (i === index) {
|
||||||
// Do a normal push for the specified stack
|
// Do a normal push for the specified stack
|
||||||
stack.pushPanZoom(origin, dimensions);
|
stack.pushPanZoom(origin, dimensions);
|
||||||
@ -61,26 +59,6 @@ define(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop one pan-zoom state from all stacks
|
|
||||||
function popPanZoom() {
|
|
||||||
stacks.forEach(function (stack) {
|
|
||||||
stack.popPanZoom();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the base pan-zoom state for all stacks
|
|
||||||
function setBasePanZoom(origin, dimensions) {
|
|
||||||
stacks.forEach(function (stack) {
|
|
||||||
stack.setBasePanZoom(origin, dimensions);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the pan-zoom state of all stacks
|
|
||||||
function clearPanZoom() {
|
|
||||||
stacks.forEach(function (stack) {
|
|
||||||
stack.clearPanZoom();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decorate a pan-zoom stack; returns an object with
|
// Decorate a pan-zoom stack; returns an object with
|
||||||
// the same interface, but whose stack-mutation methods
|
// the same interface, but whose stack-mutation methods
|
||||||
@ -92,30 +70,40 @@ define(
|
|||||||
result.pushPanZoom = function (origin, dimensions) {
|
result.pushPanZoom = function (origin, dimensions) {
|
||||||
pushPanZoom(origin, dimensions, index);
|
pushPanZoom(origin, dimensions, index);
|
||||||
};
|
};
|
||||||
result.setBasePanZoom = setBasePanZoom;
|
result.setBasePanZoom = function () {
|
||||||
result.popPanZoom = popPanZoom;
|
self.setBasePanZoom.apply(self, arguments);
|
||||||
result.clearPanZoom = clearPanZoom;
|
};
|
||||||
|
result.popPanZoom = function () {
|
||||||
|
self.popPanZoom.apply(self, arguments);
|
||||||
|
};
|
||||||
|
result.clearPanZoom = function () {
|
||||||
|
self.clearPanZoom.apply(self, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the stacks in this group ...
|
// Create the stacks in this group ...
|
||||||
while (stacks.length < count) {
|
this.stacks = [];
|
||||||
stacks.push(new PlotPanZoomStack([], []));
|
while (this.stacks.length < count) {
|
||||||
|
this.stacks.push(new PlotPanZoomStack([], []));
|
||||||
}
|
}
|
||||||
// ... and their decorated-to-synchronize versions.
|
// ... and their decorated-to-synchronize versions.
|
||||||
decoratedStacks = stacks.map(decorateStack);
|
this.decoratedStacks = this.stacks.map(decorateStack);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
/**
|
||||||
* Pop a pan-zoom state from all stacks in the group.
|
* Pop a pan-zoom state from all stacks in the group.
|
||||||
* If called when there is only one pan-zoom state on each
|
* If called when there is only one pan-zoom state on each
|
||||||
* stack, this acts as a no-op (that is, the lowest
|
* stack, this acts as a no-op (that is, the lowest
|
||||||
* pan-zoom state on the stack cannot be popped, to ensure
|
* pan-zoom state on the stack cannot be popped, to ensure
|
||||||
* that some pan-zoom state is always available.)
|
* that some pan-zoom state is always available.)
|
||||||
* @memberof platform/features/plot.PlotPanZoomStackGroup#
|
|
||||||
*/
|
*/
|
||||||
popPanZoom: popPanZoom,
|
PlotPanZoomStackGroup.prototype.popPanZoom = function () {
|
||||||
|
this.stacks.forEach(function (stack) {
|
||||||
|
stack.popPanZoom();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the base pan-zoom state for all stacks in this group.
|
* Set the base pan-zoom state for all stacks in this group.
|
||||||
@ -125,18 +113,25 @@ define(
|
|||||||
* interfering with the user's chosen pan/zoom states.
|
* interfering with the user's chosen pan/zoom states.
|
||||||
* @param {number[]} origin the base origin
|
* @param {number[]} origin the base origin
|
||||||
* @param {number[]} dimensions the base dimensions
|
* @param {number[]} dimensions the base dimensions
|
||||||
* @memberof platform/features/plot.PlotPanZoomStackGroup#
|
|
||||||
*/
|
*/
|
||||||
setBasePanZoom: setBasePanZoom,
|
PlotPanZoomStackGroup.prototype.setBasePanZoom = function (origin, dimensions) {
|
||||||
|
this.stacks.forEach(function (stack) {
|
||||||
|
stack.setBasePanZoom(origin, dimensions);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all pan-zoom stacks in this group down to
|
* Clear all pan-zoom stacks in this group down to
|
||||||
* their bottom element; in effect, pop all elements
|
* their bottom element; in effect, pop all elements
|
||||||
* but the last, e.g. to remove any temporary user
|
* but the last, e.g. to remove any temporary user
|
||||||
* modifications to pan-zoom state.
|
* modifications to pan-zoom state.
|
||||||
* @memberof platform/features/plot.PlotPanZoomStackGroup#
|
|
||||||
*/
|
*/
|
||||||
clearPanZoom: clearPanZoom,
|
PlotPanZoomStackGroup.prototype.clearPanZoom = function () {
|
||||||
|
this.stacks.forEach(function (stack) {
|
||||||
|
stack.clearPanZoom();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current stack depth; that is, the number
|
* Get the current stack depth; that is, the number
|
||||||
* of items on each stack in the group.
|
* of items on each stack in the group.
|
||||||
@ -144,14 +139,14 @@ define(
|
|||||||
* panning or zooming relative to the base value has
|
* panning or zooming relative to the base value has
|
||||||
* been applied.
|
* been applied.
|
||||||
* @returns {number} the depth of the stacks in this group
|
* @returns {number} the depth of the stacks in this group
|
||||||
* @memberof platform/features/plot.PlotPanZoomStackGroup#
|
|
||||||
*/
|
*/
|
||||||
getDepth: function () {
|
PlotPanZoomStackGroup.prototype.getDepth = function () {
|
||||||
// All stacks are kept in sync, so look up depth
|
// All stacks are kept in sync, so look up depth
|
||||||
// from the first one.
|
// from the first one.
|
||||||
return stacks.length > 0 ?
|
return this.stacks.length > 0 ?
|
||||||
stacks[0].getDepth() : 0;
|
this.stacks[0].getDepth() : 0;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a specific pan-zoom stack in this group.
|
* Get a specific pan-zoom stack in this group.
|
||||||
* Stacks are specified by index; this index must be less
|
* Stacks are specified by index; this index must be less
|
||||||
@ -165,15 +160,11 @@ define(
|
|||||||
* @param {number} index the index of the stack to get
|
* @param {number} index the index of the stack to get
|
||||||
* @returns {PlotPanZoomStack} the pan-zoom stack in the
|
* @returns {PlotPanZoomStack} the pan-zoom stack in the
|
||||||
* group identified by that index
|
* group identified by that index
|
||||||
* @memberof platform/features/plot.PlotPanZoomStackGroup#
|
|
||||||
*/
|
*/
|
||||||
getPanZoomStack: function (index) {
|
PlotPanZoomStackGroup.prototype.getPanZoomStack = function (index) {
|
||||||
return decoratedStacks[index];
|
return this.decoratedStacks[index];
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return PlotPanZoomStackGroup;
|
return PlotPanZoomStackGroup;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -48,8 +48,7 @@ define(
|
|||||||
function PlotPosition(x, y, width, height, panZoomStack) {
|
function PlotPosition(x, y, width, height, panZoomStack) {
|
||||||
var panZoom = panZoomStack.getPanZoom(),
|
var panZoom = panZoomStack.getPanZoom(),
|
||||||
origin = panZoom.origin,
|
origin = panZoom.origin,
|
||||||
dimensions = panZoom.dimensions,
|
dimensions = panZoom.dimensions;
|
||||||
position;
|
|
||||||
|
|
||||||
function convert(v, i) {
|
function convert(v, i) {
|
||||||
return v * dimensions[i] + origin[i];
|
return v * dimensions[i] + origin[i];
|
||||||
@ -57,45 +56,42 @@ define(
|
|||||||
|
|
||||||
if (!dimensions || !origin) {
|
if (!dimensions || !origin) {
|
||||||
// We need both dimensions and origin to compute a position
|
// We need both dimensions and origin to compute a position
|
||||||
position = [];
|
this.position = [];
|
||||||
} else {
|
} else {
|
||||||
// Convert from pixel to domain-range space.
|
// Convert from pixel to domain-range space.
|
||||||
// Note that range is reversed from the y-axis in pixel space
|
// Note that range is reversed from the y-axis in pixel space
|
||||||
//(positive range points up, positive pixel-y points down)
|
//(positive range points up, positive pixel-y points down)
|
||||||
position = [ x / width, (height - y) / height ].map(convert);
|
this.position =
|
||||||
|
[ x / width, (height - y) / height ].map(convert);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
/**
|
||||||
* Get the domain value corresponding to this pixel position.
|
* Get the domain value corresponding to this pixel position.
|
||||||
* @returns {number} the domain value
|
* @returns {number} the domain value
|
||||||
* @memberof platform/features/plot.PlotPosition#
|
|
||||||
*/
|
*/
|
||||||
getDomain: function () {
|
PlotPosition.prototype.getDomain = function () {
|
||||||
return position[0];
|
return this.position[0];
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the range value corresponding to this pixel position.
|
* Get the range value corresponding to this pixel position.
|
||||||
* @returns {number} the range value
|
* @returns {number} the range value
|
||||||
* @memberof platform/features/plot.PlotPosition#
|
|
||||||
*/
|
*/
|
||||||
getRange: function () {
|
PlotPosition.prototype.getRange =function () {
|
||||||
return position[1];
|
return this.position[1];
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the domain and values corresponding to this
|
* Get the domain and values corresponding to this
|
||||||
* pixel position.
|
* pixel position.
|
||||||
* @returns {number[]} an array containing the domain and
|
* @returns {number[]} an array containing the domain and
|
||||||
* the range value, in that order
|
* the range value, in that order
|
||||||
* @memberof platform/features/plot.PlotPosition#
|
|
||||||
*/
|
*/
|
||||||
getPosition: function () {
|
PlotPosition.prototype.getPosition = function () {
|
||||||
return position;
|
return this.position;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return PlotPosition;
|
return PlotPosition;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -49,8 +49,7 @@ define(
|
|||||||
min = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
|
min = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
domainOffset = Number.POSITIVE_INFINITY,
|
domainOffset = Number.POSITIVE_INFINITY;
|
||||||
buffers;
|
|
||||||
|
|
||||||
// Remove any undefined data sets
|
// Remove any undefined data sets
|
||||||
datas = (datas || []).filter(identity);
|
datas = (datas || []).filter(identity);
|
||||||
@ -85,41 +84,48 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert to Float32Array
|
// Convert to Float32Array
|
||||||
buffers = vertices.map(function (v) { return new Float32Array(v); });
|
this.buffers = vertices.map(function (v) {
|
||||||
|
return new Float32Array(v);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
this.domainOffset = domainOffset;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
/**
|
||||||
* Get the dimensions which bound all data in the provided
|
* Get the dimensions which bound all data in the provided
|
||||||
* data sets. This is given as a two-element array where the
|
* data sets. This is given as a two-element array where the
|
||||||
* first element is domain, and second is range.
|
* first element is domain, and second is range.
|
||||||
* @returns {number[]} the dimensions which bound this data set
|
* @returns {number[]} the dimensions which bound this data set
|
||||||
* @memberof platform/features/plot.PlotPreparer#
|
|
||||||
*/
|
*/
|
||||||
getDimensions: function () {
|
PlotPreparer.prototype.getDimensions = function () {
|
||||||
|
var max = this.max, min = this.min;
|
||||||
return [max[0] - min[0], max[1] - min[1]];
|
return [max[0] - min[0], max[1] - min[1]];
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the origin of this data set's boundary.
|
* Get the origin of this data set's boundary.
|
||||||
* This is given as a two-element array where the
|
* This is given as a two-element array where the
|
||||||
* first element is domain, and second is range.
|
* first element is domain, and second is range.
|
||||||
* The domain value here is not adjusted by the domain offset.
|
* The domain value here is not adjusted by the domain offset.
|
||||||
* @returns {number[]} the origin of this data set's boundary
|
* @returns {number[]} the origin of this data set's boundary
|
||||||
* @memberof platform/features/plot.PlotPreparer#
|
|
||||||
*/
|
*/
|
||||||
getOrigin: function () {
|
PlotPreparer.prototype.getOrigin = function () {
|
||||||
return min;
|
return this.min;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the domain offset; this offset will have been subtracted
|
* Get the domain offset; this offset will have been subtracted
|
||||||
* from all domain values in all buffers returned by this
|
* from all domain values in all buffers returned by this
|
||||||
* preparer, in order to minimize loss-of-precision due to
|
* preparer, in order to minimize loss-of-precision due to
|
||||||
* conversion to the 32-bit float format needed by WebGL.
|
* conversion to the 32-bit float format needed by WebGL.
|
||||||
* @returns {number} the domain offset
|
* @returns {number} the domain offset
|
||||||
* @memberof platform/features/plot.PlotPreparer#
|
|
||||||
*/
|
*/
|
||||||
getDomainOffset: function () {
|
PlotPreparer.prototype.getDomainOffset = function () {
|
||||||
return domainOffset;
|
return this.domainOffset;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all renderable buffers for this data set. This will
|
* Get all renderable buffers for this data set. This will
|
||||||
* be returned as an array which can be correlated back to
|
* be returned as an array which can be correlated back to
|
||||||
@ -136,13 +142,10 @@ define(
|
|||||||
* cause aliasing artifacts (particularly for timestamps)
|
* cause aliasing artifacts (particularly for timestamps)
|
||||||
*
|
*
|
||||||
* @returns {Float32Array[]} the buffers for these traces
|
* @returns {Float32Array[]} the buffers for these traces
|
||||||
* @memberof platform/features/plot.PlotPreparer#
|
|
||||||
*/
|
*/
|
||||||
getBuffers: function () {
|
PlotPreparer.prototype.getBuffers = function () {
|
||||||
return buffers;
|
return this.buffers;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
return PlotPreparer;
|
return PlotPreparer;
|
||||||
|
|
||||||
|
@ -30,40 +30,52 @@ define(
|
|||||||
* insertion into a plot line.
|
* insertion into a plot line.
|
||||||
* @constructor
|
* @constructor
|
||||||
* @memberof platform/features/plot
|
* @memberof platform/features/plot
|
||||||
|
* @implements {TelemetrySeries}
|
||||||
*/
|
*/
|
||||||
function PlotSeriesWindow(series, domain, range, start, end) {
|
function PlotSeriesWindow(series, domain, range, start, end) {
|
||||||
return {
|
this.series = series;
|
||||||
getPointCount: function () {
|
this.domain = domain;
|
||||||
return end - start;
|
this.range = range;
|
||||||
},
|
this.start = start;
|
||||||
getDomainValue: function (index) {
|
this.end = end;
|
||||||
return series.getDomainValue(index + start, domain);
|
}
|
||||||
},
|
|
||||||
getRangeValue: function (index) {
|
PlotSeriesWindow.prototype.getPointCount = function () {
|
||||||
return series.getRangeValue(index + start, range);
|
return this.end - this.start;
|
||||||
},
|
};
|
||||||
split: function () {
|
|
||||||
var mid = Math.floor((end + start) / 2);
|
PlotSeriesWindow.prototype.getDomainValue = function (index) {
|
||||||
return ((end - start) > 1) ?
|
return this.series.getDomainValue(index + this.start, this.domain);
|
||||||
|
};
|
||||||
|
|
||||||
|
PlotSeriesWindow.prototype.getRangeValue = function (index) {
|
||||||
|
return this.series.getRangeValue(index + this.start, this.range);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split this series into two series of equal (or nearly-equal) size.
|
||||||
|
* @returns {PlotSeriesWindow[]} two series
|
||||||
|
*/
|
||||||
|
PlotSeriesWindow.prototype.split = function () {
|
||||||
|
var mid = Math.floor((this.end + this.start) / 2);
|
||||||
|
return ((this.end - this.start) > 1) ?
|
||||||
[
|
[
|
||||||
new PlotSeriesWindow(
|
new PlotSeriesWindow(
|
||||||
series,
|
this.series,
|
||||||
domain,
|
this.domain,
|
||||||
range,
|
this.range,
|
||||||
start,
|
this.start,
|
||||||
mid
|
mid
|
||||||
),
|
),
|
||||||
new PlotSeriesWindow(
|
new PlotSeriesWindow(
|
||||||
series,
|
this.series,
|
||||||
domain,
|
this.domain,
|
||||||
range,
|
this.range,
|
||||||
mid,
|
mid,
|
||||||
end
|
this.end
|
||||||
)
|
)
|
||||||
] : [];
|
] : [];
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
return PlotSeriesWindow;
|
return PlotSeriesWindow;
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,14 @@ define(
|
|||||||
* domain and range values.
|
* domain and range values.
|
||||||
*/
|
*/
|
||||||
function PlotTickGenerator(panZoomStack, formatter) {
|
function PlotTickGenerator(panZoomStack, formatter) {
|
||||||
|
this.panZoomStack = panZoomStack;
|
||||||
|
this.formatter = formatter;
|
||||||
|
}
|
||||||
|
|
||||||
// Generate ticks; interpolate from start up to
|
// Generate ticks; interpolate from start up to
|
||||||
// start + span in count steps, using the provided
|
// start + span in count steps, using the provided
|
||||||
// formatter to represent each value.
|
// formatter to represent each value.
|
||||||
function generateTicks(start, span, count, format) {
|
PlotTickGenerator.prototype.generateTicks = function (start, span, count, format) {
|
||||||
var step = span / (count - 1),
|
var step = span / (count - 1),
|
||||||
result = [],
|
result = [],
|
||||||
i;
|
i;
|
||||||
@ -55,45 +58,38 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
/**
|
||||||
* Generate tick marks for the domain axis.
|
* Generate tick marks for the domain axis.
|
||||||
* @param {number} count the number of ticks
|
* @param {number} count the number of ticks
|
||||||
* @returns {string[]} labels for those ticks
|
* @returns {string[]} labels for those ticks
|
||||||
* @memberof platform/features/plot.PlotTickGenerator#
|
|
||||||
*/
|
*/
|
||||||
generateDomainTicks: function (count) {
|
PlotTickGenerator.prototype.generateDomainTicks = function (count) {
|
||||||
var panZoom = panZoomStack.getPanZoom();
|
var panZoom = this.panZoomStack.getPanZoom();
|
||||||
return generateTicks(
|
return this.generateTicks(
|
||||||
panZoom.origin[0],
|
panZoom.origin[0],
|
||||||
panZoom.dimensions[0],
|
panZoom.dimensions[0],
|
||||||
count,
|
count,
|
||||||
formatter.formatDomainValue
|
this.formatter.formatDomainValue
|
||||||
);
|
);
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate tick marks for the range axis.
|
* Generate tick marks for the range axis.
|
||||||
* @param {number} count the number of ticks
|
* @param {number} count the number of ticks
|
||||||
* @returns {string[]} labels for those ticks
|
* @returns {string[]} labels for those ticks
|
||||||
* @memberof platform/features/plot.PlotTickGenerator#
|
|
||||||
*/
|
*/
|
||||||
generateRangeTicks: function (count) {
|
PlotTickGenerator.prototype.generateRangeTicks = function (count) {
|
||||||
var panZoom = panZoomStack.getPanZoom();
|
var panZoom = this.panZoomStack.getPanZoom();
|
||||||
return generateTicks(
|
return this.generateTicks(
|
||||||
panZoom.origin[1],
|
panZoom.origin[1],
|
||||||
panZoom.dimensions[1],
|
panZoom.dimensions[1],
|
||||||
count,
|
count,
|
||||||
formatter.formatRangeValue
|
this.formatter.formatRangeValue
|
||||||
);
|
);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return PlotTickGenerator;
|
return PlotTickGenerator;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -21,10 +21,6 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*global define,Float32Array*/
|
/*global define,Float32Array*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares data to be rendered in a GL Plot. Handles
|
|
||||||
* the conversion from data API to displayable buffers.
|
|
||||||
*/
|
|
||||||
define(
|
define(
|
||||||
['./PlotLine', './PlotLineBuffer'],
|
['./PlotLine', './PlotLineBuffer'],
|
||||||
function (PlotLine, PlotLineBuffer) {
|
function (PlotLine, PlotLineBuffer) {
|
||||||
@ -44,84 +40,37 @@ define(
|
|||||||
* @param {TelemetryHandle} handle the handle to telemetry access
|
* @param {TelemetryHandle} handle the handle to telemetry access
|
||||||
* @param {string} domain the key to use when looking up domain values
|
* @param {string} domain the key to use when looking up domain values
|
||||||
* @param {string} range the key to use when looking up range values
|
* @param {string} range the key to use when looking up range values
|
||||||
* @param {number} maxDuration maximum plot duration to display
|
* @param {number} fixedDuration maximum plot duration to display
|
||||||
* @param {number} maxPoints maximum number of points to display
|
* @param {number} maxPoints maximum number of points to display
|
||||||
*/
|
*/
|
||||||
function PlotUpdater(handle, domain, range, fixedDuration, maxPoints) {
|
function PlotUpdater(handle, domain, range, fixedDuration, maxPoints) {
|
||||||
var ids = [],
|
this.handle = handle;
|
||||||
lines = {},
|
this.domain = domain;
|
||||||
dimensions = [0, 0],
|
this.range = range;
|
||||||
origin = [0, 0],
|
this.fixedDuration = fixedDuration;
|
||||||
domainExtrema,
|
this.maxPoints = maxPoints;
|
||||||
rangeExtrema,
|
|
||||||
buffers = {},
|
this.ids = [];
|
||||||
bufferArray = [],
|
this.lines = {};
|
||||||
domainOffset;
|
this.buffers = {};
|
||||||
|
this.bufferArray = [];
|
||||||
|
|
||||||
|
// Use a default MAX_POINTS if none is provided
|
||||||
|
this.maxPoints = maxPoints !== undefined ? maxPoints : MAX_POINTS;
|
||||||
|
this.dimensions = [0, 0];
|
||||||
|
this.origin = [0, 0];
|
||||||
|
|
||||||
|
// Initially prepare state for these objects.
|
||||||
|
// Note that this may be an empty array at this time,
|
||||||
|
// so we also need to check during update cycles.
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
// Look up a domain object's id (for mapping, below)
|
// Look up a domain object's id (for mapping, below)
|
||||||
function getId(domainObject) {
|
function getId(domainObject) {
|
||||||
return domainObject.getId();
|
return domainObject.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this set of ids matches the current set of ids
|
|
||||||
// (used to detect if line preparation can be skipped)
|
|
||||||
function idsMatch(nextIds) {
|
|
||||||
return ids.length === nextIds.length &&
|
|
||||||
nextIds.every(function (id, index) {
|
|
||||||
return ids[index] === id;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare plot lines for this group of telemetry objects
|
|
||||||
function prepareLines(telemetryObjects) {
|
|
||||||
var nextIds = telemetryObjects.map(getId),
|
|
||||||
next = {};
|
|
||||||
|
|
||||||
// Detect if we already have everything we need prepared
|
|
||||||
if (idsMatch(nextIds)) {
|
|
||||||
// Nothing to prepare, move on
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Built up a set of ids. Note that we can only
|
|
||||||
// create plot lines after our domain offset has
|
|
||||||
// been determined.
|
|
||||||
if (domainOffset !== undefined) {
|
|
||||||
// Update list of ids in use
|
|
||||||
ids = nextIds;
|
|
||||||
|
|
||||||
// Create buffers for these objects
|
|
||||||
bufferArray = ids.map(function (id) {
|
|
||||||
buffers[id] = buffers[id] || new PlotLineBuffer(
|
|
||||||
domainOffset,
|
|
||||||
INITIAL_SIZE,
|
|
||||||
maxPoints
|
|
||||||
);
|
|
||||||
next[id] = lines[id] || new PlotLine(buffers[id]);
|
|
||||||
return buffers[id];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are no more lines, clear the domain offset
|
|
||||||
if (Object.keys(next).length < 1) {
|
|
||||||
domainOffset = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update to the current set of lines
|
|
||||||
lines = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize the domain offset, based on these observed values
|
|
||||||
function initializeDomainOffset(values) {
|
|
||||||
domainOffset =
|
|
||||||
((domainOffset === undefined) && (values.length > 0)) ?
|
|
||||||
(values.reduce(function (a, b) {
|
|
||||||
return (a || 0) + (b || 0);
|
|
||||||
}, 0) / values.length) :
|
|
||||||
domainOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used in the reduce step of updateExtrema
|
// Used in the reduce step of updateExtrema
|
||||||
function reduceExtrema(a, b) {
|
function reduceExtrema(a, b) {
|
||||||
return [ Math.min(a[0], b[0]), Math.max(a[1], b[1]) ];
|
return [ Math.min(a[0], b[0]), Math.max(a[1], b[1]) ];
|
||||||
@ -137,164 +86,167 @@ define(
|
|||||||
return extrema[0];
|
return extrema[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand range slightly so points near edges are visible
|
// Check if this set of ids matches the current set of ids
|
||||||
function expandRange() {
|
// (used to detect if line preparation can be skipped)
|
||||||
var padding = PADDING_RATIO * dimensions[1],
|
PlotUpdater.prototype.idsMatch = function (nextIds) {
|
||||||
top;
|
var ids = this.ids;
|
||||||
padding = Math.max(padding, 1.0);
|
return ids.length === nextIds.length &&
|
||||||
top = Math.ceil(origin[1] + dimensions[1] + padding / 2);
|
nextIds.every(function (id, index) {
|
||||||
origin[1] = Math.floor(origin[1] - padding / 2);
|
return ids[index] === id;
|
||||||
dimensions[1] = top - origin[1];
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prepare plot lines for this group of telemetry objects
|
||||||
|
PlotUpdater.prototype.prepareLines = function (telemetryObjects) {
|
||||||
|
var nextIds = telemetryObjects.map(getId),
|
||||||
|
next = {},
|
||||||
|
self = this;
|
||||||
|
|
||||||
|
// Detect if we already have everything we need prepared
|
||||||
|
if (this.idsMatch(nextIds)) {
|
||||||
|
// Nothing to prepare, move on
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Built up a set of ids. Note that we can only
|
||||||
|
// create plot lines after our domain offset has
|
||||||
|
// been determined.
|
||||||
|
if (this.domainOffset !== undefined) {
|
||||||
|
// Update list of ids in use
|
||||||
|
this.ids = nextIds;
|
||||||
|
|
||||||
|
// Create buffers for these objects
|
||||||
|
this.bufferArray = this.ids.map(function (id) {
|
||||||
|
self.buffers[id] = self.buffers[id] || new PlotLineBuffer(
|
||||||
|
self.domainOffset,
|
||||||
|
INITIAL_SIZE,
|
||||||
|
self.maxPoints
|
||||||
|
);
|
||||||
|
next[id] =
|
||||||
|
self.lines[id] || new PlotLine(self.buffers[id]);
|
||||||
|
return self.buffers[id];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are no more lines, clear the domain offset
|
||||||
|
if (Object.keys(next).length < 1) {
|
||||||
|
this.domainOffset = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update to the current set of lines
|
||||||
|
this.lines = next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize the domain offset, based on these observed values
|
||||||
|
PlotUpdater.prototype.initializeDomainOffset = function (values) {
|
||||||
|
this.domainOffset =
|
||||||
|
((this.domainOffset === undefined) && (values.length > 0)) ?
|
||||||
|
(values.reduce(function (a, b) {
|
||||||
|
return (a || 0) + (b || 0);
|
||||||
|
}, 0) / values.length) :
|
||||||
|
this.domainOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Expand range slightly so points near edges are visible
|
||||||
|
PlotUpdater.prototype.expandRange = function () {
|
||||||
|
var padding = PADDING_RATIO * this.dimensions[1],
|
||||||
|
top;
|
||||||
|
padding = Math.max(padding, 1.0);
|
||||||
|
top = Math.ceil(this.origin[1] + this.dimensions[1] + padding / 2);
|
||||||
|
this.origin[1] = Math.floor(this.origin[1] - padding / 2);
|
||||||
|
this.dimensions[1] = top - this.origin[1];
|
||||||
|
};
|
||||||
|
|
||||||
// Update dimensions and origin based on extrema of plots
|
// Update dimensions and origin based on extrema of plots
|
||||||
function updateBounds() {
|
PlotUpdater.prototype.updateBounds = function () {
|
||||||
|
var bufferArray = this.bufferArray;
|
||||||
if (bufferArray.length > 0) {
|
if (bufferArray.length > 0) {
|
||||||
domainExtrema = bufferArray.map(function (lineBuffer) {
|
this.domainExtrema = bufferArray.map(function (lineBuffer) {
|
||||||
return lineBuffer.getDomainExtrema();
|
return lineBuffer.getDomainExtrema();
|
||||||
}).reduce(reduceExtrema);
|
}).reduce(reduceExtrema);
|
||||||
|
|
||||||
rangeExtrema = bufferArray.map(function (lineBuffer) {
|
this.rangeExtrema = bufferArray.map(function (lineBuffer) {
|
||||||
return lineBuffer.getRangeExtrema();
|
return lineBuffer.getRangeExtrema();
|
||||||
}).reduce(reduceExtrema);
|
}).reduce(reduceExtrema);
|
||||||
|
|
||||||
// Calculate best-fit dimensions
|
// Calculate best-fit dimensions
|
||||||
dimensions =
|
this.dimensions = [ this.domainExtrema, this.rangeExtrema ]
|
||||||
[dimensionsOf(domainExtrema), dimensionsOf(rangeExtrema)];
|
.map(dimensionsOf);
|
||||||
origin = [originOf(domainExtrema), originOf(rangeExtrema)];
|
this.origin = [ this.domainExtrema, this.rangeExtrema ]
|
||||||
|
.map(originOf);
|
||||||
|
|
||||||
// Enforce some minimum visible area
|
// Enforce some minimum visible area
|
||||||
expandRange();
|
this.expandRange();
|
||||||
|
|
||||||
// ...then enforce a fixed duration if needed
|
// ...then enforce a fixed duration if needed
|
||||||
if (fixedDuration !== undefined) {
|
if (this.fixedDuration !== undefined) {
|
||||||
origin[0] = origin[0] + dimensions[0] - fixedDuration;
|
this.origin[0] = this.origin[0] + this.dimensions[0] -
|
||||||
dimensions[0] = fixedDuration;
|
this.fixedDuration;
|
||||||
}
|
this.dimensions[0] = this.fixedDuration;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enforce maximum duration on all plot lines; not that
|
|
||||||
// domain extrema must be up-to-date for this to behave correctly.
|
|
||||||
function enforceDuration() {
|
|
||||||
var cutoff;
|
|
||||||
|
|
||||||
function enforceDurationForBuffer(plotLineBuffer) {
|
|
||||||
var index = plotLineBuffer.findInsertionIndex(cutoff);
|
|
||||||
if (index > 0) {
|
|
||||||
// Leave one point untrimmed, such that line will
|
|
||||||
// continue off left edge of visible plot area.
|
|
||||||
plotLineBuffer.trim(index - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fixedDuration !== undefined &&
|
|
||||||
domainExtrema !== undefined &&
|
|
||||||
(domainExtrema[1] - domainExtrema[0] > fixedDuration)) {
|
|
||||||
cutoff = domainExtrema[1] - fixedDuration;
|
|
||||||
bufferArray.forEach(enforceDurationForBuffer);
|
|
||||||
updateBounds(); // Extrema may have changed now
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Add latest data for this domain object
|
// Add latest data for this domain object
|
||||||
function addPointFor(domainObject) {
|
PlotUpdater.prototype.addPointFor = function (domainObject) {
|
||||||
var line = lines[domainObject.getId()];
|
var line = this.lines[domainObject.getId()];
|
||||||
if (line) {
|
if (line) {
|
||||||
line.addPoint(
|
line.addPoint(
|
||||||
handle.getDomainValue(domainObject, domain),
|
this.handle.getDomainValue(domainObject, this.domain),
|
||||||
handle.getRangeValue(domainObject, range)
|
this.handle.getRangeValue(domainObject, this.range)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Handle new telemetry data
|
/**
|
||||||
function update() {
|
* Update with latest data.
|
||||||
var objects = handle.getTelemetryObjects();
|
*/
|
||||||
|
PlotUpdater.prototype.update = function update() {
|
||||||
|
var objects = this.handle.getTelemetryObjects(),
|
||||||
|
self = this;
|
||||||
|
|
||||||
// Initialize domain offset if necessary
|
// Initialize domain offset if necessary
|
||||||
if (domainOffset === undefined) {
|
if (this.domainOffset === undefined) {
|
||||||
initializeDomainOffset(objects.map(function (obj) {
|
this.initializeDomainOffset(objects.map(function (obj) {
|
||||||
return handle.getDomainValue(obj, domain);
|
return self.handle.getDomainValue(obj, self.domain);
|
||||||
}).filter(function (value) {
|
}).filter(function (value) {
|
||||||
return typeof value === 'number';
|
return typeof value === 'number';
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure lines are available
|
// Make sure lines are available
|
||||||
prepareLines(objects);
|
this.prepareLines(objects);
|
||||||
|
|
||||||
// Add new data
|
// Add new data
|
||||||
objects.forEach(addPointFor);
|
objects.forEach(function (domainObject, index) {
|
||||||
|
self.addPointFor(domainObject, index);
|
||||||
|
});
|
||||||
|
|
||||||
// Then, update extrema
|
// Then, update extrema
|
||||||
updateBounds();
|
this.updateBounds();
|
||||||
}
|
};
|
||||||
|
|
||||||
// Add historical data for this domain object
|
|
||||||
function setHistorical(domainObject, series) {
|
|
||||||
var count = series ? series.getPointCount() : 0,
|
|
||||||
line;
|
|
||||||
|
|
||||||
// Nothing to do if it's an empty series
|
|
||||||
if (count < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize domain offset if necessary
|
|
||||||
if (domainOffset === undefined) {
|
|
||||||
initializeDomainOffset([
|
|
||||||
series.getDomainValue(0, domain),
|
|
||||||
series.getDomainValue(count - 1, domain)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure lines are available
|
|
||||||
prepareLines(handle.getTelemetryObjects());
|
|
||||||
|
|
||||||
// Look up the line for this domain object
|
|
||||||
line = lines[domainObject.getId()];
|
|
||||||
|
|
||||||
// ...and put the data into it.
|
|
||||||
if (line) {
|
|
||||||
line.addSeries(series, domain, range);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update extrema
|
|
||||||
updateBounds();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use a default MAX_POINTS if none is provided
|
|
||||||
maxPoints = maxPoints !== undefined ? maxPoints : MAX_POINTS;
|
|
||||||
|
|
||||||
// Initially prepare state for these objects.
|
|
||||||
// Note that this may be an empty array at this time,
|
|
||||||
// so we also need to check during update cycles.
|
|
||||||
update();
|
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
/**
|
||||||
* Get the dimensions which bound all data in the provided
|
* Get the dimensions which bound all data in the provided
|
||||||
* data sets. This is given as a two-element array where the
|
* data sets. This is given as a two-element array where the
|
||||||
* first element is domain, and second is range.
|
* first element is domain, and second is range.
|
||||||
* @returns {number[]} the dimensions which bound this data set
|
* @returns {number[]} the dimensions which bound this data set
|
||||||
* @memberof platform/features/plot.PlotUpdater#
|
|
||||||
*/
|
*/
|
||||||
getDimensions: function () {
|
PlotUpdater.prototype.getDimensions = function () {
|
||||||
return dimensions;
|
return this.dimensions;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the origin of this data set's boundary.
|
* Get the origin of this data set's boundary.
|
||||||
* This is given as a two-element array where the
|
* This is given as a two-element array where the
|
||||||
* first element is domain, and second is range.
|
* first element is domain, and second is range.
|
||||||
* The domain value here is not adjusted by the domain offset.
|
* The domain value here is not adjusted by the domain offset.
|
||||||
* @returns {number[]} the origin of this data set's boundary
|
* @returns {number[]} the origin of this data set's boundary
|
||||||
* @memberof platform/features/plot.PlotUpdater#
|
|
||||||
*/
|
*/
|
||||||
getOrigin: function () {
|
PlotUpdater.prototype.getOrigin = function () {
|
||||||
// Pad range if necessary
|
return this.origin;
|
||||||
return origin;
|
};
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* Get the domain offset; this offset will have been subtracted
|
* Get the domain offset; this offset will have been subtracted
|
||||||
* from all domain values in all buffers returned by this
|
* from all domain values in all buffers returned by this
|
||||||
@ -303,9 +255,10 @@ define(
|
|||||||
* @returns {number} the domain offset
|
* @returns {number} the domain offset
|
||||||
* @memberof platform/features/plot.PlotUpdater#
|
* @memberof platform/features/plot.PlotUpdater#
|
||||||
*/
|
*/
|
||||||
getDomainOffset: function () {
|
PlotUpdater.prototype.getDomainOffset = function () {
|
||||||
return domainOffset;
|
return this.domainOffset;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all renderable buffers for this data set. This will
|
* Get all renderable buffers for this data set. This will
|
||||||
* be returned as an array which can be correlated back to
|
* be returned as an array which can be correlated back to
|
||||||
@ -324,22 +277,45 @@ define(
|
|||||||
* @returns {Float32Array[]} the buffers for these traces
|
* @returns {Float32Array[]} the buffers for these traces
|
||||||
* @memberof platform/features/plot.PlotUpdater#
|
* @memberof platform/features/plot.PlotUpdater#
|
||||||
*/
|
*/
|
||||||
getLineBuffers: function () {
|
PlotUpdater.prototype.getLineBuffers = function () {
|
||||||
return bufferArray;
|
return this.bufferArray;
|
||||||
},
|
};
|
||||||
/**
|
|
||||||
* Update with latest data.
|
|
||||||
* @memberof platform/features/plot.PlotUpdater#
|
|
||||||
*/
|
|
||||||
update: update,
|
|
||||||
/**
|
/**
|
||||||
* Fill in historical data.
|
* Fill in historical data.
|
||||||
* @memberof platform/features/plot.PlotUpdater#
|
|
||||||
*/
|
*/
|
||||||
addHistorical: setHistorical
|
PlotUpdater.prototype.addHistorical = function (domainObject, series) {
|
||||||
};
|
var count = series ? series.getPointCount() : 0,
|
||||||
|
line;
|
||||||
|
|
||||||
|
// Nothing to do if it's an empty series
|
||||||
|
if (count < 1) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize domain offset if necessary
|
||||||
|
if (this.domainOffset === undefined) {
|
||||||
|
this.initializeDomainOffset([
|
||||||
|
series.getDomainValue(0, this.domain),
|
||||||
|
series.getDomainValue(count - 1, this.domain)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure lines are available
|
||||||
|
this.prepareLines(this.handle.getTelemetryObjects());
|
||||||
|
|
||||||
|
// Look up the line for this domain object
|
||||||
|
line = this.lines[domainObject.getId()];
|
||||||
|
|
||||||
|
// ...and put the data into it.
|
||||||
|
if (line) {
|
||||||
|
line.addSeries(series, this.domain, this.range);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update extrema
|
||||||
|
this.updateBounds();
|
||||||
|
};
|
||||||
|
|
||||||
return PlotUpdater;
|
return PlotUpdater;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user