diff --git a/lib/graph3d/Graph3d.js b/lib/graph3d/Graph3d.js index aae7e869..f84908ef 100644 --- a/lib/graph3d/Graph3d.js +++ b/lib/graph3d/Graph3d.js @@ -846,6 +846,12 @@ Graph3d.prototype.getPointDrawingMethod = function() { case Graph3d.STYLE.DOTSIZE: pointDrawingMethod = Graph3d.prototype._redrawDotSizeGraphPoint; break; + case Graph3d.STYLE.SURFACE: + pointDrawingMethod = Graph3d.prototype._redrawSurfaceGraphPoint; + break; + case Graph3d.STYLE.GRID: + pointDrawingMethod = Graph3d.prototype._redrawGridGraphPoint; + break; } return pointDrawingMethod; @@ -875,11 +881,7 @@ Graph3d.prototype.redraw = function() { } 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) { + if (this.style === Graph3d.STYLE.LINE) { this._redrawDataLine(); } else { @@ -1414,108 +1416,6 @@ Graph3d.prototype._hsv2rgb = function(H, S, V) { }; -Graph3d.prototype._drawGridLine = function(ctx, from, to) { - if (from === undefined || to === undefined) { - return; - } - - // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 - var zAvg = (from.point.z + to.point.z) / 2; - var h = (1 - (zAvg - this.zMin) * this.scale.z / this.verticalRatio) * 240; - - ctx.lineWidth = this._getStrokeWidth(from) * 2; - ctx.strokeStyle = this._hsv2rgb(h, 1, 1); - this._line(ctx, from.screen, to.screen); -}; - - -/** - * Draw all datapoints as a grid - * This function can be used when the style is 'grid' - */ -Graph3d.prototype._redrawDataGrid = function() { - var ctx = this._getContext(), - point, right, top, cross, - i, - topSideVisible, fillStyle, strokeStyle, lineWidth, - h, s, v, zAvg; - - if (this.dataPoints === undefined || this.dataPoints.length <= 0) - return; // TODO: throw exception? - - this._calcTranslations(this.dataPoints); - - if (this.style === Graph3d.STYLE.SURFACE) { - for (i = 0; i < this.dataPoints.length; i++) { - point = this.dataPoints[i]; - right = point.pointRight; - top = point.pointTop; - cross = point.pointCross; - - if (point !== undefined && right !== undefined && top !== undefined && cross !== undefined) { - - if (this.showGrayBottom || this.showShadow) { - // calculate the cross product of the two vectors from center - // to left and right, in order to know whether we are looking at the - // bottom or at the top side. We can also use the cross product - // for calculating light intensity - var aDiff = Point3d.subtract(cross.trans, point.trans); - var bDiff = Point3d.subtract(top.trans, right.trans); - var crossproduct = Point3d.crossProduct(aDiff, bDiff); - var len = crossproduct.length(); - // FIXME: there is a bug with determining the surface side (shadow or colored) - - topSideVisible = (crossproduct.z > 0); - } - else { - topSideVisible = true; - } - - if (topSideVisible) { - // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 - zAvg = (point.point.z + right.point.z + top.point.z + cross.point.z) / 4; - h = (1 - (zAvg - this.zMin) * this.scale.z / this.verticalRatio) * 240; - s = 1; // saturation - - if (this.showShadow) { - v = Math.min(1 + (crossproduct.x / len) / 2, 1); // value. TODO: scale - fillStyle = this._hsv2rgb(h, s, v); - strokeStyle = fillStyle; - } - else { - v = 1; - fillStyle = this._hsv2rgb(h, s, v); - strokeStyle = this.axisColor; // TODO: should be customizable - } - } - else { - fillStyle = 'gray'; - strokeStyle = this.axisColor; - } - - ctx.lineWidth = this._getStrokeWidth(point); - ctx.fillStyle = fillStyle; - ctx.strokeStyle = strokeStyle; - ctx.beginPath(); - ctx.moveTo(point.screen.x, point.screen.y); - ctx.lineTo(right.screen.x, right.screen.y); - ctx.lineTo(cross.screen.x, cross.screen.y); - ctx.lineTo(top.screen.x, top.screen.y); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); // TODO: only draw stroke when strokeWidth > 0 - } - } - } - else { // grid style - for (i = 0; i < this.dataPoints.length; i++) { - point = this.dataPoints[i]; - this._drawGridLine(ctx, point, point.pointRight); - this._drawGridLine(ctx, point, point.pointTop); - } - } -}; - Graph3d.prototype._getStrokeWidth = function(point) { if (point !== undefined) { if (this.showPerspective) { @@ -1539,7 +1439,7 @@ Graph3d.prototype._getStrokeWidth = function(point) { * 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; + var i, j, surface; // calculate all corner points var me = this; @@ -1605,16 +1505,40 @@ Graph3d.prototype._redrawBar = function(ctx, point, xWidth, yWidth, color, borde // 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(); + this._polygon(ctx, surface.corners); + } +}; + + +/** + * Draw a polygon using the passed points and fill it with the passed style and stroke. + * + * @param points an array of points. + * @param fillStyle optional; the fill style to set + * @param strokeStyle optional; the stroke style to set + */ +Graph3d.prototype._polygon = function(ctx, points, fillStyle, strokeStyle) { + if (points.length < 2) { + return; + } + + if (fillStyle !== undefined) { + ctx.fillStyle = fillStyle; + } + if (strokeStyle !== undefined) { + ctx.strokeStyle = strokeStyle; + } + ctx.beginPath(); + ctx.moveTo(points[0].screen.x, points[0].screen.y); + + for (var i = 1; i < points.length; ++i) { + var point = points[i]; + ctx.lineTo(point.screen.x, point.screen.y); } + + ctx.closePath(); + ctx.fill(); + ctx.stroke(); // TODO: only draw stroke when strokeWidth > 0 }; @@ -1796,6 +1720,96 @@ Graph3d.prototype._redrawDotSizeGraphPoint = function(ctx, point) { }; +/** + * Draw single datapoint for graph style 'surface'. + */ +Graph3d.prototype._redrawSurfaceGraphPoint = function(ctx, point) { + var right = point.pointRight; + var top = point.pointTop; + var cross = point.pointCross; + + if (point === undefined || right === undefined || top === undefined || cross === undefined) { + return; + } + + var topSideVisible = true; + var fillStyle; + var strokeStyle; + var lineWidth; + + if (this.showGrayBottom || this.showShadow) { + // calculate the cross product of the two vectors from center + // to left and right, in order to know whether we are looking at the + // bottom or at the top side. We can also use the cross product + // for calculating light intensity + var aDiff = Point3d.subtract(cross.trans, point.trans); + var bDiff = Point3d.subtract(top.trans, right.trans); + var crossproduct = Point3d.crossProduct(aDiff, bDiff); + var len = crossproduct.length(); + // FIXME: there is a bug with determining the surface side (shadow or colored) + + topSideVisible = (crossproduct.z > 0); + } + + if (topSideVisible) { + + // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 + var zAvg = (point.point.z + right.point.z + top.point.z + cross.point.z) / 4; + var h = (1 - (zAvg - this.zMin) * this.scale.z / this.verticalRatio) * 240; + var s = 1; // saturation + var v; + + if (this.showShadow) { + v = Math.min(1 + (crossproduct.x / len) / 2, 1); // value. TODO: scale + fillStyle = this._hsv2rgb(h, s, v); + strokeStyle = fillStyle; + } + else { + v = 1; + fillStyle = this._hsv2rgb(h, s, v); + strokeStyle = this.axisColor; // TODO: should be customizable + } + } + else { + fillStyle = 'gray'; + strokeStyle = this.axisColor; + } + + ctx.lineWidth = this._getStrokeWidth(point); + // TODO: only draw stroke when strokeWidth > 0 + + var points = [point, right, cross, top]; + this._polygon(ctx, points, fillStyle, strokeStyle); +}; + + +/** + * Helper method for _redrawGridGraphPoint() + */ +Graph3d.prototype._drawGridLine = function(ctx, from, to) { + if (from === undefined || to === undefined) { + return; + } + + // calculate Hue from the current value. At zMin the hue is 240, at zMax the hue is 0 + var zAvg = (from.point.z + to.point.z) / 2; + var h = (1 - (zAvg - this.zMin) * this.scale.z / this.verticalRatio) * 240; + + ctx.lineWidth = this._getStrokeWidth(from) * 2; + ctx.strokeStyle = this._hsv2rgb(h, 1, 1); + this._line(ctx, from.screen, to.screen); +}; + + +/** + * Draw single datapoint for graph style 'Grid'. + */ +Graph3d.prototype._redrawGridGraphPoint = function(ctx, point) { + this._drawGridLine(ctx, point, point.pointRight); + this._drawGridLine(ctx, point, point.pointTop); +}; + + /** * Draw all datapoints for currently selected graph style. *