diff --git a/platform/features/plot/src/elements/PlotLineBuffer.js b/platform/features/plot/src/elements/PlotLineBuffer.js index 8a1f6a715f..d875c9bc06 100644 --- a/platform/features/plot/src/elements/PlotLineBuffer.js +++ b/platform/features/plot/src/elements/PlotLineBuffer.js @@ -5,6 +5,13 @@ define( function () { "use strict"; + /** + * Contains the buffer used to draw a plot. + * @param {number} domainOffset number to subtract from domain values + * @param {number} initialSize initial buffer size + * @param {number} maxSize maximum buffer size + * @constructor + */ function PlotLineBuffer(domainOffset, initialSize, maxSize) { var buffer = new Float32Array(initialSize * 2), length = 0; @@ -49,10 +56,60 @@ define( return canDouble; } + // Decrease the size of the buffer + function halveBufferSize() { + var sz = Math.max(initialSize, buffer.length / 2), + canHalve = sz < buffer.length; + + if (canHalve) { + buffer = new Float32Array(buffer.subarray(0, sz)); + } + + return canHalve; + } + + return { + /** + * Get the WebGL-displayable buffer of points to plot. + * @returns {Float32Array} displayable buffer for this line + */ getBuffer: function () { return buffer; }, + /** + * Remove values from this buffer. + * Normally, values are removed from the start + * of the buffer; a truthy value in the second argument + * will cause values to be removed from the end. + * @param {number} count number of values to remove + * @param {boolean} [fromEnd] true if the most recent + * values should be removed + */ + trim: function (count, fromEnd) { + // If we're removing values from the start... + if (!fromEnd) { + // ...do so by shifting buffer contents over + buffer.set(buffer.subarray(2 * count)); + } + // Reduce used buffer size accordingly + length -= count; + // Finally, if less than half of the buffer is being + // used, free up some memory. + if (length < buffer.length / 4) { + halveBufferSize(); + } + }, + /** + * Insert data from the provided series at the specified + * index. If this would exceed the buffer's maximum capacity, + * this operation fails and the buffer is unchanged. + * @param {TelemetrySeries} series the series to insert + * @param {number} index the index at which to insert this + * series + * @returns {boolean} true if insertion succeeded; otherwise + * false + */ insert: function (series, index) { var sz = series.getPointCount(), free = (buffer.length / 2) - length, @@ -66,13 +123,21 @@ define( // Resize if necessary if (sz > free) { if (!doubleBufferSize()) { - // TODO: Figure out which data to discard - i = 0; + // Can't make room for this, insertion fails + return false; } } + // Shift data over if necessary + if (index < length) { + buffer.set( + buffer.subarray(index, length - index), + index + sz + ); + } + // Insert data into the set - for (i = 0; i < series.getPointCount(); i += 1) { + for (i = 0; i < sz; i += 1) { buffer[(i + index) * 2] = series.getDomainValue(i) - domainOffset; buffer[(i + index) * 2 + 1] = @@ -81,6 +146,9 @@ define( // Increase the length length += sz; + + // Indicate that insertion was successful + return true; }, /** * Find an index for inserting data with this