Skip to content

Temporal Bounding Box (TBox) ​

A TBox is a two-dimensional bounding box with an optional numeric (X) axis and an optional temporal (T) axis. It is used internally by MobilityDB to index and query temporal number sequences, and is useful as a lightweight summary type.

Dimensions ​

A TBox can have:

  • X only: a numeric range (integer or float span).
  • T only: a timestamp range (TsTzSpan).
  • XT: both a numeric and a temporal range.

MEOS outputs different WKT prefixes depending on the X type:

  • Integer X: TBOX X(...) or TBOX XT(...)
  • Float X: TBOXFLOAT X(...) or TBOXFLOAT XT(...)
  • T only: TBOX T(...)

Creating a TBox ​

From a WKT string ​

ts
import { initMeos, TBox } from 'meos.js';
await initMeos();

const floatXT = TBox.fromString('TBOXFLOAT XT([1.5, 10.5],[2020-01-01, 2020-12-31])');
const intX    = TBox.fromString('TBOX X([1, 10])');
const tOnly   = TBox.fromString('TBOX T([2020-01-01, 2020-12-31])');

From scalar values ​

ts
const fromInt   = TBox.fromInt(5);            // X-only, point span [5, 5]
const fromFloat = TBox.fromFloat(3.14);       // X-only, point span [3.14, 3.14]

From a span or span set ​

ts
import { IntSpan, FloatSpan } from 'meos.js';

const span = IntSpan.fromBounds(1, 10);
const box  = TBox.fromSpan(span.inner);       // X-only TBox from IntSpan

XT boxes from a numeric span and a temporal span ​

ts
import { TsTzSpan } from 'meos.js';

const numSpan  = FloatSpan.fromBounds(1.5, 10.5);
const timeSpan = TsTzSpan.fromString('[2020-01-01, 2020-12-31]');

const box = TBox.fromNumSpanTsTzSpan(numSpan.inner, timeSpan.inner);

Using TBox.make ​

The most flexible constructor: pass 0 for either dimension to omit it.

ts
import { IntSpan } from 'meos.js';

const numSpan = IntSpan.fromBounds(1, 10);

const xOnly = TBox.make(numSpan.inner, 0);  // no T dimension
const tOnly = TBox.make(0, timeSpan.inner); // no X dimension

Reading dimensions ​

ts
const b = TBox.fromString('TBOXFLOAT XT([1.5, 10.5],[2020-01-01, 2020-12-31])');

b.hasX();     // true
b.hasT();     // true

b.xmin();     // 1.5
b.xmax();     // 10.5
b.xminInc();  // true
b.xmaxInc();  // true

TimestampTz returns BigInt ​

tmin() and tmax() return BigInt at runtime, even though the TypeScript type is number. This is a quirk of the WASM binding: compare with 0n, not 0:

ts
b.tmin() === 0n  // correct comparison for epoch 2000-01-01

Topological predicates ​

ts
const a = TBox.fromString('TBOX X([1, 5])');
const b = TBox.fromString('TBOX X([3, 10])');

a.overlaps(b);         // true
a.isContainedIn(b);    // false
a.contains(b);         // false
a.isSame(b);           // false
a.isAdjacent(TBox.fromString('TBOX X([5, 10])')); // depends on bound inclusivity

Position predicates ​

Position is split across the two axes:

ts
// On the X axis
a.isLeft(b);           // true if max(a.x) < min(b.x)
a.isOverOrLeft(b);     // true if max(a.x) <= max(b.x)
a.isRight(b);          // true if min(a.x) > max(b.x)
a.isOverOrRight(b);    // true if min(a.x) >= min(b.x)

// On the T axis
a.isBefore(b);         // true if max(a.t) < min(b.t)
a.isOverOrBefore(b);
a.isAfter(b);
a.isOverOrAfter(b);

Set operations ​

ts
const a = TBox.fromString('TBOXFLOAT X([1.0, 5.0])');
const b = TBox.fromString('TBOXFLOAT X([3.0, 10.0])');

const i = a.intersection(b);   // TBOXFLOAT X([3.0, 5.0])  (null if disjoint)
const u = a.union(b);          // TBOXFLOAT X([1.0, 10.0]) (strict=false allows non-touching)

Math operations ​

Expanding ​

ts
// Float box: expand by 0.5 on each side
const fb = TBox.fromString('TBOXFLOAT X([2.0, 8.0])');
const expanded = fb.expandFloat(0.5);  // TBOXFLOAT X([1.5, 8.5])

// Integer box: expand by 2 on each side
const ib = TBox.make(IntSpan.fromBounds(2, 8).inner, 0);
const expanded2 = ib.expandInt(2);  // TBOX X([0, 10])

expandInt and shiftScaleInt require an integer-typed TBox. Using them on a float TBox (prefixed TBOXFLOAT) will throw a MEOS error.

Shifting and scaling ​

ts
const ib = TBox.make(IntSpan.fromBounds(1, 5).inner, 0);
const shifted = ib.shiftScaleInt(2, 0, true, false);  // shift +2, keep width -> [3, 7]
const scaled  = ib.shiftScaleInt(0, 10, false, true); // no shift, rescale width to 10

const fb = TBox.fromString('TBOXFLOAT X([1.0, 5.0])');
const fs  = fb.shiftScaleFloat(0.5, 0, true, false);  // shift +0.5

Rounding ​

ts
const b = TBox.fromString('TBOXFLOAT X([1.567, 9.123])');
b.round(2); // TBOXFLOAT X([1.57, 9.12])

Conversions ​

ts
import { IntSpan, FloatSpan, TsTzSpan } from 'meos.js';

const b = TBox.fromString('TBOXFLOAT XT([1.5, 10.5],[2020-01-01, 2020-12-31])');

const xInt   = new IntSpan(b.toIntSpan());     // X as IntSpan
const xFloat = new FloatSpan(b.toFloatSpan()); // X as FloatSpan
const t      = new TsTzSpan(b.toTsTzSpan());   // T as TsTzSpan