diff --git a/src/js/tools/drawing/BaseTool.js b/src/js/tools/drawing/BaseTool.js index 4b58408a..6b35121e 100644 --- a/src/js/tools/drawing/BaseTool.js +++ b/src/js/tools/drawing/BaseTool.js @@ -98,11 +98,11 @@ var pixels = []; var dx = Math.abs(x1 - x0); var dy = Math.abs(y1 - y0); + var sx = (x0 < x1) ? 1 : -1; var sy = (y0 < y1) ? 1 : -1; var err = dx - dy; while (true) { - // Do what you need to for this pixels.push({'col': x0, 'row': y0}); @@ -120,6 +120,65 @@ y0 += sy; } } + + return pixels; + }; + + var dist = function (x0, x1, y0, y1) { + var dx = Math.abs(x1 - x0); + var dy = Math.abs(y1 - y0); + return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); + }; + + var MAX_STEP = 5; + ns.BaseTool.prototype.getUniformLinePixels_ = function (x0, x1, y0, y1) { + var pixels = []; + + x1 = pskl.utils.normalize(x1, 0); + y1 = pskl.utils.normalize(y1, 0); + + var dx = Math.abs(x1 - x0); + var dy = Math.abs(y1 - y0); + + var ratio = Math.max(dx, dy) / Math.min(dx, dy); + // in pixel art, lines should use uniform number of pixels for each step + var pixelStep = Math.round(ratio); + // invalid step, bail out + if (pixelStep === 0 || isNaN(pixelStep)) { + return pixels; + } + // the tool should make it easy to draw straight lines + if (pixelStep > MAX_STEP && pixelStep < MAX_STEP * 2) { + pixelStep = MAX_STEP; + } else if (pixelStep >= MAX_STEP * 2) { + pixelStep = Infinity; + } + + var sx = (x0 < x1) ? 1 : -1; + var sy = (y0 < y1) ? 1 : -1; + + var x = x0; + var y = y0; + var maxDistance = dist(x0, x1, y0, y1); + + var i = 0; + while (true) { + i++; + + pixels.push({'col': x, 'row': y}); + if (dist(x0, x, y0, y) >= maxDistance) { + break; + } + + var isAtStep = i % pixelStep === 0; + if (dx >= dy || isAtStep) { + x += sx; + } + if (dy >= dx || isAtStep) { + y += sy; + } + } + return pixels; }; })(); diff --git a/src/js/tools/drawing/Stroke.js b/src/js/tools/drawing/Stroke.js index 527d327e..bfd31928 100644 --- a/src/js/tools/drawing/Stroke.js +++ b/src/js/tools/drawing/Stroke.js @@ -90,13 +90,13 @@ }; ns.Stroke.prototype.draw_ = function (col, row, color, targetFrame, penSize, isStraight) { + var linePixels; if (isStraight) { - var coords = this.getStraightLineCoordinates_(col, row); - col = coords.col; - row = coords.row; + linePixels = this.getUniformLinePixels_(this.startCol, col, this.startRow, row); + } else { + linePixels = this.getLinePixels_(col, this.startCol, row, this.startRow); } - var linePixels = this.getLinePixels_(this.startCol, col, this.startRow, row); pskl.PixelUtils.resizePixels(linePixels, penSize).forEach(function (point) { targetFrame.setPixel(point[0], point[1], color); }); @@ -108,50 +108,4 @@ this.draw_(replayData.col, replayData.row, replayData.color, frame, replayData.penSize, replayData.isStraight); }; - /** - * Convert col, row to be on the nearest straight line or 45 degrees diagonal. - */ - ns.Stroke.prototype.getStraightLineCoordinates_ = function(col, row) { - // coordinates translated using startCol, startRow as origin - var tCol = col - this.startCol; - var tRow = this.startRow - row; - - var dist = Math.sqrt(Math.pow(tCol, 2) + Math.pow(tRow, 2)); - - var axisDistance = Math.round(dist); - var diagDistance = Math.round(dist / Math.sqrt(2)); - - var PI8 = Math.PI / 8; - var angle = Math.atan2(tRow, tCol); - if (angle < PI8 && angle >= -PI8) { - row = this.startRow; - col = this.startCol + axisDistance; - } else if (angle >= PI8 && angle < 3 * PI8) { - row = this.startRow - diagDistance; - col = this.startCol + diagDistance; - } else if (angle >= 3 * PI8 && angle < 5 * PI8) { - row = this.startRow - axisDistance; - col = this.startCol; - } else if (angle >= 5 * PI8 && angle < 7 * PI8) { - row = this.startRow - diagDistance; - col = this.startCol - diagDistance; - } else if (angle >= 7 * PI8 || angle < -7 * PI8) { - row = this.startRow; - col = this.startCol - axisDistance; - } else if (angle >= -7 * PI8 && angle < -5 * PI8) { - row = this.startRow + diagDistance; - col = this.startCol - diagDistance; - } else if (angle >= -5 * PI8 && angle < -3 * PI8) { - row = this.startRow + axisDistance; - col = this.startCol; - } else if (angle >= -3 * PI8 && angle < -PI8) { - row = this.startRow + diagDistance; - col = this.startCol + diagDistance; - } - - return { - col : col, - row : row - }; - }; })();