123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- import type { Bounds } from "../excalidraw/element/bounds";
- import { API } from "../excalidraw/tests/helpers/api";
- import {
- elementPartiallyOverlapsWithOrContainsBBox,
- elementsOverlappingBBox,
- isElementInsideBBox,
- } from "./withinBounds";
- const makeElement = (x: number, y: number, width: number, height: number) =>
- API.createElement({
- type: "rectangle",
- x,
- y,
- width,
- height,
- });
- const makeBBox = (
- minX: number,
- minY: number,
- maxX: number,
- maxY: number,
- ): Bounds => [minX, minY, maxX, maxY];
- describe("isElementInsideBBox()", () => {
- it("should return true if element is fully inside", () => {
- const bbox = makeBBox(0, 0, 100, 100);
- // bbox contains element
- expect(isElementInsideBBox(makeElement(0, 0, 100, 100), bbox)).toBe(true);
- expect(isElementInsideBBox(makeElement(10, 10, 90, 90), bbox)).toBe(true);
- });
- it("should return false if element is only partially overlapping", () => {
- const bbox = makeBBox(0, 0, 100, 100);
- // element contains bbox
- expect(isElementInsideBBox(makeElement(-10, -10, 110, 110), bbox)).toBe(
- false,
- );
- // element overlaps bbox from top-left
- expect(isElementInsideBBox(makeElement(-10, -10, 100, 100), bbox)).toBe(
- false,
- );
- // element overlaps bbox from top-right
- expect(isElementInsideBBox(makeElement(90, -10, 100, 100), bbox)).toBe(
- false,
- );
- // element overlaps bbox from bottom-left
- expect(isElementInsideBBox(makeElement(-10, 90, 100, 100), bbox)).toBe(
- false,
- );
- // element overlaps bbox from bottom-right
- expect(isElementInsideBBox(makeElement(90, 90, 100, 100), bbox)).toBe(
- false,
- );
- });
- it("should return false if element outside", () => {
- const bbox = makeBBox(0, 0, 100, 100);
- // outside diagonally
- expect(isElementInsideBBox(makeElement(110, 110, 100, 100), bbox)).toBe(
- false,
- );
- // outside on the left
- expect(isElementInsideBBox(makeElement(-110, 10, 50, 50), bbox)).toBe(
- false,
- );
- // outside on the right
- expect(isElementInsideBBox(makeElement(110, 10, 50, 50), bbox)).toBe(false);
- // outside on the top
- expect(isElementInsideBBox(makeElement(10, -110, 50, 50), bbox)).toBe(
- false,
- );
- // outside on the bottom
- expect(isElementInsideBBox(makeElement(10, 110, 50, 50), bbox)).toBe(false);
- });
- it("should return true if bbox contains element and flag enabled", () => {
- const bbox = makeBBox(0, 0, 100, 100);
- // element contains bbox
- expect(
- isElementInsideBBox(makeElement(-10, -10, 110, 110), bbox, true),
- ).toBe(true);
- // bbox contains element
- expect(isElementInsideBBox(makeElement(0, 0, 100, 100), bbox)).toBe(true);
- expect(isElementInsideBBox(makeElement(10, 10, 90, 90), bbox)).toBe(true);
- });
- });
- describe("elementPartiallyOverlapsWithOrContainsBBox()", () => {
- it("should return true if element overlaps, is inside, or contains", () => {
- const bbox = makeBBox(0, 0, 100, 100);
- // bbox contains element
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(0, 0, 100, 100),
- bbox,
- ),
- ).toBe(true);
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(10, 10, 90, 90),
- bbox,
- ),
- ).toBe(true);
- // element contains bbox
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(-10, -10, 110, 110),
- bbox,
- ),
- ).toBe(true);
- // element overlaps bbox from top-left
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(-10, -10, 100, 100),
- bbox,
- ),
- ).toBe(true);
- // element overlaps bbox from top-right
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(90, -10, 100, 100),
- bbox,
- ),
- ).toBe(true);
- // element overlaps bbox from bottom-left
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(-10, 90, 100, 100),
- bbox,
- ),
- ).toBe(true);
- // element overlaps bbox from bottom-right
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(90, 90, 100, 100),
- bbox,
- ),
- ).toBe(true);
- });
- it("should return false if element does not overlap", () => {
- const bbox = makeBBox(0, 0, 100, 100);
- // outside diagonally
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(110, 110, 100, 100),
- bbox,
- ),
- ).toBe(false);
- // outside on the left
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(-110, 10, 50, 50),
- bbox,
- ),
- ).toBe(false);
- // outside on the right
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(110, 10, 50, 50),
- bbox,
- ),
- ).toBe(false);
- // outside on the top
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(10, -110, 50, 50),
- bbox,
- ),
- ).toBe(false);
- // outside on the bottom
- expect(
- elementPartiallyOverlapsWithOrContainsBBox(
- makeElement(10, 110, 50, 50),
- bbox,
- ),
- ).toBe(false);
- });
- });
- describe("elementsOverlappingBBox()", () => {
- it("should return elements that overlap bbox", () => {
- const bbox = makeBBox(0, 0, 100, 100);
- const rectOutside = makeElement(110, 110, 100, 100);
- const rectInside = makeElement(10, 10, 90, 90);
- const rectContainingBBox = makeElement(-10, -10, 110, 110);
- const rectOverlappingTopLeft = makeElement(-10, -10, 50, 50);
- expect(
- elementsOverlappingBBox({
- bounds: bbox,
- type: "overlap",
- elements: [
- rectOutside,
- rectInside,
- rectContainingBBox,
- rectOverlappingTopLeft,
- ],
- }),
- ).toEqual([rectInside, rectContainingBBox, rectOverlappingTopLeft]);
- });
- it("should return elements inside/containing bbox", () => {
- const bbox = makeBBox(0, 0, 100, 100);
- const rectOutside = makeElement(110, 110, 100, 100);
- const rectInside = makeElement(10, 10, 90, 90);
- const rectContainingBBox = makeElement(-10, -10, 110, 110);
- const rectOverlappingTopLeft = makeElement(-10, -10, 50, 50);
- expect(
- elementsOverlappingBBox({
- bounds: bbox,
- type: "contain",
- elements: [
- rectOutside,
- rectInside,
- rectContainingBBox,
- rectOverlappingTopLeft,
- ],
- }),
- ).toEqual([rectInside, rectContainingBBox]);
- });
- it("should return elements inside bbox", () => {
- const bbox = makeBBox(0, 0, 100, 100);
- const rectOutside = makeElement(110, 110, 100, 100);
- const rectInside = makeElement(10, 10, 90, 90);
- const rectContainingBBox = makeElement(-10, -10, 110, 110);
- const rectOverlappingTopLeft = makeElement(-10, -10, 50, 50);
- expect(
- elementsOverlappingBBox({
- bounds: bbox,
- type: "inside",
- elements: [
- rectOutside,
- rectInside,
- rectContainingBBox,
- rectOverlappingTopLeft,
- ],
- }),
- ).toEqual([rectInside]);
- });
- // TODO test linear, freedraw, and diamond element types (+rotated)
- });
|