fourth point for curves

Third and fourth points are available by pressing `Ctrl` or `Enter`.
This commit is contained in:
abakkk 2020-06-19 15:52:12 +02:00
parent 4d901db080
commit f0b3876bac
1 changed files with 56 additions and 35 deletions

81
draw.js
View File

@ -370,10 +370,21 @@ var DrawingArea = new Lang.Class({
this._redisplay(); this._redisplay();
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} else if (this.currentElement && this.currentElement.shape == Shapes.LINE) {
if (event.get_key_symbol() == Clutter.KEY_Return || event.get_key_symbol() == 65421 || event.get_key_symbol() == 65507) {
// 65507 is 'Ctrl' key alone
this.currentElement.addPoint();
this.updatePointerCursor(true);
this._redisplay();
return Clutter.EVENT_STOP;
} else {
return Clutter.EVENT_PROPAGATE;
}
} else if (this.currentElement && } else if (this.currentElement &&
(this.currentElement.shape == Shapes.POLYGON || this.currentElement.shape == Shapes.POLYLINE) && (this.currentElement.shape == Shapes.POLYGON || this.currentElement.shape == Shapes.POLYLINE) &&
(event.get_key_symbol() == Clutter.KEY_Return || event.get_key_symbol() == 65421)) { (event.get_key_symbol() == Clutter.KEY_Return || event.get_key_symbol() == 65421)) {
this.currentElement.addPolyPoint(); this.currentElement.addPoint();
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} else if (event.get_key_symbol() == Clutter.KEY_Escape) { } else if (event.get_key_symbol() == Clutter.KEY_Escape) {
@ -1207,6 +1218,10 @@ const DrawingElement = new Lang.Class({
cr.moveTo(points[0][0], points[0][1]); cr.moveTo(points[0][0], points[0][1]);
cr.curveTo(points[0][0], points[0][1], points[1][0], points[1][1], points[2][0], points[2][1]); cr.curveTo(points[0][0], points[0][1], points[1][0], points[1][1], points[2][0], points[2][1]);
} else if (shape == Shapes.LINE && points.length == 4) {
cr.moveTo(points[0][0], points[0][1]);
cr.curveTo(points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
} else if (shape == Shapes.NONE || shape == Shapes.LINE) { } else if (shape == Shapes.NONE || shape == Shapes.LINE) {
cr.moveTo(points[0][0], points[0][1]); cr.moveTo(points[0][0], points[0][1]);
for (let j = 1; j < points.length; j++) { for (let j = 1; j < points.length; j++) {
@ -1323,7 +1338,12 @@ const DrawingElement = new Lang.Class({
}); });
transAttribute += transAttribute ? '"' : ''; transAttribute += transAttribute ? '"' : '';
if (this.shape == Shapes.LINE && points.length == 3) { if (this.shape == Shapes.LINE && points.length == 4) {
row += `<path ${attributes} d="M${points[0][0]} ${points[0][1]}`;
row += ` C ${points[1][0]} ${points[1][1]}, ${points[2][0]} ${points[2][1]}, ${points[3][0]} ${points[3][1]}`;
row += `${fill ? 'z' : ''}"${transAttribute}/>`;
} else if (this.shape == Shapes.LINE && points.length == 3) {
row += `<path ${attributes} d="M${points[0][0]} ${points[0][1]}`; row += `<path ${attributes} d="M${points[0][0]} ${points[0][1]}`;
row += ` C ${points[0][0]} ${points[0][1]}, ${points[1][0]} ${points[1][1]}, ${points[2][0]} ${points[2][1]}`; row += ` C ${points[0][0]} ${points[0][1]}, ${points[1][0]} ${points[1][1]}, ${points[2][0]} ${points[2][1]}`;
row += `${fill ? 'z' : ''}"${transAttribute}/>`; row += `${fill ? 'z' : ''}"${transAttribute}/>`;
@ -1385,27 +1405,29 @@ const DrawingElement = new Lang.Class({
}, },
get isStraightLine() { get isStraightLine() {
return this.shape == Shapes.LINE && (this.points.length < 3 || this.points[2] == this.points[1] || this.points[2] == this.points[0]); return this.shape == Shapes.LINE && this.points.length == 2;
},
smooth: function(i) {
if (i < 2)
return;
this.points[i-1] = [(this.points[i-2][0] + this.points[i][0]) / 2, (this.points[i-2][1] + this.points[i][1]) / 2];
}, },
smoothAll: function() { smoothAll: function() {
for (let i = 0; i < this.points.length; i++) { for (let i = 0; i < this.points.length; i++) {
this.smooth(i); this._smooth(i);
} }
}, },
// For polygons and polylines. addPoint: function() {
addPolyPoint: function() { if (this.shape == Shapes.POLYGON || this.shape == Shapes.POLYLINE) {
// copy last point // copy last point
let [lastPoint, secondToLastPoint] = [this.points[this.points.length - 1], this.points[this.points.length - 2]]; let [lastPoint, secondToLastPoint] = [this.points[this.points.length - 1], this.points[this.points.length - 2]];
if (!getNearness(secondToLastPoint, lastPoint, MIN_DRAWING_SIZE)) if (!getNearness(secondToLastPoint, lastPoint, MIN_DRAWING_SIZE))
this.points.push([lastPoint[0], lastPoint[1]]); this.points.push([lastPoint[0], lastPoint[1]]);
} else if (this.shape == Shapes.LINE) {
if (this.points.length == 2) {
this.points[2] = this.points[1];
} else if (this.points.length == 3) {
this.points[3] = this.points[2];
this.points[2] = this.points[1];
}
}
}, },
startDrawing: function(startX, startY) { startDrawing: function(startX, startY) {
@ -1420,10 +1442,12 @@ const DrawingElement = new Lang.Class({
if (x == points[points.length - 1][0] && y == points[points.length - 1][1]) if (x == points[points.length - 1][0] && y == points[points.length - 1][1])
return; return;
transform = transform || this.transformations.length >= 1 || this.shape == Shapes.LINE && points.length == 3; transform = transform || this.transformations.length >= 1;
if (this.shape == Shapes.NONE) { if (this.shape == Shapes.NONE) {
this._addPoint(x, y, transform); points.push([x, y]);
if (transform)
this._smooth(points.length - 1);
} else if ((this.shape == Shapes.RECTANGLE || this.shape == Shapes.TEXT || this.shape == Shapes.POLYGON || this.shape == Shapes.POLYLINE) && transform) { } else if ((this.shape == Shapes.RECTANGLE || this.shape == Shapes.TEXT || this.shape == Shapes.POLYGON || this.shape == Shapes.POLYLINE) && transform) {
if (points.length < 2) if (points.length < 2)
@ -1442,14 +1466,6 @@ const DrawingElement = new Lang.Class({
this.transformations[0] = { type: Transformations.ROTATION, this.transformations[0] = { type: Transformations.ROTATION,
angle: getAngle(center[0], center[1], center[0] + 1, center[1], x, y) }; angle: getAngle(center[0], center[1], center[0] + 1, center[1], x, y) };
} else if (this.shape == Shapes.LINE && transform) {
if (points.length < 2)
return;
if (points.length == 2)
points[2] = points[1];
points[1] = [x, y];
} else if (this.shape == Shapes.POLYGON || this.shape == Shapes.POLYLINE) { } else if (this.shape == Shapes.POLYGON || this.shape == Shapes.POLYLINE) {
points[points.length - 1] = [x, y]; points[points.length - 1] = [x, y];
@ -1576,7 +1592,8 @@ const DrawingElement = new Lang.Class({
if (!this._originalCenter) { if (!this._originalCenter) {
let points = this.points; let points = this.points;
this._originalCenter = this.shape == Shapes.ELLIPSE ? [points[0][0], points[0][1]] : this._originalCenter = this.shape == Shapes.ELLIPSE ? [points[0][0], points[0][1]] :
this.shape == Shapes.LINE && points.length == 3 ? getCurveCenter(points[0], points[1], points[2]) : this.shape == Shapes.LINE && points.length == 4 ? getCurveCenter(points[0], points[1], points[2], points[3]) :
this.shape == Shapes.LINE && points.length == 3 ? getCurveCenter(points[0], points[0], points[1], points[2]) :
this.shape == Shapes.TEXT && this.textWidth ? [Math.min(points[0][0], points[1][0]), this.shape == Shapes.TEXT && this.textWidth ? [Math.min(points[0][0], points[1][0]),
Math.max(points[0][1], points[1][1]) - this._getLineOffset()] : Math.max(points[0][1], points[1][1]) - this._getLineOffset()] :
points.length >= 3 ? getCentroid(points) : points.length >= 3 ? getCentroid(points) :
@ -1616,10 +1633,10 @@ const DrawingElement = new Lang.Class({
return transformation.elementTransformedCenter; return transformation.elementTransformedCenter;
}, },
_addPoint: function(x, y, smoothedStroke) { _smooth: function(i) {
this.points.push([x, y]); if (i < 2)
if (smoothedStroke) return;
this.smooth(this.points.length - 1); this.points[i-1] = [(this.points[i-2][0] + this.points[i][0]) / 2, (this.points[i-2][1] + this.points[i][1]) / 2];
} }
}); });
@ -1702,11 +1719,15 @@ control point: p0 ---- p1 ---- p2 ---- p3 (p2 is not on the curve)
t: 0 ---- 1/3 ---- 2/3 ---- 1 t: 0 ---- 1/3 ---- 2/3 ---- 1
*/ */
// Here, p0 = p1 and t = 2/3. // If the curve has a symmetry axis, it is truly a center (the intersection of the curve and the axis).
// If the curve has a symmetry axis, p(2/3) is truly a center (the intersection of the curve and the axis).
// In other cases, it is not a notable point, just a visual approximation. // In other cases, it is not a notable point, just a visual approximation.
const getCurveCenter = function(p1, p2, p3) { const getCurveCenter = function(p0, p1, p2, p3) {
if (p0[0] == p1[0] && p0[1] == p1[1])
// p0 = p1, t = 2/3
return [(p1[0] + 6*p1[0] + 12*p2[0] + 8*p3[0]) / 27, (p1[1] + 6*p1[1] + 12*p2[1] + 8*p3[1]) / 27]; return [(p1[0] + 6*p1[0] + 12*p2[0] + 8*p3[0]) / 27, (p1[1] + 6*p1[1] + 12*p2[1] + 8*p3[1]) / 27];
else
// t = 1/2
return [(p0[0] + 3*p1[0] + 3*p2[0] + p3[0]) / 8, (p0[1] + 3*p1[1] + 3*p2[1] + p3[1]) / 8];
}; };
const getAngle = function(xO, yO, xA, yA, xB, yB) { const getAngle = function(xO, yO, xA, yA, xB, yB) {