aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvkalev <vjk1883@gmail.com>2021-08-11 20:02:23 -0400
committervkalev <vjk1883@gmail.com>2021-08-11 20:02:23 -0400
commitf4da02dac8ea9d92443533b82bee2557cdd8957e (patch)
tree9f7aedd8fff62ec7a99b003e1c1e16245614f9ae /src
parent61d01ac7e7a2ff2df3a083aaa87ca5d8edbf71e8 (diff)
added circle shape generation using only 4 Bézier curves
Diffstat (limited to 'src')
-rw-r--r--src/client/util/InteractionUtils.tsx4
-rw-r--r--src/client/views/GestureOverlay.tsx54
-rw-r--r--src/client/views/InkControls.tsx24
-rw-r--r--src/client/views/InkStrokeProperties.ts9
-rw-r--r--src/client/views/InkingStroke.tsx2
5 files changed, 56 insertions, 37 deletions
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index ba935e3bf..cb6a53157 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -299,8 +299,6 @@ export namespace InteractionUtils {
return points;
case "circle":
-
-
const centerX = (Math.max(left, right) + Math.min(left, right)) / 2;
const centerY = (Math.max(top, bottom) + Math.min(top, bottom)) / 2;
const radius = Math.max(centerX - Math.min(left, right), centerY - Math.min(top, bottom));
@@ -315,7 +313,6 @@ export namespace InteractionUtils {
points.push({ X: newX, Y: y });
}
points.push({ X: Math.sqrt(Math.pow(radius, 2) - (Math.pow((Math.min(top, bottom) - centerY), 2))) + centerX, Y: Math.min(top, bottom) });
-
} else {
for (var x = Math.min(left, right); x < Math.max(left, right); x++) {
const y = Math.sqrt(Math.pow(radius, 2) - (Math.pow((x - centerX), 2))) + centerY;
@@ -327,7 +324,6 @@ export namespace InteractionUtils {
points.push({ X: x, Y: newY });
}
points.push({ X: Math.min(left, right), Y: Math.sqrt(Math.pow(radius, 2) - (Math.pow((Math.min(left, right) - centerX), 2))) + centerY });
-
}
return points;
// case "arrow":
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 6a4f55bef..f7b5cc030 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -726,39 +726,35 @@ export class GestureOverlay extends Touchable {
break;
case "circle":
-
+ // Approximation of a circle using Bézier curves in which the constant "c" reduces the maximum radial drift to 0.019608%,
+ // making the curves indistinguishable from a circle.
+ // Source: https://spencermortensen.com/articles/bezier-circle/
+ const c = 0.551915024494;
const centerX = (Math.max(left, right) + Math.min(left, right)) / 2;
const centerY = (Math.max(top, bottom) + Math.min(top, bottom)) / 2;
const radius = Math.max(centerX - Math.min(left, right), centerY - Math.min(top, bottom));
- if (centerX - Math.min(left, right) < centerY - Math.min(top, bottom)) {
- for (var y = Math.min(top, bottom); y < Math.max(top, bottom); y++) {
- const x = Math.sqrt(Math.pow(radius, 2) - (Math.pow((y - centerY), 2))) + centerX;
- this._points.push({ X: x, Y: y });
- }
- for (var y = Math.max(top, bottom); y > Math.min(top, bottom); y--) {
- const x = Math.sqrt(Math.pow(radius, 2) - (Math.pow((y - centerY), 2))) + centerX;
- const newX = centerX - (x - centerX);
- this._points.push({ X: newX, Y: y });
- }
- this._points.push({ X: Math.sqrt(Math.pow(radius, 2) - (Math.pow((Math.min(top, bottom) - centerY), 2))) + centerX, Y: Math.min(top, bottom) });
- this._points.push({ X: Math.sqrt(Math.pow(radius, 2) - (Math.pow((Math.min(top, bottom) - centerY), 2))) + centerX, Y: Math.min(top, bottom) - 1 });
-
-
- } else {
- for (var x = Math.min(left, right); x < Math.max(left, right); x++) {
- const y = Math.sqrt(Math.pow(radius, 2) - (Math.pow((x - centerX), 2))) + centerY;
- this._points.push({ X: x, Y: y });
- }
- for (var x = Math.max(left, right); x > Math.min(left, right); x--) {
- const y = Math.sqrt(Math.pow(radius, 2) - (Math.pow((x - centerX), 2))) + centerY;
- const newY = centerY - (y - centerY);
- this._points.push({ X: x, Y: newY });
- }
- this._points.push({ X: Math.min(left, right), Y: Math.sqrt(Math.pow(radius, 2) - (Math.pow((Math.min(left, right) - centerX), 2))) + centerY });
- this._points.push({ X: Math.min(left, right), Y: Math.sqrt(Math.pow(radius, 2) - (Math.pow((Math.min(left, right) - centerX), 2))) + centerY - 1 });
-
- }
+ // Dividing the circle into four equal sections, and fiting each section to a cubic Bézier curve.
+ this._points.push({ X: centerX - radius, Y: centerY });
+ this._points.push({ X: centerX - radius, Y: centerY + (c * radius) });
+ this._points.push({ X: centerX - (c * radius), Y: centerY + radius });
+ this._points.push({ X: centerX, Y: centerY + radius });
+
+ this._points.push({ X: centerX, Y: centerY + radius });
+ this._points.push({ X: centerX + (c * radius), Y: centerY + radius });
+ this._points.push({ X: centerX + radius, Y: centerY + (c * radius) });
+ this._points.push({ X: centerX + radius, Y: centerY });
+
+ this._points.push({ X: centerX + radius, Y: centerY });
+ this._points.push({ X: centerX + radius, Y: centerY - (c * radius) });
+ this._points.push({ X: centerX + (c * radius), Y: centerY - radius });
+ this._points.push({ X: centerX, Y: centerY - radius });
+
+ this._points.push({ X: centerX, Y: centerY - radius });
+ this._points.push({ X: centerX - (c * radius), Y: centerY - radius });
+ this._points.push({ X: centerX - radius, Y: centerY - (c * radius) });
+ this._points.push({ X: centerX - radius, Y: centerY });
break;
+
case "line":
if (Math.abs(firstx - lastx) < 20) {
lastx = firstx;
diff --git a/src/client/views/InkControls.tsx b/src/client/views/InkControls.tsx
index 6213a4075..55a70ccd2 100644
--- a/src/client/views/InkControls.tsx
+++ b/src/client/views/InkControls.tsx
@@ -87,16 +87,38 @@ export class InkControls extends React.Component<InkControlProps> {
if (!formatInstance) return (null);
// Accessing the current ink's data and extracting all control points.
+ // Separate case for circle shape (?)
const data = this.props.data;
+ const [left, right, top, bottom, scaleX, scaleY, strokeWidth] = this.props.format;
+ const centerX = (Math.max(left, right) + Math.min(left, right)) / 2;
+ const centerY = (Math.max(top, bottom) + Math.min(top, bottom)) / 2;
+ const radius = Math.max(centerX - Math.min(left, right), centerY - Math.min(top, bottom));
const controlPoints: ControlPoint[] = [];
if (data.length >= 4) {
+ // const distance = Math.sqrt((Math.pow(data[0].X - centerX, 2)) + (Math.pow(data[0].Y - centerY, 2)));
+ // if (Math.abs(distance - radius) <= 2.5) {
+ // controlPoints.push({ X: data[0].X, Y: data[0].Y, I: 0 });
+ // const topPoint = formatInstance.rotatePoint(data[0], { X: centerX, Y: centerY }, Math.PI / 2);
+ // const rightPoint = formatInstance.rotatePoint(data[0], { X: centerX, Y: centerY }, Math.PI);
+ // const bottomPoint = formatInstance.rotatePoint(data[0], { X: centerX, Y: centerY }, Math.PI * 1.5);
+ // for (let i = 0; i <= data.length - 4; i += 4) {
+ // const currPoint = data[i];
+ // const isTopPoint = Math.sqrt((Math.pow(currPoint.X - topPoint.X, 2)) + (Math.pow(currPoint.Y - topPoint.Y, 2))) <= 2.5;
+ // const isRightPoint = Math.sqrt((Math.pow(currPoint.X - rightPoint.X, 2)) + (Math.pow(currPoint.Y - rightPoint.Y, 2))) <= 2.5;
+ // const isBottomPoint = Math.sqrt((Math.pow(currPoint.X - bottomPoint.X, 2)) + (Math.pow(currPoint.Y - bottomPoint.Y, 2))) <= 2.5;
+ // if (isTopPoint || isRightPoint || isBottomPoint) {
+ // controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i });
+ // }
+ // }
+ // controlPoints.push({ X: data[0].X, Y: data[0].Y, I: 0 });
+ // } else {
for (let i = 0; i <= data.length - 4; i += 4) {
controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i });
controlPoints.push({ X: data[i + 3].X, Y: data[i + 3].Y, I: i + 3 });
}
+ // }
}
const addedPoints = this.props.addedPoints;
- const [left, top, scaleX, scaleY, strokeWidth] = this.props.format;
return (
<>
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 76ca5b5ec..7ef6606c4 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -266,8 +266,13 @@ export class InkStrokeProperties {
this.applyFunction((doc: Doc, ink: InkData) => {
const brokenIndices = Cast(doc.brokenInkIndices, listSpec("number"));
if (brokenIndices) {
- brokenIndices.splice(brokenIndices.indexOf(controlIndex), 1);
- doc.brokenInkIndices = brokenIndices;
+ let newBrokenIndices = new List;
+ for (let i = 0; i < brokenIndices.length; i++) {
+ if (brokenIndices[i] !== controlIndex) {
+ newBrokenIndices.push(brokenIndices[i]);
+ }
+ }
+ doc.brokenInkIndices = newBrokenIndices;
const [controlPoint, handleA, handleB] = [ink[controlIndex], ink[handleIndexA], ink[handleIndexB]];
const oppositeHandleA = this.rotatePoint(handleA, controlPoint, Math.PI);
const angleDifference = this.angleChange(handleB, oppositeHandleA, controlPoint);
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 21059b330..d30244a8f 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -138,7 +138,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
inkDoc={inkDoc}
data={data}
addedPoints={addedPoints}
- format={[left, top, scaleX, scaleY, strokeWidth]}
+ format={[left, right, top, bottom, scaleX, scaleY, strokeWidth]}
ScreenToLocalTransform={this.props.ScreenToLocalTransform} />
<InkHandles
inkDoc={inkDoc}