Published
Edited
Jan 4, 2021
Insert cell
md`# Routes and Prefixes Routeviews`
Insert cell
pfxData = await FileAttachment("uniq_pfx").csv({array: true})
Insert cell
MARGIN_TOP = 75
Insert cell
CIDR_NUM_HEIGHT = 25
Insert cell
CIDR_RANGE = [8, 32]
Insert cell
IP_RANGE = [0, 223]
Insert cell
CELL_NUM = Math.floor(256 * CIDR_NUM_HEIGHT / (IP_RANGE[0] - IP_RANGE[0] + 1))
Insert cell
//CELL_NUM = 12800
Insert cell
Insert cell
{
const w = 800
const h = CELL_NUM * ( (IP_RANGE[1] - IP_RANGE[0] + 1) / 256 ) + 150
const points = generateRects(pfxArr)
return html`
<div style="width:${w}px;height:${h}px;position:relative">
<div style="position:absolute;top:0;left:0">
${shapesLayer({ points, w, h })}
</div>
</div>`
}
Insert cell
shapesLayer = ({ points, w, h }) => {
const ctx = DOM.context2d(w, h)
const groups = _.groupBy(points, 'color')

ctx.clearRect(0, 0, w, h)
ctx.lineWidth = 0.5
//ctx.shadowBlur = 30
// scale
ctx.fillStyle = 'black'
ctx.font = '16px sans-serif'
d3.range(IP_RANGE[0], IP_RANGE[1] + 1).forEach((o, i) => {
const y = i * (CELL_NUM / 256) + MARGIN_TOP;
ctx.fillText(String(o), 100, y + 5);
ctx.beginPath();
ctx.moveTo(100, y);
ctx.lineTo(800, y);
ctx.stroke();
})
ctx.font = '16px sans-serif';
d3.range(Math.floor(CIDR_RANGE[0] / 4),Math.floor((CIDR_RANGE[1])/ 4 + 1)).forEach(cidr => {
ctx.fillText(`${String(cidr*4)}/`, cidr*24*4, 15);
})
_.keys(groups).forEach(color => {
// draw rectangle lines
ctx.beginPath()
ctx.shadowColor = null;
ctx.fillStyle = color
ctx.strokeStyle = color
ctx.strokeWidth = 0;
ctx.globalAlpha = 1
groups[color].forEach(function (p) { roundRect({ctx,p}) })
ctx.stroke()
// fill rectangles with tranparent background
ctx.globalAlpha = 0.3
ctx.fill()
})
return ctx.canvas
}
Insert cell
colors = ['#d370e3', '#42b0f5', '#eb6272', '#8bc66f', '#ecbf6e', '#db985c']
Insert cell
generateRects = pfxArr => {
const cidrLine = (cidr) => {
if (!pfxArr[cidr]) {
return null
}
return pfxArr[cidr].map((pp, i) => ({
x: cidr * 24,
y: pp[1] + MARGIN_TOP,
w: 21,
h: CELL_NUM / Math.pow(2, cidr),
r: .2,
color: colors[cidr % colors.length],
}))
}
return d3.range(CIDR_RANGE[0],CIDR_RANGE[1] + 1).flatMap(cidr => cidrLine(cidr)).filter(r => r);
}
Insert cell
generateRects(pfxArr)
Insert cell
roundRect = ({ ctx, p }) => {
const x = p.x, y = p.y, w = p.w, r = p.r, h = p.h
ctx.moveTo(x, y + r)
ctx.lineTo(x, y + h - r)
ctx.arcTo(x, y + h, x + r, y + h, r)
ctx.lineTo(x + w - r, y + h)
ctx.arcTo(x + w, y + h, x + w, y + h - r, r)
ctx.lineTo(x + w, y + r)
ctx.arcTo(x + w, y, x + w - r, y, r)
ctx.lineTo(x + r, y)
ctx.arcTo(x, y, x, y + r, r)
}
Insert cell
d3 = require("d3")
Insert cell
_ = require("lodash")
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