UNPKG

romgrk-2d-geometry

Version:

Javascript library for 2d geometry

86 lines (73 loc) 2.4 kB
import Errors from '../utils/errors' import { Matrix } from './Matrix' import type { Box } from './Box' import type { Point } from './Point' import type { Vector } from './Vector' export type AnyShape = Shape<unknown> let ORIGIN_POINT: Point /** * Base class representing shape * Implement common methods of affine transformations */ export class Shape<T> { get name(): string { throw(Errors.CANNOT_INVOKE_ABSTRACT_METHOD); } get box(): Box { throw(Errors.CANNOT_INVOKE_ABSTRACT_METHOD); } clone() { throw(Errors.CANNOT_INVOKE_ABSTRACT_METHOD); } /** * Returns new shape translated by given vector. * Translation vector may be also defined by a pair of numbers. */ translate(v: Vector): T; translate(p: { x: number, y: number }): T; translate(x: number, y: number): T; translate(a: unknown, b?: unknown): T { return this.transform(new Matrix().translate(a as any, b as any)) } /** * Returns new shape rotated by given angle around given center point. * If center point is omitted, rotates around zero point (0,0). * Positive value of angle defines rotation in counterclockwise direction, * negative angle defines rotation in clockwise direction * @param angle - angle in radians * @param [center=(0,0)] center */ rotate(angle: number, center: Point = ORIGIN_POINT): T { return this.transform(new Matrix().rotate(angle, center.x, center.y)); } /** * Return new shape with coordinates multiplied by scaling factor */ scale(s: number): T; scale(sx: number, sy: number): T; scale(a: unknown, b?: unknown): T { return this.transform(new Matrix().scale(a, b ?? a)); } transform(...args): T { throw(Errors.CANNOT_INVOKE_ABSTRACT_METHOD); } /** * This method returns an object that defines how data will be * serialized when called JSON.stringify() method * @returns {Object} */ toJSON() { return Object.assign({}, this, {name: this.name}); } svg(attrs = {}) { throw(Errors.CANNOT_INVOKE_ABSTRACT_METHOD); } } /** * There is a circular dependency between Shape & Point, so we inject point later * when everything is properly defined. * @private */ export function _setupShape(point: Function) { ORIGIN_POINT = point() }