mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
fix: lasso selection issues (#9353)
Some checks failed
Tests / test (push) Successful in 7m13s
Auto release excalidraw next / Auto-release-excalidraw-next (push) Failing after 1m45s
Build Docker image / build-docker (push) Failing after 6s
Cancel previous runs / cancel (push) Failing after 1s
Publish Docker / publish-docker (push) Failing after 20s
New Sentry production release / sentry (push) Failing after 2m5s
Some checks failed
Tests / test (push) Successful in 7m13s
Auto release excalidraw next / Auto-release-excalidraw-next (push) Failing after 1m45s
Build Docker image / build-docker (push) Failing after 6s
Cancel previous runs / cancel (push) Failing after 1s
Publish Docker / publish-docker (push) Failing after 20s
New Sentry production release / sentry (push) Failing after 2m5s
* revert stroke slicing hack for knot * fix incorrect closing of path * nonzero enclosure * lint
This commit is contained in:
parent
e48b63a0ae
commit
6fc85022ae
3 changed files with 35 additions and 15 deletions
|
@ -191,11 +191,7 @@ export class AnimatedTrail implements Trail {
|
||||||
});
|
});
|
||||||
|
|
||||||
const stroke = this.trailAnimation
|
const stroke = this.trailAnimation
|
||||||
? _stroke.slice(
|
? _stroke.slice(0, _stroke.length / 2)
|
||||||
// slicing from 6th point to get rid of the initial notch type of thing
|
|
||||||
Math.min(_stroke.length, 6),
|
|
||||||
_stroke.length / 2,
|
|
||||||
)
|
|
||||||
: _stroke;
|
: _stroke;
|
||||||
|
|
||||||
return getSvgPathFromStroke(stroke, true);
|
return getSvgPathFromStroke(stroke, true);
|
||||||
|
|
|
@ -2,9 +2,9 @@ import { simplify } from "points-on-curve";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
polygonFromPoints,
|
polygonFromPoints,
|
||||||
polygonIncludesPoint,
|
|
||||||
lineSegment,
|
lineSegment,
|
||||||
lineSegmentIntersectionPoints,
|
lineSegmentIntersectionPoints,
|
||||||
|
polygonIncludesPointNonZero,
|
||||||
} from "@excalidraw/math";
|
} from "@excalidraw/math";
|
||||||
|
|
||||||
import type { GlobalPoint, LineSegment } from "@excalidraw/math/types";
|
import type { GlobalPoint, LineSegment } from "@excalidraw/math/types";
|
||||||
|
@ -35,8 +35,6 @@ export const getLassoSelectedElementIds = (input: {
|
||||||
if (simplifyDistance) {
|
if (simplifyDistance) {
|
||||||
path = simplify(lassoPath, simplifyDistance) as GlobalPoint[];
|
path = simplify(lassoPath, simplifyDistance) as GlobalPoint[];
|
||||||
}
|
}
|
||||||
// close the path to form a polygon for enclosure check
|
|
||||||
const closedPath = polygonFromPoints(path);
|
|
||||||
// as the path might not enclose a shape anymore, clear before checking
|
// as the path might not enclose a shape anymore, clear before checking
|
||||||
enclosedElements.clear();
|
enclosedElements.clear();
|
||||||
for (const element of elements) {
|
for (const element of elements) {
|
||||||
|
@ -44,15 +42,11 @@ export const getLassoSelectedElementIds = (input: {
|
||||||
!intersectedElements.has(element.id) &&
|
!intersectedElements.has(element.id) &&
|
||||||
!enclosedElements.has(element.id)
|
!enclosedElements.has(element.id)
|
||||||
) {
|
) {
|
||||||
const enclosed = enclosureTest(closedPath, element, elementsSegments);
|
const enclosed = enclosureTest(path, element, elementsSegments);
|
||||||
if (enclosed) {
|
if (enclosed) {
|
||||||
enclosedElements.add(element.id);
|
enclosedElements.add(element.id);
|
||||||
} else {
|
} else {
|
||||||
const intersects = intersectionTest(
|
const intersects = intersectionTest(path, element, elementsSegments);
|
||||||
closedPath,
|
|
||||||
element,
|
|
||||||
elementsSegments,
|
|
||||||
);
|
|
||||||
if (intersects) {
|
if (intersects) {
|
||||||
intersectedElements.add(element.id);
|
intersectedElements.add(element.id);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +73,9 @@ const enclosureTest = (
|
||||||
}
|
}
|
||||||
|
|
||||||
return segments.some((segment) => {
|
return segments.some((segment) => {
|
||||||
return segment.some((point) => polygonIncludesPoint(point, lassoPolygon));
|
return segment.some((point) =>
|
||||||
|
polygonIncludesPointNonZero(point, lassoPolygon),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,34 @@ export const polygonIncludesPoint = <Point extends LocalPoint | GlobalPoint>(
|
||||||
return inside;
|
return inside;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const polygonIncludesPointNonZero = <Point extends [number, number]>(
|
||||||
|
point: Point,
|
||||||
|
polygon: Point[],
|
||||||
|
): boolean => {
|
||||||
|
const [x, y] = point;
|
||||||
|
let windingNumber = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < polygon.length; i++) {
|
||||||
|
const j = (i + 1) % polygon.length;
|
||||||
|
const [xi, yi] = polygon[i];
|
||||||
|
const [xj, yj] = polygon[j];
|
||||||
|
|
||||||
|
if (yi <= y) {
|
||||||
|
if (yj > y) {
|
||||||
|
if ((xj - xi) * (y - yi) - (x - xi) * (yj - yi) > 0) {
|
||||||
|
windingNumber++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (yj <= y) {
|
||||||
|
if ((xj - xi) * (y - yi) - (x - xi) * (yj - yi) < 0) {
|
||||||
|
windingNumber--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return windingNumber !== 0;
|
||||||
|
};
|
||||||
|
|
||||||
export const pointOnPolygon = <Point extends LocalPoint | GlobalPoint>(
|
export const pointOnPolygon = <Point extends LocalPoint | GlobalPoint>(
|
||||||
p: Point,
|
p: Point,
|
||||||
poly: Polygon<Point>,
|
poly: Polygon<Point>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue