Skip to content

Instantly share code, notes, and snippets.

@youssef22222
Created June 5, 2025 09:56
Show Gist options
  • Save youssef22222/d1910712b22633a3558c92d7638d9bea to your computer and use it in GitHub Desktop.
Save youssef22222/d1910712b22633a3558c92d7638d9bea to your computer and use it in GitHub Desktop.
Speed Violation Map - 4530 EEB (ECTE) - 1749117377
<!DOCTYPE html>
<html>
<head>
<title>Speed Violation Path</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<style>
html, body { height: 100%; margin: 0; padding: 0; }
#map { height: 100%; }
.number-icon {
background-color: #4285F4;
border: 2px solid white;
border-radius: 50%;
color: white;
font-weight: bold;
text-align: center;
font-size: 12px;
line-height: 20px;
width: 24px;
height: 24px;
margin-left: -12px;
margin-top: -12px;
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
}
.start-icon {
background-color: #00C853;
}
.end-icon {
background-color: #D50000;
}
.violation-icon {
background-color: #FF6F00;
width: 30px;
height: 30px;
line-height: 26px;
font-size: 14px;
}
.popup-content {
min-width: 250px;
}
.popup-content table {
width: 100%;
border-collapse: collapse;
}
.popup-content td {
padding: 2px 5px;
border-bottom: 1px solid #eee;
}
.popup-content td:first-child {
font-weight: bold;
width: 40%;
}
.speed-ok { color: green; }
.speed-violation { color: red; font-weight: bold; }
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet-polylinedecorator@1.6.0/dist/leaflet.polylineDecorator.js"></script>
<script>
// Initialize the map
var map = L.map('map').setView([26.6070902, 49.937345], 14);
// Add OpenStreetMap tile layer
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; OpenStreetMap contributors'
}).addTo(map);
// Define the coordinates
var latlngs = [
[26.440163, 50.050197],
[26.481817, 50.00516],
[26.511242, 49.97325],
[26.526303, 49.962013],
[26.530078, 49.959192],
[26.644792, 49.929107],
[26.649395, 49.928283],
[26.70256, 49.900157],
[26.761285, 49.862723],
[26.823267, 49.803368]
];
// Speed data for each point
var speedData = [{"time": "06/05/25,11:42:44", "speed": 41, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/05/25,11:49:50", "speed": 70, "speed_limit": 60, "street_name": "", "street_name_ar": "613"}, {"time": "06/05/25,11:53:56", "speed": 71, "speed_limit": 60, "street_name": "", "street_name_ar": "613"}, {"time": "06/05/25,11:55:41", "speed": 71, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/05/25,11:56:05", "speed": 74, "speed_limit": 60, "street_name": "", "street_name_ar": "613"}, {"time": "06/05/25,12:07:27", "speed": 70, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/05/25,12:07:53", "speed": 71, "speed_limit": 60, "street_name": "", "street_name_ar": "613"}, {"time": "06/05/25,12:13:25", "speed": 75, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/05/25,12:48:42", "speed": 74, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/05/25,12:56:17", "speed": 76, "speed_limit": 40, "street_name": "", "street_name_ar": ""}];
// Draw the polyline (straight lines between points)
var polyline = L.polyline(latlngs, {
color: 'blue',
weight: 4,
opacity: 0.6,
dashArray: '10, 5'
}).addTo(map);
// Add directional arrows
var decorator = L.polylineDecorator(polyline, {
patterns: [
{
offset: 25,
repeat: 50,
symbol: L.Symbol.arrowHead({
pixelSize: 12,
polygon: false,
pathOptions: {
stroke: true,
color: 'blue',
weight: 2,
opacity: 0.8
}
})
}
]
}).addTo(map);
// Function to create numbered div icons
function createNumberedIcon(number, extraClass = '') {
return L.divIcon({
className: 'number-icon ' + extraClass,
html: number.toString(),
iconSize: [24, 24]
});
}
// Function to create popup content
function createPopupContent(pointNum, lat, lon, data) {
var isViolation = data.speed && data.speed_limit && (data.speed > data.speed_limit);
var speedClass = isViolation ? 'speed-violation' : 'speed-ok';
var html = '<div class="popup-content">';
html += '<h4 style="margin: 0 0 5px 0;">Point ' + pointNum + '</h4>';
html += '<table>';
html += '<tr><td>Latitude:</td><td>' + lat.toFixed(6) + '</td></tr>';
html += '<tr><td>Longitude:</td><td>' + lon.toFixed(6) + '</td></tr>';
if (data.time) {
html += '<tr><td>Time:</td><td>' + data.time + '</td></tr>';
}
if (data.street_name_ar) {
html += '<tr><td>Street (AR):</td><td style="direction: rtl;">' + data.street_name_ar + '</td></tr>';
}
if (data.street_name) {
html += '<tr><td>Street (EN):</td><td>' + data.street_name + '</td></tr>';
}
if (data.speed_limit) {
html += '<tr><td>Speed Limit:</td><td>' + data.speed_limit + ' km/h</td></tr>';
}
if (data.speed) {
html += '<tr><td>Vehicle Speed:</td><td class="' + speedClass + '">' + data.speed + ' km/h</td></tr>';
}
if (isViolation) {
var overSpeed = data.speed - data.speed_limit;
html += '<tr><td>Over Speed:</td><td class="speed-violation">+' + overSpeed + ' km/h</td></tr>';
}
html += '</table>';
html += '</div>';
return html;
}
// Add markers for all points
for (var i = 0; i < latlngs.length; i++) {
var iconClass = '';
var icon;
var data = speedData[i] || {};
if (i === 0) {
iconClass = 'start-icon';
icon = createNumberedIcon('S', iconClass);
} else if (i === latlngs.length - 1) {
iconClass = 'end-icon';
icon = createNumberedIcon('E', iconClass);
} else {
icon = createNumberedIcon(i + 1);
}
var popupContent = createPopupContent(i + 1, latlngs[i][0], latlngs[i][1], data);
L.marker(latlngs[i], {icon: icon})
.addTo(map)
.bindPopup(popupContent);
}
// Add violation marker if provided
var violationLat = null;
var violationLon = null;
var violationDetails = {"time": "2025-06-05 15:56:17", "street_name_ar": "", "street_name": "", "speed_limit": 40, "speed": 76};
if (violationLat && violationLon) {
var lastPoint = latlngs[latlngs.length - 1];
if (Math.abs(lastPoint[0] - violationLat) > 0.0001 || Math.abs(lastPoint[1] - violationLon) > 0.0001) {
var violationPopup = createPopupContent('Violation', violationLat, violationLon, violationDetails);
L.marker([violationLat, violationLon], {
icon: createNumberedIcon('V', 'violation-icon')
})
.addTo(map)
.bindPopup(violationPopup);
}
}
// Fit the map to show all points
map.fitBounds(polyline.getBounds().pad(0.1));
// Add a legend
var legend = L.control({position: 'bottomright'});
legend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'legend');
div.style.background = 'white';
div.style.padding = '10px';
div.style.border = '2px solid #ccc';
div.style.borderRadius = '5px';
div.style.fontSize = '12px';
div.innerHTML = '<h4 style="margin: 0 0 5px 0;">Legend</h4>' +
'<p style="margin: 2px 0;"><span style="color: #00C853; font-weight: bold;">S</span> Start Point</p>' +
'<p style="margin: 2px 0;"><span style="color: #D50000; font-weight: bold;">E</span> End Point</p>' +
'<p style="margin: 2px 0;"><span style="color: #4285F4; font-weight: bold;">1-9</span> Path Points</p>' +
'<p style="margin: 2px 0;"><span style="color: #FF6F00; font-weight: bold;">V</span> Violation Location</p>' +
'<p style="margin: 2px 0;"><span style="color: blue;">- - →</span> Vehicle Path</p>' +
'<hr style="margin: 5px 0;">' +
'<p style="margin: 2px 0; font-style: italic; font-size: 11px;">Note: Lines show direct paths<br>between GPS points, not<br>actual street routes.</p>';
return div;
};
legend.addTo(map);
// Add info control
var info = L.control({position: 'topleft'});
info.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info');
div.style.background = 'rgba(255,255,255,0.9)';
div.style.padding = '8px';
div.style.border = '2px solid #ccc';
div.style.borderRadius = '5px';
div.style.fontSize = '14px';
var violationCount = 0;
for (var i = 0; i < speedData.length; i++) {
if (speedData[i].speed && speedData[i].speed_limit && speedData[i].speed > speedData[i].speed_limit) {
violationCount++;
}
}
div.innerHTML = '<b>Total Points:</b> ' + latlngs.length + '<br>' +
'<b>Violations:</b> ' + violationCount;
return div;
};
info.addTo(map);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment