From 9b7b754cb04920bcd1b5daa4c94ecf78879d44dd Mon Sep 17 00:00:00 2001 From: dhakim Date: Thu, 25 Jul 2019 11:04:57 -0700 Subject: [PATCH 01/13] Fast animation by splitting tubes into static and dynamic portions such that only the dynamic portions require update each frame. animate.js - now tracks the previous frame. Should allow rewind in the future. animations-controller.js - now treats static and dynamic tube segments separately draw.js - Added method for creation of TubeBufferGeometry object for static tube segments. added method for updating draw range of TubeBufferGeometry sceneplotview3d.js - now adds both static and dynamic tubes to the scene. trajectory.js - New function to grab an interpolated tube segment / last two points of a trajectory for the current frame view.js - split tubes into static and dynamic --- emperor/support_files/js/animate.js | 10 +++ .../support_files/js/animations-controller.js | 42 +++++++--- emperor/support_files/js/draw.js | 80 ++++++++++++++++++- emperor/support_files/js/sceneplotview3d.js | 6 +- emperor/support_files/js/trajectory.js | 20 ++++- emperor/support_files/js/view.js | 12 ++- 6 files changed, 154 insertions(+), 16 deletions(-) diff --git a/emperor/support_files/js/animate.js b/emperor/support_files/js/animate.js index fa8d926f..a96ac310 100644 --- a/emperor/support_files/js/animate.js +++ b/emperor/support_files/js/animate.js @@ -137,6 +137,15 @@ function(_, trajectory) { * @default -1 */ this.currentFrame = -1; + + /* + * @type {Integer} + * The previous frame served by the director + * (Note, more or less always equals currentFrame - 1 in current implementation, + * but built more generically to allow rewind and frame skipping in the future) + */ + this.previousFrame = -1; + /** * @type {Array} * Array where each element in the trajectory is a trajectory with the @@ -276,6 +285,7 @@ function(_, trajectory) { */ AnimationDirector.prototype.updateFrame = function() { if (this.animationCycleFinished() === false) { + this.previousFrame = this.currentFrame; this.currentFrame = this.currentFrame + 1; } }; diff --git a/emperor/support_files/js/animations-controller.js b/emperor/support_files/js/animations-controller.js index 311d1c8f..231912ef 100644 --- a/emperor/support_files/js/animations-controller.js +++ b/emperor/support_files/js/animations-controller.js @@ -11,6 +11,9 @@ define([ draw, Color, ColorViewController) { var EmperorViewController = ViewControllers.EmperorViewController; var drawTrajectoryLine = draw.drawTrajectoryLine; + var drawTrajectoryLineStatic = draw.drawTrajectoryLineStatic; + var drawTrajectoryLineDynamic = draw.drawTrajectoryLineDynamic; + var updateStaticTrajectoryDrawRange = draw.updateStaticTrajectoryDrawRange; var ColorEditor = Color.ColorEditor, ColorFormatter = Color.ColorFormatter; /** @@ -440,13 +443,16 @@ define([ this.playing = false; this.director = null; - view.tubes.forEach(function(tube) { - if (tube.parent !== null) { + var allTubes = view.staticTubes.concat(view.dynamicTubes); + allTubes.forEach(function(tube) { + if (tube !== null && tube.parent !== null) { tube.parent.remove(tube); } }); - view.tubes = []; + view.staticTubes = []; + view.dynamicTubes = []; + view.needsUpdate = true; this._updateButtons(); @@ -538,19 +544,35 @@ define([ var radius = view.getGeometryFactor(); radius *= 0.45 * this.getRadius(); - view.tubes.forEach(function(tube) { - if (tube === undefined) { + var i = 0; + for (i = 0; i < this.director.trajectories.length; i++) { + var trajectory = this.director.trajectories[i]; + + //Ensure static tubes are constructed + if (view.staticTubes[i] === null || view.staticTubes[i] === undefined) + { + var color = this._colors[trajectory.metadataCategoryName] || 'red'; + view.staticTubes[i] = drawTrajectoryLineStatic(trajectory, color, radius); + } + + //Ensure static tube draw ranges are set to visible segment + updateStaticTrajectoryDrawRange(trajectory, this.director.currentFrame, view.staticTubes[i]); + } + + //Remove any old dynamic tubes from the scene + view.dynamicTubes.forEach(function(tube) { + if (tube === undefined || tube === null) { return; } if (tube.parent !== null) { tube.parent.remove(tube); } }); - - view.tubes = this.director.trajectories.map(function(trajectory) { - color = scope._colors[trajectory.metadataCategoryName] || 'red'; - - var tube = drawTrajectoryLine(trajectory, scope.director.currentFrame, + + //Construct new dynamic tubes containing necessary interpolated segment for the current frame + view.dynamicTubes = this.director.trajectories.map(function(trajectory) { + var color = scope._colors[trajectory.metadataCategoryName] || 'red'; + var tube = drawTrajectoryLineDynamic(trajectory, scope.director.currentFrame, color, radius); return tube; }); diff --git a/emperor/support_files/js/draw.js b/emperor/support_files/js/draw.js index 05001be1..e72d916b 100644 --- a/emperor/support_files/js/draw.js +++ b/emperor/support_files/js/draw.js @@ -1,5 +1,9 @@ /** @module draw */ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { + + var NUM_TUBE_SEGMENTS = 3; + var NUM_TUBE_CROSS_SECTION_POINTS = 10; + // useful for some calculations var ZERO = new THREE.Vector3(); @@ -295,11 +299,80 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { // the line will contain the two vertices and the described material // we increase the number of points to have a smoother transition on // edges i. e. where the trajectory changes the direction it is going - lineGeometry = new THREE.TubeGeometry(path, (points.length - 1) * 3, radius, - 10, false); + lineGeometry = new THREE.TubeGeometry(path, (points.length - 1) * NUM_TUBE_SEGMENTS, radius, + NUM_TUBE_CROSS_SECTION_POINTS, false); + + return new THREE.Mesh(lineGeometry, material); + } + + function drawTrajectoryLineDynamic(trajectory, currentFrame, color, radius) { + // based on the example described in: + // https://github.com/mrdoob/three.js/wiki/Drawing-lines + var material, points = [], lineGeometry, limit = 0, path; + + _trajectory = trajectory.representativeInterpolatedCoordinatesAtIndex(currentFrame); + if (_trajectory === null || _trajectory.length == 0) + return null; + + material = new THREE.MeshPhongMaterial({color: color}); + material.matrixAutoUpdate = true; + material.transparent = false; + + for (var index = 0; index < _trajectory.length; index++) { + points.push(new THREE.Vector3(_trajectory[index].x, + _trajectory[index].y, _trajectory[index].z)); + } + + path = new THREE.EmperorTrajectory(points); + + // the line will contain the two vertices and the described material + // we increase the number of points to have a smoother transition on + // edges i. e. where the trajectory changes the direction it is going + lineGeometry = new THREE.TubeGeometry(path, (points.length - 1) * NUM_TUBE_SEGMENTS, radius, + NUM_TUBE_CROSS_SECTION_POINTS, false); return new THREE.Mesh(lineGeometry, material); } + + function drawTrajectoryLineStatic(trajectory, color, radius) { + var _trajectory = trajectory.coordinates; + + var material = new THREE.MeshPhongMaterial({color: color}); + material.matrixAutoUpdate = true; + material.transparent = false; + + var allPoints = []; + for (var index = 0; index < _trajectory.length; index++) { + allPoints.push(new THREE.Vector3(_trajectory[index].x, + _trajectory[index].y, _trajectory[index].z)); + } + + var path = new THREE.EmperorTrajectory(allPoints); + + //Tubes are straight segments, but adding vertices along them might change lighting effects + //under certain models and lighting conditions. + var tubeBufferGeom = new THREE.TubeBufferGeometry(path, (allPoints.length - 1) * NUM_TUBE_SEGMENTS, radius, NUM_TUBE_CROSS_SECTION_POINTS, false) + + return new THREE.Mesh(tubeBufferGeom, material); + } + + function updateStaticTrajectoryDrawRange(trajectory, currentFrame, threeMesh) + { + //Blah, reverse engineering the number of points in a THREE tube is not fun, and may be implementation/version dependent. + //Number of points drawn per tube segment = 2 (triangles) * 3 (points per triangle) * NUM_TUBE_CROSS_SECTION_POINTS (number of vertices in a cross section of tube) + //Number of tube segments per pair of consecutive points = NUM_TUBE_SEGMENTS + + var multiplier = 2 * 3 * NUM_TUBE_CROSS_SECTION_POINTS * NUM_TUBE_SEGMENTS + if (currentFrame < trajectory._intervalValues.length) + { + var intervalValue = trajectory._intervalValues[currentFrame]; + threeMesh.geometry.setDrawRange(0, intervalValue * multiplier); + } + else + { + threeMesh.geometry.setDrawRange(0, (trajectory.coordinates.length - 1) * multiplier); + } + } /** @@ -415,5 +488,8 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { return {'formatSVGLegend': formatSVGLegend, 'makeLine': makeLine, 'makeLabel': makeLabel, 'makeArrow': makeArrow, 'drawTrajectoryLine': drawTrajectoryLine, + 'drawTrajectoryLineStatic': drawTrajectoryLineStatic, + 'drawTrajectoryLineDynamic': drawTrajectoryLineDynamic, + 'updateStaticTrajectoryDrawRange': updateStaticTrajectoryDrawRange, 'makeLineCollection': makeLineCollection}; }); diff --git a/emperor/support_files/js/sceneplotview3d.js b/emperor/support_files/js/sceneplotview3d.js index a77d852f..6eb5218c 100644 --- a/emperor/support_files/js/sceneplotview3d.js +++ b/emperor/support_files/js/sceneplotview3d.js @@ -677,9 +677,13 @@ define([ }); _.each(this.decViews, function(view) { - view.tubes.forEach(function(tube) { + view.staticTubes.forEach(function(tube) { scope.scene.add(tube); }); + view.dynamicTubes.forEach(function(tube) { + if (tube !== null) + scope.scene.add(tube); + }); }); // check if the visible dimensions have changed diff --git a/emperor/support_files/js/trajectory.js b/emperor/support_files/js/trajectory.js index 2a678491..7bc72f1b 100644 --- a/emperor/support_files/js/trajectory.js +++ b/emperor/support_files/js/trajectory.js @@ -186,7 +186,25 @@ define([ return output; }; - + + /** + * + * Grab only the interpolated portion of representativeCoordinatesAtIndex. + * + * @param {integer} idx Value for which to determine the required number of + * points. + * + * @return {Array[]} Array containing the representative float x, y, z + * coordinates needed to draw the interpolated portion of a trajectory at the given index. + */ + TrajectoryOfSamples.prototype.representativeInterpolatedCoordinatesAtIndex = function(idx) { + if (idx === 0) + return null; + if (this.interpolatedCoordinates.length -1 <= idx) + return null; + return [this.coordinates[this._intervalValues[idx]], this.interpolatedCoordinates[idx]]; + } + /** * * Function to interpolate a certain number of steps between two three diff --git a/emperor/support_files/js/view.js b/emperor/support_files/js/view.js index 4328872c..3d0bba4b 100644 --- a/emperor/support_files/js/view.js +++ b/emperor/support_files/js/view.js @@ -63,10 +63,18 @@ function DecompositionView(decomp, asPointCloud) { */ this.backgroundColor = '#000000'; /** - * Tube objects on screen (used for animations) + * Static tubes objects covering an entire trajectory. + * Can use setDrawRange on the underlying geometry to display + * just part of the trajectory. * @type {THREE.Mesh[]} */ - this.tubes = []; + this.staticTubes = []; + /** + * Dynamic tubes covering the final tube segment of a trajectory + * Must be rebuilt each frame by the animations controller + * @type {THREE.Mesh[]} + */ + this.dynamicTubes = []; /** * Array of THREE.Mesh objects on screen (represent samples). * @type {THREE.Mesh[]} From 74b544c7fe8626d16fa3b512a1136904bcdf670f Mon Sep 17 00:00:00 2001 From: dhakim Date: Thu, 25 Jul 2019 11:21:02 -0700 Subject: [PATCH 02/13] Updated tests for split of tubes field --- tests/javascript_tests/test_decomposition_view.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/javascript_tests/test_decomposition_view.js b/tests/javascript_tests/test_decomposition_view.js index 0fd26253..1b3fe4f2 100644 --- a/tests/javascript_tests/test_decomposition_view.js +++ b/tests/javascript_tests/test_decomposition_view.js @@ -82,7 +82,8 @@ requirejs([ equal(dv.getVisibleCount(), 2, 'visibleCount set correctly'); deepEqual(dv.visibleDimensions, [0, 1, 2], 'visibleDimensions set correctly'); - deepEqual(dv.tubes, [], 'tubes set correctly'); + deepEqual(dv.staticTubes, [], 'tubes set correctly'); + deepEqual(dv.dynamicTubes, [], 'tubes set correctly'); equal(dv.axesColor, '#FFFFFF'); equal(dv.backgroundColor, '#000000'); @@ -138,7 +139,8 @@ requirejs([ equal(dv.getVisibleCount(), 2, 'visibleCount set correctly'); deepEqual(dv.visibleDimensions, [0, 1], 'visibleDimensions set correctly'); - deepEqual(dv.tubes, [], 'tubes set correctly'); + deepEqual(dv.staticTubes, [], 'tubes set correctly'); + deepEqual(dv.dynamicTubes, [], 'tubes set correctly'); equal(dv.axesColor, '#FFFFFF'); equal(dv.backgroundColor, '#000000'); @@ -160,7 +162,8 @@ requirejs([ equal(view.count, 2); equal(view.getVisibleCount(), 2); deepEqual(view.visibleDimensions, [0, 1, 2]); - deepEqual(view.tubes, []); + deepEqual(view.staticTubes, [], 'tubes set correctly'); + deepEqual(view.dynamicTubes, [], 'tubes set correctly'); equal(view.axesColor, '#FFFFFF'); equal(view.backgroundColor, '#000000'); deepEqual(view.axesOrientation, [1, 1, 1]); @@ -199,7 +202,8 @@ requirejs([ equal(view.count, 2); equal(view.getVisibleCount(), 2); deepEqual(view.visibleDimensions, [0, 1, 2]); - deepEqual(view.tubes, []); + deepEqual(view.staticTubes, [], 'tubes set correctly'); + deepEqual(view.dynamicTubes, [], 'tubes set correctly'); equal(view.axesColor, '#FFFFFF'); equal(view.backgroundColor, '#000000'); deepEqual(view.axesOrientation, [1, 1, 1]); From 72c246bff3290b31d989161afb70b70eeebebc17 Mon Sep 17 00:00:00 2001 From: dhakim Date: Thu, 25 Jul 2019 11:29:07 -0700 Subject: [PATCH 03/13] Fix for potential divide by zero --- emperor/support_files/js/trajectory.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/emperor/support_files/js/trajectory.js b/emperor/support_files/js/trajectory.js index 7bc72f1b..3b8c5988 100644 --- a/emperor/support_files/js/trajectory.js +++ b/emperor/support_files/js/trajectory.js @@ -202,7 +202,16 @@ define([ return null; if (this.interpolatedCoordinates.length -1 <= idx) return null; - return [this.coordinates[this._intervalValues[idx]], this.interpolatedCoordinates[idx]]; + + lastStaticPoint = this.coordinates[this._intervalValues[idx]]; + interpPoint = this.interpolatedCoordinates[idx]; + if (lastStaticPoint.x === interpPoint.x + && lastStaticPoint.y === interpPoint.y + && lastStaticPoint.z === interpPoint.z) { + return null; //Shouldn't pass on a zero length segment + } + + return [lastStaticPoint, interpPoint]; } /** From ca138246dce17f1c2bd150823277c5ba243371f3 Mon Sep 17 00:00:00 2001 From: dhakim Date: Thu, 25 Jul 2019 11:38:41 -0700 Subject: [PATCH 04/13] Updated test for trajectory to check dynamic tube section equivalence --- tests/javascript_tests/test_trajectory.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/javascript_tests/test_trajectory.js b/tests/javascript_tests/test_trajectory.js index 77f72adb..328e9f29 100644 --- a/tests/javascript_tests/test_trajectory.js +++ b/tests/javascript_tests/test_trajectory.js @@ -361,15 +361,24 @@ requirejs(['underscore', 'trajectory'], function(_, trajectory) { {'x': 6.75, 'y': 6.75, 'z': 6.75}, {'x': 8, 'y': 8, 'z': 8}]; - deepEqual(trajectory.representativeCoordinatesAtIndex(3), + var fullCoordinates3 = trajectory.representativeCoordinatesAtIndex(3); + deepEqual(fullCoordinates3, [{'x': 0, 'y': 0, 'z': 0}, {'x': 0.75, 'y': 0.75, 'z': 0.75}], 'Coordinates are retrieved correctly at index 3'); - deepEqual(trajectory.representativeCoordinatesAtIndex(11), + + var fullCoordinates11 = trajectory.representativeCoordinatesAtIndex(11); + deepEqual(fullCoordinates11, [{'x': 0, 'y': 0, 'z': 0}, {'x': 1, 'y': 1, 'z': 1}, {'x': -9, 'y': -9, 'z': -9}, {'x': 3, 'y': 3, 'z': 3}, {'x': 4.25, 'y': 4.25, 'z': 4.25}], 'Coordinates are retrieved correctly at index 11'); + + var dynamicCoordinates3 = trajectory.representativeInterpolatedCoordinatesAtIndex(3); + var dynamicCoordinates11 = trajectory.representativeInterpolatedCoordinatesAtIndex(11); + + deepEqual(fullCoordinates3.slice(-2), dynamicCoordinates3, "Dynamic coordinates match on frame 3"); + deepEqual(fullCoordinates11.slice(-2), dynamicCoordinates11, "Dynamic coordinates match on frame 11"); }); From 8f515746bf4b7f8c83c8511f9c011b7588546596 Mon Sep 17 00:00:00 2001 From: dhakim Date: Mon, 29 Jul 2019 11:04:40 -0700 Subject: [PATCH 05/13] Updated comment for jsdoc --- emperor/support_files/js/animate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emperor/support_files/js/animate.js b/emperor/support_files/js/animate.js index a96ac310..498c0563 100644 --- a/emperor/support_files/js/animate.js +++ b/emperor/support_files/js/animate.js @@ -138,7 +138,7 @@ function(_, trajectory) { */ this.currentFrame = -1; - /* + /** * @type {Integer} * The previous frame served by the director * (Note, more or less always equals currentFrame - 1 in current implementation, From cef653d6352acf142c8c60969754bc356aaee5e2 Mon Sep 17 00:00:00 2001 From: dhakim Date: Mon, 29 Jul 2019 11:06:23 -0700 Subject: [PATCH 06/13] Moved variable declaration into for loop. Added utility method to view to retrieve all tubes --- emperor/support_files/js/animations-controller.js | 6 ++---- emperor/support_files/js/sceneplotview3d.js | 5 +---- emperor/support_files/js/view.js | 8 ++++++++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/emperor/support_files/js/animations-controller.js b/emperor/support_files/js/animations-controller.js index 231912ef..d8f909dd 100644 --- a/emperor/support_files/js/animations-controller.js +++ b/emperor/support_files/js/animations-controller.js @@ -443,8 +443,7 @@ define([ this.playing = false; this.director = null; - var allTubes = view.staticTubes.concat(view.dynamicTubes); - allTubes.forEach(function(tube) { + view.getTubes().forEach(function(tube) { if (tube !== null && tube.parent !== null) { tube.parent.remove(tube); } @@ -544,8 +543,7 @@ define([ var radius = view.getGeometryFactor(); radius *= 0.45 * this.getRadius(); - var i = 0; - for (i = 0; i < this.director.trajectories.length; i++) { + for (var i = 0; i < this.director.trajectories.length; i++) { var trajectory = this.director.trajectories[i]; //Ensure static tubes are constructed diff --git a/emperor/support_files/js/sceneplotview3d.js b/emperor/support_files/js/sceneplotview3d.js index 6eb5218c..94cc02d9 100644 --- a/emperor/support_files/js/sceneplotview3d.js +++ b/emperor/support_files/js/sceneplotview3d.js @@ -677,10 +677,7 @@ define([ }); _.each(this.decViews, function(view) { - view.staticTubes.forEach(function(tube) { - scope.scene.add(tube); - }); - view.dynamicTubes.forEach(function(tube) { + view.getTubes().forEach(function(tube) { if (tube !== null) scope.scene.add(tube); }); diff --git a/emperor/support_files/js/view.js b/emperor/support_files/js/view.js index 3d0bba4b..ea567bb4 100644 --- a/emperor/support_files/js/view.js +++ b/emperor/support_files/js/view.js @@ -128,6 +128,14 @@ DecompositionView.prototype.getGeometryFactor = function() { this.decomp.dimensionRanges.min[0]) * 0.012; }; +/** + * Retrieve a shallow copy of concatenated static and dynamic tube arrays + * @type {THREE.Mesh[]} + */ +DecompositionView.prototype.getTubes = function() { + return this.staticTubes.concat(this.dynamicTubes); +}; + /** * * Helper method to initialize the base THREE.js objects. From e50f99749ee8fb975da8818f00aec47bea6e7dde Mon Sep 17 00:00:00 2001 From: dhakim Date: Mon, 29 Jul 2019 11:07:32 -0700 Subject: [PATCH 07/13] Added test for interpolating trajectories with duplicate points --- tests/javascript_tests/test_trajectory.js | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/javascript_tests/test_trajectory.js b/tests/javascript_tests/test_trajectory.js index 328e9f29..eae02c4b 100644 --- a/tests/javascript_tests/test_trajectory.js +++ b/tests/javascript_tests/test_trajectory.js @@ -533,6 +533,32 @@ requirejs(['underscore', 'trajectory'], function(_, trajectory) { equal(result, 92, 'The minimum delta is computed correctly for one ' + 'category'); }); + + /** + * + * Test trajectories with duplicate points. + * + */ + test('Test Duplicate Points In Trajectories', function() { + var result; + trajectory = new TrajectoryOfSamples(['A','B','C','D'], + 'Nonsense', + [1,2,3,4], + [{'x': 0, 'y': 0, 'z': 0}, {'x': 10, 'y': 10, 'z': 10}, {'x': 10, 'y': 10, 'z': 10}, {'x': 0, 'y': 0, 'z': 0}], + 2, + 5); + + for (var i = 0; i < 20; i++) { + var interpTubeCoords = trajectory.representativeInterpolatedCoordinatesAtIndex(i); + if (interpTubeCoords !== null) { + var dx = interpTubeCoords[1].x - interpTubeCoords[0].x; + var dy = interpTubeCoords[1].y - interpTubeCoords[0].y; + var dz = interpTubeCoords[1].z - interpTubeCoords[0].z; + var lenSq = dx * dx + dy * dy + dz * dz; + notEqual(lenSq, 0, "Interpolated tube should never be built between consecutive duplicate points in a trajectory"); + } + } + }); }); }); From f6b30ab5f8c14c11b0fb58347f52a9599471b93c Mon Sep 17 00:00:00 2001 From: dhakim Date: Mon, 29 Jul 2019 11:12:29 -0700 Subject: [PATCH 08/13] Removed drawTrajectoryLine --- .../support_files/js/animations-controller.js | 1 - emperor/support_files/js/draw.js | 27 ------------------- 2 files changed, 28 deletions(-) diff --git a/emperor/support_files/js/animations-controller.js b/emperor/support_files/js/animations-controller.js index d8f909dd..41f160b5 100644 --- a/emperor/support_files/js/animations-controller.js +++ b/emperor/support_files/js/animations-controller.js @@ -10,7 +10,6 @@ define([ ], function($, _, DecompositionView, ViewControllers, AnimationDirector, draw, Color, ColorViewController) { var EmperorViewController = ViewControllers.EmperorViewController; - var drawTrajectoryLine = draw.drawTrajectoryLine; var drawTrajectoryLineStatic = draw.drawTrajectoryLineStatic; var drawTrajectoryLineDynamic = draw.drawTrajectoryLineDynamic; var updateStaticTrajectoryDrawRange = draw.updateStaticTrajectoryDrawRange; diff --git a/emperor/support_files/js/draw.js b/emperor/support_files/js/draw.js index e72d916b..7f7a4d6b 100644 --- a/emperor/support_files/js/draw.js +++ b/emperor/support_files/js/draw.js @@ -278,32 +278,6 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { return arrow; } - - function drawTrajectoryLine(trajectory, currentFrame, color, radius) { - // based on the example described in: - // https://github.com/mrdoob/three.js/wiki/Drawing-lines - var material, points = [], lineGeometry, limit = 0, path; - - _trajectory = trajectory.representativeCoordinatesAtIndex(currentFrame); - - material = new THREE.MeshPhongMaterial({color: color}); - material.matrixAutoUpdate = true; - material.transparent = false; - - for (var index = 0; index < _trajectory.length; index++) { - points.push(new THREE.Vector3(_trajectory[index].x, - _trajectory[index].y, _trajectory[index].z)); - } - - path = new THREE.EmperorTrajectory(points); - // the line will contain the two vertices and the described material - // we increase the number of points to have a smoother transition on - // edges i. e. where the trajectory changes the direction it is going - lineGeometry = new THREE.TubeGeometry(path, (points.length - 1) * NUM_TUBE_SEGMENTS, radius, - NUM_TUBE_CROSS_SECTION_POINTS, false); - - return new THREE.Mesh(lineGeometry, material); - } function drawTrajectoryLineDynamic(trajectory, currentFrame, color, radius) { // based on the example described in: @@ -487,7 +461,6 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { return {'formatSVGLegend': formatSVGLegend, 'makeLine': makeLine, 'makeLabel': makeLabel, 'makeArrow': makeArrow, - 'drawTrajectoryLine': drawTrajectoryLine, 'drawTrajectoryLineStatic': drawTrajectoryLineStatic, 'drawTrajectoryLineDynamic': drawTrajectoryLineDynamic, 'updateStaticTrajectoryDrawRange': updateStaticTrajectoryDrawRange, From 33e52343b15ac991a392a3bf7f84876e38622485 Mon Sep 17 00:00:00 2001 From: dhakim Date: Mon, 29 Jul 2019 11:43:19 -0700 Subject: [PATCH 09/13] Used preferred Material property setting through constructor. Removed the Blah. --- emperor/support_files/js/draw.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/emperor/support_files/js/draw.js b/emperor/support_files/js/draw.js index 7f7a4d6b..fef6835a 100644 --- a/emperor/support_files/js/draw.js +++ b/emperor/support_files/js/draw.js @@ -311,9 +311,11 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { function drawTrajectoryLineStatic(trajectory, color, radius) { var _trajectory = trajectory.coordinates; - var material = new THREE.MeshPhongMaterial({color: color}); - material.matrixAutoUpdate = true; - material.transparent = false; + var material = new THREE.MeshPhongMaterial({ + color: color, + matrixAutoUpdate: true, + transparent: false} + ); var allPoints = []; for (var index = 0; index < _trajectory.length; index++) { @@ -332,7 +334,7 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { function updateStaticTrajectoryDrawRange(trajectory, currentFrame, threeMesh) { - //Blah, reverse engineering the number of points in a THREE tube is not fun, and may be implementation/version dependent. + //Reverse engineering the number of points in a THREE tube is not fun, and may be implementation/version dependent. //Number of points drawn per tube segment = 2 (triangles) * 3 (points per triangle) * NUM_TUBE_CROSS_SECTION_POINTS (number of vertices in a cross section of tube) //Number of tube segments per pair of consecutive points = NUM_TUBE_SEGMENTS From 80aa711e860b662da13942841e3517bd0c51add8 Mon Sep 17 00:00:00 2001 From: dhakim Date: Mon, 29 Jul 2019 13:27:20 -0700 Subject: [PATCH 10/13] Updated material constructor parameters for consistency. Added dispose functions for each tube type. Moving forward, project should decide if it wants to dispose all meshes the same, or each type of mesh differently, difference is whether or not materials and geometries should have potential to be reused. --- emperor/support_files/js/draw.js | 33 ++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/emperor/support_files/js/draw.js b/emperor/support_files/js/draw.js index fef6835a..3bc6e7e5 100644 --- a/emperor/support_files/js/draw.js +++ b/emperor/support_files/js/draw.js @@ -279,6 +279,9 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { return arrow; } + /** + * Returns a new trajectory line dynamic mesh + */ function drawTrajectoryLineDynamic(trajectory, currentFrame, color, radius) { // based on the example described in: // https://github.com/mrdoob/three.js/wiki/Drawing-lines @@ -288,9 +291,10 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { if (_trajectory === null || _trajectory.length == 0) return null; - material = new THREE.MeshPhongMaterial({color: color}); - material.matrixAutoUpdate = true; - material.transparent = false; + material = new THREE.MeshPhongMaterial({ + color: color, + matrixAutoUpdate: true, + transparent: false}); for (var index = 0; index < _trajectory.length; index++) { points.push(new THREE.Vector3(_trajectory[index].x, @@ -307,7 +311,18 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { return new THREE.Mesh(lineGeometry, material); } - + + /** + * Disposes a trajectory line dynamic mesh + */ + function disposeTrajectoryLineDynamic(mesh) { + mesh.geometry.dispose(); + mesh.material.dispose(); + } + + /** + * Returns a new trajectory line static mesh + */ function drawTrajectoryLineStatic(trajectory, color, radius) { var _trajectory = trajectory.coordinates; @@ -332,6 +347,14 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { return new THREE.Mesh(tubeBufferGeom, material); } + /** + * Disposes a trajectory line static mesh + */ + function disposeTrajectoryLineStatic(mesh) { + mesh.geometry.dispose(); + mesh.material.dispose(); + } + function updateStaticTrajectoryDrawRange(trajectory, currentFrame, threeMesh) { //Reverse engineering the number of points in a THREE tube is not fun, and may be implementation/version dependent. @@ -464,7 +487,9 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { return {'formatSVGLegend': formatSVGLegend, 'makeLine': makeLine, 'makeLabel': makeLabel, 'makeArrow': makeArrow, 'drawTrajectoryLineStatic': drawTrajectoryLineStatic, + 'disposeTrajectoryLineStatic': disposeTrajectoryLineStatic, 'drawTrajectoryLineDynamic': drawTrajectoryLineDynamic, + 'disposeTrajectoryLineDynamic': disposeTrajectoryLineDynamic, 'updateStaticTrajectoryDrawRange': updateStaticTrajectoryDrawRange, 'makeLineCollection': makeLineCollection}; }); From d768c561c29d1d6c6681b88042f63c2fccf6c61d Mon Sep 17 00:00:00 2001 From: dhakim Date: Mon, 29 Jul 2019 13:41:31 -0700 Subject: [PATCH 11/13] animations-controller now disposes of tube objects when removing them from the scene. Draw no longer sets matrixAutoUpdate property on tube materials -- matrixAutoUpdate is a property of meshes. It's unclear what was intended by setting it previously --- emperor/support_files/js/animations-controller.js | 12 +++++++++++- emperor/support_files/js/draw.js | 2 -- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/emperor/support_files/js/animations-controller.js b/emperor/support_files/js/animations-controller.js index 41f160b5..84bba05b 100644 --- a/emperor/support_files/js/animations-controller.js +++ b/emperor/support_files/js/animations-controller.js @@ -12,6 +12,8 @@ define([ var EmperorViewController = ViewControllers.EmperorViewController; var drawTrajectoryLineStatic = draw.drawTrajectoryLineStatic; var drawTrajectoryLineDynamic = draw.drawTrajectoryLineDynamic; + var disposeTrajectoryLineStatic = draw.disposeTrajectoryLineStatic; + var disposeTrajectoryLineDynamic = draw.disposeTrajectoryLineDynamic; var updateStaticTrajectoryDrawRange = draw.updateStaticTrajectoryDrawRange; var ColorEditor = Color.ColorEditor, ColorFormatter = Color.ColorFormatter; @@ -442,9 +444,16 @@ define([ this.playing = false; this.director = null; - view.getTubes().forEach(function(tube) { + view.staticTubes.forEach(function(tube) { if (tube !== null && tube.parent !== null) { tube.parent.remove(tube); + disposeTrajectoryLineStatic(tube); + } + }); + view.dynamicTubes.forEach(function(tube) { + if (tube !== null && tube.parent !== null) { + tube.parent.remove(tube); + disposeTrajectoryLineDynamic(tube); } }); @@ -563,6 +572,7 @@ define([ } if (tube.parent !== null) { tube.parent.remove(tube); + disposeTrajectoryLineDynamic(tube); } }); diff --git a/emperor/support_files/js/draw.js b/emperor/support_files/js/draw.js index 3bc6e7e5..0419f09b 100644 --- a/emperor/support_files/js/draw.js +++ b/emperor/support_files/js/draw.js @@ -293,7 +293,6 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { material = new THREE.MeshPhongMaterial({ color: color, - matrixAutoUpdate: true, transparent: false}); for (var index = 0; index < _trajectory.length; index++) { @@ -328,7 +327,6 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { var material = new THREE.MeshPhongMaterial({ color: color, - matrixAutoUpdate: true, transparent: false} ); From d19145c0b48494428fa5756106d70f0e79b0fc45 Mon Sep 17 00:00:00 2001 From: dhakim Date: Tue, 30 Jul 2019 11:37:38 -0700 Subject: [PATCH 12/13] Ran fixjsstyle --- emperor/support_files/js/animate.js | 4 ++-- .../support_files/js/animations-controller.js | 4 ++-- emperor/support_files/js/draw.js | 18 +++++++++--------- emperor/support_files/js/trajectory.js | 18 +++++++++--------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/emperor/support_files/js/animate.js b/emperor/support_files/js/animate.js index 498c0563..2f76dec6 100644 --- a/emperor/support_files/js/animate.js +++ b/emperor/support_files/js/animate.js @@ -137,7 +137,7 @@ function(_, trajectory) { * @default -1 */ this.currentFrame = -1; - + /** * @type {Integer} * The previous frame served by the director @@ -145,7 +145,7 @@ function(_, trajectory) { * but built more generically to allow rewind and frame skipping in the future) */ this.previousFrame = -1; - + /** * @type {Array} * Array where each element in the trajectory is a trajectory with the diff --git a/emperor/support_files/js/animations-controller.js b/emperor/support_files/js/animations-controller.js index 84bba05b..475fae64 100644 --- a/emperor/support_files/js/animations-controller.js +++ b/emperor/support_files/js/animations-controller.js @@ -459,7 +459,7 @@ define([ view.staticTubes = []; view.dynamicTubes = []; - + view.needsUpdate = true; this._updateButtons(); @@ -575,7 +575,7 @@ define([ disposeTrajectoryLineDynamic(tube); } }); - + //Construct new dynamic tubes containing necessary interpolated segment for the current frame view.dynamicTubes = this.director.trajectories.map(function(trajectory) { var color = scope._colors[trajectory.metadataCategoryName] || 'red'; diff --git a/emperor/support_files/js/draw.js b/emperor/support_files/js/draw.js index 0419f09b..7b26216b 100644 --- a/emperor/support_files/js/draw.js +++ b/emperor/support_files/js/draw.js @@ -278,7 +278,7 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { return arrow; } - + /** * Returns a new trajectory line dynamic mesh */ @@ -301,7 +301,7 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { } path = new THREE.EmperorTrajectory(points); - + // the line will contain the two vertices and the described material // we increase the number of points to have a smoother transition on // edges i. e. where the trajectory changes the direction it is going @@ -310,7 +310,7 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { return new THREE.Mesh(lineGeometry, material); } - + /** * Disposes a trajectory line dynamic mesh */ @@ -324,12 +324,12 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { */ function drawTrajectoryLineStatic(trajectory, color, radius) { var _trajectory = trajectory.coordinates; - + var material = new THREE.MeshPhongMaterial({ color: color, transparent: false} ); - + var allPoints = []; for (var index = 0; index < _trajectory.length; index++) { allPoints.push(new THREE.Vector3(_trajectory[index].x, @@ -337,14 +337,14 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { } var path = new THREE.EmperorTrajectory(allPoints); - + //Tubes are straight segments, but adding vertices along them might change lighting effects //under certain models and lighting conditions. - var tubeBufferGeom = new THREE.TubeBufferGeometry(path, (allPoints.length - 1) * NUM_TUBE_SEGMENTS, radius, NUM_TUBE_CROSS_SECTION_POINTS, false) + var tubeBufferGeom = new THREE.TubeBufferGeometry(path, (allPoints.length - 1) * NUM_TUBE_SEGMENTS, radius, NUM_TUBE_CROSS_SECTION_POINTS, false); return new THREE.Mesh(tubeBufferGeom, material); } - + /** * Disposes a trajectory line static mesh */ @@ -359,7 +359,7 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { //Number of points drawn per tube segment = 2 (triangles) * 3 (points per triangle) * NUM_TUBE_CROSS_SECTION_POINTS (number of vertices in a cross section of tube) //Number of tube segments per pair of consecutive points = NUM_TUBE_SEGMENTS - var multiplier = 2 * 3 * NUM_TUBE_CROSS_SECTION_POINTS * NUM_TUBE_SEGMENTS + var multiplier = 2 * 3 * NUM_TUBE_CROSS_SECTION_POINTS * NUM_TUBE_SEGMENTS; if (currentFrame < trajectory._intervalValues.length) { var intervalValue = trajectory._intervalValues[currentFrame]; diff --git a/emperor/support_files/js/trajectory.js b/emperor/support_files/js/trajectory.js index 3b8c5988..0c87a5c5 100644 --- a/emperor/support_files/js/trajectory.js +++ b/emperor/support_files/js/trajectory.js @@ -186,7 +186,7 @@ define([ return output; }; - + /** * * Grab only the interpolated portion of representativeCoordinatesAtIndex. @@ -200,20 +200,20 @@ define([ TrajectoryOfSamples.prototype.representativeInterpolatedCoordinatesAtIndex = function(idx) { if (idx === 0) return null; - if (this.interpolatedCoordinates.length -1 <= idx) + if (this.interpolatedCoordinates.length - 1 <= idx) return null; - + lastStaticPoint = this.coordinates[this._intervalValues[idx]]; interpPoint = this.interpolatedCoordinates[idx]; - if (lastStaticPoint.x === interpPoint.x - && lastStaticPoint.y === interpPoint.y - && lastStaticPoint.z === interpPoint.z) { + if (lastStaticPoint.x === interpPoint.x && + lastStaticPoint.y === interpPoint.y && + lastStaticPoint.z === interpPoint.z) { return null; //Shouldn't pass on a zero length segment } - + return [lastStaticPoint, interpPoint]; - } - + }; + /** * * Function to interpolate a certain number of steps between two three From a27dd72808955d1ba7e081930b98980b2c86a252 Mon Sep 17 00:00:00 2001 From: dhakim Date: Tue, 30 Jul 2019 12:28:48 -0700 Subject: [PATCH 13/13] Manually fixed lines over 80 characters --- emperor/support_files/js/animate.js | 2 - .../support_files/js/animations-controller.js | 17 +++++--- emperor/support_files/js/draw.js | 33 ++++++++++----- emperor/support_files/js/trajectory.js | 6 ++- tests/javascript_tests/test_trajectory.js | 40 ++++++++++++------- 5 files changed, 65 insertions(+), 33 deletions(-) diff --git a/emperor/support_files/js/animate.js b/emperor/support_files/js/animate.js index 2f76dec6..38aad867 100644 --- a/emperor/support_files/js/animate.js +++ b/emperor/support_files/js/animate.js @@ -141,8 +141,6 @@ function(_, trajectory) { /** * @type {Integer} * The previous frame served by the director - * (Note, more or less always equals currentFrame - 1 in current implementation, - * but built more generically to allow rewind and frame skipping in the future) */ this.previousFrame = -1; diff --git a/emperor/support_files/js/animations-controller.js b/emperor/support_files/js/animations-controller.js index 475fae64..0fb09c1b 100644 --- a/emperor/support_files/js/animations-controller.js +++ b/emperor/support_files/js/animations-controller.js @@ -558,11 +558,15 @@ define([ if (view.staticTubes[i] === null || view.staticTubes[i] === undefined) { var color = this._colors[trajectory.metadataCategoryName] || 'red'; - view.staticTubes[i] = drawTrajectoryLineStatic(trajectory, color, radius); + view.staticTubes[i] = drawTrajectoryLineStatic(trajectory, + color, + radius); } //Ensure static tube draw ranges are set to visible segment - updateStaticTrajectoryDrawRange(trajectory, this.director.currentFrame, view.staticTubes[i]); + updateStaticTrajectoryDrawRange(trajectory, + this.director.currentFrame, + view.staticTubes[i]); } //Remove any old dynamic tubes from the scene @@ -576,11 +580,14 @@ define([ } }); - //Construct new dynamic tubes containing necessary interpolated segment for the current frame + //Construct new dynamic tubes containing necessary + //interpolated segment for the current frame view.dynamicTubes = this.director.trajectories.map(function(trajectory) { var color = scope._colors[trajectory.metadataCategoryName] || 'red'; - var tube = drawTrajectoryLineDynamic(trajectory, scope.director.currentFrame, - color, radius); + var tube = drawTrajectoryLineDynamic(trajectory, + scope.director.currentFrame, + color, + radius); return tube; }); diff --git a/emperor/support_files/js/draw.js b/emperor/support_files/js/draw.js index 7b26216b..f5684190 100644 --- a/emperor/support_files/js/draw.js +++ b/emperor/support_files/js/draw.js @@ -287,7 +287,8 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { // https://github.com/mrdoob/three.js/wiki/Drawing-lines var material, points = [], lineGeometry, limit = 0, path; - _trajectory = trajectory.representativeInterpolatedCoordinatesAtIndex(currentFrame); + _trajectory = trajectory.representativeInterpolatedCoordinatesAtIndex( + currentFrame); if (_trajectory === null || _trajectory.length == 0) return null; @@ -305,8 +306,11 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { // the line will contain the two vertices and the described material // we increase the number of points to have a smoother transition on // edges i. e. where the trajectory changes the direction it is going - lineGeometry = new THREE.TubeGeometry(path, (points.length - 1) * NUM_TUBE_SEGMENTS, radius, - NUM_TUBE_CROSS_SECTION_POINTS, false); + lineGeometry = new THREE.TubeGeometry(path, + (points.length - 1) * NUM_TUBE_SEGMENTS, + radius, + NUM_TUBE_CROSS_SECTION_POINTS, + false); return new THREE.Mesh(lineGeometry, material); } @@ -338,9 +342,14 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { var path = new THREE.EmperorTrajectory(allPoints); - //Tubes are straight segments, but adding vertices along them might change lighting effects - //under certain models and lighting conditions. - var tubeBufferGeom = new THREE.TubeBufferGeometry(path, (allPoints.length - 1) * NUM_TUBE_SEGMENTS, radius, NUM_TUBE_CROSS_SECTION_POINTS, false); + //Tubes are straight segments, but adding vertices along them might change + //lighting effects under certain models and lighting conditions. + var tubeBufferGeom = new THREE.TubeBufferGeometry( + path, + (allPoints.length - 1) * NUM_TUBE_SEGMENTS, + radius, + NUM_TUBE_CROSS_SECTION_POINTS, + false); return new THREE.Mesh(tubeBufferGeom, material); } @@ -355,9 +364,12 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { function updateStaticTrajectoryDrawRange(trajectory, currentFrame, threeMesh) { - //Reverse engineering the number of points in a THREE tube is not fun, and may be implementation/version dependent. - //Number of points drawn per tube segment = 2 (triangles) * 3 (points per triangle) * NUM_TUBE_CROSS_SECTION_POINTS (number of vertices in a cross section of tube) - //Number of tube segments per pair of consecutive points = NUM_TUBE_SEGMENTS + //Reverse engineering the number of points in a THREE tube is not fun, and + //may be implementation/version dependent. + //Number of points drawn per tube segment = + // 2 (triangles) * 3 (points per triangle) * NUM_TUBE_CROSS_SECTION_POINTS + //Number of tube segments per pair of consecutive points = + // NUM_TUBE_SEGMENTS var multiplier = 2 * 3 * NUM_TUBE_CROSS_SECTION_POINTS * NUM_TUBE_SEGMENTS; if (currentFrame < trajectory._intervalValues.length) @@ -367,7 +379,8 @@ define(['underscore', 'three', 'jquery'], function(_, THREE, $) { } else { - threeMesh.geometry.setDrawRange(0, (trajectory.coordinates.length - 1) * multiplier); + threeMesh.geometry.setDrawRange(0, + (trajectory.coordinates.length - 1) * multiplier); } } diff --git a/emperor/support_files/js/trajectory.js b/emperor/support_files/js/trajectory.js index 0c87a5c5..66a2ee30 100644 --- a/emperor/support_files/js/trajectory.js +++ b/emperor/support_files/js/trajectory.js @@ -195,9 +195,11 @@ define([ * points. * * @return {Array[]} Array containing the representative float x, y, z - * coordinates needed to draw the interpolated portion of a trajectory at the given index. + * coordinates needed to draw the interpolated portion of a trajectory at the + * given index. */ - TrajectoryOfSamples.prototype.representativeInterpolatedCoordinatesAtIndex = function(idx) { + TrajectoryOfSamples.prototype.representativeInterpolatedCoordinatesAtIndex = + function(idx) { if (idx === 0) return null; if (this.interpolatedCoordinates.length - 1 <= idx) diff --git a/tests/javascript_tests/test_trajectory.js b/tests/javascript_tests/test_trajectory.js index eae02c4b..c09614a2 100644 --- a/tests/javascript_tests/test_trajectory.js +++ b/tests/javascript_tests/test_trajectory.js @@ -366,19 +366,25 @@ requirejs(['underscore', 'trajectory'], function(_, trajectory) { [{'x': 0, 'y': 0, 'z': 0}, {'x': 0.75, 'y': 0.75, 'z': 0.75}], 'Coordinates are retrieved correctly at index 3'); - + var fullCoordinates11 = trajectory.representativeCoordinatesAtIndex(11); deepEqual(fullCoordinates11, [{'x': 0, 'y': 0, 'z': 0}, {'x': 1, 'y': 1, 'z': 1}, {'x': -9, 'y': -9, 'z': -9}, {'x': 3, 'y': 3, 'z': 3}, {'x': 4.25, 'y': 4.25, 'z': 4.25}], 'Coordinates are retrieved correctly at index 11'); - - var dynamicCoordinates3 = trajectory.representativeInterpolatedCoordinatesAtIndex(3); - var dynamicCoordinates11 = trajectory.representativeInterpolatedCoordinatesAtIndex(11); - - deepEqual(fullCoordinates3.slice(-2), dynamicCoordinates3, "Dynamic coordinates match on frame 3"); - deepEqual(fullCoordinates11.slice(-2), dynamicCoordinates11, "Dynamic coordinates match on frame 11"); + + var dynamicCoordinates3 = + trajectory.representativeInterpolatedCoordinatesAtIndex(3); + var dynamicCoordinates11 = + trajectory.representativeInterpolatedCoordinatesAtIndex(11); + + deepEqual(fullCoordinates3.slice(-2), + dynamicCoordinates3, + 'Dynamic coordinates match on frame 3'); + deepEqual(fullCoordinates11.slice(-2), + dynamicCoordinates11, + 'Dynamic coordinates match on frame 11'); }); @@ -533,7 +539,7 @@ requirejs(['underscore', 'trajectory'], function(_, trajectory) { equal(result, 92, 'The minimum delta is computed correctly for one ' + 'category'); }); - + /** * * Test trajectories with duplicate points. @@ -541,21 +547,27 @@ requirejs(['underscore', 'trajectory'], function(_, trajectory) { */ test('Test Duplicate Points In Trajectories', function() { var result; - trajectory = new TrajectoryOfSamples(['A','B','C','D'], + trajectory = new TrajectoryOfSamples(['A', 'B', 'C', 'D'], 'Nonsense', - [1,2,3,4], - [{'x': 0, 'y': 0, 'z': 0}, {'x': 10, 'y': 10, 'z': 10}, {'x': 10, 'y': 10, 'z': 10}, {'x': 0, 'y': 0, 'z': 0}], + [1, 2, 3, 4], + [{'x': 0, 'y': 0, 'z': 0}, + {'x': 10, 'y': 10, 'z': 10}, + {'x': 10, 'y': 10, 'z': 10}, + {'x': 0, 'y': 0, 'z': 0}], 2, 5); - + for (var i = 0; i < 20; i++) { - var interpTubeCoords = trajectory.representativeInterpolatedCoordinatesAtIndex(i); + var interpTubeCoords = + trajectory.representativeInterpolatedCoordinatesAtIndex(i); if (interpTubeCoords !== null) { var dx = interpTubeCoords[1].x - interpTubeCoords[0].x; var dy = interpTubeCoords[1].y - interpTubeCoords[0].y; var dz = interpTubeCoords[1].z - interpTubeCoords[0].z; var lenSq = dx * dx + dy * dy + dz * dz; - notEqual(lenSq, 0, "Interpolated tube should never be built between consecutive duplicate points in a trajectory"); + notEqual(lenSq, 0, + 'Interpolated tube should never be built between' + + 'consecutive duplicate points in a trajectory'); } } });