mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-11-04 04:44:31 +01:00 
			
		
		
		
	fix: lasso selection issues (#9353)
* revert stroke slicing hack for knot * fix incorrect closing of path * nonzero enclosure * lint
This commit is contained in:
		@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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),
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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>,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user