Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ __pycache__
images
examples/debug
examples/release


webapp/data/*
31 changes: 31 additions & 0 deletions webapp/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Road Network Visualization with OpenStreetMap</title>

<!-- Leaflet CSS and JS -->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>

<!-- D3.js -->
<script src="https://d3js.org/d3.v7.min.js"></script>

<link rel="stylesheet" href="styles.css" />
</head>
<body>

<!-- Map container -->
<div id="map"></div>

<!-- Slider for time step -->
<div class="slider-container">
<label for="timeSlider">Time Step:</label>
<input type="range" id="timeSlider" min="0" step="300" value="0" />
<span id="timeLabel">Time Step: 0</span>
</div>

<script src="script.js"></script>
</body>
</html>
223 changes: 223 additions & 0 deletions webapp/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
// Initialize the Leaflet map
const baseZoom = 13;

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
const map = L.map('map').setView([44.4949, 11.3426], baseZoom); // Centered on Bologna, Italy

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

// Add OpenStreetMap tile layer with inverted grayscale effect
const tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OSM</a>'
}).addTo(map);
tileLayer.getContainer().style.filter = 'grayscale(100%) invert(100%)';

// Create an overlay for D3 visualizations
L.svg().addTo(map);
const overlay = d3.select(map.getPanes().overlayPane).select("svg");

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
const g = overlay.append("g").attr("class", "leaflet-zoom-hide");

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

let nodes, edges, densities;

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'let' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
let timeStep = 0;

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'let' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

// Load CSV data for nodes, edges, and densities
Promise.all([
d3.dsv(";", "./data/nodes.csv", parseNodes),
d3.dsv(";", "./data/edges.csv", parseEdges),
d3.dsv(";", "./data/densities.csv", parseDensity)
]).then(([nodesData, edgesData, densityData]) => {

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'destructuring binding' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
nodes = nodesData;
edges = edgesData;
densities = densityData;

// console.log("Nodes:", nodes);
// console.log("Edges:", edges);
// console.log("Densities:", densities);

if (!nodes.length || !edges.length || !densities.length) {
console.error("Missing CSV data.");
return;
}

// Create a map of nodes keyed by their id for quick lookup
const nodeMap = new Map(nodes.map(d => [d.id, d]));

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

// Filter out edges whose nodes do not exist
edges = edges.filter(d => nodeMap.has(d.u) && nodeMap.has(d.v));

// Create a color scale for density values using three color stops
const colorScale = d3.scaleLinear()

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
.domain([0, 0.5, 1])
.range(["green", "yellow", "red"]);

// Function to project geographic coordinates into Leaflet's layer point coordinates
function project(d) {
return map.latLngToLayerPoint([d.y, d.x]);
}

// D3 line generator to draw paths
const lineGenerator = d3.line()

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
.x(d => d[0])
.y(d => d[1]);

// Draw edges as SVG paths
const link = g.selectAll("path")

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
.data(edges)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", "white")
.attr("stroke-dasharray", d =>
d.name.toLowerCase().includes("autostrada") ? "4,4" : "none"
)
.style("pointer-events", "all")
.style("cursor", "pointer")
.on("click", function(event, d) {
const densityData = densities.find(row => row.time === timeStep);

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
const densityValue = densityData ? densityData.densities[edges.indexOf(d)] : "N/A";

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
alert(`Edge ID: ${d.osm_id} - from ${d.u} to ${d.v}.\n\nDensity at time step ${timeStep}: ${densityValue}`);
});


// Draw nodes as SVG circles
const node = g.selectAll("circle")

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
.data(nodes)
.enter()
.append("circle")
.attr("fill", "blue")
.style("cursor", "pointer")
.on("click", function(event, d) {
alert(`Node ID: ${d.id}`);
});

// Function to update node and edge positions, and color edges based on density
function update() {
// Project nodes to current map coordinates
nodes.forEach(d => d.projected = project(d));

// Update edge paths
link.attr("d", d => {
if (d.geometry && d.geometry.length > 0) {
const projectedCoords = d.geometry.map(pt => {

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
const point = map.latLngToLayerPoint([pt.y, pt.x]);

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
return [point.x, point.y];
});
return lineGenerator(projectedCoords);
} else {
// Fallback: draw a straight line between the two nodes
const start = project(nodeMap.get(d.u));

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
const end = project(nodeMap.get(d.v));

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
return lineGenerator([[start.x, start.y], [end.x, end.y]]);
}
});

// Update node positions
node.attr("cx", d => d.projected.x)
.attr("cy", d => d.projected.y);


// Update node radius based on zoom level
function updateNodeRadius() {
const zoomLevel = map.getZoom();

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
const radiusScale = 3 + (zoomLevel - baseZoom);

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
node.attr("r", radiusScale);
}
// Update edge stroke width based on zoom level
function updateEdgeStrokeWidth() {
const zoomLevel = map.getZoom();

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
const strokeWidthScale = 3 + (zoomLevel - baseZoom);

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
link.attr("stroke-width", strokeWidthScale);
}

// Add event listener to map
map.on('zoomend', function() {
updateNodeRadius();
updateEdgeStrokeWidth();
});

// Initial render (default zoom level)
updateNodeRadius();
updateEdgeStrokeWidth();

updateDensityVisualization();
}

map.on("zoomend", update);
update(); // Initial render

// Update edge colors based on the current time step density data
function updateDensityVisualization() {
const currentDensityRow = densities.find(d => d.time === timeStep);

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
if (!currentDensityRow) {
console.error("No density data for time step:", timeStep);
return;
}
const currentDensities = currentDensityRow.densities;

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).

// For each edge, update the stroke color based on its density value
edges.forEach((edge, index) => {
let density = currentDensities[index];

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'let' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
if (density === undefined || isNaN(density)) {
console.warn(`Edge index ${index} has invalid density. Defaulting to 0.`);
density = 0;
}
const color = colorScale(density);

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
link.filter((d, i) => i === index)
.attr("stroke", color);
});
}

// Set up the time slider based on the density data's maximum time value
const maxTimeStep = d3.max(densities, d => d.time);

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
const timeSlider = document.getElementById('timeSlider');

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
const timeLabel = document.getElementById('timeLabel');

Check notice

Code scanning / Jshint (reported by Codacy)

Prohibits the use of __iterator__ property due to compatibility issues Note

'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
// Round up max to the nearest 300 for step consistency
timeSlider.max = Math.ceil(maxTimeStep / 300) * 300;
timeSlider.step = 300;
timeLabel.textContent = `Time Step: ${timeStep}`;

// Update the visualization when the slider value changes
timeSlider.addEventListener('input', function() {
timeStep = parseInt(timeSlider.value);
timeLabel.textContent = `Time Step: ${timeStep}`;
update();
});
}).catch(error => {
console.error("Error loading CSV files:", error);
});

// Parsing function for nodes CSV
function parseNodes(d) {
return {
id: d.id,
x: +d.lon, // Longitude
y: +d.lat // Latitude
};
}

// Parsing function for edges CSV, including geometry parsing
function parseEdges(d) {
let geometry = [];
if (d.geometry) {
const coordsStr = d.geometry.replace(/^LINESTRING\s*\(/, '').replace(/\)$/, '');
geometry = coordsStr.split(",").map(coordStr => {
const coords = coordStr.trim().split(/\s+/);
return { x: +coords[0], y: +coords[1] };
});
}
return {
osm_id: d.id,
u: d.source_id,
v: d.target_id,
name: d.name,
geometry: geometry
};
}

// Parsing function for density CSV
function parseDensity(d) {
const time = +d.time;
const densities = Object.keys(d)
.filter(key => key !== 'time')
.map(key => {
const val = d[key] ? d[key].trim() : "";
return val === "" ? 0 : +val;
});
return { time, densities };
}
46 changes: 46 additions & 0 deletions webapp/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
body, html {

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected newline after "," (selector-list-comma-newline-after) Warning

Expected newline after "," (selector-list-comma-newline-after)

Check warning

Code scanning / Csslint (reported by Codacy)

Rule doesn't have all its properties in alphabetical order. Warning

Rule doesn't have all its properties in alphabetical order.
margin: 0;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
padding: 0;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
width: 100%;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
height: 100%;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
}

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)

Check warning

Code scanning / Stylelint (reported by Codacy)

Unexpected whitespace at end of line (no-eol-whitespace) Warning

Unexpected whitespace at end of line (no-eol-whitespace)
/* Fullscreen map */

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)
#map {

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)

