Browse Source

More cleanups, more optimisations:

-Never push into arrays that have a known length
-Move more functions back into the main updateGraph method
newShading
Ludo Stellingwerff 9 years ago
parent
commit
c4d4fd4dec
5 changed files with 38 additions and 145 deletions
  1. +14
    -21
      lib/timeline/component/GraphGroup.js
  2. +24
    -26
      lib/timeline/component/LineGraph.js
  3. +0
    -27
      lib/timeline/component/graph2d_types/bar.js
  4. +0
    -54
      lib/timeline/component/graph2d_types/line.js
  5. +0
    -17
      lib/timeline/component/graph2d_types/points.js

+ 14
- 21
lib/timeline/component/GraphGroup.js View File

@ -1,8 +1,5 @@
var util = require('../../util'); var util = require('../../util');
var DOMutil = require('../../DOMutil'); var DOMutil = require('../../DOMutil');
var Line = require('./graph2d_types/line');
var Bar = require('./graph2d_types/bar');
var Points = require('./graph2d_types/points');
/** /**
* /** * /**
@ -16,7 +13,7 @@ var Points = require('./graph2d_types/points');
*/ */
function GraphGroup(group, groupId, options, groupsUsingDefaultStyles) { function GraphGroup(group, groupId, options, groupsUsingDefaultStyles) {
this.id = groupId; this.id = groupId;
var fields = ['sampling', 'style', 'sort', 'yAxisOrientation', 'barChart', 'drawPoints', 'shaded', 'interpolation']
var fields = ['sampling', 'style', 'sort', 'yAxisOrientation', 'barChart', 'drawPoints', 'shaded', 'interpolation'];
this.options = util.selectiveBridgeObject(fields, options); this.options = util.selectiveBridgeObject(fields, options);
this.usingDefaultStyle = group.className === undefined; this.usingDefaultStyle = group.className === undefined;
this.groupsUsingDefaultStyles = groupsUsingDefaultStyles; this.groupsUsingDefaultStyles = groupsUsingDefaultStyles;
@ -29,7 +26,6 @@ function GraphGroup(group, groupId, options, groupsUsingDefaultStyles) {
this.visible = group.visible === undefined ? true : group.visible; this.visible = group.visible === undefined ? true : group.visible;
} }
function insertionSort (a,compare) { function insertionSort (a,compare) {
for (var i = 0; i < a.length; i++) { for (var i = 0; i < a.length; i++) {
var k = a[i]; var k = a[i];
@ -59,9 +55,12 @@ GraphGroup.prototype.setItems = function (items) {
} }
}; };
GraphGroup.prototype.getItems = function () {
return this.itemsData;
}
/** /**
* this is used for plotting barcharts, this way, we only have to calculate it once.
* this is used for barcharts and shading, this way, we only have to calculate it once.
* @param pos * @param pos
*/ */
GraphGroup.prototype.setZeroPosition = function (pos) { GraphGroup.prototype.setZeroPosition = function (pos) {
@ -105,16 +104,6 @@ GraphGroup.prototype.setOptions = function (options) {
} }
} }
} }
if (this.options.style == 'line') {
this.type = new Line(this.id, this.options);
}
else if (this.options.style == 'bar') {
this.type = new Bar(this.id, this.options);
}
else if (this.options.style == 'points') {
this.type = new Points(this.id, this.options);
}
}; };
@ -132,6 +121,8 @@ GraphGroup.prototype.update = function (group) {
}; };
//TODO: move these render functions into the type specific files and call them from LineGraph
/** /**
* draw the icon for the legend. * draw the icon for the legend.
* *
@ -216,11 +207,13 @@ GraphGroup.prototype.getLegend = function (iconWidth, iconHeight) {
}; };
GraphGroup.prototype.getYRange = function (groupData) { GraphGroup.prototype.getYRange = function (groupData) {
return this.type.getYRange(groupData);
};
GraphGroup.prototype.getData = function (groupData) {
return this.type.getData(groupData);
var yMin = groupData[0].y;
var yMax = groupData[0].y;
for (var j = 0; j < groupData.length; j++) {
yMin = yMin > groupData[j].y ? groupData[j].y : yMin;
yMax = yMax < groupData[j].y ? groupData[j].y : yMax;
}
return {min: yMin, max: yMax, yAxisOrientation: this.options.yAxisOrientation};
}; };
module.exports = GraphGroup; module.exports = GraphGroup;

+ 24
- 26
lib/timeline/component/LineGraph.js View File

@ -595,6 +595,9 @@ LineGraph.prototype._updateGraph = function () {
var processedGroupData = {}; var processedGroupData = {};
var groupRanges = {}; var groupRanges = {};
var changeCalled = false; var changeCalled = false;
// this is the range of the SVG canvas
var minDate = this.body.util.toGlobalTime(-this.body.domProps.root.width);
var maxDate = this.body.util.toGlobalTime(2 * this.body.domProps.root.width);
// getting group Ids // getting group Ids
var groupIds = []; var groupIds = [];
@ -607,9 +610,6 @@ LineGraph.prototype._updateGraph = function () {
} }
} }
if (groupIds.length > 0) { if (groupIds.length > 0) {
// this is the range of the SVG canvas
var minDate = this.body.util.toGlobalTime(-this.body.domProps.root.width);
var maxDate = this.body.util.toGlobalTime(2 * this.body.domProps.root.width);
var groupsData = {}; var groupsData = {};
// fill groups data, this only loads the data we require based on the timewindow // fill groups data, this only loads the data we require based on the timewindow
@ -778,15 +778,17 @@ LineGraph.prototype._getRelevantData = function (groupIds, groupsData, minDate,
if (groupIds.length > 0) { if (groupIds.length > 0) {
for (i = 0; i < groupIds.length; i++) { for (i = 0; i < groupIds.length; i++) {
group = this.groups[groupIds[i]]; group = this.groups[groupIds[i]];
groupsData[groupIds[i]] = [];
var itemsData = group.getItems();
// optimization for sorted data // optimization for sorted data
if (group.options.sort == true) { if (group.options.sort == true) {
var dataContainer = groupsData[groupIds[i]];
var guess = Math.max(0, util.binarySearchValue(group.itemsData, minDate, 'x', 'before'));
for (j = guess; j < group.itemsData.length; j++) {
var max = maxDate.getTime();
var guess = Math.max(0, util.binarySearchValue(itemsData, minDate, 'x', 'before'));
var dataContainer = new Array(itemsData.length-guess);
for (j = guess; j < itemsData.length; j++) {
item = group.itemsData[j]; item = group.itemsData[j];
dataContainer.push(item);
if (item.x > maxDate) {
dataContainer[j-guess] = item;
if (item.x.getTime() > max) {
groupsData[groupIds[i]] = dataContainer.splice(0,j-guess);
break; break;
} }
} }
@ -823,12 +825,12 @@ LineGraph.prototype._applySampling = function (groupIds, groupsData) {
var pointsPerPixel = amountOfPoints / xDistance; var pointsPerPixel = amountOfPoints / xDistance;
increment = Math.min(Math.ceil(0.2 * amountOfPoints), Math.max(1, Math.round(pointsPerPixel))); increment = Math.min(Math.ceil(0.2 * amountOfPoints), Math.max(1, Math.round(pointsPerPixel)));
var sampledData = [];
var sampledData = new Array(amountOfPoints);
for (var j = 0; j < amountOfPoints; j += increment) { for (var j = 0; j < amountOfPoints; j += increment) {
sampledData.push(dataContainer[j]);
var idx = Math.round(j/increment);
sampledData[idx]=dataContainer[j];
} }
groupsData[groupIds[i]] = sampledData;
groupsData[groupIds[i]] = sampledData.splice(0,Math.round(amountOfPoints/increment));
} }
} }
} }
@ -858,10 +860,10 @@ LineGraph.prototype._getYRanges = function (groupIds, groupsData, groupRanges) {
// if bar graphs are stacked, their range need to be handled differently and accumulated over all groups. // if bar graphs are stacked, their range need to be handled differently and accumulated over all groups.
if (options.stack === true && options.style === 'bar') { if (options.stack === true && options.style === 'bar') {
if (options.yAxisOrientation === 'left') { if (options.yAxisOrientation === 'left') {
combinedDataLeft = combinedDataLeft.concat(group.getData(groupData));
combinedDataLeft = combinedDataLeft.concat(group.getItems());
} }
else { else {
combinedDataRight = combinedDataRight.concat(group.getData(groupData));
combinedDataRight = combinedDataRight.concat(group.getItems());
} }
} }
else { else {
@ -873,10 +875,6 @@ LineGraph.prototype._getYRanges = function (groupIds, groupsData, groupRanges) {
// if bar graphs are stacked, their range need to be handled differently and accumulated over all groups. // if bar graphs are stacked, their range need to be handled differently and accumulated over all groups.
Bars.getStackedYRange(combinedDataLeft, groupRanges, groupIds, '__barStackLeft', 'left'); Bars.getStackedYRange(combinedDataLeft, groupRanges, groupIds, '__barStackLeft', 'left');
Bars.getStackedYRange(combinedDataRight, groupRanges, groupIds, '__barStackRight', 'right'); Bars.getStackedYRange(combinedDataRight, groupRanges, groupIds, '__barStackRight', 'right');
// if line graphs are stacked, their range need to be handled differently and accumulated over all groups.
//LineFunctions.getStackedYRange(combinedDataLeft , groupRanges, groupIds, '__lineStackLeft' , 'left' );
//LineFunctions.getStackedYRange(combinedDataRight, groupRanges, groupIds, '__lineStackRight', 'right');
} }
}; };
@ -991,7 +989,7 @@ LineGraph.prototype._toggleAxisVisiblity = function (axisUsed, axis) {
var changed = false; var changed = false;
if (axisUsed == false) { if (axisUsed == false) {
if (axis.dom.frame.parentNode && axis.hidden == false) { if (axis.dom.frame.parentNode && axis.hidden == false) {
axis.hide()
axis.hide();
changed = true; changed = true;
} }
} }
@ -1015,14 +1013,14 @@ LineGraph.prototype._toggleAxisVisiblity = function (axisUsed, axis) {
* @private * @private
*/ */
LineGraph.prototype._convertXcoordinates = function (datapoints) { LineGraph.prototype._convertXcoordinates = function (datapoints) {
var extractedData = [];
var extractedData = new Array(datapoints.length);
var xValue, yValue; var xValue, yValue;
var toScreen = this.body.util.toScreen; var toScreen = this.body.util.toScreen;
for (var i = 0; i < datapoints.length; i++) { for (var i = 0; i < datapoints.length; i++) {
xValue = toScreen(datapoints[i].x) + this.props.width; xValue = toScreen(datapoints[i].x) + this.props.width;
yValue = datapoints[i].y; yValue = datapoints[i].y;
extractedData.push({x: xValue, y: yValue});
extractedData[i] = {x: xValue, y: yValue};
} }
return extractedData; return extractedData;
@ -1040,8 +1038,8 @@ LineGraph.prototype._convertXcoordinates = function (datapoints) {
* @private * @private
*/ */
LineGraph.prototype._convertYcoordinates = function (datapoints, group) { LineGraph.prototype._convertYcoordinates = function (datapoints, group) {
var extractedData = [];
var xValue, yValue;
var extractedData = new Array(datapoints.length);
var xValue, yValue, labelValue;
var toScreen = this.body.util.toScreen; var toScreen = this.body.util.toScreen;
var axis = this.yAxisLeft; var axis = this.yAxisLeft;
var svgHeight = Number(this.svg.style.height.replace('px', '')); var svgHeight = Number(this.svg.style.height.replace('px', ''));
@ -1050,10 +1048,10 @@ LineGraph.prototype._convertYcoordinates = function (datapoints, group) {
} }
for (var i = 0; i < datapoints.length; i++) { for (var i = 0; i < datapoints.length; i++) {
var labelValue = datapoints[i].label ? datapoints[i].label : null;
labelValue = datapoints[i].label ? datapoints[i].label : null;
xValue = toScreen(datapoints[i].x) + this.props.width; xValue = toScreen(datapoints[i].x) + this.props.width;
yValue = Math.round(axis.convertValue(datapoints[i].y)); yValue = Math.round(axis.convertValue(datapoints[i].y));
extractedData.push({x: xValue, y: yValue, label: labelValue});
extractedData[i] = {x: xValue, y: yValue, label: labelValue};
} }
group.setZeroPosition(Math.min(svgHeight, axis.convertValue(0))); group.setZeroPosition(Math.min(svgHeight, axis.convertValue(0)));

+ 0
- 27
lib/timeline/component/graph2d_types/bar.js View File

@ -2,35 +2,8 @@ var DOMutil = require('../../../DOMutil');
var Points = require('./points'); var Points = require('./points');
function Bargraph(groupId, options) { function Bargraph(groupId, options) {
this.groupId = groupId;
this.options = options;
} }
Bargraph.prototype.getYRange = function(groupData) {
var yMin = groupData[0].y;
var yMax = groupData[0].y;
for (var j = 0; j < groupData.length; j++) {
yMin = yMin > groupData[j].y ? groupData[j].y : yMin;
yMax = yMax < groupData[j].y ? groupData[j].y : yMax;
}
return {min: yMin, max: yMax, yAxisOrientation: this.options.yAxisOrientation};
};
Bargraph.prototype.getData = function(groupData) {
var combinedData = [];
for (var j = 0; j < groupData.length; j++) {
combinedData.push({
x: groupData[j].x,
y: groupData[j].y,
groupId: this.groupId
});
}
return combinedData;
}
/** /**
* draw a bar graph * draw a bar graph
* *

+ 0
- 54
lib/timeline/component/graph2d_types/line.js View File

@ -1,62 +1,8 @@
var DOMutil = require('../../../DOMutil'); var DOMutil = require('../../../DOMutil');
function Line(groupId, options) { function Line(groupId, options) {
this.groupId = groupId;
this.options = options;
} }
Line.prototype.getData = function (groupData) {
var combinedData = [];
for (var j = 0; j < groupData.length; j++) {
combinedData.push({
x: groupData[j].x,
y: groupData[j].y,
groupId: this.groupId
});
}
return combinedData;
}
Line.prototype.getYRange = function (groupData) {
var yMin = groupData[0].y;
var yMax = groupData[0].y;
for (var j = 0; j < groupData.length; j++) {
yMin = yMin > groupData[j].y ? groupData[j].y : yMin;
yMax = yMax < groupData[j].y ? groupData[j].y : yMax;
}
return {min: yMin, max: yMax, yAxisOrientation: this.options.yAxisOrientation};
};
/**
* Fill the intersections object with counters of how many datapoints share the same x coordinates
* @param intersections
* @param combinedData
* @private
*/
Line._getDataIntersections = function (intersections, combinedData) {
// get intersections
var coreDistance;
for (var i = 0; i < combinedData.length; i++) {
if (i + 1 < combinedData.length) {
coreDistance = Math.abs(combinedData[i + 1].x - combinedData[i].x);
}
if (i > 0) {
coreDistance = Math.min(coreDistance, Math.abs(combinedData[i - 1].x - combinedData[i].x));
}
if (coreDistance === 0) {
if (intersections[combinedData[i].x] === undefined) {
intersections[combinedData[i].x] = {
amount: 0,
resolved: 0,
accumulatedPositive: 0,
accumulatedNegative: 0
};
}
intersections[combinedData[i].x].amount += 1;
}
}
};
Line.calcPath = function (dataset, group) { Line.calcPath = function (dataset, group) {
if (dataset != null) { if (dataset != null) {
if (dataset.length > 0) { if (dataset.length > 0) {

+ 0
- 17
lib/timeline/component/graph2d_types/points.js View File

@ -1,25 +1,8 @@
var DOMutil = require('../../../DOMutil'); var DOMutil = require('../../../DOMutil');
function Points(groupId, options) { function Points(groupId, options) {
this.groupId = groupId;
this.options = options;
} }
Points.prototype.getYRange = function(groupData) {
var yMin = groupData[0].y;
var yMax = groupData[0].y;
for (var j = 0; j < groupData.length; j++) {
yMin = yMin > groupData[j].y ? groupData[j].y : yMin;
yMax = yMax < groupData[j].y ? groupData[j].y : yMax;
}
return {min: yMin, max: yMax, yAxisOrientation: this.options.yAxisOrientation};
};
Points.prototype.draw = function(dataset, group, framework, offset) {
Points.draw(dataset, group, framework, offset);
};
/** /**
* draw the data points * draw the data points
* *

Loading…
Cancel
Save