Public
Edited
Jun 30, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
return htl.html`
<div style='display: flex'>
${drawGraph()}
</div>
`;
}
Insert cell
drawGraph = () => {
document.getElementById("div-1").innerHTML = `
<div>
${graph.members.length}

(
${d3.mean(graph, (d) => d.count).toFixed(2)}
|
${Math.sqrt(d3.variance(graph, (d) => d.count)).toFixed(2)}
)
</div>
`;

const lines = graph.traceList.map((trace, i) =>
Plot.line(
trace.map((d) => graph[d]),
{
x: "x",
y: "y",
stroke: d3.schemeTableau10[i % 10] + (showTrace ? "FF" : "50")
}
)
);

return [
Plot.plot({
aspectRatio: 1.0,
width: width / 2.5,
grid: true,
x: { nice: true },
y: { nice: true },
color: { legend: true, scheme: "Blues" },
marks: [
Plot.dot(graph, { x: "x", y: "y", stroke: "gray", r: 1 }),
Plot.voronoi(graph, {
x: "x",
y: "y",
fill: "count",
stroke: "gray",
fillOpacity: (d) => (d.count === 0 ? 0.5 : 0.5)
}),
Plot.dot(graph.slice(graph.enter, graph.enter + 1), {
x: "x",
y: "y",
r: 5,
fill: "red"
}),
Plot.dot(
graph.exits.map((d) => graph[d]),
{
x: "x",
y: "y",
r: 5,
fill: "orange"
}
),
Plot.frame()
].concat(lines)
}),
Plot.plot({
grid: true,
x: { nice: true },
y: { nice: true, domain: [0, 6] },
color: { legend: true, scheme: "Oranges" },
marks: [
Plot.dot(
graph,
Plot.bin(
{ r: "count", stroke: "count" },
{
x: "neighbors",
y: "count"
}
)
)
]
})
];
}
Insert cell
graph.members
Insert cell
{
const kwargs = {
aspectRatio: 1.0,
width: width / 2.5,
grid: true,
x: { nice: true },
y: { nice: true }
};

const plt1 = Plot.plot(
Object.assign(
{
color: {
legend: true,
domain: ["Voronoi", "Delaunay"],
range: ["blue", "red"]
},
marks: [
Plot.dot(graph, { x: "x", y: "y", r: 2, stroke: "gray" }),
Plot.voronoiMesh(graph, { x: "x", y: "y", stroke: "blue" }),
Plot.delaunayMesh(graph, { x: "x", y: "y", stroke: "red" }),
Plot.frame()
]
},
kwargs
)
),
plt2 = Plot.plot(
Object.assign(
{
color: {
legend: true,
scheme: "Blues",
nice: true
},
marks: [
Plot.dot(graph, { x: "x", y: "y", r: 2, stroke: "gray" }),
Plot.voronoi(graph, {
x: "x",
y: "y",
fill: "neighbors",
stroke: "gray",
opacity: 0.5
}),
Plot.text(graph, {
x: "x",
y: "y",
text: "neighbors",
fill: "gray"
}),
Plot.frame()
]
},
kwargs
)
);

return htl.html`
<div style="display: flex">
<div>
${plt1}
</div>
<div>
${plt2}
</div>
</div>
`;
}
Insert cell
updateGraph = (n = 2) => {
graph.members.map((d) => {
if (graph.exits.indexOf(d.nodeIdx) > -1) {
if (graph.traceList.length > 10) {
graph.traceList[graph.traceIdx] = d.trace;
} else {
graph.traceList.push(d.trace);
}
graph.traceIdx += 1;
graph.traceIdx %= 10;
}
});

graph.members = graph.members.filter(
(d) => graph.exits.indexOf(d.nodeIdx) < 0
);
graph.map((d) => (d.count = 0));

graph.members.map((d) => {
graph[d.nodeIdx].count += 1;
});

graph.members.map((d) => {
var neighborsNode = [...graph.delaunay.neighbors(d.nodeIdx)]
.sort((a, b) => graph[a].count - graph[b].count)
.map((d) => graph[d]);

neighborsNode = neighborsNode.filter(
(d) => d.count === neighborsNode[0].count
);
d3.shuffle(neighborsNode);

graph[d.nodeIdx].count -= 1;
d.nodeIdx = neighborsNode[0].i;
graph[d.nodeIdx].count += 1;
d.trace.push(d.nodeIdx);

d.age += 1;
});

for (let i = 0; i < n; ++i) {
graph.members.push({ nodeIdx: graph.enter, age: 0, trace: [graph.enter] });
}
}
Insert cell
graph.map((d) => d.count)
Insert cell
graph.enter
Insert cell
[...graph.delaunay.neighbors(graph.enter)].sort(
(a, b) => graph[a].count - graph[b].count
)
Insert cell
[...graph.delaunay.neighbors(graph.enter)].sort(
(a, b) => graph[a].count - graph[b].count
)
Insert cell
[...graph.delaunay.neighbors(graph.enter)]
.sort((a, b) => graph[a].count - graph[b].count)
.map((d) => graph[d])
Insert cell
[graph.enter, graph.exits]
Insert cell
graph = {
const graph = [],
rnd = d3.randomUniform();

for (let i = 0; i < nodes; ++i) {
graph.push({ x: rnd(), y: rnd(), count: 0, i });
}

d3.shuffle(graph);
graph.enter = graph[0].i;
graph.exits = graph.slice(1, 1 + exits).map((d) => d.i);
graph.members = [];

graph.sort((a, b) => a.i - b.i);

const delaunay = d3.Delaunay.from(graph.map((d) => [d.x, d.y]));
graph.map((d, i) => {
Object.assign(d, { neighbors: [...delaunay.neighbors(i)].length });
});
graph.delaunay = delaunay;
graph.traceList = [];
graph.traceIdx = 0;

return graph;
}
Insert cell
d3 = require("d3")
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