/* ------------------ */ /* index-elems.js */ /* ------------------ */ // ==================== lanes var drawLanesSimulation = function drawLanesSimulation() { // drawLanesSimulation simulationRolls .on("tick", function() { tickRollsForce(this.alpha()) redrawLanesDiagram() }) .on("end", function() { }) } var drawLanesDiagram = function drawLanesDiagram() { // drawLanesDiagram var linkGroup = d3.select('svg').selectAll('g.links').data(['links']).enter().append("g").attr("class", "links") var linkElements = d3.select('svg').select("g.links").selectAll("line").data(links) linkElements.enter().append("line").call(drawLink) linkElements.call(drawLink) linkElements.exit().remove() var nodeGroup = d3.select('svg').selectAll('g.nodes').data(['nodes']).enter().append("g").attr("class", "nodes") var rectElements = d3.select('svg').select("g.nodes").selectAll("rect").data(nodes, function(d) { return d.id }) rectElements.enter().append("rect").call(drawNodeRect) rectElements.call(drawNodeRect) rectElements.exit().remove() var nodeElements = d3.select('svg').select("g.nodes").selectAll("circle").data(nodes, function(d) { return d.id }) nodeElements.enter().append("circle").call(drawNodeCircle) nodeElements.call(drawNodeCircle) nodeElements.exit().remove() var textElements = d3.select('svg').select("g.nodes").selectAll("text").data(nodes, function(d) { return d.id }) textElements.enter().append("text").call(drawNodeText) textElements.call(drawNodeText) textElements.exit().remove() } var redrawLanesDiagram = function redrawLanesDiagram() { // redrawLanesDiagram // nodes have been redefined in the simulation var linkGroup = d3.select('svg').selectAll('g.links').data(['links']).enter().append("g").attr("class", "links") var linkElements = d3.select('svg').select("g.links").selectAll("line").data(links) linkElements.enter().append("line").call(redrawLink) linkElements.call(redrawLink) linkElements.exit().remove() var nodeGroup = d3.select('svg').selectAll('g.nodes').data(['nodes']).enter().append("g").attr("class", "nodes") var rectElements = d3.select('svg').select("g.nodes").selectAll("rect").data(nodes, function(d) { return d.id }) rectElements.enter().append("rect").call(redrawNodeRect) rectElements.call(redrawNodeRect) rectElements.exit().remove() var nodeElements = d3.select('svg').select("g.nodes").selectAll("circle").data(nodes, function(d) { return d.id }) nodeElements.enter().append("circle").call(redrawNodeCircle) nodeElements.call(redrawNodeCircle) nodeElements.exit().remove() var textElements = d3.select('svg').select("g.nodes").selectAll("text").data(nodes, function(d) { return d.id }) textElements.enter().append("text").call(redrawNodeText) textElements.call(redrawNodeText) textElements.exit().remove() } function drawNodeRect(nodeRect) { // drawNodeRect nodeRect .attr("x", function(d) { return xa(d.x - d.r / 8) }) .attr("y", function(d) { return ya(d.y) - (height / 2) }) // ya(d.y - d.r) }) .attr("height", function (d) { return height }) // xa(2 * d.r) }) .attr("width", function (d) { return ya(d.r / 4) }) .attr("stroke-width", 1) .style("stroke", "grey") .style("fill", function(d) { return d.color }) } function redrawNodeRect(nodeRect) { // redrawNodeRect nodeRect .attr("x", function(d) { return xa(d.x - d.r / 8) }) .attr("y", function(d) { return ya(d.y) - (height / 2) }) // ya(d.y - d.r) }) .attr("height", function (d) { return height }) // xa(2 * d.r) }) .attr("width", function (d) { return ya(d.r / 4) }) .style("fill", function(d) { return "transparent" }) // d.color .style("stroke", "transparent") // grey } function drawNodeText(nodeText) { // drawNodeText nodeText .attr("x", function(d) { return xa(d.x) }) .attr("y", function(d) { return ya(d.y) }) .text(function(d) { return "" + Math.round(xa(d.x)) + ":" + Math.round(ya(d.y))}) .style("font-size", function(d) { return ma(d.t) }) .style("font-family", "sans-serif") .style("fill", "white") .style("text-anchor", "middle") } function redrawNodeText(nodeText) { // redrawNodeText nodeText .attr("x", function(d) { return xa(d.x) }) .attr("y", function(d) { return ya(d.y) }) .text(function(d) { return "" + Math.round(xa(d.x)) + ":" + Math.round(ya(d.y))}) .style("font-size", function(d) { return ma(d.t) }) .style("fill", "transparent") // white } function drawLink(link) { // drawLink link .attr("x1", function(d) { return xa(d.source.x) }) .attr("y1", function(d) { return ya(d.source.y) }) .attr("x2", function(d) { return xa(d.target.x) }) .attr("y2", function(d) { return ya(d.target.y) }) .attr("stroke-width", 1) .style("stroke", "red") } function redrawLink(link) { // redrawLink link .attr("x1", function(d) { return xa(d.source.x) }) .attr("y1", function(d) { return ya(d.source.y) }) .attr("x2", function(d) { return xa(d.target.x) }) .attr("y2", function(d) { return ya(d.target.y) }) .style("stroke", "transparent") // grey .style("fill", function(d) { return "transparent" }) } function drawNodeCircle(nodeCircle) { // drawNodeCircle nodeCircle .attr("cx", function(d) { return xa(d.x) }) .attr("cy", function(d) { return ya(d.y) }) .attr("r", function(d) { return ma(d.r) }) .style("fill", function(d) { return d.color }) .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)) } function redrawNodeCircle(nodeCircle) { // redrawNodeCircle nodeCircle .attr("cx", function(d) { return xa(d.x) }) .attr("cy", function(d) { return ya(d.y) }) .attr("r", function(d) { return ma(d.r) }) .style("fill", function(d) { return "transparent" }) // d.color .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)) } // ==================== rings - voro var drawVoroSimulation = function drawVoroSimulation() { // drawVoroSimulation simulationVoro .on("tick", function() { contentionForce(this.alpha(), seeds, seedsArea) tickVoroForce(this.alpha()) redrawVoroDiagam() }) .on("end", function() { }) } var drawVoroDiagam = function drawVoroDiagam() { // drawVoroDiagam var rings = polygons.map(function(d) {return inscribeTriangle(xa(d[0][0]), ya(d[0][1]), xa(d[1][0]), ya(d[1][1]), xa(d[2][0]), ya(d[2][1]))}) var rs = rings.map(function(d) { return d.radius }) stateRing.radiusMin = Math.min(...rs) stateRing.radiusMax = Math.max(...rs) var seedsGroup = d3.select('svg').selectAll('g.seeds').data(['g_seeds']).enter().append("g").attr("class", "seeds") var seedElements = d3.select('svg').select("g.seeds").selectAll("circle").data(seeds) seedElements.enter().append("circle").call(drawSeed) seedElements.call(drawSeed) seedElements.exit().remove() var polygonsGroup = d3.select('svg').selectAll('g.polygons').data(['g_polygons']).enter().append("g").attr("class", "polygons") var polygonElements = d3.select('svg').select("g.polygons").selectAll("path").data(polygons) polygonElements.enter().append("path").call(drawPolygon); polygonElements.call(drawPolygon) polygonElements.exit().remove() var ringsGroup = d3.select('svg').selectAll('g.rings').data(['g_rings']).enter().append("g").attr("class", "rings") var ringElements = d3.select('svg').select("g.rings").selectAll("circle").data(rings) ringElements.enter().append("circle").call(drawRing) ringElements.call(drawRing) ringElements.exit().remove() } var redrawVoroDiagam = function redrawVoroDiagam() { // redrawVoroDiagam var rings = polygons.map(function(d) {return inscribeTriangle(xa(d[0][0]), ya(d[0][1]), xa(d[1][0]), ya(d[1][1]), xa(d[2][0]), ya(d[2][1]))}) var rs = rings.map(function(d) { return d.radius }) stateRing.radiusMin = Math.min(...rs) stateRing.radiusMax = Math.max(...rs) var seedsGroup = d3.select('svg').selectAll('g.seeds').data(['g_seeds']).enter().append("g").attr("class", "seeds") var seedElements = d3.select('svg').select("g.seeds").selectAll("circle").data(seeds) seedElements = d3.select('svg').select("g.seeds").selectAll("circle").data(seeds) seedElements.enter().append("circle").call(redrawSeed) seedElements.call(redrawSeed); seedElements.exit().remove() var polygonsGroup = d3.select('svg').selectAll('g.polygons').data(['g_polygons']).enter().append("g").attr("class", "polygons") var polygonElements = d3.select('svg').select("g.polygons").selectAll("path").data(polygons) polygonElements.enter().append("path").call(redrawPolygon); polygonElements.call(redrawPolygon) polygonElements.exit().remove() // projection var ringsGroup = d3.select('svg').selectAll('g.rings').data(['g_rings']).enter().append("g").attr("class", "rings") var ringElements = d3.select('svg').select("g.rings").selectAll("circle").data(rings) ringElements.enter().append("circle").call(redrawRing) ringElements.call(redrawRing) ringElements.exit().remove() } function drawSeed(seed) { // drawSeed seed .attr("cx", function(d, i) { return d.x} ) .attr("cy", function(d, i) { return d.y} ) .attr("r", function(d, i) { return d.r }) .style("fill", function(d, i) { return 'transparent' }) .attr("stroke", "red") } function redrawSeed(seed) { // redrawSeed seed .attr("cx", function(d, i) { return xa(d.x)} ) .attr("cy", function(d, i) { return ya(d.y)} ) .attr("r", function(d, i) { return ma(d.r) }) .style("fill", function(d, i) { return 'transparent' }) // gold .attr("stroke", "transparent ") // "transparent" } function drawPolygon(polygon) { // drawPolygon polygon .attr("d", function(d) { return d ? "M" + d.join("L") + "Z" : null; }) .attr("stroke", "#000") .style("fill", function(d, i) { return 'transparent' }) } function redrawPolygon(polygon) { // redrawPolygon polygon .attr("d", function(d) { // return d ? "M" + d.join("L") + "Z" : null; }) return d ? "M" + d.map(function(p) {return [xa(p[0]), ya(p[1])]}).join("L") + "Z" : null; }) .attr("stroke", "transparent") // transparent brown .style("fill", function(d, i) { return 'transparent' }) // transparent } function drawRing(ring) { // drawRing ring .attr('cx', function(d) {return d[0] }) .attr('cy', function(d) {return d[1] }) .attr('r', function(d) {return d.radius }) .style("fill", function(d, i) { return 'transparent' }) .attr("stroke", "grey") } function redrawRing(ring) { // redrawRing - no projection ring .attr('cx', function(d) {return d[0] }) .attr('cy', function(d) {return d[1] }) .attr('r', function(d) {return d.radius }) .style("fill", function(d, i) { return 'transparent' }) // transparent // gold .attr("stroke", function(d) { var d = Math.floor(((d.radius - stateRing.radiusMin) / (stateRing.radiusMax - stateRing.radiusMin)) * 256) var c = d3.interpolatePlasma(d / 256) return c }) } function inscribeTriangle(x0, y0, x1, y1, x2, y2) { var x01 = x0 - x1, y01 = y0 - y1, x02 = x0 - x2, y02 = y0 - y2, x12 = x1 - x2, y12 = y1 - y2, l01 = Math.sqrt(x01 * x01 + y01 * y01), l02 = Math.sqrt(x02 * x02 + y02 * y02), l12 = Math.sqrt(x12 * x12 + y12 * y12), k0 = l01 / (l01 + l02), k1 = l12 / (l12 + l01), center = segmentIntersection(x0, y0, x1 - k0 * x12, y1 - k0 * y12, x1, y1, x2 + k1 * x02, y2 + k1 * y02); center.radius = Math.sqrt((l02 + l12 - l01) * (l12 + l01 - l02) * (l01 + l02 - l12) / (l01 + l02 + l12)) / 2; return center; } function segmentIntersection(x0, y0, x1, y1, x2, y2, x3, y3) { var x02 = x0 - x2, y02 = y0 - y2, x10 = x1 - x0, y10 = y1 - y0, x32 = x3 - x2, y32 = y3 - y2, t = (x32 * y02 - y32 * x02) / (y32 * x10 - x32 * y10); return [x0 + t * x10, y0 + t * y10]; } // ==================== common function drawSvg(svgElement) { // drawNodeRect svgElement .attr("width", widthPct) .attr("height", heightPct) .style('border', '1px solid lightgrey') .on("touchmove mousemove", function() {mousemove(this)}) .on("mouseleave", function() {mouseleave(this)}) .on("mousedown", function() {mousedown(this)}) .on("touchstart", function() {touchstart(this)}) .on("touchmove", function() {touchmove(this)}) .on("mouseup", function() {mouseup(this)}) .on("touchend", function() {touchend(this)}) }