Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue-Pen tool is not smooth #14

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 70 additions & 3 deletions src/util/checkPointOnDrawing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { onEllipse } from './onShape/onEllipse';
import { onLineSegmentWithThreshold } from './onShape/onLineSegmentWithThreshold';
import { onRectangleSide } from './onShape/onRectangleSide';
import { DrawingsElement, Tools } from './types';

interface Point {
x: number;
y: number;
}
const checkPointOnDrawing = (
drawing: DrawingsElement,
x1: number,
Expand Down Expand Up @@ -54,7 +57,7 @@ const checkPointOnDrawing = (
(1.414 * 2)
);
} else if (drawing.shape === Tools.Pen) {
let flag: boolean = false;
let flag = false;

const isNearPoint = (
x: number,
Expand All @@ -67,14 +70,78 @@ const checkPointOnDrawing = (
return distance <= threshold;
};

drawing.pointPath?.every((point) => {


const smoothedPath = drawing.pointPath?.length ? smoothPath(drawing.pointPath) : []; // Apply smoothing algorithm
smoothedPath.every((point: Point) => {
flag = isNearPoint(point.x, point.y, x1, y1, threshold);
return !flag;
});

return flag;
}
function smoothPath(path: { x: number; y: number }[], tolerance = 1) {
if (path.length < 2) {
return path;
}
// Find the point with the maximum distance from the line formed by the first and last points
let farthestPointIndex = 0;
let farthestDistance = 0;
for (let i = 1; i < path.length - 1; i++) {
const distance = perpendicularDistance(
path[0],
path[path.length - 1],
path[i]
);
if (distance > farthestDistance) {
farthestPointIndex = i;
farthestDistance = distance;
}
}

// If the farthest point is within the tolerance, the path is considered smooth
if (farthestDistance <= tolerance) {
return [path[0], path[path.length - 1]];
}

// Recursively simplify the two sub-paths formed by splitting at the farthest point
const simplifiedLeft: { x: number; y: number }[] = smoothPath(
path.slice(0, farthestPointIndex + 1),
tolerance
);
const simplifiedRight: { x: number; y: number }[] = smoothPath(
path.slice(farthestPointIndex),
tolerance
);

// Combine the simplified sub-paths
return [
...simplifiedLeft.slice(0, simplifiedLeft.length - 1),
...simplifiedRight,
];
}

// Helper function to calculate the perpendicular distance from a point to a line segment
function perpendicularDistance(
p1: { x: number; y: number },
p2: { x: number; y: number },
p: { x: number; y: number }
): number {
const x1 = p1.x;
const y1 = p1.y;
const x2 = p2.x;
const y2 = p2.y;
const px = p.x;
const py = p.y;

const A = y2 - y1;
const B = x1 - x2;
const C = x1 * y2 - x2 * y1;

const distance =
Math.abs(A * px + B * py + C) / Math.sqrt(A * A + B * B);
return distance;
}
return false;
};

Expand Down