Created
June 16, 2025 03:30
-
-
Save youssef22222/9c5f3eb9fef7b8703e5c0edf9cdd24ec to your computer and use it in GitHub Desktop.
Speed Violation Map - 6379 XBDMazda (FMC150) - 1750044625
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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: '© 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