Public
Edited
Nov 9, 2022
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
selectTrace
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
// Make path points for trace 2, 3 and 4
mkPoints = () => {
const points = [
{ x: 0.2, y: 0.7 },
{ x: 0.6, y: 0.7 },
{ x: 0.6, y: 0.2 },
{ x: 1.0, y: 0.2 }
];
return points;
}
Insert cell
// Summary traces
traces = {
const traces = [
{ name: "passiveCar", trace: trace1 },
{ name: "method1", trace: trace2 },
{ name: "method2", trace: trace3 },
{ name: "Bezier", trace: trace4 }
];

const concat = [].concat(trace1, trace2, trace3, trace4);

traces.concat = concat;

return traces;
}
Insert cell
// Estimate speed based on the neighbor nodes
computeSpeed = (trace) => {
function dist(a, b) {
return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}

for (let i = 0; i < trace.length - 1; ++i) {
trace[i].v = dist(trace[i], trace[i + 1]);
trace[i].vx = trace[i + 1].x - trace[i].x;
}

return trace;
}
Insert cell
// Compute Bezier point with parameter r
bezier = (r) => {
var pts = mkPoints();
while (pts.length > 1) {
for (let i = 0; i < pts.length - 1; ++i) {
pts[i].x += r * (pts[i + 1].x - pts[i].x);
pts[i].y += r * (pts[i + 1].y - pts[i].y);
}
pts.pop();
}
return { x: pts[0].x, y: pts[0].y };
}
Insert cell
trace1 = {
const trace = [];
const traceId = "trace1";
const scale = d3.scaleLinear().domain([0, n]).range([0.1, 0.9]);

var x,
time,
y = 0.2;
for (let i = 0; i < n + 1; i++) {
x = scale(i);
time = i / n;
trace.push({ x, y, time, traceId });
}

return computeSpeed(trace);
}
Insert cell
trace2 = {
const trace = [];
const traceId = "trace2";

// Define distance
function dist(a, b) {
return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}

// Find the fittest node with equal-split method
// The distance between nodes are kept unchanged.
function guess(t1, r1, r3) {
const r2 = (r1 + r3) / 2;
const t2 = bezier(r2),
t3 = bezier(r3);

const d2 = dist(t1, t2),
d3 = dist(t1, t3);

if (Math.abs(d3 - speed) < eps) return r3;

if (Math.abs(d2 - speed) < eps) return r2;

if (d2 < speed) return guess(t1, r2, r3);
if (d2 > speed) return guess(t1, r1, r2);
}

var r, t, time;

r = 0;
time = 0;
t = bezier(r);
trace.push(Object.assign(t, { time, r: 0, traceId }));
for (let i = 1; i < n + 1; i++) {
r = guess(trace[i - 1], r, r + 0.1);
t = bezier(r);
time = i / n;
trace.push(
Object.assign(t, { time, r: r, traceId })
);
}

return computeSpeed(trace);
}
Insert cell
trace3 = {
const trace = [];
const traceId = "trace3";

// Define distance, not norm2 but x-axis projection
function dist(a, b) {
return Math.abs(a.x - b.x);
}

// Find the fittest node with dichotomy method
// The distance between nodes are kept unchanged.
function guess(t1, r1, r3) {
const r2 = (r1 + r3) / 2;
const t2 = bezier(r2),
t3 = bezier(r3);

const d2 = dist(t1, t2),
d3 = dist(t1, t3);

if (Math.abs(d3 - speed) < eps) return r3;

if (Math.abs(d2 - speed) < eps) return r2;

if (d2 < speed) return guess(t1, r2, r3);
if (d2 > speed) return guess(t1, r1, r2);
}

var r, t, time;

r = 0;
time = 0;
t = bezier(r);
trace.push(Object.assign(t, { time, r: 0, traceId }));
for (let i = 1; i < n + 1; i++) {
r = guess(trace[i - 1], r, r + 0.1);
t = bezier(r);
time = i / n;
trace.push(
Object.assign(t, { time, r: r, traceId })
);
}

return computeSpeed(trace);
}
Insert cell
trace4 = {
const trace = [];
const traceId = "trace4";

var r, t, time;

for (let i = 0; i < n + 1; i++) {
r = i / n;
t = bezier(r);
time = i / n;
trace.push(Object.assign(t, { dist: 0, r: r, time, traceId }));
}

return computeSpeed(trace);
}
Insert cell
Insert cell
speed = 0.8 / n
Insert cell
n = 50
Insert cell
canvasScale = {
const xScale = d3.scaleLinear().domain([0, 1.2]).range([0, width]);
const yScale = d3.scaleLinear().domain([0, 1]).range([0, height]);
return { xScale, yScale };
}
Insert cell
height = (width * 9) / 16
Insert cell
colorMap = d3[`interpolate${palette}`]
Insert cell
Insert cell
d3 = require("d3")
Insert cell
import { toc } from "@nebrius/indented-toc"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more