A 3D and higher-dimensional extension of GeoJSON.
Install
pnpm add -D @types/hyper-geojson@github:kamataryo/types__hyper-geojson#main
Usage
cube.ts
import type { Polyhedron } from 'hyper-geojson'
// A unit cube: six square faces, each turned to face outward
export const cube: Polyhedron = {
type: 'Polyhedron',
coordinates: [
[[[0, 0, 0], [0, 0, 1], [0, 1, 1], [0, 1, 0], [0, 0, 0]]],
[[[0, 0, 0], [1, 0, 0], [1, 0, 1], [0, 0, 1], [0, 0, 0]]],
[[[0, 0, 0], [0, 1, 0], [1, 1, 0], [1, 0, 0], [0, 0, 0]]],
[[[1, 1, 1], [1, 0, 1], [1, 0, 0], [1, 1, 0], [1, 1, 1]]],
[[[1, 1, 1], [1, 1, 0], [0, 1, 0], [0, 1, 1], [1, 1, 1]]],
[[[1, 1, 1], [0, 1, 1], [0, 0, 1], [1, 0, 1], [1, 1, 1]]],
],
}corners.ts
import type { HyperFeature, HyperPosition, Polychoron } from 'hyper-geojson'
// Every corner of a polychoron: cells, then faces, then rings, then positions
export function corners(feature: HyperFeature<Polychoron>): HyperPosition[] {
return feature.geometry.coordinates.flat(3)
}depth.ts
import type { Polytope } from 'hyper-geojson'
// A 5-polytope nests its positions five levels deep
export const fine: Polytope<5> = {
type: 'Polytope5',
coordinates: [[[[[[0, 0, 0, 0, 0]]]]]],
}
export const tooShallow: Polytope<5> = {
type: 'Polytope5',
// @ts-expect-error four levels are one too few
coordinates: [[[[[0, 0, 0, 0, 0]]]]],
}Viewer
Sample
cells
Live editor
Orientation
Every boundary faces away from what it bounds. This is GeoJSON's right-hand rule, carried to every dimension:
- A polygon's exterior ring runs counterclockwise, and its holes run clockwise.
- A polyhedron's faces, by the right-hand rule, turn their normals away from the solid, and so into any void inside it.
- A polychoron's cells face away from it in the same way.
So the two neighbours of every shared boundary traverse it in opposite directions: each edge of a polyhedron by two faces, each face of a polychoron by two cells. A point's winding number is then 1 inside the solid, and 0 outside it or in a void.
A void needs no nesting level of its own: it is a boundary that faces the other way. The types check only the nesting depth, so a twisted or open boundary still type-checks, just as an open ring does in GeoJSON.