|
|
@ -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. |
|
|
|
* |
|
|
|