Skip to content
This repository has been archived by the owner on Jul 29, 2019. It is now read-only.

Added generic graph drawing loop; isolated point drawing of graph style 'Bar' #2208

Merged
merged 4 commits into from
Oct 22, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 160 additions & 14 deletions lib/graph3d/Graph3d.js
Original file line number Diff line number Diff line change
Expand Up @@ -831,21 +831,34 @@ Graph3d.prototype.redraw = function() {
this._redrawClear();
this._redrawAxis();

if (this.style === Graph3d.STYLE.GRID ||
this.style === Graph3d.STYLE.SURFACE) {
this._redrawDataGrid();
}
else if (this.style === Graph3d.STYLE.LINE) {
this._redrawDataLine();
}
else if (this.style === Graph3d.STYLE.BAR ||
this.style === Graph3d.STYLE.BARCOLOR ||
this.style === Graph3d.STYLE.BARSIZE) {
this._redrawDataBar();
var pointDrawingMethod = undefined;
switch (this.style) {
case Graph3d.STYLE.BAR:
pointDrawingMethod = Graph3d.prototype._redrawBarGraphPoint;
break;
}
else {
// style is DOT, DOTLINE, DOTCOLOR, DOTSIZE
this._redrawDataDot();

if (pointDrawingMethod !== undefined) {
// Use generic drawing loop
// Pass the method reference here
this._redrawDataGraph(pointDrawingMethod);
} else {
// Use the old style drawing methods

if (this.style === Graph3d.STYLE.GRID ||
this.style === Graph3d.STYLE.SURFACE) {
this._redrawDataGrid();
}
else if (this.style === Graph3d.STYLE.LINE) {
this._redrawDataLine();
} else if (this.style === Graph3d.STYLE.BARCOLOR ||
this.style === Graph3d.STYLE.BARSIZE) {
this._redrawDataBar();
}
else {
// style is DOT, DOTLINE, DOTCOLOR, DOTSIZE
this._redrawDataDot();
}
}

this._redrawInfo();
Expand Down Expand Up @@ -1563,6 +1576,137 @@ Graph3d.prototype._redrawDataDot = function() {
}
};


/**
* Draw a bar element in the view with the given properties.
*/
Graph3d.prototype._redrawBar = function(ctx, point, xWidth, yWidth, color, borderColor) {
var i, j, surface, corners;

// calculate all corner points
var me = this;
var point3d = point.point;
var top = [
{point: new Point3d(point3d.x - xWidth, point3d.y - yWidth, point3d.z)},
{point: new Point3d(point3d.x + xWidth, point3d.y - yWidth, point3d.z)},
{point: new Point3d(point3d.x + xWidth, point3d.y + yWidth, point3d.z)},
{point: new Point3d(point3d.x - xWidth, point3d.y + yWidth, point3d.z)}
];
var bottom = [
{point: new Point3d(point3d.x - xWidth, point3d.y - yWidth, this.zMin)},
{point: new Point3d(point3d.x + xWidth, point3d.y - yWidth, this.zMin)},
{point: new Point3d(point3d.x + xWidth, point3d.y + yWidth, this.zMin)},
{point: new Point3d(point3d.x - xWidth, point3d.y + yWidth, this.zMin)}
];

// calculate screen location of the points
top.forEach(function (obj) {
obj.screen = me._convert3Dto2D(obj.point);
});
bottom.forEach(function (obj) {
obj.screen = me._convert3Dto2D(obj.point);
});

// create five sides, calculate both corner points and center points
var surfaces = [
{corners: top, center: Point3d.avg(bottom[0].point, bottom[2].point)},
{corners: [top[0], top[1], bottom[1], bottom[0]], center: Point3d.avg(bottom[1].point, bottom[0].point)},
{corners: [top[1], top[2], bottom[2], bottom[1]], center: Point3d.avg(bottom[2].point, bottom[1].point)},
{corners: [top[2], top[3], bottom[3], bottom[2]], center: Point3d.avg(bottom[3].point, bottom[2].point)},
{corners: [top[3], top[0], bottom[0], bottom[3]], center: Point3d.avg(bottom[0].point, bottom[3].point)}
];
point.surfaces = surfaces;

// calculate the distance of each of the surface centers to the camera
for (j = 0; j < surfaces.length; j++) {
surface = surfaces[j];
var transCenter = this._convertPointToTranslation(surface.center);
surface.dist = this.showPerspective ? transCenter.length() : -transCenter.z;
// TODO: this dept calculation doesn't work 100% of the cases due to perspective,
// but the current solution is fast/simple and works in 99.9% of all cases
// the issue is visible in example 14, with graph.setCameraPosition({horizontal: 2.97, vertical: 0.5, distance: 0.9})
}

// order the surfaces by their (translated) depth
surfaces.sort(function (a, b) {
var diff = b.dist - a.dist;
if (diff) return diff;

// if equal depth, sort the top surface last
if (a.corners === top) return 1;
if (b.corners === top) return -1;

// both are equal
return 0;
});

// draw the ordered surfaces
ctx.lineWidth = this._getStrokeWidth(point);
ctx.strokeStyle = borderColor;
ctx.fillStyle = color;
// NOTE: we start at j=2 instead of j=0 as we don't need to draw the two surfaces at the backside
for (j = 2; j < surfaces.length; j++) {
surface = surfaces[j];
corners = surface.corners;
ctx.beginPath();
ctx.moveTo(corners[3].screen.x, corners[3].screen.y);
ctx.lineTo(corners[0].screen.x, corners[0].screen.y);
ctx.lineTo(corners[1].screen.x, corners[1].screen.y);
ctx.lineTo(corners[2].screen.x, corners[2].screen.y);
ctx.lineTo(corners[3].screen.x, corners[3].screen.y);
ctx.fill();
ctx.stroke();
}
};


/**
* Draw single datapoint for graph style 'Bar'.
*/
Graph3d.prototype._redrawBarGraphPoint = function(ctx, point) {
var i, j, surface, corners;

ctx.lineJoin = 'round';
ctx.lineCap = 'round';

var xWidth = this.xBarWidth / 2;
var yWidth = this.yBarWidth / 2;


// determine color
var hue, color, borderColor;
// calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0
hue = (1 - (point.point.z - this.zMin) * this.scale.z / this.verticalRatio) * 240;
color = this._hsv2rgb(hue, 1, 1);
borderColor = this._hsv2rgb(hue, 1, 0.8);

this._redrawBar(ctx, point, xWidth, yWidth, color, borderColor);
};


/**
* Draw all datapoints for currently selected graph style.
*
* @param pointDrawMethod - method reference to draw a point in a specific graph style.
*/
Graph3d.prototype._redrawDataGraph = function(pointDrawMethod) {
var ctx = this._getContext();
var i;

if (this.dataPoints === undefined || this.dataPoints.length <= 0)
return; // TODO: throw exception?

this._calcTranslations(this.dataPoints);

for (i = 0; i < this.dataPoints.length; i++) {
var point = this.dataPoints[i];

// Using call() ensures that the correct context is used
pointDrawMethod.call(this, ctx, point);
}
};


/**
* Draw all datapoints as bars.
* This function can be used when the style is 'bar', 'bar-color', or 'bar-size'
Expand All @@ -1585,6 +1729,8 @@ Graph3d.prototype._redrawDataBar = function() {
for (i = 0; i < this.dataPoints.length; i++) {
var point = this.dataPoints[i];

// TODO: Remove code for style `Bar` here - it has been refactored to separate routine

// determine color
var hue, color, borderColor;
if (this.style === Graph3d.STYLE.BARCOLOR ) {
Expand Down