Check notice

Code scanning / Csslint (reported by Codacy)

Don't use IDs in selectors. Note

Don't use IDs in selectors.

Check warning

Code scanning / Csslint (reported by Codacy)

Rule doesn't have all its properties in alphabetical order. Warning

Rule doesn't have all its properties in alphabetical order.
width: 100%;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
height: 100vh;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
position: absolute;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
top: 0;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
left: 0;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
}

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)

Check warning

Code scanning / Stylelint (reported by Codacy)

Unexpected whitespace at end of line (no-eol-whitespace) Warning

Unexpected whitespace at end of line (no-eol-whitespace)
/* Slider container */

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)
.slider-container {

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)

Check warning

Code scanning / Csslint (reported by Codacy)

Rule doesn't have all its properties in alphabetical order. Warning

Rule doesn't have all its properties in alphabetical order.
position: absolute;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
bottom: 20px;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
left: 50%;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
transform: translateX(-50%);

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
z-index: 1000;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
width: 80%;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
padding: 10px;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)

Check notice

Code scanning / Csslint (reported by Codacy)

Using width with padding can sometimes make elements larger than you expect. Note

Using width with padding can sometimes make elements larger than you expect.
background: rgba(255, 255, 255, 0.8);

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)

Check notice

Code scanning / Csslint (reported by Codacy)

