Skip to content

Instantly share code, notes, and snippets.

@youssef22222
Created June 16, 2025 03:30
Show Gist options
  • Save youssef22222/9c5f3eb9fef7b8703e5c0edf9cdd24ec to your computer and use it in GitHub Desktop.
Save youssef22222/9c5f3eb9fef7b8703e5c0edf9cdd24ec to your computer and use it in GitHub Desktop.
Speed Violation Map - 6379 XBDMazda (FMC150) - 1750044625
<!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.249261675000003, 50.1874501], 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.258267, 50.191938],
[26.259427, 50.190745],
[26.21067, 50.172433],
[26.229257, 50.195477],
[26.245822, 50.197988],
[26.21323, 50.196847],
[26.201733, 50.195477],
[26.204402, 50.18096],
[26.204642, 50.180452],
[26.201633, 50.187477],
[26.227973, 50.195662],
[26.209787, 50.197],
[26.204683, 50.180385],
[26.201732, 50.185263],
[26.259545, 50.1907],
[26.35269, 50.178585],
[26.325273, 50.179252],
[26.292913, 50.157518],
[26.294178, 50.160653],
[26.29548, 50.161705],
[26.295628, 50.162138],
[26.281168, 50.181515],
[26.216273, 50.196472],
[26.190958, 50.18851],
[26.24627, 50.197592],
[26.25069, 50.196923],
[26.25825, 50.191535],
[26.26691, 50.18775],
[26.287703, 50.179238],
[26.28578, 50.190192],
[26.259267, 50.190837],
[26.239418, 50.195158],
[26.21851, 50.206482],
[26.239698, 50.195907],
[26.270593, 50.19398],
[26.259415, 50.190783],
[26.257953, 50.192142],
[26.259533, 50.190748],
[26.242323, 50.196708],
[26.25079, 50.196877]
];
// Speed data for each point
var speedData = [{"time": "06/11/25,14:53:12", "speed": 71, "speed_limit": 60, "street_name": "", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f \u0627\u0644\u0641\u0631\u0639\u064a"}, {"time": "06/11/25,15:08:18", "speed": 64, "speed_limit": 50, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/11/25,15:19:25", "speed": 44, "speed_limit": 40, "street_name": "", "street_name_ar": "\u0634\u0627\u0631\u0639 \u0623\u0628\u0648 \u0639\u0628\u062f\u0627\u0644\u0631\u062d\u0645\u0646 \u0628\u0646 \u0639\u0642\u064a\u0644"}, {"time": "06/13/25,15:52:03", "speed": 62, "speed_limit": 60, "street_name": "", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f \u0627\u0644\u0641\u0631\u0639\u064a"}, {"time": "06/13/25,16:27:37", "speed": 78, "speed_limit": 60, "street_name": "", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f \u0627\u0644\u0641\u0631\u0639\u064a"}, {"time": "06/13/25,16:33:33", "speed": 101, "speed_limit": 100, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/13/25,16:34:45", "speed": 67, "speed_limit": 60, "street_name": "", "street_name_ar": ""}, {"time": "06/13/25,16:36:41", "speed": 66, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/13/25,16:42:08", "speed": 42, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/13/25,16:43:09", "speed": 46, "speed_limit": 40, "street_name": "", "street_name_ar": "\u0634\u0627\u0631\u0639 \u0623\u0628\u0648 \u0639\u0628\u062f\u0627\u0644\u0631\u062d\u0645\u0646 \u0628\u0646 \u0639\u0642\u064a\u0644"}, {"time": "06/13/25,17:11:12", "speed": 73, "speed_limit": 60, "street_name": "", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f \u0627\u0644\u0641\u0631\u0639\u064a"}, {"time": "06/13/25,20:37:34", "speed": 73, "speed_limit": 60, "street_name": "", "street_name_ar": ""}, {"time": "06/13/25,20:55:27", "speed": 42, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/13/25,20:56:22", "speed": 46, "speed_limit": 40, "street_name": "", "street_name_ar": "\u0634\u0627\u0631\u0639 \u0623\u0628\u0648 \u0639\u0628\u062f\u0627\u0644\u0631\u062d\u0645\u0646 \u0628\u0646 \u0639\u0642\u064a\u0644"}, {"time": "06/14/25,20:21:57", "speed": 65, "speed_limit": 50, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/15/25,06:05:43", "speed": 96, "speed_limit": 60, "street_name": "King Saud Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u0633\u0639\u0648\u062f"}, {"time": "06/15/25,06:07:36", "speed": 114, "speed_limit": 100, "street_name": "King Saud Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u0633\u0639\u0648\u062f"}, {"time": "06/15/25,06:10:36", "speed": 56, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/15/25,06:11:03", "speed": 61, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/15/25,06:11:13", "speed": 73, "speed_limit": 40, "street_name": "King Saud Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u0633\u0639\u0648\u062f"}, {"time": "06/15/25,06:11:16", "speed": 55, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/15/25,06:13:13", "speed": 94, "speed_limit": 50, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/15/25,06:17:34", "speed": 113, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/15/25,06:19:47", "speed": 83, "speed_limit": 40, "street_name": "", "street_name_ar": ""}, {"time": "06/15/25,06:43:38", "speed": 116, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/15/25,06:43:40", "speed": 115, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/15/25,06:44:15", "speed": 98, "speed_limit": 50, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/15/25,06:44:48", "speed": 117, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/15/25,06:47:01", "speed": 52, "speed_limit": 50, "street_name": "", "street_name_ar": ""}, {"time": "06/15/25,06:48:09", "speed": 64, "speed_limit": 60, "street_name": "", "street_name_ar": ""}, {"time": "06/15/25,07:18:07", "speed": 91, "speed_limit": 50, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/15/25,07:19:29", "speed": 114, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/15/25,07:21:53", "speed": 88, "speed_limit": 50, "street_name": "", "street_name_ar": ""}, {"time": "06/15/25,13:19:34", "speed": 91, "speed_limit": 60, "street_name": "", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f \u0627\u0644\u0641\u0631\u0639\u064a"}, {"time": "06/15/25,13:27:16", "speed": 49, "speed_limit": 40, "street_name": "", "street_name_ar": "20th Street"}, {"time": "06/15/25,13:34:44", "speed": 75, "speed_limit": 50, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/15/25,22:33:40", "speed": 73, "speed_limit": 60, "street_name": "", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f \u0627\u0644\u0641\u0631\u0639\u064a"}, {"time": "06/15/25,22:43:31", "speed": 62, "speed_limit": 50, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/16/25,03:29:55", "speed": 113, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}, {"time": "06/16/25,03:30:25", "speed": 119, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f"}];
// 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-16 06:30:25", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "street_name": "King Khaled Road", "speed_limit": 110, "speed": 119};
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