Use Lanczos interpolation for smooth pen path

This commit is contained in:
Jean-Benoist Leger 2020-04-09 23:59:15 +02:00
parent 62e285bdb2
commit 0bc9af1235
No known key found for this signature in database
GPG Key ID: 497E86C9B7E87DF6
1 changed files with 65 additions and 6 deletions

View File

@ -1,3 +1,22 @@
function lanczosKernel (x) {
if(x==0) {
return 1.0;
}
return 2*Math.sin(Math.PI*x)*Math.sin(Math.PI*x/2)/Math.pow(Math.PI*x,2);
}
function lanczosInterpolate (xm1, ym1, x0, y0, x1, y1, x2, y2, a) {
var cm1 = lanczosKernel(1+a);
var c0 = lanczosKernel(a);
var c1 = lanczosKernel(1-a);
var c2 = lanczosKernel(2-a);
var delta = (cm1+c0+c1+c2-1)/4;
cm1 -= delta;
c0 -= delta;
c1 -= delta;
c2 -= delta;
return [cm1*xm1 + c0*x0 + c1*x1 + c2*x2, cm1*ym1 + c0*y0 + c1*y1 + c2*y2];
}
var whiteboard = {
canvas: null,
ctx: null,
@ -19,6 +38,7 @@ var whiteboard = {
mouseOverlay: null,
ownCursor: null,
startCoords: [],
penSmoothLastCoords: [],
svgLine: null,
svgRect: null,
svgCirle: null,
@ -97,8 +117,7 @@ var whiteboard = {
}
if (_this.tool === "pen") {
_this.drawPenLine(_this.prevX, _this.prevY, _this.prevX, _this.prevY, _this.drawcolor, _this.thickness);
_this.sendFunction({ "t": _this.tool, "d": [_this.prevX, _this.prevY, _this.prevX, _this.prevY], "c": _this.drawcolor, "th": _this.thickness });
_this.penSmoothLastCoords = [_this.prevX, _this.prevY, _this.prevX, _this.prevY, _this.prevX, _this.prevY]
} else if (_this.tool === "eraser") {
_this.drawEraserLine(_this.prevX, _this.prevY, _this.prevX, _this.prevY, _this.thickness);
_this.sendFunction({ "t": _this.tool, "d": [_this.prevX, _this.prevY, _this.prevX, _this.prevY], "th": _this.thickness });
@ -179,6 +198,8 @@ var whiteboard = {
_this.drawPenLine(currX, currY, _this.startCoords[0], _this.startCoords[1], _this.drawcolor, _this.thickness);
_this.sendFunction({ "t": _this.tool, "d": [currX, currY, _this.startCoords[0], _this.startCoords[1]], "c": _this.drawcolor, "th": _this.thickness });
_this.svgContainer.find("line").remove();
} else if (_this.tool === "pen") {
_this.pushPointSmoothPen(currX, currY);
} else if (_this.tool === "rect") {
if (_this.pressedKeys.shift) {
if ((currY - _this.startCoords[1]) * (currX - _this.startCoords[0]) > 0) {
@ -305,8 +326,7 @@ var whiteboard = {
if (_this.drawFlag) {
if (_this.tool === "pen") {
_this.drawPenLine(currX, currY, _this.prevX, _this.prevY, _this.drawcolor, _this.thickness);
_this.sendFunction({ "t": _this.tool, "d": [currX, currY, _this.prevX, _this.prevY], "c": _this.drawcolor, "th": _this.thickness });
_this.pushPointSmoothPen(currX, currY);
} else if (_this.tool == "eraser") {
_this.drawEraserLine(currX, currY, _this.prevX, _this.prevY, _this.thickness);
_this.sendFunction({ "t": _this.tool, "d": [currX, currY, _this.prevX, _this.prevY], "th": _this.thickness });
@ -425,6 +445,17 @@ var whiteboard = {
}
_this.mouseOverlay.find(".xCanvasBtn").click(); //Remove all current drops
},
pushPointSmoothPen: function (X, Y) {
var _this = this;
if(_this.penSmoothLastCoords.length>=8) {
_this.penSmoothLastCoords = [_this.penSmoothLastCoords[2], _this.penSmoothLastCoords[3], _this.penSmoothLastCoords[4], _this.penSmoothLastCoords[5], _this.penSmoothLastCoords[6], _this.penSmoothLastCoords[7]]
}
_this.penSmoothLastCoords.push(X, Y)
if(_this.penSmoothLastCoords.length>=8) {
_this.drawPenSmoothLine(_this.penSmoothLastCoords, _this.drawcolor, _this.thickness);
_this.sendFunction({ "t": _this.tool, "d": _this.penSmoothLastCoords, "c": _this.drawcolor, "th": _this.thickness });
}
},
dragCanvasRectContent: function (xf, yf, xt, yt, width, height) {
var tempCanvas = document.createElement('canvas');
tempCanvas.width = width;
@ -455,6 +486,30 @@ var whiteboard = {
_this.ctx.stroke();
_this.ctx.closePath();
},
drawPenSmoothLine: function (coords, color, thickness) {
var _this = this;
var xm1 = coords[0];
var ym1 = coords[1];
var x0 = coords[2];
var y0 = coords[3];
var x1 = coords[4];
var y1 = coords[5];
var x2 = coords[6];
var y2 = coords[7];
var length = Math.sqrt(Math.pow(x0-x1,2)+Math.pow(y0-y1,2));
var steps = Math.ceil(length/5);
_this.ctx.beginPath();
_this.ctx.moveTo(x0, y0);
for (var i=0; i<steps; i++) {
var point = lanczosInterpolate(xm1, ym1, x0, y0, x1, y1, x2, y2, (i+1)/steps);
_this.ctx.lineTo(point[0], point[1]);
}
_this.ctx.strokeStyle = color;
_this.ctx.lineWidth = thickness;
_this.ctx.lineCap = _this.lineCap;
_this.ctx.stroke();
_this.ctx.closePath();
},
drawEraserLine: function (fromX, fromY, toX, toY, thickness) {
var _this = this;
_this.ctx.beginPath();
@ -704,7 +759,11 @@ var whiteboard = {
var thickness = content["th"];
window.requestAnimationFrame(function () {
if (tool === "line" || tool === "pen") {
_this.drawPenLine(data[0], data[1], data[2], data[3], color, thickness);
if(data.length == 4) {
_this.drawPenLine(data[0], data[1], data[2], data[3], color, thickness);
} else {
_this.drawPenSmoothLine(data, color, thickness);
}
} else if (tool === "rect") {
_this.drawRec(data[0], data[1], data[2], data[3], color, thickness);
} else if (tool === "circle") {
@ -880,4 +939,4 @@ var whiteboard = {
_this.mouseOverlay.css({ "cursor": "crosshair" });
}
}
}
}