svg = {
const svg = d3.create("svg")
.attr("width", mapSize.width)
.attr("height", mapSize.height)
.attr("viewBox", [-mapSize.width / 2 -50, -mapSize.height / 2 -50, mapSize.width +100, mapSize.height +100])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;");
const [hide, show, solo] = ['Hide', 'Show', 'Solo']
const nosolo = Object.values(layers).filter(it=> it === "Solo").length === 0
const points = delaunay.points
if (layers.cells === solo || (nosolo && layers.cells === show)){
const voi = svg.append('g').selectAll('path').data(d3.range(rawPoints.length)).join('path')
.attr('fill', d=>{
if (tags[d].includes('Industry')) return 'tan'
if (tags[d].includes('Commercial')) return 'lightblue'
if (tags[d].includes('Residential')) return 'limegreen'
if (tags[d].includes('Outskirts')) return 'lightyellow'
if (tags[d].includes('Corporations')) return 'steelblue'
if (tags[d].includes('Downtown')) return 'gold'
return 'transparent'
})
.attr('d', d => voronoi.renderCell(d))
}
if (layers.debug === solo || (nosolo && layers.debug === show)){
const debugNeighbors = voronoi.neighbors(debugCell)
const debug = svg.append('g')
debug.append('path')
.attr('fill', 'darkgray')
.attr('d', voronoi.renderCell(debugCell))
debug.append('path')
.attr('fill', 'lightgray')
.attr('d', [...debugNeighbors].map(it=>voronoi.renderCell(it)).join(' '))
}
if (layers.cells === solo || (nosolo && layers.cells === show)){
const voi = svg.append('path')
.attr('stroke', 'gray')
.attr('d', voronoi.render())
}
if (layers.links === solo || (nosolo && layers.links === show)){
const lines = svg.append('g')
.selectAll('line').data(links).join('line')
.attr('stroke', 'cyan')
.attr('stroke-width', '2px')
.attr('x1', d=>points[d.source*2])
.attr('y1', d=>points[d.source*2+1])
.attr('x2', d=>points[d.target*2])
.attr('y2', d=>points[d.target*2+1])
}
// dots should be on top
if (layers.raw === solo || (nosolo && layers.raw === show)){
svg.append('g')
.attr('fill', 'gray')
.selectAll('circle').data(rawPoints).join('circle')
.attr('cx', d=>d.x)
.attr('cy', d=>d.y)
.attr('r', 2)
}
if (layers.relaxed === solo || (nosolo && layers.relaxed === show)){
const dots = svg.append('path')
.attr('d', delaunay.renderPoints())
}
if (layers.centroids === solo || (nosolo && layers.centroids === show)){
svg.append('g')
.attr('fill', 'transparent')
.attr('stroke', 'blue')
.attr('stroke-width', '1')
.selectAll('circle').data(centroids).join('circle')
.attr('cx', d=>d[0])
.attr('cy', d=>d[1])
.attr('r', 3)
// index label
svg.append('g')
.attr('text-anchor', 'middle')
.selectAll('text').data(centroids).join('text')
.attr('x', d=>d[0])
.attr('y', d=>d[1]-8)
.text((d,i)=> i+": "+ tags[i].join(', '))
}
return svg
}