Compare commits

...

3 commits

Author SHA1 Message Date
Ridhi Bandaru
fadbac9ffe
Merge 75864e11bb into 6fc85022ae 2025-04-09 03:56:59 -04:00
Ryan Di
6fc85022ae
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
* revert stroke slicing hack for knot

* fix incorrect closing of path

* nonzero enclosure

* lint
2025-04-08 00:50:52 +10:00
Ridhi Bandaru
75864e11bb chore: extend Node.js support to v23.x 2025-02-16 22:55:16 -05:00
5 changed files with 37 additions and 17 deletions

View file

@ -23,7 +23,7 @@
]
},
"engines": {
"node": "18.0.0 - 22.x.x"
"node": "18.0.0 - 23.x.x"
},
"dependencies": {
"@excalidraw/random-username": "1.0.0",

View file

@ -43,7 +43,7 @@
"vitest-canvas-mock": "0.3.3"
},
"engines": {
"node": "18.0.0 - 22.x.x"
"node": "18.0.0 - 23.x.x"
},
"homepage": ".",
"prettier": "@excalidraw/prettier-config",

View file

@ -191,11 +191,7 @@ export class AnimatedTrail implements Trail {
});
const stroke = this.trailAnimation
? _stroke.slice(
// slicing from 6th point to get rid of the initial notch type of thing
Math.min(_stroke.length, 6),
_stroke.length / 2,
)
? _stroke.slice(0, _stroke.length / 2)
: _stroke;
return getSvgPathFromStroke(stroke, true);

View file

@ -2,9 +2,9 @@ import { simplify } from "points-on-curve";
import {
polygonFromPoints,
polygonIncludesPoint,
lineSegment,
lineSegmentIntersectionPoints,
polygonIncludesPointNonZero,
} from "@excalidraw/math";
import type { GlobalPoint, LineSegment } from "@excalidraw/math/types";
@ -35,8 +35,6 @@ export const getLassoSelectedElementIds = (input: {
if (simplifyDistance) {
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
enclosedElements.clear();
for (const element of elements) {
@ -44,15 +42,11 @@ export const getLassoSelectedElementIds = (input: {
!intersectedElements.has(element.id) &&
!enclosedElements.has(element.id)
) {
const enclosed = enclosureTest(closedPath, element, elementsSegments);
const enclosed = enclosureTest(path, element, elementsSegments);
if (enclosed) {
enclosedElements.add(element.id);
} else {
const intersects = intersectionTest(
closedPath,
element,
elementsSegments,
);
const intersects = intersectionTest(path, element, elementsSegments);
if (intersects) {
intersectedElements.add(element.id);
}
@ -79,7 +73,9 @@ const enclosureTest = (
}
return segments.some((segment) => {
return segment.some((point) => polygonIncludesPoint(point, lassoPolygon));
return segment.some((point) =>
polygonIncludesPointNonZero(point, lassoPolygon),
);
});
};

View file

@ -41,6 +41,34 @@ export const polygonIncludesPoint = <Point extends LocalPoint | GlobalPoint>(
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>(
p: Point,
poly: Polygon<Point>,