Published
Edited
May 11, 2022
7 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
paths = {
const paths = []

const margin = 20
const N = 10
for(let i = 0; i < N; i ++) {
paths.push([{x: margin, y: map(i, 0, N-1, margin, h - margin)}, {x: w/3 - margin, y: map(i, 0, N-1, margin, h - margin)}])
}
for(let i = 0; i < N; i ++) {
paths.push([{x: map(i, 0, N-1, w/3+margin, 2*w/3 - margin), y: margin}, {x: map(i, 0, N-1, w/3+margin, 2*w/3 - margin), y: h-margin}])
}

for(let i = 0; i < N; i ++) {
paths.push([{x: randInt(2 * w / 3 + margin, w - margin), y: randInt(margin, h - margin)}, {x: randInt(2 * w / 3 + margin, w - margin), y: randInt(margin, h - margin)}])
}
return paths
}
Insert cell
Insert cell
Insert cell
Insert cell
optimizePaths = import('https://cdn.skypack.dev/optimize-paths@1.2.1?min')
Insert cell
reorderedPaths = optimizePaths.reorder(paths)
Insert cell
Insert cell
Insert cell
Insert cell
RBush = require('rbush')
Insert cell
knn = require('rbush-knn')
Insert cell
function* range(lo, hi) {
for (let i = lo; i < hi; i++) yield i
}
Insert cell
/** Reorder paths greedily, attempting to minimize the amount of pen-up travel time. */
function reorder(pointLists) {
if (pointLists.length === 0) { return pointLists; }

const pt = i =>
i % 2 === 0
? pointLists[(i / 2)|0][0]
: pointLists[(i / 2)|0][pointLists[(i / 2)|0].length - 1]

class PointRBush extends RBush {
toBBox(i) { const {x, y} = pt(i); return {minX: x, minY: y, maxX: x, maxY: y}; }
compareMinX(a, b) { return pt(a).x - pt(b).x; }
compareMinY(a, b) { return pt(a).y - pt(b).y; }
}

const tree = new PointRBush()
tree.load([...range(2, pointLists.length * 2)])

const sortedPointLists = [];
sortedPointLists.push(pointLists[0]);

let cur = pt(1) // end of first segment
let n = pointLists.length * 2 - 2
while (n) {
const [nn] = knn(tree, cur.x, cur.y, 1)
const plId = (nn/2)|0 // path Id
tree.remove(plId * 2)
tree.remove(plId * 2 + 1)
sortedPointLists.push(
nn % 2 === 0
? pointLists[plId]
: pointLists[plId].slice().reverse()
)
// if nn corresponds to the beginning of a path, next search is from end of the path
// if nn corresponds to the end of a path, next search is from beginning of the path
cur = pt(nn % 2 === 0 ? nn + 1 : nn - 1)
n -= 2
}

return sortedPointLists
}
Insert cell
customReorderedPaths = reorder(paths)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import {randInt, map} from '@makio135/utilities'
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