Fallback background (hex or RGB) should precede RGBA background. Note

Fallback background (hex or RGB) should precede RGBA background.
}

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)

Check warning

Code scanning / Stylelint (reported by Codacy)

Unexpected whitespace at end of line (no-eol-whitespace) Warning

Unexpected whitespace at end of line (no-eol-whitespace)
.slider-container input {

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)
width: 100%;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
}

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)

Check warning

Code scanning / Stylelint (reported by Codacy)

Unexpected whitespace at end of line (no-eol-whitespace) Warning

Unexpected whitespace at end of line (no-eol-whitespace)
/* SVG container on top of Leaflet */

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)
.leaflet-overlay-pane svg {

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)
position: absolute;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
}

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)
.leaflet-zoom-hide {

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected empty line before rule (rule-empty-line-before) Warning

Expected empty line before rule (rule-empty-line-before)
pointer-events: auto;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
}

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)

Check warning

Code scanning / Stylelint (reported by Codacy)

Unexpected whitespace at end of line (no-eol-whitespace) Warning

Unexpected whitespace at end of line (no-eol-whitespace)
circle {

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)
fill: black;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
stroke: white;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
stroke-width: 1;

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 2 spaces (indentation) Warning

Expected indentation of 2 spaces (indentation)
}

Check warning

Code scanning / Stylelint (reported by Codacy)

Expected indentation of 0 spaces (indentation) Warning

Expected indentation of 0 spaces (indentation)

Check warning

Code scanning / Stylelint (reported by Codacy)

Unexpected whitespace at end of line (no-eol-whitespace) Warning

Unexpected whitespace at end of line (no-eol-whitespace)

Check warning

Code scanning / Stylelint (reported by Codacy)

Unexpected missing end-of-source newline (no-missing-end-of-source-newline) Warning

Unexpected missing end-of-source newline (no-missing-end-of-source-newline)
Loading