mirror of
https://github.com/nasa/openmct.git
synced 2024-12-20 21:53:08 +00:00
Merge branch 'open1070' into open-master
Merge in changes for WTD-1070
This commit is contained in:
commit
c8ec3e713d
120
platform/features/plot/src/Canvas2DChart.js
Normal file
120
platform/features/plot/src/Canvas2DChart.js
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*global define,Float32Array*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new chart which uses Canvas's 2D API for rendering.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {CanvasElement} canvas the canvas object to render upon
|
||||||
|
* @throws {Error} an error is thrown if Canvas's 2D API is unavailable.
|
||||||
|
*/
|
||||||
|
function Canvas2DChart(canvas) {
|
||||||
|
var c2d = canvas.getContext('2d'),
|
||||||
|
width = canvas.width,
|
||||||
|
height = canvas.height,
|
||||||
|
dimensions = [ width, height ],
|
||||||
|
origin = [ 0, 0 ];
|
||||||
|
|
||||||
|
// Convert from logical to physical x coordinates
|
||||||
|
function x(v) {
|
||||||
|
return ((v - origin[0]) / dimensions[0]) * width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert from logical to physical y coordinates
|
||||||
|
function y(v) {
|
||||||
|
return height - ((v - origin[1]) / dimensions[1]) * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the color to be used for drawing operations
|
||||||
|
function setColor(color) {
|
||||||
|
var mappedColor = color.map(function (c, i) {
|
||||||
|
return i < 3 ? Math.floor(c * 255) : (c);
|
||||||
|
}).join(',');
|
||||||
|
c2d.strokeStyle = "rgba(" + mappedColor + ")";
|
||||||
|
c2d.fillStyle = "rgba(" + mappedColor + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c2d) {
|
||||||
|
throw new Error("Canvas 2d API unavailable.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Clear the chart.
|
||||||
|
*/
|
||||||
|
clear: function () {
|
||||||
|
width = canvas.width;
|
||||||
|
height = canvas.height;
|
||||||
|
c2d.clearRect(0, 0, width, height);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 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 (newDimensions, newOrigin) {
|
||||||
|
dimensions = newDimensions;
|
||||||
|
origin = newOrigin;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
setColor(color);
|
||||||
|
|
||||||
|
// Configure context to draw two-pixel-thick lines
|
||||||
|
c2d.lineWidth = 2;
|
||||||
|
|
||||||
|
// Start a new path...
|
||||||
|
if (buf.length > 1) {
|
||||||
|
c2d.beginPath();
|
||||||
|
c2d.moveTo(x(buf[0]), y(buf[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...and add points to it...
|
||||||
|
for (i = 2; i < points * 2; i = i + 2) {
|
||||||
|
c2d.lineTo(x(buf[i]), y(buf[i + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...before finally drawing it.
|
||||||
|
c2d.stroke();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
var x1 = x(min[0]),
|
||||||
|
y1 = y(min[1]),
|
||||||
|
w = x(max[0]) - x1,
|
||||||
|
h = y(max[1]) - y1;
|
||||||
|
|
||||||
|
setColor(color);
|
||||||
|
c2d.fillRect(x1, y1, w, h);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return Canvas2DChart;
|
||||||
|
}
|
||||||
|
);
|
@ -4,8 +4,8 @@
|
|||||||
* Module defining MCTChart. Created by vwoeltje on 11/12/14.
|
* Module defining MCTChart. Created by vwoeltje on 11/12/14.
|
||||||
*/
|
*/
|
||||||
define(
|
define(
|
||||||
["./GLChart"],
|
["./GLChart", "./Canvas2DChart"],
|
||||||
function (GLChart) {
|
function (GLChart, Canvas2DChart) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
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>";
|
||||||
@ -43,22 +43,38 @@ define(
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function MCTChart($interval, $log) {
|
function MCTChart($interval, $log) {
|
||||||
|
// Get an underlying chart implementation
|
||||||
|
function getChart(Charts, canvas) {
|
||||||
|
// Try the first available option...
|
||||||
|
var Chart = Charts[0];
|
||||||
|
|
||||||
|
// This function recursively try-catches all options;
|
||||||
|
// if these all fail, issue a warning.
|
||||||
|
if (!Chart) {
|
||||||
|
$log.warn("Cannot initialize mct-chart.");
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try first option; if it fails, try remaining options
|
||||||
|
try {
|
||||||
|
return new Chart(canvas);
|
||||||
|
} catch (e) {
|
||||||
|
$log.warn([
|
||||||
|
"Could not instantiate chart",
|
||||||
|
Chart.name,
|
||||||
|
";",
|
||||||
|
e.message
|
||||||
|
].join(" "));
|
||||||
|
|
||||||
|
return getChart(Charts.slice(1), canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function linkChart(scope, element) {
|
function linkChart(scope, element) {
|
||||||
var canvas = element.find("canvas")[0],
|
var canvas = element.find("canvas")[0],
|
||||||
activeInterval,
|
activeInterval,
|
||||||
chart;
|
chart;
|
||||||
|
|
||||||
// Try to initialize GLChart, which allows drawing using WebGL.
|
|
||||||
// This may fail, particularly where browsers do not support
|
|
||||||
// WebGL, so catch that here.
|
|
||||||
try {
|
|
||||||
chart = new GLChart(canvas);
|
|
||||||
} catch (e) {
|
|
||||||
$log.warn("Cannot initialize mct-chart; " + e.message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle drawing, based on contents of the "draw" object
|
// Handle drawing, based on contents of the "draw" object
|
||||||
// in scope
|
// in scope
|
||||||
function doDraw(draw) {
|
function doDraw(draw) {
|
||||||
@ -118,6 +134,15 @@ define(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to initialize a chart.
|
||||||
|
chart = getChart([GLChart, Canvas2DChart], canvas);
|
||||||
|
|
||||||
|
// If that failed, there's nothing more we can do here.
|
||||||
|
// (A warning will already have been issued)
|
||||||
|
if (!chart) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check for resize, on a timer
|
// Check for resize, on a timer
|
||||||
activeInterval = $interval(drawIfResized, 1000);
|
activeInterval = $interval(drawIfResized, 1000);
|
||||||
|
|
||||||
|
76
platform/features/plot/test/Canvas2DChartSpec.js
Normal file
76
platform/features/plot/test/Canvas2DChartSpec.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MergeModelsSpec. Created by vwoeltje on 11/6/14.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
["../src/Canvas2DChart"],
|
||||||
|
function (Canvas2DChart) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("A canvas 2d chart", function () {
|
||||||
|
var mockCanvas,
|
||||||
|
mock2d,
|
||||||
|
chart;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockCanvas = jasmine.createSpyObj("canvas", [ "getContext" ]);
|
||||||
|
mock2d = jasmine.createSpyObj(
|
||||||
|
"2d",
|
||||||
|
[
|
||||||
|
"clearRect",
|
||||||
|
"beginPath",
|
||||||
|
"moveTo",
|
||||||
|
"lineTo",
|
||||||
|
"stroke",
|
||||||
|
"fillRect"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockCanvas.getContext.andReturn(mock2d);
|
||||||
|
|
||||||
|
chart = new Canvas2DChart(mockCanvas);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Note that tests below are less specific than they
|
||||||
|
// could be, esp. w.r.t. arguments to drawing calls;
|
||||||
|
// this is a fallback option so is a lower test priority.
|
||||||
|
|
||||||
|
it("allows the canvas to be cleared", function () {
|
||||||
|
chart.clear();
|
||||||
|
expect(mock2d.clearRect).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("doees not construct if 2D is unavailable", function () {
|
||||||
|
mockCanvas.getContext.andReturn(undefined);
|
||||||
|
expect(function () {
|
||||||
|
return new Canvas2DChart(mockCanvas);
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows dimensions to be set", function () {
|
||||||
|
// No return value, just verify API is present
|
||||||
|
chart.setDimensions([120, 120], [0, 10]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows lines to be drawn", function () {
|
||||||
|
var testBuffer = [ 0, 1, 3, 8 ],
|
||||||
|
testColor = [ 0.25, 0.33, 0.66, 1.0 ],
|
||||||
|
testPoints = 2;
|
||||||
|
chart.drawLine(testBuffer, testColor, testPoints);
|
||||||
|
expect(mock2d.beginPath).toHaveBeenCalled();
|
||||||
|
expect(mock2d.lineTo.calls.length).toEqual(1);
|
||||||
|
expect(mock2d.stroke).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows squares to be drawn", function () {
|
||||||
|
var testMin = [0, 1],
|
||||||
|
testMax = [10, 10],
|
||||||
|
testColor = [ 0.25, 0.33, 0.66, 1.0 ];
|
||||||
|
|
||||||
|
chart.drawSquare(testMin, testMax, testColor);
|
||||||
|
expect(mock2d.fillRect).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
@ -1,4 +1,5 @@
|
|||||||
[
|
[
|
||||||
|
"Canvas2DChart",
|
||||||
"GLChart",
|
"GLChart",
|
||||||
"MCTChart",
|
"MCTChart",
|
||||||
"PlotController",
|
"PlotController",
|
||||||
|
Loading…
Reference in New Issue
Block a user