mirror of
https://github.com/nasa/openmct.git
synced 2025-05-29 21:54:20 +00:00
[Plot] Add JSDoc
Add inline comments to Plot scripts. WTD-533.
This commit is contained in:
parent
870172ec6f
commit
622f1f8be7
@ -1,4 +1,4 @@
|
|||||||
/*global define,Promise,Float32Array*/
|
/*global define,Float32Array*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module defining GLPlot. Created by vwoeltje on 11/12/14.
|
* Module defining GLPlot. Created by vwoeltje on 11/12/14.
|
||||||
@ -8,6 +8,7 @@ define(
|
|||||||
function () {
|
function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
// WebGL shader sources (for drawing plain colors)
|
||||||
var FRAGMENT_SHADER = [
|
var FRAGMENT_SHADER = [
|
||||||
"precision mediump float;",
|
"precision mediump float;",
|
||||||
"uniform vec4 uColor;",
|
"uniform vec4 uColor;",
|
||||||
@ -24,6 +25,13 @@ define(
|
|||||||
"}"
|
"}"
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new chart which uses WebGL for rendering.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {CanvasElement} canvas the canvas object to render upon
|
||||||
|
* @throws {Error} an error is thrown if WebGL is unavailable.
|
||||||
|
*/
|
||||||
function GLChart(canvas) {
|
function GLChart(canvas) {
|
||||||
var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"),
|
var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"),
|
||||||
vertexShader,
|
vertexShader,
|
||||||
@ -35,6 +43,7 @@ define(
|
|||||||
uOrigin,
|
uOrigin,
|
||||||
buffer;
|
buffer;
|
||||||
|
|
||||||
|
// Ensure a context was actually available before proceeding
|
||||||
if (!gl) {
|
if (!gl) {
|
||||||
throw new Error("WebGL unavailable.");
|
throw new Error("WebGL unavailable.");
|
||||||
}
|
}
|
||||||
@ -47,25 +56,33 @@ define(
|
|||||||
gl.shaderSource(fragmentShader, FRAGMENT_SHADER);
|
gl.shaderSource(fragmentShader, FRAGMENT_SHADER);
|
||||||
gl.compileShader(fragmentShader);
|
gl.compileShader(fragmentShader);
|
||||||
|
|
||||||
|
// Assemble vertex/fragment shaders into programs
|
||||||
program = gl.createProgram();
|
program = gl.createProgram();
|
||||||
gl.attachShader(program, vertexShader);
|
gl.attachShader(program, vertexShader);
|
||||||
gl.attachShader(program, fragmentShader);
|
gl.attachShader(program, fragmentShader);
|
||||||
gl.linkProgram(program);
|
gl.linkProgram(program);
|
||||||
gl.useProgram(program);
|
gl.useProgram(program);
|
||||||
|
|
||||||
|
// Get locations for attribs/uniforms from the
|
||||||
|
// shader programs (to pass values into shaders at draw-time)
|
||||||
aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
|
aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
|
||||||
gl.enableVertexAttribArray(aVertexPosition);
|
|
||||||
|
|
||||||
uColor = gl.getUniformLocation(program, "uColor");
|
uColor = gl.getUniformLocation(program, "uColor");
|
||||||
uDimensions = gl.getUniformLocation(program, "uDimensions");
|
uDimensions = gl.getUniformLocation(program, "uDimensions");
|
||||||
uOrigin = gl.getUniformLocation(program, "uOrigin");
|
uOrigin = gl.getUniformLocation(program, "uOrigin");
|
||||||
|
gl.enableVertexAttribArray(aVertexPosition);
|
||||||
|
|
||||||
|
// Create a buffer to holds points which will be drawn
|
||||||
buffer = gl.createBuffer();
|
buffer = gl.createBuffer();
|
||||||
|
|
||||||
|
// Use a line width of 2.0 for legibility
|
||||||
gl.lineWidth(2.0);
|
gl.lineWidth(2.0);
|
||||||
|
|
||||||
|
// Enable blending, for smoothness
|
||||||
gl.enable(gl.BLEND);
|
gl.enable(gl.BLEND);
|
||||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// Utility function to handle drawing of a buffer;
|
||||||
|
// drawType will determine whether this is a box, line, etc.
|
||||||
function doDraw(drawType, buf, color, points) {
|
function doDraw(drawType, buf, color, points) {
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||||
gl.bufferData(gl.ARRAY_BUFFER, buf, gl.DYNAMIC_DRAW);
|
gl.bufferData(gl.ARRAY_BUFFER, buf, gl.DYNAMIC_DRAW);
|
||||||
@ -75,23 +92,51 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* Clear the chart.
|
||||||
|
*/
|
||||||
clear: function () {
|
clear: function () {
|
||||||
gl.viewport(0, 0, canvas.width, canvas.height);
|
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT);
|
gl.clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Set the logical boundaries of the chart.
|
||||||
|
* @param {number[]} dimensions the horizontal and
|
||||||
|
* vertical dimensions of the chart
|
||||||
|
* @param {number[]} origin the horizontal/vertical
|
||||||
|
* origin of the chart
|
||||||
|
*/
|
||||||
setDimensions: function (dimensions, origin) {
|
setDimensions: function (dimensions, origin) {
|
||||||
gl.uniform2fv(uDimensions, dimensions);
|
gl.uniform2fv(uDimensions, dimensions);
|
||||||
gl.uniform2fv(uOrigin, origin);
|
gl.uniform2fv(uOrigin, origin);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Draw the supplied buffer as a line strip (a sequence
|
||||||
|
* of line segments), in the chosen color.
|
||||||
|
* @param {Float32Array} buf the line strip to draw,
|
||||||
|
* in alternating x/y positions
|
||||||
|
* @param {number[]} color the color to use when drawing
|
||||||
|
* the line, as an RGBA color where each element
|
||||||
|
* is in the range of 0.0-1.0
|
||||||
|
* @param {number} points the number of points to draw
|
||||||
|
*/
|
||||||
drawLine: function (buf, color, points) {
|
drawLine: function (buf, color, points) {
|
||||||
doDraw(gl.LINE_STRIP, buf, color, points);
|
doDraw(gl.LINE_STRIP, buf, color, points);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Draw a rectangle extending from one corner to another,
|
||||||
|
* in the chosen color.
|
||||||
|
* @param {number[]} min the first corner of the rectangle
|
||||||
|
* @param {number[]} max the opposite corner
|
||||||
|
* @param {number[]} color the color to use when drawing
|
||||||
|
* the rectangle, as an RGBA color where each element
|
||||||
|
* is in the range of 0.0-1.0
|
||||||
|
*/
|
||||||
drawSquare: function (min, max, color) {
|
drawSquare: function (min, max, color) {
|
||||||
doDraw(gl.TRIANGLE_FAN, new Float32Array(
|
doDraw(gl.TRIANGLE_FAN, new Float32Array(
|
||||||
min.concat([min[0], max[1]]).concat(max).concat([max[0], min[1]])
|
min.concat([min[0], max[1]]).concat(max).concat([max[0], min[1]])
|
||||||
), color, 4);
|
), color, 4);
|
||||||
},
|
}
|
||||||
gl: gl
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return GLChart;
|
return GLChart;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*global define,Promise*/
|
/*global define*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module defining MCTChart. Created by vwoeltje on 11/12/14.
|
* Module defining MCTChart. Created by vwoeltje on 11/12/14.
|
||||||
@ -11,6 +11,34 @@ define(
|
|||||||
var TEMPLATE = "<canvas style='position: absolute; background: none; width: 100%; height: 100%;'></canvas>";
|
var TEMPLATE = "<canvas style='position: absolute; background: none; width: 100%; height: 100%;'></canvas>";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The mct-chart directive provides a canvas element which can be
|
||||||
|
* drawn upon, to support Plot view and similar visualizations.
|
||||||
|
*
|
||||||
|
* This directive takes one attribute, "draw", which is an Angular
|
||||||
|
* expression which will be two-way bound to a drawing object. This
|
||||||
|
* drawing object should contain:
|
||||||
|
*
|
||||||
|
* * `dimensions`: An object describing the logical bounds of the
|
||||||
|
* drawable area, containing two fields:
|
||||||
|
* * `origin`: The position, in logical coordinates, of the
|
||||||
|
* lower-left corner of the chart area. A two-element array.
|
||||||
|
* * `dimensions`: A two-element array containing the width
|
||||||
|
* and height of the chart area, in logical coordinates.
|
||||||
|
* * `lines`: An array of lines to be drawn, where each line is
|
||||||
|
* expressed as an object containing:
|
||||||
|
* * `buffer`: A Float32Array containing points in the line,
|
||||||
|
* in logical coordinate, in sequential x/y pairs.
|
||||||
|
* * `color`: The color of the line, as a four-element RGBA
|
||||||
|
* array, where each element is in the range of 0.0-1.0
|
||||||
|
* * `points`: The number of points in the line.
|
||||||
|
* * `boxes`: An array of rectangles to draw in the chart area
|
||||||
|
* (used for marquee zoom). Each is an object containing:
|
||||||
|
* * `start`: The first corner of the rectangle (as a two-element
|
||||||
|
* array, logical coordinates)
|
||||||
|
* * `end`: The opposite corner of the rectangle (again, as a
|
||||||
|
* two-element array)
|
||||||
|
* * `color`: The color of the box, as a four-element RGBA
|
||||||
|
* array, where each element is in the range of 0.0-1.0
|
||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
@ -30,20 +58,29 @@ define(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle drawing, based on contents of the "draw" object
|
||||||
|
// in scope
|
||||||
function doDraw(draw) {
|
function doDraw(draw) {
|
||||||
|
// Ensure canvas context has same resolution
|
||||||
|
// as canvas element
|
||||||
canvas.width = canvas.offsetWidth;
|
canvas.width = canvas.offsetWidth;
|
||||||
canvas.height = canvas.offsetHeight;
|
canvas.height = canvas.offsetHeight;
|
||||||
|
|
||||||
|
// Clear previous contents
|
||||||
chart.clear();
|
chart.clear();
|
||||||
|
|
||||||
|
// Nothing to draw if no draw object defined
|
||||||
if (!draw) {
|
if (!draw) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set logical boundaries for the chart
|
||||||
chart.setDimensions(
|
chart.setDimensions(
|
||||||
draw.dimensions || [1, 1],
|
draw.dimensions || [1, 1],
|
||||||
draw.origin || [0, 0]
|
draw.origin || [0, 0]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Draw line segments
|
||||||
(draw.lines || []).forEach(function (line) {
|
(draw.lines || []).forEach(function (line) {
|
||||||
chart.drawLine(
|
chart.drawLine(
|
||||||
line.buffer,
|
line.buffer,
|
||||||
@ -52,6 +89,7 @@ define(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Draw boxes (e.g. marquee zoom rect)
|
||||||
(draw.boxes || []).forEach(function (box) {
|
(draw.boxes || []).forEach(function (box) {
|
||||||
chart.drawSquare(
|
chart.drawSquare(
|
||||||
box.start,
|
box.start,
|
||||||
@ -62,6 +100,9 @@ define(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue a drawing call, if-and-only-if canvas size
|
||||||
|
// has changed. This will be called on a timer, since
|
||||||
|
// there is no event to depend on.
|
||||||
function drawIfResized() {
|
function drawIfResized() {
|
||||||
if (canvas.width !== canvas.offsetWidth ||
|
if (canvas.width !== canvas.offsetWidth ||
|
||||||
canvas.height !== canvas.offsetHeight) {
|
canvas.height !== canvas.offsetHeight) {
|
||||||
@ -69,14 +110,25 @@ define(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for resize, on a timer
|
||||||
$interval(drawIfResized, 1000);
|
$interval(drawIfResized, 1000);
|
||||||
|
|
||||||
|
// Watch "draw" for external changes to the set of
|
||||||
|
// things to be drawn.
|
||||||
scope.$watchCollection("draw", doDraw);
|
scope.$watchCollection("draw", doDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
// Apply directive only to elements
|
||||||
restrict: "E",
|
restrict: "E",
|
||||||
|
|
||||||
|
// Template to use (a canvas element)
|
||||||
template: TEMPLATE,
|
template: TEMPLATE,
|
||||||
|
|
||||||
|
// Link function; set up scope
|
||||||
link: linkChart,
|
link: linkChart,
|
||||||
|
|
||||||
|
// Initial, isolate scope for the directive
|
||||||
scope: { draw: "=" }
|
scope: { draw: "=" }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*global define,moment,Promise*/
|
/*global define*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module defining PlotController. Created by vwoeltje on 11/12/14.
|
* Module defining PlotController. Created by vwoeltje on 11/12/14.
|
||||||
@ -32,6 +32,13 @@ define(
|
|||||||
RANGE_TICKS = 7;
|
RANGE_TICKS = 7;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The PlotController is responsible for any computation/logic
|
||||||
|
* associated with displaying the plot view. Specifically, these
|
||||||
|
* responsibilities include:
|
||||||
|
*
|
||||||
|
* * Describing axes and labeling.
|
||||||
|
* * Handling user interactions.
|
||||||
|
* * Deciding what needs to be drawn in the chart area.
|
||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
@ -50,6 +57,8 @@ define(
|
|||||||
formatter.formatDomainValue)(v);
|
formatter.formatDomainValue)(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts from pixel coordinates to domain-range,
|
||||||
|
// to interpret mouse gestures.
|
||||||
function mousePositionToDomainRange(mousePosition) {
|
function mousePositionToDomainRange(mousePosition) {
|
||||||
return new PlotPosition(
|
return new PlotPosition(
|
||||||
mousePosition.x,
|
mousePosition.x,
|
||||||
@ -60,11 +69,36 @@ define(
|
|||||||
).getPosition();
|
).getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Utility function to get the mouse position (in x,y
|
||||||
|
// pixel coordinates in the canvas area) from a mouse
|
||||||
|
// event object.
|
||||||
|
function toMousePosition($event) {
|
||||||
|
var target = $event.target,
|
||||||
|
bounds = target.getBoundingClientRect();
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: $event.clientX - bounds.left,
|
||||||
|
y: $event.clientY - bounds.top,
|
||||||
|
width: bounds.width,
|
||||||
|
height: bounds.height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a domain-range position to a displayable
|
||||||
|
// position. This will subtract the domain offset, which
|
||||||
|
// is used to bias domain values to minimize loss-of-precision
|
||||||
|
// associated with conversion to a 32-bit floating point
|
||||||
|
// format (which is needed in the chart area itself, by WebGL.)
|
||||||
function toDisplayable(position) {
|
function toDisplayable(position) {
|
||||||
return [ position[0] - domainOffset, position[1] ];
|
return [ position[0] - domainOffset, position[1] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the drawable marquee area to reflect current
|
||||||
|
// mouse position (or don't show it at all, if no marquee
|
||||||
|
// zoom is in progress)
|
||||||
function updateMarqueeBox() {
|
function updateMarqueeBox() {
|
||||||
|
// Express this as a box in the draw object, which
|
||||||
|
// is passed to an mct-chart in the template for rendering.
|
||||||
$scope.draw.boxes = marqueeStart ?
|
$scope.draw.boxes = marqueeStart ?
|
||||||
[{
|
[{
|
||||||
start: toDisplayable(mousePositionToDomainRange(marqueeStart)),
|
start: toDisplayable(mousePositionToDomainRange(marqueeStart)),
|
||||||
@ -73,9 +107,12 @@ define(
|
|||||||
}] : undefined;
|
}] : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the bounds (origin and dimensions) of the drawing area.
|
||||||
function updateDrawingBounds() {
|
function updateDrawingBounds() {
|
||||||
var panZoom = panZoomStack.getPanZoom();
|
var panZoom = panZoomStack.getPanZoom();
|
||||||
|
|
||||||
|
// Communicate pan-zoom state from stack to the draw object
|
||||||
|
// which is passed to mct-chart in the template.
|
||||||
$scope.draw.dimensions = panZoom.dimensions;
|
$scope.draw.dimensions = panZoom.dimensions;
|
||||||
$scope.draw.origin = [
|
$scope.draw.origin = [
|
||||||
panZoom.origin[0] - domainOffset,
|
panZoom.origin[0] - domainOffset,
|
||||||
@ -83,6 +120,7 @@ define(
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update tick marks in scope.
|
||||||
function updateTicks() {
|
function updateTicks() {
|
||||||
var tickGenerator = new PlotTickGenerator(panZoomStack, formatter);
|
var tickGenerator = new PlotTickGenerator(panZoomStack, formatter);
|
||||||
|
|
||||||
@ -92,6 +130,8 @@ define(
|
|||||||
tickGenerator.generateRangeTicks(RANGE_TICKS);
|
tickGenerator.generateRangeTicks(RANGE_TICKS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Populate the scope with axis information (specifically, options
|
||||||
|
// available for each axis.)
|
||||||
function setupAxes(metadatas) {
|
function setupAxes(metadatas) {
|
||||||
$scope.axes = [
|
$scope.axes = [
|
||||||
new PlotAxis("domain", metadatas, AXIS_DEFAULTS[0]),
|
new PlotAxis("domain", metadatas, AXIS_DEFAULTS[0]),
|
||||||
@ -99,34 +139,48 @@ define(
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Respond to newly-available telemetry data; update the
|
||||||
|
// drawing area accordingly.
|
||||||
function plotTelemetry() {
|
function plotTelemetry() {
|
||||||
var prepared, data, telemetry;
|
var prepared, datas, telemetry;
|
||||||
|
|
||||||
|
// Get a reference to the TelemetryController
|
||||||
telemetry = $scope.telemetry;
|
telemetry = $scope.telemetry;
|
||||||
|
|
||||||
|
// Nothing to plot without TelemetryController
|
||||||
if (!telemetry) {
|
if (!telemetry) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure axes have been initialized (we will want to
|
||||||
|
// get the active axis below)
|
||||||
if (!$scope.axes) {
|
if (!$scope.axes) {
|
||||||
setupAxes(telemetry.getMetadata());
|
setupAxes(telemetry.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
data = telemetry.getResponse();
|
// Get data sets
|
||||||
|
datas = telemetry.getResponse();
|
||||||
|
|
||||||
|
// Prepare data sets for rendering
|
||||||
prepared = new PlotPreparer(
|
prepared = new PlotPreparer(
|
||||||
data,
|
datas,
|
||||||
($scope.axes[0].active || {}).key,
|
($scope.axes[0].active || {}).key,
|
||||||
($scope.axes[1].active || {}).key
|
($scope.axes[1].active || {}).key
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Fit to the boundaries of the data, but don't
|
||||||
|
// override any user-initiated pan-zoom changes.
|
||||||
panZoomStack.setBasePanZoom(
|
panZoomStack.setBasePanZoom(
|
||||||
prepared.getOrigin(),
|
prepared.getOrigin(),
|
||||||
prepared.getDimensions()
|
prepared.getDimensions()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Track the domain offset, used to bias domain values
|
||||||
|
// to minimize loss of precision when converted to 32-bit
|
||||||
|
// floating point values for display.
|
||||||
domainOffset = prepared.getDomainOffset();
|
domainOffset = prepared.getDomainOffset();
|
||||||
|
|
||||||
|
// Draw the buffers. Select color by index.
|
||||||
$scope.draw.lines = prepared.getBuffers().map(function (buf, i) {
|
$scope.draw.lines = prepared.getBuffers().map(function (buf, i) {
|
||||||
return {
|
return {
|
||||||
buffer: buf,
|
buffer: buf,
|
||||||
@ -140,19 +194,11 @@ define(
|
|||||||
updateTicks();
|
updateTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toMousePosition($event) {
|
// Perform a marquee zoom.
|
||||||
var target = $event.target,
|
|
||||||
bounds = target.getBoundingClientRect();
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: $event.clientX - bounds.left,
|
|
||||||
y: $event.clientY - bounds.top,
|
|
||||||
width: bounds.width,
|
|
||||||
height: bounds.height
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function marqueeZoom(start, end) {
|
function marqueeZoom(start, end) {
|
||||||
|
// Determine what boundary is described by the marquee,
|
||||||
|
// in domain-range values. Use the minima for origin, so that
|
||||||
|
// it doesn't matter what direction the user marqueed in.
|
||||||
var a = mousePositionToDomainRange(start),
|
var a = mousePositionToDomainRange(start),
|
||||||
b = mousePositionToDomainRange(end),
|
b = mousePositionToDomainRange(end),
|
||||||
origin = [
|
origin = [
|
||||||
@ -164,7 +210,10 @@ define(
|
|||||||
Math.max(a[1], b[1]) - origin[1]
|
Math.max(a[1], b[1]) - origin[1]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Push the new state onto the pan-zoom stack
|
||||||
panZoomStack.pushPanZoom(origin, dimensions);
|
panZoomStack.pushPanZoom(origin, dimensions);
|
||||||
|
|
||||||
|
// Make sure tick marks reflect new bounds
|
||||||
updateTicks();
|
updateTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,25 +222,49 @@ define(
|
|||||||
$scope.draw = {};
|
$scope.draw = {};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* Get the color (as a style-friendly string) to use
|
||||||
|
* for plotting the trace at the specified index.
|
||||||
|
* @param {number} index the index of the trace
|
||||||
|
* @returns {string} the color, in #RRGGBB form
|
||||||
|
*/
|
||||||
getColor: function (index) {
|
getColor: function (index) {
|
||||||
return PlotPalette.getStringColor(index);
|
return PlotPalette.getStringColor(index);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Get the coordinates (as displayable text) for the
|
||||||
|
* current mouse position.
|
||||||
|
* @returns {string[]} the displayable domain and range
|
||||||
|
* coordinates over which the mouse is hovered
|
||||||
|
*/
|
||||||
getHoverCoordinates: function () {
|
getHoverCoordinates: function () {
|
||||||
return mousePosition ?
|
return mousePosition ?
|
||||||
mousePositionToDomainRange(
|
mousePositionToDomainRange(
|
||||||
mousePosition
|
mousePosition
|
||||||
).map(formatValue) : [];
|
).map(formatValue) : [];
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Handle mouse movement over the chart area.
|
||||||
|
* @param $event the mouse event
|
||||||
|
*/
|
||||||
hover: function ($event) {
|
hover: function ($event) {
|
||||||
mousePosition = toMousePosition($event);
|
mousePosition = toMousePosition($event);
|
||||||
if (marqueeStart) {
|
if (marqueeStart) {
|
||||||
updateMarqueeBox();
|
updateMarqueeBox();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Initiate a marquee zoom action.
|
||||||
|
* @param $event the mouse event
|
||||||
|
*/
|
||||||
startMarquee: function ($event) {
|
startMarquee: function ($event) {
|
||||||
mousePosition = marqueeStart = toMousePosition($event);
|
mousePosition = marqueeStart = toMousePosition($event);
|
||||||
updateMarqueeBox();
|
updateMarqueeBox();
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Complete a marquee zoom action.
|
||||||
|
* @param $event the mouse event
|
||||||
|
*/
|
||||||
endMarquee: function ($event) {
|
endMarquee: function ($event) {
|
||||||
mousePosition = toMousePosition($event);
|
mousePosition = toMousePosition($event);
|
||||||
if (marqueeStart) {
|
if (marqueeStart) {
|
||||||
@ -201,13 +274,26 @@ define(
|
|||||||
updateDrawingBounds();
|
updateDrawingBounds();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Check if the plot is zoomed or panned out
|
||||||
|
* of its default state (to determine whether back/unzoom
|
||||||
|
* controls should be shown)
|
||||||
|
* @returns {boolean} true if not in default state
|
||||||
|
*/
|
||||||
isZoomed: function () {
|
isZoomed: function () {
|
||||||
return panZoomStack.getDepth() > 1;
|
return panZoomStack.getDepth() > 1;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Undo the most recent pan/zoom change and restore
|
||||||
|
* the prior state.
|
||||||
|
*/
|
||||||
stepBackPanZoom: function () {
|
stepBackPanZoom: function () {
|
||||||
panZoomStack.popPanZoom();
|
panZoomStack.popPanZoom();
|
||||||
updateDrawingBounds();
|
updateDrawingBounds();
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Undo all pan/zoom changes and restore the initial state.
|
||||||
|
*/
|
||||||
unzoom: function () {
|
unzoom: function () {
|
||||||
panZoomStack.clearPanZoom();
|
panZoomStack.clearPanZoom();
|
||||||
updateDrawingBounds();
|
updateDrawingBounds();
|
||||||
|
@ -5,10 +5,30 @@ define(
|
|||||||
function () {
|
function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A PlotAxis provides a template-ready set of options
|
||||||
|
* for the domain or range axis, sufficient to populate
|
||||||
|
* selectors.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {string} axisType the field in metadatas to
|
||||||
|
* look at for axis options; usually one of
|
||||||
|
* "domains" or "ranges"
|
||||||
|
* @param {object[]} metadatas metadata objects, as
|
||||||
|
* returned by the `getMetadata()` method of
|
||||||
|
* a `telemetry` capability.
|
||||||
|
* @param {object} defaultValue the value to use for the
|
||||||
|
* active state in the event that no options are
|
||||||
|
* found; should contain "name" and "key" at
|
||||||
|
* minimum.
|
||||||
|
*
|
||||||
|
*/
|
||||||
function PlotAxis(axisType, metadatas, defaultValue) {
|
function PlotAxis(axisType, metadatas, defaultValue) {
|
||||||
var keys = {},
|
var keys = {},
|
||||||
options = [];
|
options = [];
|
||||||
|
|
||||||
|
// Look through all metadata objects and assemble a list
|
||||||
|
// of all possible domain or range options
|
||||||
function buildOptionsForMetadata(m) {
|
function buildOptionsForMetadata(m) {
|
||||||
(m[axisType] || []).forEach(function (option) {
|
(m[axisType] || []).forEach(function (option) {
|
||||||
if (!keys[option.key]) {
|
if (!keys[option.key]) {
|
||||||
@ -24,7 +44,18 @@ define(
|
|||||||
// template, so expose properties directly to facilitate
|
// template, so expose properties directly to facilitate
|
||||||
// two-way data binding (for drop-down menus)
|
// two-way data binding (for drop-down menus)
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* The set of options applicable for this axis;
|
||||||
|
* an array of objects, where each object contains a
|
||||||
|
* "key" field and a "name" field (for machine- and
|
||||||
|
* human-readable names respectively)
|
||||||
|
*/
|
||||||
options: options,
|
options: options,
|
||||||
|
/**
|
||||||
|
* The currently chosen option for this axis. An
|
||||||
|
* initial value is provided; this will be updated
|
||||||
|
* directly form the plot template.
|
||||||
|
*/
|
||||||
active: options[0] || defaultValue
|
active: options[0] || defaultValue
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,15 @@ define(
|
|||||||
function () {
|
function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
// Date format to use for domain values; in particular,
|
||||||
|
// use day-of-year instead of month/day
|
||||||
var DATE_FORMAT = "YYYY-DDD HH:mm:ss";
|
var DATE_FORMAT = "YYYY-DDD HH:mm:ss";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PlotFormatter is responsible for formatting (as text
|
||||||
|
* for display) values along either the domain or range of a
|
||||||
|
* plot.
|
||||||
|
*/
|
||||||
function PlotFormatter() {
|
function PlotFormatter() {
|
||||||
function formatDomainValue(v) {
|
function formatDomainValue(v) {
|
||||||
return moment.utc(v).format(DATE_FORMAT);
|
return moment.utc(v).format(DATE_FORMAT);
|
||||||
@ -17,7 +24,20 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* Format a domain value.
|
||||||
|
* @param {number} v the domain value; a timestamp
|
||||||
|
* in milliseconds since start of 1970
|
||||||
|
* @returns {string} a textual representation of the
|
||||||
|
* data and time, suitable for display.
|
||||||
|
*/
|
||||||
formatDomainValue: formatDomainValue,
|
formatDomainValue: formatDomainValue,
|
||||||
|
/**
|
||||||
|
* Format a range value.
|
||||||
|
* @param {number} v the range value; a numeric value
|
||||||
|
* @returns {string} a textual representation of the
|
||||||
|
* value, suitable for display.
|
||||||
|
*/
|
||||||
formatRangeValue: formatRangeValue
|
formatRangeValue: formatRangeValue
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -52,18 +52,57 @@ define(
|
|||||||
}).concat([1]); // RGBA
|
}).concat([1]); // RGBA
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PlotPalette allows a consistent set of colors to be retrieved
|
||||||
|
* by index, in various color formats. All PlotPalette methods are
|
||||||
|
* static, so there is no need for a constructor call; using
|
||||||
|
* this will simply return PlotPalette itself.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
function PlotPalette() {
|
function PlotPalette() {
|
||||||
return PlotPalette;
|
return PlotPalette;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a color in the plot's palette, by index.
|
||||||
|
* This will be returned as a three element array of RGB
|
||||||
|
* values, as integers in the range of 0-255.
|
||||||
|
* @param {number} i the index of the color to look up
|
||||||
|
* @return {number[]} the color, as integer RGB values
|
||||||
|
*/
|
||||||
PlotPalette.getIntegerColor = function (i) {
|
PlotPalette.getIntegerColor = function (i) {
|
||||||
return integerPalette[Math.floor(i) % integerPalette.length];
|
return integerPalette[Math.floor(i) % integerPalette.length];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a color in the plot's palette, by index.
|
||||||
|
* This will be returned as a three element array of RGB
|
||||||
|
* values, in the range of 0.0-1.0.
|
||||||
|
*
|
||||||
|
* This format is present specifically to support use with
|
||||||
|
* WebGL, which expects colors of that form.
|
||||||
|
*
|
||||||
|
* @param {number} i the index of the color to look up
|
||||||
|
* @return {number[]} the color, as floating-point RGB values
|
||||||
|
*/
|
||||||
PlotPalette.getFloatColor = function (i) {
|
PlotPalette.getFloatColor = function (i) {
|
||||||
return floatPalette[Math.floor(i) % floatPalette.length];
|
return floatPalette[Math.floor(i) % floatPalette.length];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up a color in the plot's palette, by index.
|
||||||
|
* This will be returned as a string using #-prefixed
|
||||||
|
* six-digit RGB hex notation (e.g. #FF0000)
|
||||||
|
* See http://www.w3.org/TR/css3-color/#rgb-color.
|
||||||
|
*
|
||||||
|
* This format is useful for representing colors in in-line
|
||||||
|
* styles.
|
||||||
|
*
|
||||||
|
* @param {number} i the index of the color to look up
|
||||||
|
* @return {string} the color, as a style-friendly string
|
||||||
|
*/
|
||||||
PlotPalette.getStringColor = function (i) {
|
PlotPalette.getStringColor = function (i) {
|
||||||
return stringPalette[Math.floor(i) % stringPalette.length];
|
return stringPalette[Math.floor(i) % stringPalette.length];
|
||||||
};
|
};
|
||||||
|
@ -5,9 +5,30 @@ define(
|
|||||||
function () {
|
function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PlotPanZoomStack is responsible for maintaining the
|
||||||
|
* pan-zoom state of a plot (expressed as a boundary starting
|
||||||
|
* at an origin and extending to certain dimensions) in a
|
||||||
|
* stack, to support the back and unzoom buttons in plot controls.
|
||||||
|
*
|
||||||
|
* Dimensions and origins are here described each by two-element
|
||||||
|
* arrays, where the first element describes a value or quantity
|
||||||
|
* along the domain axis, and the second element describes the same
|
||||||
|
* along the range axis.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {number[]} origin the plot's origin, initially
|
||||||
|
* @param {number[]} dimensions the plot's dimensions, initially
|
||||||
|
*/
|
||||||
function PlotPanZoomStack(origin, dimensions) {
|
function PlotPanZoomStack(origin, dimensions) {
|
||||||
|
// Use constructor parameters as the stack's initial state
|
||||||
var stack = [{ origin: origin, dimensions: dimensions }];
|
var stack = [{ origin: origin, dimensions: dimensions }];
|
||||||
|
|
||||||
|
// Various functions which follow are simply wrappers for
|
||||||
|
// normal stack-like array methods, with the exception that
|
||||||
|
// they prevent undesired modification and enforce that this
|
||||||
|
// stack must remain non-empty.
|
||||||
|
// See JSDoc for specific methods below for more detail.
|
||||||
function getDepth() {
|
function getDepth() {
|
||||||
return stack.length;
|
return stack.length;
|
||||||
}
|
}
|
||||||
@ -43,13 +64,70 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* Get the current stack depth; that is, the number
|
||||||
|
* of items on the stack. A depth of one means that no
|
||||||
|
* panning or zooming relative to the base value has
|
||||||
|
* been applied.
|
||||||
|
* @returns {number} the depth of the stack
|
||||||
|
*/
|
||||||
getDepth: getDepth,
|
getDepth: getDepth,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push a new pan-zoom state onto the stack; this will
|
||||||
|
* become the active pan-zoom state.
|
||||||
|
* @param {number[]} origin the new origin
|
||||||
|
* @param {number[]} dimensions the new dimensions
|
||||||
|
*/
|
||||||
pushPanZoom: pushPanZoom,
|
pushPanZoom: pushPanZoom,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pop a pan-zoom state from the stack. Whatever pan-zoom
|
||||||
|
* state was previously present will become current.
|
||||||
|
* If called when there is only one pan-zoom state on the
|
||||||
|
* stack, this acts as a no-op (that is, the lowest
|
||||||
|
* pan-zoom state on the stack cannot be popped, to ensure
|
||||||
|
* that some pan-zoom state is always available.)
|
||||||
|
*/
|
||||||
popPanZoom: popPanZoom,
|
popPanZoom: popPanZoom,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the base pan-zoom state; that is, the state at the
|
||||||
|
* bottom of the stack. This allows the "unzoomed" state of
|
||||||
|
* a plot to be updated (e.g. as new data comes in) without
|
||||||
|
* interfering with the user's chosen zoom level.
|
||||||
|
* @param {number[]} origin the base origin
|
||||||
|
* @param {number[]} dimensions the base dimensions
|
||||||
|
*/
|
||||||
setBasePanZoom: setBasePanZoom,
|
setBasePanZoom: setBasePanZoom,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the pan-zoom stack down to its bottom element;
|
||||||
|
* in effect, pop all elements but the last, e.g. to remove
|
||||||
|
* any temporary user modifications to pan-zoom state.
|
||||||
|
*/
|
||||||
clearPanZoom: clearPanZoom,
|
clearPanZoom: clearPanZoom,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current pan-zoom state (the state at the top
|
||||||
|
* of the stack), expressed as an object with "origin" and
|
||||||
|
* "dimensions" fields.
|
||||||
|
* @returns {object} the current pan-zoom state
|
||||||
|
*/
|
||||||
getPanZoom: getPanZoom,
|
getPanZoom: getPanZoom,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current origin, as represented on the top of the
|
||||||
|
* stack.
|
||||||
|
* @returns {number[]} the current plot origin
|
||||||
|
*/
|
||||||
getOrigin: getOrigin,
|
getOrigin: getOrigin,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current dimensions, as represented on the top of
|
||||||
|
* the stack.
|
||||||
|
* @returns {number[]} the current plot dimensions
|
||||||
|
*/
|
||||||
getDimensions: getDimensions
|
getDimensions: getDimensions
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -5,27 +5,65 @@ define(
|
|||||||
function () {
|
function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A PlotPosition converts from pixel coordinates to domain-range
|
||||||
|
* coordinates, based on the current plot boundary as described on
|
||||||
|
* the pan-zoom stack.
|
||||||
|
*
|
||||||
|
* These coordinates are not updated after construction; that is,
|
||||||
|
* they represent the result of the conversion at the time the
|
||||||
|
* PlotPosition was instantiated. Care should be taken when retaining
|
||||||
|
* PlotPosition objects across changes to the pan-zoom stack.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {number} x the horizontal pixel position in the plot area
|
||||||
|
* @param {number} y the vertical pixel position in the plot area
|
||||||
|
* @param {number} width the width of the plot area
|
||||||
|
* @param {number} height the height of the plot area
|
||||||
|
* @param {PanZoomStack} panZoomStack the applicable pan-zoom stack,
|
||||||
|
* used to determine the plot's domain-range boundaries.
|
||||||
|
*/
|
||||||
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;
|
position;
|
||||||
|
|
||||||
|
function convert(v, i) {
|
||||||
|
return v * dimensions[i] + origin[i];
|
||||||
|
}
|
||||||
|
|
||||||
if (!dimensions || !origin) {
|
if (!dimensions || !origin) {
|
||||||
|
// We need both dimensions and origin to compute a position
|
||||||
position = [];
|
position = [];
|
||||||
} else {
|
} else {
|
||||||
position = [ x / width, (height - y) / height ].map(function (v, i) {
|
// Convert from pixel to domain-range space.
|
||||||
return v * dimensions[i] + origin[i];
|
// Note that range is reversed from the y-axis in pixel space
|
||||||
});
|
//(positive range points up, positive pixel-y points down)
|
||||||
|
position = [ x / width, (height - y) / height ].map(convert);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* Get the domain value corresponding to this pixel position.
|
||||||
|
* @returns {number} the domain value
|
||||||
|
*/
|
||||||
getDomain: function () {
|
getDomain: function () {
|
||||||
return position[0];
|
return position[0];
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Get the range value corresponding to this pixel position.
|
||||||
|
* @returns {number} the range value
|
||||||
|
*/
|
||||||
getRange: function () {
|
getRange: function () {
|
||||||
return position[1];
|
return position[1];
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Get the domain and values corresponding to this
|
||||||
|
* pixel position.
|
||||||
|
* @returns {number[]} an array containing the domain and
|
||||||
|
* the range value, in that order
|
||||||
|
*/
|
||||||
getPosition: function () {
|
getPosition: function () {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,16 @@ define(
|
|||||||
|
|
||||||
function identity(x) { return x; }
|
function identity(x) { return x; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PlotPreparer is responsible for handling data sets and
|
||||||
|
* preparing them to be rendered. It creates a WebGL-plottable
|
||||||
|
* Float32Array for each trace, and tracks the boundaries of the
|
||||||
|
* data sets (since this is convenient to do during the same pass).
|
||||||
|
* @constructor
|
||||||
|
* @param {Telemetry[]} datas telemetry data objects
|
||||||
|
* @param {string} domain the key to use when looking up domain values
|
||||||
|
* @param {string} range the key to use when looking up range values
|
||||||
|
*/
|
||||||
function PlotPreparer(datas, domain, range) {
|
function PlotPreparer(datas, domain, range) {
|
||||||
var index,
|
var index,
|
||||||
vertices = [],
|
vertices = [],
|
||||||
@ -23,14 +33,18 @@ define(
|
|||||||
// Remove any undefined data sets
|
// Remove any undefined data sets
|
||||||
datas = (datas || []).filter(identity);
|
datas = (datas || []).filter(identity);
|
||||||
|
|
||||||
// Filter out un
|
// Do a first pass to determine the domain offset.
|
||||||
|
// This will be use to reduce the magnitude of domain values
|
||||||
|
// in the buffer, to minimize loss-of-precision when
|
||||||
|
// converting to a 32-bit float.
|
||||||
datas.forEach(function (data) {
|
datas.forEach(function (data) {
|
||||||
domainOffset = Math.min(data.getDomainValue(0, domain), domainOffset);
|
domainOffset = Math.min(data.getDomainValue(0, domain), domainOffset);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Assemble buffers, and track bounds of the data present
|
||||||
datas.forEach(function (data, i) {
|
datas.forEach(function (data, i) {
|
||||||
vertices.push([]);
|
vertices.push([]);
|
||||||
for (index = 0; index < data.getPointCount(); index = index + 1) {
|
for (index = 0; index < data.getPointCount(); index += 1) {
|
||||||
x = data.getDomainValue(index, domain);
|
x = data.getDomainValue(index, domain);
|
||||||
y = data.getRangeValue(index, range);
|
y = data.getRangeValue(index, range);
|
||||||
vertices[i].push(x - domainOffset);
|
vertices[i].push(x - domainOffset);
|
||||||
@ -42,23 +56,62 @@ define(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If range is empty, add some padding
|
||||||
if (max[1] === min[1]) {
|
if (max[1] === min[1]) {
|
||||||
max[1] = max[1] + 1.0;
|
max[1] = max[1] + 1.0;
|
||||||
min[1] = min[1] - 1.0;
|
min[1] = min[1] - 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert to Float32Array
|
||||||
buffers = vertices.map(function (v) { return new Float32Array(v); });
|
buffers = vertices.map(function (v) { return new Float32Array(v); });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* Get the dimensions which bound all data in the provided
|
||||||
|
* data sets. This is given as a two-element array where the
|
||||||
|
* first element is domain, and second is range.
|
||||||
|
* @returns {number[]} the dimensions which bound this data set
|
||||||
|
*/
|
||||||
getDimensions: function () {
|
getDimensions: function () {
|
||||||
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.
|
||||||
|
* This is given as a two-element array where the
|
||||||
|
* first element is domain, and second is range.
|
||||||
|
* The domain value here is not adjusted by the domain offset.
|
||||||
|
* @returns {number[]} the origin of this data set's boundary
|
||||||
|
*/
|
||||||
getOrigin: function () {
|
getOrigin: function () {
|
||||||
return min;
|
return min;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Get the domain offset; this offset will have been subtracted
|
||||||
|
* from all domain values in all buffers returned by this
|
||||||
|
* preparer, in order to minimize loss-of-precision due to
|
||||||
|
* conversion to the 32-bit float format needed by WebGL.
|
||||||
|
* @returns {number} the domain offset
|
||||||
|
*/
|
||||||
getDomainOffset: function () {
|
getDomainOffset: function () {
|
||||||
return domainOffset;
|
return domainOffset;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Get all renderable buffers for this data set. This will
|
||||||
|
* be returned as an array which can be correlated back to
|
||||||
|
* the provided telemetry data objects (from the constructor
|
||||||
|
* call) by index.
|
||||||
|
*
|
||||||
|
* Internally, these are flattened; each buffer contains a
|
||||||
|
* sequence of alternating domain and range values.
|
||||||
|
*
|
||||||
|
* All domain values in all buffers will have been adjusted
|
||||||
|
* from their original values by subtraction of the domain
|
||||||
|
* offset; this minimizes loss-of-precision resulting from
|
||||||
|
* the conversion to 32-bit floats, which may otherwise
|
||||||
|
* cause aliasing artifacts (particularly for timestamps)
|
||||||
|
*
|
||||||
|
* @returns {Float32Array[]} the buffers for these traces
|
||||||
|
*/
|
||||||
getBuffers: function () {
|
getBuffers: function () {
|
||||||
return buffers;
|
return buffers;
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,22 @@ define(
|
|||||||
function () {
|
function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PlotTickGenerator provides labels for ticks along the
|
||||||
|
* domain and range axes of the plot, to support the plot
|
||||||
|
* template.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {PlotPanZoomStack} panZoomStack the pan-zoom stack for
|
||||||
|
* this plot, used to determine plot boundaries
|
||||||
|
* @param {PlotFormatter} formatter used to format (for display)
|
||||||
|
* domain and range values.
|
||||||
|
*/
|
||||||
function PlotTickGenerator(panZoomStack, formatter) {
|
function PlotTickGenerator(panZoomStack, formatter) {
|
||||||
|
|
||||||
|
// Generate ticks; interpolate from start up to
|
||||||
|
// start + span in count steps, using the provided
|
||||||
|
// formatter to represent each value.
|
||||||
function generateTicks(start, span, count, format) {
|
function generateTicks(start, span, count, format) {
|
||||||
var step = span / (count - 1),
|
var step = span / (count - 1),
|
||||||
result = [],
|
result = [],
|
||||||
@ -23,6 +37,11 @@ define(
|
|||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* Generate tick marks for the domain axis.
|
||||||
|
* @param {number} count the number of ticks
|
||||||
|
* @returns {string[]} labels for those ticks
|
||||||
|
*/
|
||||||
generateDomainTicks: function (count) {
|
generateDomainTicks: function (count) {
|
||||||
var panZoom = panZoomStack.getPanZoom();
|
var panZoom = panZoomStack.getPanZoom();
|
||||||
return generateTicks(
|
return generateTicks(
|
||||||
@ -32,6 +51,12 @@ define(
|
|||||||
formatter.formatDomainValue
|
formatter.formatDomainValue
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate tick marks for the range axis.
|
||||||
|
* @param {number} count the number of ticks
|
||||||
|
* @returns {string[]} labels for those ticks
|
||||||
|
*/
|
||||||
generateRangeTicks: function (count) {
|
generateRangeTicks: function (count) {
|
||||||
var panZoom = panZoomStack.getPanZoom();
|
var panZoom = panZoomStack.getPanZoom();
|
||||||
return generateTicks(
|
return generateTicks(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user