import { fuzzyIsNull, fuzzyEqual } from '../../math/float'; import { Vector2D } from '../Vector2D'; import { Matrix } from '../Matrix'; import { Shape } from './Shape'; import { Line } from './Line'; import { Circle } from './Circle'; import { Rectangle } from './Rectangle'; import { Polygon } from './Polygon'; import { Polyline } from './Polyline'; import { intersectPointLineHelper, intersectPointCircleHelper, intersectPointRectangleHelper, intersectPointPolygonHelper, intersectPointPolylineHelper, } from './internal/intersections'; export class Point extends Shape { x: number; y: number; constructor(x = 0, y = 0) { super(); this.x = x; this.y = y; } clone() { return new Point(this.x, this.y); } isNull() { return this.x === 0 && this.y === 0; } fuzzyIsNull(epsilon?: number) { return fuzzyIsNull(this.x, epsilon) && fuzzyIsNull(this.y, epsilon); } equals(other: Point) { return this.x === other.x && this.y === other.y; } fuzzyEquals(other: Point, epsilon?: number) { return fuzzyEqual(this.x, other.x, epsilon) && fuzzyEqual(this.y, other.y, epsilon); } translate(dx: number, dy: number) { this.x += dx; this.y += dy; return this; } translated(dx: number, dy: number) { return new Point(this.x + dx, this.y + dy); } transform(matrix: Matrix) { const px = this.x; const py = this.y; this.x = matrix.a * px + matrix.c * py + matrix.e; this.y = matrix.b * px + matrix.d * py + matrix.f; return this; } transformed(matrix: Matrix) { return new Point(this.x * matrix.a + this.y * matrix.c + matrix.e, this.x * matrix.b + this.y * matrix.d + matrix.f); } draw(context: CanvasRenderingContext2D, stroked?: boolean, filled?: boolean) { context.fillRect(this.x, this.y, 1, 1); } map(callbackfn: (value: number, index: number, point: Point) => number, thisArg?: any) { return new Point(callbackfn.call(thisArg, this.x, 0, this), callbackfn.call(thisArg, this.y, 1, this)); } boundingRectangle() { return new Rectangle(this.toVector2D()); } containsPoint(other: Point, epsilon?: number) { return false; } containsLine(other: Line, epsilon?: number) { return false; } containsCircle(other: Circle, epsilon?: number) { return false; } containsRectangle(other: Rectangle, epsilon?: number) { return false; } containsPolygon(other: Polygon, epsilon?: number) { return false; } containsPolyline(other: Polyline, epsilon?: number) { return false; } contains(other: Shape, epsilon?: number) { return other.containsPoint(this, epsilon); } intersectsPoint(other: Point, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number): boolean { return this.fuzzyEquals(other, epsilon) && (callbackfn === undefined || callbackfn.call(thisArg, [this.toVector2D()], this, other)); } intersectsLine(other: Line, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number): boolean { return intersectPointLineHelper(this, other, this.toVector2D(), other.p1, other.p2, callbackfn, thisArg, epsilon); } intersectsCircle(other: Circle, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number): boolean { return intersectPointCircleHelper(this, other, this.toVector2D(), other.c, other.r, callbackfn, thisArg, epsilon); } intersectsRectangle(other: Rectangle, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number): boolean { return intersectPointRectangleHelper(this, other, this.toVector2D(), other.topLeft(), other.topRight(), other.bottomRight(), other.bottomLeft(), callbackfn, thisArg, epsilon); } intersectsPolygon(other: Polygon, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number): boolean { return intersectPointPolygonHelper(this, other, this.toVector2D(), other.points, callbackfn, thisArg, epsilon); } intersectsPolyline(other: Polyline, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number): boolean { return intersectPointPolylineHelper(this, other, this.toVector2D(), other.points, callbackfn, thisArg, epsilon); } intersects(other: Shape, callbackfn?: (points: Vector2D[], thisShape: Shape, otherShape: Shape) => any, thisArg?: any, epsilon?: number) { return other.intersectsPoint(this, callbackfn, thisArg, epsilon); } toVector2D() { return new Vector2D(this.x, this.y); } static create(x?: number, y?: number) { return new Point(x, y); } static fromVector2D(v: Vector2D) { return new Point(v.x, v.y); } static readonly className: string = 'Point'; }