A collection of math utilities for common operations including 2D vector math, rectangle operations, and value clamping.
Installation
Clamping operations
Utilities for constraining numeric values within specified ranges.
clamp
Clamps a value between a minimum and maximum.
function clamp < T extends number | bigint >( x : T , min : T , max : T ) : T
import { clamp } from "@temelj/math" ;
clamp ( 5 , 0 , 10 ); // 5
clamp ( 12 , 0 , 10 ); // 10
clamp ( - 2 , 0 , 10 ); // 0
clampWithOverflow
Clamps a value with wrapping overflow behavior.
function clampWithOverflow < T extends number | bigint >( x : T , min : T , max : T ) : T
Example
Use case: Circular indexing
import { clampWithOverflow } from "@temelj/math" ;
clampWithOverflow ( 5 , 0 , 10 ); // 5
clampWithOverflow ( 12 , 0 , 10 ); // 2
clampWithOverflow ( - 2 , 0 , 10 ); // 8
clampWithOverflow wraps values that exceed the range back into the valid range, making it useful for circular buffers and cyclic operations.
Vector2
A 2D vector type with comprehensive operations.
Types
interface Vector2 {
x : number ;
y : number ;
}
Construction
Creates a new vector from x and y coordinates. vector2 . of ( x : number , y : number ): Vector2
import { vector2 } from "@temelj/math" ;
const v = vector2 . of ( 10 , 20 );
// { x: 10, y: 20 }
Creates a zero vector. import { vector2 } from "@temelj/math" ;
const origin = vector2 . zero ();
// { x: 0, y: 0 }
Creates a copy of a vector. vector2 . copy ( v : Vector2 ): Vector2
import { vector2 } from "@temelj/math" ;
const v1 = vector2 . of ( 5 , 10 );
const v2 = vector2 . copy ( v1 );
Arithmetic operations
Addition
Subtraction
Multiplication
Division
vector2 . plus ( a : Vector2 , b : Vector2 ): Vector2
vector2 . add ( v : Vector2 , x : number , y : number ): Vector2
import { vector2 } from "@temelj/math" ;
const v1 = vector2 . of ( 1 , 2 );
const v2 = vector2 . of ( 3 , 4 );
vector2 . plus ( v1 , v2 ); // { x: 4, y: 6 }
vector2 . add ( v1 , 10 , 20 ); // { x: 11, y: 22 }
vector2 . minus ( a : Vector2 , b : Vector2 ): Vector2
vector2 . subtract ( v : Vector2 , x : number , y : number ): Vector2
import { vector2 } from "@temelj/math" ;
const v1 = vector2 . of ( 10 , 20 );
const v2 = vector2 . of ( 3 , 5 );
vector2 . minus ( v1 , v2 ); // { x: 7, y: 15 }
vector2 . subtract ( v1 , 2 , 3 ); // { x: 8, y: 17 }
vector2 . times ( a : Vector2 , b : Vector2 ): Vector2
vector2 . multiply ( v : Vector2 , x : number , y : number ): Vector2
vector2 . scale ( v : Vector2 , x : number ): Vector2
import { vector2 } from "@temelj/math" ;
const v1 = vector2 . of ( 2 , 3 );
const v2 = vector2 . of ( 4 , 5 );
vector2 . times ( v1 , v2 ); // { x: 8, y: 15 }
vector2 . multiply ( v1 , 2 , 3 ); // { x: 4, y: 9 }
vector2 . scale ( v1 , 2 ); // { x: 4, y: 6 }
vector2 . divided ( a : Vector2 , b : Vector2 ): Vector2
vector2 . divide ( v : Vector2 , x : number , y : number ): Vector2
import { vector2 } from "@temelj/math" ;
const v1 = vector2 . of ( 10 , 20 );
const v2 = vector2 . of ( 2 , 4 );
vector2 . divided ( v1 , v2 ); // { x: 5, y: 5 }
vector2 . divide ( v1 , 2 , 2 ); // { x: 5, y: 10 }
Manipulation
Negates both components of a vector. vector2 . negate ( v : Vector2 ): Vector2
import { vector2 } from "@temelj/math" ;
const v = vector2 . of ( 5 , - 10 );
vector2 . negate ( v ); // { x: -5, y: 10 }
Snaps a vector to the nearest grid point. vector2 . snap ( v : Vector2 , size : number ): Vector2
import { vector2 } from "@temelj/math" ;
const v = vector2 . of ( 23 , 47 );
vector2 . snap ( v , 10 ); // { x: 20, y: 50 }
Clamps vector components between min and max vectors. vector2 . clamp ( v : Vector2 , min : Vector2 , max : Vector2 ): Vector2
vector2 . clampMin ( v : Vector2 , min : Vector2 ): Vector2
vector2 . clampMax ( v : Vector2 , max : Vector2 ): Vector2
import { vector2 } from "@temelj/math" ;
const v = vector2 . of ( 15 , - 5 );
const min = vector2 . of ( 0 , 0 );
const max = vector2 . of ( 10 , 10 );
vector2 . clamp ( v , min , max ); // { x: 10, y: 0 }
vector2 . clampMin ( v , min ); // { x: 15, y: 0 }
vector2 . clampMax ( v , max ); // { x: 10, y: -5 }
Utility
vector2 . equals ( a : Vector2 , b : Vector2 ): boolean
vector2 . displayString ( v : Vector2 ): string
import { vector2 } from "@temelj/math" ;
const v1 = vector2 . of ( 5 , 10 );
const v2 = vector2 . of ( 5 , 10 );
const v3 = vector2 . of ( 3 , 7 );
vector2 . equals ( v1 , v2 ); // true
vector2 . equals ( v1 , v3 ); // false
vector2 . displayString ( v1 ); // "Vector2(5, 10)"
Rectangle
Rectangle type and operations for 2D bounding boxes.
Types
interface Rectangle {
position : Vector2 ;
size : Vector2 ;
}
Construction
Creates a rectangle from position and size vectors. rectangle . of ( position : Vector2 , size : Vector2 ): Rectangle
import { rectangle , vector2 } from "@temelj/math" ;
const rect = rectangle . of (
vector2 . of ( 10 , 20 ),
vector2 . of ( 100 , 50 )
);
Creates a rectangle from explicit bounds. rectangle . ofBounds ( x : number , y : number , width : number , height : number ): Rectangle
import { rectangle } from "@temelj/math" ;
const rect = rectangle . ofBounds ( 10 , 20 , 100 , 50 );
// position: { x: 10, y: 20 }
// size: { x: 100, y: 50 }
Creates a rectangle from a DOM DOMRect object. rectangle . fromDOM ( rect : DOMRect ): Rectangle
import { rectangle } from "@temelj/math" ;
const element = document . getElementById ( 'myElement' );
const domRect = element . getBoundingClientRect ();
const rect = rectangle . fromDOM ( domRect );
Operations
Expands rectangle to include another rectangle. rectangle . expand ( a : Rectangle , b : Rectangle ): Rectangle
import { rectangle } from "@temelj/math" ;
const rect1 = rectangle . ofBounds ( 0 , 0 , 100 , 100 );
const rect2 = rectangle . ofBounds ( 50 , 50 , 100 , 100 );
const expanded = rectangle . expand ( rect1 , rect2 );
// position: { x: 0, y: 0 }
// size: { x: 150, y: 150 }
Gets the center point of a rectangle. rectangle . center ( r : Rectangle ): Vector2
import { rectangle } from "@temelj/math" ;
const rect = rectangle . ofBounds ( 0 , 0 , 100 , 50 );
const center = rectangle . center ( rect );
// { x: 50, y: 25 }
Checks if two rectangles overlap. rectangle . overlaps ( a : Rectangle , b : Rectangle ): boolean
import { rectangle } from "@temelj/math" ;
const rect1 = rectangle . ofBounds ( 0 , 0 , 100 , 100 );
const rect2 = rectangle . ofBounds ( 50 , 50 , 100 , 100 );
const rect3 = rectangle . ofBounds ( 200 , 200 , 50 , 50 );
rectangle . overlaps ( rect1 , rect2 ); // true
rectangle . overlaps ( rect1 , rect3 ); // false
Utility
rectangle . displayString ( r : Rectangle ): string
import { rectangle } from "@temelj/math" ;
const rect = rectangle . ofBounds ( 10 , 20 , 100 , 50 );
rectangle . displayString ( rect );
// "Rectangle(10, 20, 100, 50)"
All vector and rectangle operations are immutable - they return new objects rather than modifying existing ones.