Skip to content

Math & Geometry

Ripl ships with a focused set of math and geometry utilities used throughout the rendering engine. These cover angle conversion, point operations, bounding boxes, polygon generation, SVG path sampling, and common numeric helpers like clamp, min/max, and extent calculation.

NOTE

For the full API, see the Math & Geometry API Reference.

Demo

The demo below visualizes several geometry utilities: polygon vertex generation, midpoints, waypoints, and bounding boxes.

Points

A Point is a simple [x, y] tuple used throughout Ripl:

ts
import type {
    Point,
} from '@ripl/web';

const p: Point = [100, 200];

Midpoint and Waypoint

ts
import {
    getMidpoint,
    getWaypoint,
} from '@ripl/web';

const a: Point = [0, 0];
const b: Point = [100, 100];

getMidpoint(a, b); // [50, 50]
getWaypoint(a, b, 0.25); // [25, 25]
getWaypoint(a, b, 0.75); // [75, 75]

Equality and Distance

ts
import {
    arePointsEqual,
    getHypLength,
} from '@ripl/web';

arePointsEqual([0, 0], [0, 0]); // true
getHypLength(3, 4); // 5

Angles

ts
import {
    degreesToRadians,
    radiansToDegrees,
    TAU,
} from '@ripl/web';

degreesToRadians(90); // π/2
radiansToDegrees(TAU); // 360
TAU; // 6.283... (2π)

Theta Points

Compute a point at a given angle and distance from a center:

ts
import {
    getThetaPoint,
} from '@ripl/web';

getThetaPoint(0, 100, 200, 200); // [300, 200]
getThetaPoint(Math.PI / 2, 100, 200, 200); // [200, 300]

Polygons

Generate vertex points for a regular polygon:

ts
import {
    getPolygonPoints,
} from '@ripl/web';

const hexagon = getPolygonPoints(6, 200, 200, 80);
// 7 points (6 vertices + closing point)

const triangle = getPolygonPoints(3, 100, 100, 50, false);
// 3 points (no closing point)

Bounding Boxes

The Box class represents an axis-aligned bounding box:

ts
import {
    Box,
    getContainingBox,
    isPointInBox,
} from '@ripl/web';

const box = new Box(10, 20, 110, 220);
box.width; // 200
box.height; // 100

isPointInBox([50, 50], box); // true
isPointInBox([0, 0], box); // false

Box.empty(); // Box(0, 0, 0, 0)

Containing Box

Compute the smallest box that contains a collection of items:

ts
const boxes = [
    new Box(0, 0, 50, 50),
    new Box(100, 100, 200, 200),
];

const container = getContainingBox(boxes, box => box);
// Box(0, 0, 200, 200)

Numeric Helpers

ts
import {
    clamp,
    fractional,
    getExtent,
    getTotal,
    max,
    maxOf,
    min,
    minOf,
} from '@ripl/web';

clamp(150, 0, 100); // 100
clamp(-5, 0, 100); // 0
fractional(3.7); // 0.7

min(10, 20, 5); // 5
max(10, 20, 5); // 20

const data = [{ v: 10 }, { v: 50 }, { v: 30 }];
minOf(data, d => d.v); // 10
maxOf(data, d => d.v); // 50
getExtent(data, d => d.v); // [10, 50]
getTotal(data, d => d.v); // 90

SVG Path Utilities

Measure and sample points along SVG path strings:

ts
import {
    getPathLength,
    samplePathPoint,
} from '@ripl/web';

const d = 'M 0,0 L 100,0 L 100,100';
getPathLength(d); // ~200

const point = samplePathPoint(d, 50);
// { x: 50, y: 0, angle: 0 }

samplePathPoint returns the position and tangent angle at a given distance along the path — this powers the Text on Path feature.

Border Radius

Normalize a border radius value into a four-corner tuple:

ts
import {
    normaliseBorderRadius,
} from '@ripl/web';

normaliseBorderRadius(8); // [8, 8, 8, 8]
normaliseBorderRadius([4, 8, 4, 8]); // [4, 8, 4, 8]