Skip to main content

geometry

2D and 3D shape primitives, transforms, direction, and angle brands.

import type {
  Point2D, Point3D, Size, Size3D,
  Rect, Bounds, Bounds3D,
  Vector2D, Vector3D,
  AffineMatrix2D, AffineMatrix3D,
  Direction, Origin,
  Degrees, Radians,
} from '@gentleduck/ttest/geometry'

Shape primitives shared by UI / canvas / physics APIs.

Points

interface Point2D { x: number; y: number }
interface Point3D { x: number; y: number; z: number }

Sizes

interface Size   { width: number; height: number }
interface Size3D extends Size { depth: number }

Rect

interface Rect extends Point2D, Size {}

Top-left corner plus size.

Bounds

interface Bounds   { minX: number; minY: number; maxX: number; maxY: number }
interface Bounds3D extends Bounds { minZ: number; maxZ: number }

Axis-aligned bounds described by min/max corners.

Vectors

type Vector2D = Point2D
type Vector3D = Point3D

Same shape as Point2D / Point3D but semantically a direction or offset.

Affine matrices

type AffineMatrix2D = readonly [number, number, number, number, number, number, number, number, number]  // 3x3
type AffineMatrix3D = readonly [/* 16 numbers */]  // 4x4

Row-major homogeneous transforms.

Direction

type Direction = 'north' | 'south' | 'east' | 'west'
              | 'northeast' | 'northwest' | 'southeast' | 'southwest'

Cardinal and intercardinal directions.

Origin

type Origin =
  | 'top-left' | 'top-center' | 'top-right'
  | 'center-left' | 'center' | 'center-right'
  | 'bottom-left' | 'bottom-center' | 'bottom-right'

Where (0, 0) of a rect refers to.

Angle brands

type Degrees = number & { readonly [DEG_UNIT]: 'deg' }
type Radians = number & { readonly [RAD_UNIT]: 'rad' }

Branded scalars — Degrees and Radians are not assignable to each other.

function rotate(angle: Radians) { /* ... */ }
rotate(Math.PI as Radians)
rotate(90 as Degrees)  // Error.