Source
97 chart lines · 1 file · 2.6 kBBenchmark harness excluded · shared/mount.ts
1983 ASA automobile data406 records · CSV · 17.4 kB
@charts-poc/demo-data/carsSelection: Complete published snapshot
- name
- string
- economy (mpg)
- number | null
- cylinders
- number
- displacement (cc)
- number
- power (hp)
- number | null
- weight (lb)
- number
- 0-60 mph (s)
- number
- year
- number
1983 ASA Data Exposition@observablehq/sample-datasets@1.0.1 · revision 732c0148de74 · cars.csv · ISC distribution; upstream source credited · SHA-256 eaad8395d37ePinned snapshot
cases/37-delaunay-network/tanstack.ts97 lines · entry
cases/37-delaunay-network/tanstack.ts
import { cars } from '@charts-poc/demo-data/cars'
import { defineChart, dot, link } from '@tanstack/charts'
import { Delaunay } from 'd3-delaunay'
import { scaleLinear } from 'd3-scale'
import { tanstackMount } from '../../shared/mount'
import type { CarsRow } from '@charts-poc/demo-data/cars'
import type { ConformanceInput } from '../../types'
type CompleteCar = CarsRow & {
readonly 'economy (mpg)': number
readonly 'power (hp)': number
}
interface DelaunayEdge {
id: string
x1: number
y1: number
x2: number
y2: number
}
function delaunayEdges(
points: readonly CompleteCar[],
): readonly DelaunayEdge[] {
const delaunay = Delaunay.from(
points,
(point) => point['weight (lb)'],
(point) => point['economy (mpg)'],
)
const edges: DelaunayEdge[] = []
const addEdge = (sourceIndex: number, targetIndex: number) => {
const source = points[sourceIndex]
const target = points[targetIndex]
if (!source || !target) return
edges.push({
id: `${source.name}:${source.year}:${target.name}:${target.year}`,
x1: source['weight (lb)'],
y1: source['economy (mpg)'],
x2: target['weight (lb)'],
y2: target['economy (mpg)'],
})
}
for (let index = 0; index < delaunay.halfedges.length; index++) {
const opposite = delaunay.halfedges[index]
if (opposite > index) {
addEdge(delaunay.triangles[index], delaunay.triangles[opposite])
}
}
for (let index = 0; index < delaunay.hull.length; index++) {
addEdge(
delaunay.hull[index],
delaunay.hull[(index + 1) % delaunay.hull.length],
)
}
return edges
}
const definition = (input: ConformanceInput) => {
const points = cars
.filter((row): row is CompleteCar => {
return row['economy (mpg)'] !== null && row['power (hp)'] !== null
})
.slice(input.revision * 3, input.revision * 3 + 24)
const edges = delaunayEdges(points)
return defineChart({
marks: [
link(edges, {
x1: 'x1',
y1: 'y1',
x2: 'x2',
y2: 'y2',
stroke: '#94a3b8',
strokeOpacity: 0.75,
strokeWidth: 1,
}),
dot(points, {
x: 'weight (lb)',
y: 'economy (mpg)',
fill: '#2563eb',
stroke: '#ffffff',
strokeWidth: 1,
r: 4,
}),
],
x: { scale: scaleLinear, grid: true, axis: { label: 'Weight (lb)' } },
y: {
scale: scaleLinear,
grid: true,
axis: { label: 'Fuel economy (mpg)' },
},
})
}
export const mount = tanstackMount(definition, 'Delaunay spatial network')