import type { GlobalPoint, LineSegment, Polygon, Radians } from "../../math"; import { pointFrom, lineSegment, polygon, pointOnLineSegment, pointOnPolygon, polygonIncludesPoint, segmentsIntersectAt, } from "../../math"; import { pointInEllipse, pointOnEllipse, type Ellipse } from "./shape"; describe("point and line", () => { // const l: Line = line(point(1, 0), point(1, 2)); // it("point on left or right of line", () => { // expect(pointLeftofLine(point(0, 1), l)).toBe(true); // expect(pointLeftofLine(point(1, 1), l)).toBe(false); // expect(pointLeftofLine(point(2, 1), l)).toBe(false); // expect(pointRightofLine(point(0, 1), l)).toBe(false); // expect(pointRightofLine(point(1, 1), l)).toBe(false); // expect(pointRightofLine(point(2, 1), l)).toBe(true); // }); const s: LineSegment = lineSegment( pointFrom(1, 0), pointFrom(1, 2), ); it("point on the line", () => { expect(pointOnLineSegment(pointFrom(0, 1), s)).toBe(false); expect(pointOnLineSegment(pointFrom(1, 1), s, 0)).toBe(true); expect(pointOnLineSegment(pointFrom(2, 1), s)).toBe(false); }); }); describe("point and polygon", () => { const poly: Polygon = polygon( pointFrom(10, 10), pointFrom(50, 10), pointFrom(50, 50), pointFrom(10, 50), ); it("point on polygon", () => { expect(pointOnPolygon(pointFrom(30, 10), poly)).toBe(true); expect(pointOnPolygon(pointFrom(50, 30), poly)).toBe(true); expect(pointOnPolygon(pointFrom(30, 50), poly)).toBe(true); expect(pointOnPolygon(pointFrom(10, 30), poly)).toBe(true); expect(pointOnPolygon(pointFrom(30, 30), poly)).toBe(false); expect(pointOnPolygon(pointFrom(30, 70), poly)).toBe(false); }); it("point in polygon", () => { const poly: Polygon = polygon( pointFrom(0, 0), pointFrom(2, 0), pointFrom(2, 2), pointFrom(0, 2), ); expect(polygonIncludesPoint(pointFrom(1, 1), poly)).toBe(true); expect(polygonIncludesPoint(pointFrom(3, 3), poly)).toBe(false); }); }); describe("point and ellipse", () => { const ellipse: Ellipse = { center: pointFrom(0, 0), angle: 0 as Radians, halfWidth: 2, halfHeight: 1, }; it("point on ellipse", () => { [ pointFrom(0, 1), pointFrom(0, -1), pointFrom(2, 0), pointFrom(-2, 0), ].forEach((p) => { expect(pointOnEllipse(p, ellipse)).toBe(true); }); expect(pointOnEllipse(pointFrom(-1.4, 0.7), ellipse, 0.1)).toBe(true); expect(pointOnEllipse(pointFrom(-1.4, 0.71), ellipse, 0.01)).toBe(true); expect(pointOnEllipse(pointFrom(1.4, 0.7), ellipse, 0.1)).toBe(true); expect(pointOnEllipse(pointFrom(1.4, 0.71), ellipse, 0.01)).toBe(true); expect(pointOnEllipse(pointFrom(1, -0.86), ellipse, 0.1)).toBe(true); expect(pointOnEllipse(pointFrom(1, -0.86), ellipse, 0.01)).toBe(true); expect(pointOnEllipse(pointFrom(-1, -0.86), ellipse, 0.1)).toBe(true); expect(pointOnEllipse(pointFrom(-1, -0.86), ellipse, 0.01)).toBe(true); expect(pointOnEllipse(pointFrom(-1, 0.8), ellipse)).toBe(false); expect(pointOnEllipse(pointFrom(1, -0.8), ellipse)).toBe(false); }); it("point in ellipse", () => { [ pointFrom(0, 1), pointFrom(0, -1), pointFrom(2, 0), pointFrom(-2, 0), ].forEach((p) => { expect(pointInEllipse(p, ellipse)).toBe(true); }); expect(pointInEllipse(pointFrom(-1, 0.8), ellipse)).toBe(true); expect(pointInEllipse(pointFrom(1, -0.8), ellipse)).toBe(true); expect(pointInEllipse(pointFrom(-1, 1), ellipse)).toBe(false); expect(pointInEllipse(pointFrom(-1.4, 0.8), ellipse)).toBe(false); }); }); describe("line and line", () => { const lineA: LineSegment = lineSegment( pointFrom(1, 4), pointFrom(3, 4), ); const lineB: LineSegment = lineSegment( pointFrom(2, 1), pointFrom(2, 7), ); const lineC: LineSegment = lineSegment( pointFrom(1, 8), pointFrom(3, 8), ); const lineD: LineSegment = lineSegment( pointFrom(1, 8), pointFrom(3, 8), ); const lineE: LineSegment = lineSegment( pointFrom(1, 9), pointFrom(3, 9), ); const lineF: LineSegment = lineSegment( pointFrom(1, 2), pointFrom(3, 4), ); const lineG: LineSegment = lineSegment( pointFrom(0, 1), pointFrom(2, 3), ); it("intersection", () => { expect(segmentsIntersectAt(lineA, lineB)).toEqual([2, 4]); expect(segmentsIntersectAt(lineA, lineC)).toBe(null); expect(segmentsIntersectAt(lineB, lineC)).toBe(null); expect(segmentsIntersectAt(lineC, lineD)).toBe(null); // Line overlapping line is not intersection! expect(segmentsIntersectAt(lineE, lineD)).toBe(null); expect(segmentsIntersectAt(lineF, lineG)).toBe(null); }); });