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, and SVG path sampling. Generic numeric helpers like numberClamp, numberExtent, and numberSum are provided by the @ripl/utilities package.

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 ​

Generic numeric helpers live in @ripl/utilities. The plain min/max wrappers have been removed in favour of the native Math.min/Math.max.

ts
import {
    numberClamp,
    numberExtent,
    numberFractional,
    numberMaxOf,
    numberMinOf,
    numberSum,
} from '@ripl/utilities';

numberClamp(150, 0, 100); // 100
numberClamp(-5, 0, 100); // 0
numberFractional(3.7); // 0.7

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

const data = [{ v: 10 }, { v: 50 }, { v: 30 }];
numberMinOf(data, d => d.v); // 10
numberMaxOf(data, d => d.v); // 50
numberExtent(data, d => d.v); // [10, 50]
numberSum(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, which powers the Text on Path feature.

Border Radius ​

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

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

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