Created
June 12, 2025 14:00
-
-
Save youssef22222/b20c11d4c2b7271f5fb5907aa1912785 to your computer and use it in GitHub Desktop.
Speed Violation Map - Testing Live Alerts - 1749736804
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 - Testing Live Alerts</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: #FF6F00; /* Orange for violation/end point */ | |
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; } | |
.legend-toggle { | |
position: absolute; | |
top: 90px; | |
right: 10px; | |
z-index: 1000; | |
background: white; | |
padding: 8px; | |
border: 2px solid #ccc; | |
border-radius: 5px; | |
cursor: pointer; | |
font-size: 14px; | |
font-family: Arial, sans-serif; | |
box-shadow: 0 1px 5px rgba(0,0,0,0.4); | |
} | |
</style> | |
</head> | |
<body> | |
<div id="map"></div> | |
<div id="legend-toggle" class="legend-toggle">Hide Legend</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.377795166666672, 49.96696052083333], 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 and the detailed path data | |
var latlngs = [ | |
[26.865333, 49.769885], | |
[26.831852, 49.796935], | |
[26.76989, 49.857938], | |
[26.765717, 49.860267], | |
[26.748828, 49.868608], | |
[26.657025, 49.9266], | |
[26.65252, 49.927458], | |
[26.558827, 49.953845], | |
[26.496802, 49.983357], | |
[26.479842, 49.989232], | |
[26.477052, 49.990785], | |
[26.46693, 50.0037], | |
[26.466152, 50.004247], | |
[26.462197, 50.006708], | |
[26.420992, 50.011375], | |
[26.421455, 50.011282], | |
[26.386642, 50.020885], | |
[26.382132, 50.022267], | |
[26.313665, 50.041115], | |
[26.310383, 50.042167], | |
[26.301035, 50.041017], | |
[26.237345, 49.993003], | |
[26.234015, 49.989727], | |
[26.234215, 49.989317], | |
[26.243065, 49.982062], | |
[26.241992, 49.982397], | |
[26.238785, 49.976587], | |
[26.242348, 49.973693], | |
[26.23859, 49.976677], | |
[26.253637, 49.965415], | |
[26.253508, 49.965323], | |
[26.256337, 49.969788], | |
[26.257537, 49.971343], | |
[26.281053, 49.959268], | |
[26.283655, 49.9634], | |
[26.28638, 49.967448], | |
[26.28974, 49.972313], | |
[26.289857, 49.972483], | |
[26.289858, 49.972303], | |
[26.278318, 49.954915], | |
[26.278075, 49.954923], | |
[26.246212, 49.979258], | |
[26.243598, 49.975003], | |
[26.242683, 49.973628], | |
[26.242437, 49.973635], | |
[26.23856, 49.976705], | |
[26.238575, 49.976978], | |
[26.238522, 49.97684] | |
]; | |
var pathData = [{"latitude": 26.865333, "longitude": 49.769885, "time": "06/12/25,12:40:52", "speed": 205, "speed_limit": 120, "street_name": "Dhahran Jubail Expressway", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0638\u0647\u0631\u0627\u0646 \u0627\u0644\u062c\u0628\u064a\u0644 \u0627\u0644\u0633\u0631\u064a\u0639", "distance_to_segment": 9.71, "vehicle_direction": 129, "segment_bearing": 132.4, "nearest_segment": [[26.8667993, 49.7679405], [26.863677, 49.7717739]], "closest_point": [26.86526236607317, 49.76982746874583], "angle_difference": 3.4}, {"latitude": 26.831852, "longitude": 49.796935, "time": "06/12/25,12:43:34", "speed": 201, "speed_limit": 120, "street_name": "Dhahran Jubail Expressway", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0638\u0647\u0631\u0627\u0646 \u0627\u0644\u062c\u0628\u064a\u0644 \u0627\u0644\u0633\u0631\u064a\u0639", "distance_to_segment": 3.19, "vehicle_direction": 149, "segment_bearing": 149.5, "nearest_segment": [[26.8329402, 49.7961802], [26.8305947, 49.7977272]], "closest_point": [26.83183496386904, 49.796909170494395], "angle_difference": 0.5}, {"latitude": 26.76989, "longitude": 49.857938, "time": "06/12/25,12:48:53", "speed": 207, "speed_limit": 120, "street_name": "Dhahran Jubail Expressway", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0638\u0647\u0631\u0627\u0646 \u0627\u0644\u062c\u0628\u064a\u0644 \u0627\u0644\u0633\u0631\u064a\u0639", "distance_to_segment": 17.59, "vehicle_direction": 148, "segment_bearing": 331.6, "nearest_segment": [[26.7677469, 49.859434], [26.7732835, 49.8560867]], "closest_point": [26.76997869613407, 49.85808470779909], "angle_difference": 3.6}, {"latitude": 26.765717, "longitude": 49.860267, "time": "06/12/25,12:49:09", "speed": 209, "speed_limit": 120, "street_name": "Dhahran Jubail Expressway", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0638\u0647\u0631\u0627\u0646 \u0627\u0644\u062c\u0628\u064a\u0644 \u0627\u0644\u0633\u0631\u064a\u0639", "distance_to_segment": 12.93, "vehicle_direction": 152, "segment_bearing": 156.3, "nearest_segment": [[26.7671185, 49.8594373], [26.7562967, 49.86475]], "closest_point": [26.765660958246606, 49.86015284474055], "angle_difference": 4.3}, {"latitude": 26.748828, "longitude": 49.868608, "time": "06/12/25,12:50:17", "speed": 206, "speed_limit": 120, "street_name": "Dhahran Jubail Expressway", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0638\u0647\u0631\u0627\u0646 \u0627\u0644\u062c\u0628\u064a\u0644 \u0627\u0644\u0633\u0631\u064a\u0639", "distance_to_segment": 3.99, "vehicle_direction": 156, "segment_bearing": 156.2, "nearest_segment": [[26.7502086, 49.8678813], [26.7471033, 49.8694173]], "closest_point": [26.748810592619794, 49.86857280785303], "angle_difference": 0.2}, {"latitude": 26.657025, "longitude": 49.9266, "time": "06/12/25,12:56:44", "speed": 215, "speed_limit": 120, "street_name": "Dhahran Jubail Expressway", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0638\u0647\u0631\u0627\u0646 \u0627\u0644\u062c\u0628\u064a\u0644 \u0627\u0644\u0633\u0631\u064a\u0639", "distance_to_segment": 7.28, "vehicle_direction": 170, "segment_bearing": 170.6, "nearest_segment": [[26.6593496, 49.9260945], [26.6545753, 49.9269804]], "closest_point": [26.657011697819282, 49.926528311771754], "angle_difference": 0.6}, {"latitude": 26.65252, "longitude": 49.927458, "time": "06/12/25,12:56:59", "speed": 216, "speed_limit": 120, "street_name": "Dhahran Jubail Expressway", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0638\u0647\u0631\u0627\u0646 \u0627\u0644\u062c\u0628\u064a\u0644 \u0627\u0644\u0633\u0631\u064a\u0639", "distance_to_segment": 11.83, "vehicle_direction": 171, "segment_bearing": 170.9, "nearest_segment": [[26.6542951, 49.9270189], [26.6486678, 49.9280291]], "closest_point": [26.652499054236333, 49.92734132201952], "angle_difference": 0.1}, {"latitude": 26.558827, "longitude": 49.953845, "time": "06/12/25,13:02:47", "speed": 210, "speed_limit": 120, "street_name": "Dhahran Jubail Expressway", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0638\u0647\u0631\u0627\u0646 \u0627\u0644\u062c\u0628\u064a\u0644 \u0627\u0644\u0633\u0631\u064a\u0639", "distance_to_segment": 4.61, "vehicle_direction": 152, "segment_bearing": 163.6, "nearest_segment": [[26.5588739, 49.9537814], [26.5558982, 49.9547582]], "closest_point": [26.55881271559285, 49.95380148432601], "angle_difference": 11.6}, {"latitude": 26.496802, "longitude": 49.983357, "time": "06/12/25,13:07:11", "speed": 198, "speed_limit": 120, "street_name": "", "street_name_ar": "To Road 95", "distance_to_segment": 1.87, "vehicle_direction": 147, "segment_bearing": 147.8, "nearest_segment": [[26.4978788, 49.9825766], [26.496404, 49.9836152]], "closest_point": [26.496791603724844, 49.983342237409396], "angle_difference": 0.8}, {"latitude": 26.479842, "longitude": 49.989232, "time": "06/12/25,13:08:24", "speed": 204, "speed_limit": 120, "street_name": "", "street_name_ar": "To Road 95", "distance_to_segment": 0.93, "vehicle_direction": 178, "segment_bearing": 166.6, "nearest_segment": [[26.4806075, 49.9890181], [26.4798324, 49.989225]], "closest_point": [26.47983961721584, 49.989223073484766], "angle_difference": 11.4}, {"latitude": 26.477052, "longitude": 49.990785, "time": "06/12/25,13:08:44", "speed": 209, "speed_limit": 120, "street_name": "", "street_name_ar": "Entry onto Hwy 95", "distance_to_segment": 3.72, "vehicle_direction": 164, "segment_bearing": 144.5, "nearest_segment": [[26.4770951, 49.9907049], [26.4768765, 49.9908793]], "closest_point": [26.477029713706518, 49.99075706546012], "angle_difference": 19.5}, {"latitude": 26.46693, "longitude": 50.0037, "time": "06/12/25,13:09:40", "speed": 187, "speed_limit": 120, "street_name": "Abu Hadriah Rd", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0623\u0628\u0648\u062d\u062f\u0631\u064a\u0629", "distance_to_segment": 2.53, "vehicle_direction": 135, "segment_bearing": 143.5, "nearest_segment": [[26.4676362, 50.0031486], [26.4663554, 50.0042057]], "closest_point": [26.466945443406445, 50.00371871148895], "angle_difference": 8.5}, {"latitude": 26.466152, "longitude": 50.004247, "time": "06/12/25,13:09:41", "speed": 190, "speed_limit": 120, "street_name": "", "street_name_ar": "", "distance_to_segment": 5.85, "vehicle_direction": 147, "segment_bearing": 155.0, "nearest_segment": [[26.4663554, 50.0042057], [26.4646757, 50.0050804]], "closest_point": [26.466178472108755, 50.00429783480173], "angle_difference": 8.0}, {"latitude": 26.462197, "longitude": 50.006708, "time": "06/12/25,13:10:00", "speed": 193, "speed_limit": 120, "street_name": "Abu Hadriah Rd", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0623\u0628\u0648\u062d\u062f\u0631\u064a\u0629", "distance_to_segment": 5.88, "vehicle_direction": 148, "segment_bearing": 153.6, "nearest_segment": [[26.463039, 50.0061762], [26.4615957, 50.0069752]], "closest_point": [26.46216917125818, 50.00665773063446], "angle_difference": 5.6}, {"latitude": 26.420992, "longitude": 50.011375, "time": "06/12/25,13:12:38", "speed": 188, "speed_limit": 120, "street_name": "Abu Hadriah Rd", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0623\u0628\u0648\u062d\u062f\u0631\u064a\u0629", "distance_to_segment": 10.06, "vehicle_direction": 175, "segment_bearing": 352.1, "nearest_segment": [[26.4202047, 50.0115992], [26.4215186, 50.0113951]], "closest_point": [26.42100745632743, 50.01147450058115], "angle_difference": 2.9}, {"latitude": 26.421455, "longitude": 50.011282, "time": "06/12/25,13:12:37", "speed": 202, "speed_limit": 120, "street_name": "Abu Hadriah Rd", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0623\u0628\u0648\u062d\u062f\u0631\u064a\u0629", "distance_to_segment": 7.42, "vehicle_direction": 178, "segment_bearing": 173.1, "nearest_segment": [[26.4216157, 50.0111851], [26.4201768, 50.0113806]], "closest_point": [26.421444985810435, 50.01120829454032], "angle_difference": 4.9}, {"latitude": 26.386642, "longitude": 50.020885, "time": "06/12/25,13:15:10", "speed": 191, "speed_limit": 120, "street_name": "Abu Hadriah Rd", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0623\u0628\u0648\u062d\u062f\u0631\u064a\u0629", "distance_to_segment": 5.16, "vehicle_direction": 165, "segment_bearing": 162.7, "nearest_segment": [[26.3866396, 50.0208317], [26.3865701, 50.0208558]], "closest_point": [26.38662524380454, 50.02083667819152], "angle_difference": 2.3}, {"latitude": 26.382132, "longitude": 50.022267, "time": "06/12/25,13:15:30", "speed": 199, "speed_limit": 120, "street_name": "Abu Hadriah Rd", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0623\u0628\u0648\u062d\u062f\u0631\u064a\u0629", "distance_to_segment": 8.04, "vehicle_direction": 164, "segment_bearing": 164.6, "nearest_segment": [[26.3836845, 50.0217064], [26.3819761, 50.0222314]], "closest_point": [26.382108551677817, 50.02219069692645], "angle_difference": 0.6}, {"latitude": 26.313665, "longitude": 50.041115, "time": "06/12/25,13:20:28", "speed": 187, "speed_limit": 120, "street_name": "", "street_name_ar": "", "distance_to_segment": 10.76, "vehicle_direction": 158, "segment_bearing": 158.3, "nearest_segment": [[26.3169083, 50.0395578], [26.3114624, 50.0419781]], "closest_point": [26.313622026509645, 50.04101830565172], "angle_difference": 0.3}, {"latitude": 26.310383, "longitude": 50.042167, "time": "06/12/25,13:20:43", "speed": 186, "speed_limit": 60, "street_name": "", "street_name_ar": "", "distance_to_segment": 12.93, "vehicle_direction": 158, "segment_bearing": 177.2, "nearest_segment": [[26.3114624, 50.0419781], [26.3103844, 50.0420373]], "closest_point": [26.3103844, 50.0420373], "angle_difference": 19.2}, {"latitude": 26.301035, "longitude": 50.041017, "time": "06/12/25,13:21:25", "speed": 191, "speed_limit": 120, "street_name": "", "street_name_ar": "", "distance_to_segment": 13.24, "vehicle_direction": 178, "segment_bearing": 211.7, "nearest_segment": [[26.3013544, 50.041392], [26.3003995, 50.040735]], "closest_point": [26.300962505747243, 50.04112236493448], "angle_difference": null}, {"latitude": 26.237345, "longitude": 49.993003, "time": "06/12/25,13:26:45", "speed": 182, "speed_limit": 120, "street_name": "", "street_name_ar": "", "distance_to_segment": 2.66, "vehicle_direction": 214, "segment_bearing": 217.0, "nearest_segment": [[26.2406077, 49.9957155], [26.2356212, 49.9915191]], "closest_point": [26.237361371957444, 49.99298354552336], "angle_difference": 3.0}, {"latitude": 26.234015, "longitude": 49.989727, "time": "06/12/25,13:27:53", "speed": 130, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 1.65, "vehicle_direction": 263, "segment_bearing": 278.9, "nearest_segment": [[26.2339676, 49.9899587], [26.23401, 49.9896555]], "closest_point": [26.234000289003074, 49.98972494278935], "angle_difference": 15.9}, {"latitude": 26.234215, "longitude": 49.989317, "time": "06/12/25,13:27:57", "speed": 133, "speed_limit": 40, "street_name": "", "street_name_ar": "Makkah Road", "distance_to_segment": 2.27, "vehicle_direction": 284, "segment_bearing": 307.2, "nearest_segment": [[26.23401, 49.9896555], [26.2343928, 49.9890932]], "closest_point": [26.234232385205708, 49.98932883542014], "angle_difference": 23.2}, {"latitude": 26.243065, "longitude": 49.982062, "time": "06/12/25,13:29:36", "speed": 106, "speed_limit": 40, "street_name": "", "street_name_ar": "Makkah Road", "distance_to_segment": 3.71, "vehicle_direction": 206, "segment_bearing": 144.7, "nearest_segment": [[26.2433696, 49.9817765], [26.2422129, 49.9826886]], "closest_point": [26.243042968767927, 49.982034060600654], "angle_difference": null}, {"latitude": 26.241992, "longitude": 49.982397, "time": "06/12/25,13:29:48", "speed": 125, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 3.69, "vehicle_direction": 204, "segment_bearing": 55.4, "nearest_segment": [[26.241533, 49.9815916], [26.2422129, 49.9826886]], "closest_point": [26.242021023163804, 49.98237901198808], "angle_difference": null}, {"latitude": 26.238785, "longitude": 49.976587, "time": "06/12/25,13:30:55", "speed": 121, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 3.76, "vehicle_direction": 298, "segment_bearing": 325.1, "nearest_segment": [[26.2385397, 49.9768235], [26.2415708, 49.9744657]], "closest_point": [26.23880714205558, 49.976615465003256], "angle_difference": 27.1}, {"latitude": 26.242348, "longitude": 49.973693, "time": "06/12/25,13:31:45", "speed": 108, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 5.15, "vehicle_direction": 190, "segment_bearing": 145.2, "nearest_segment": [[26.2446578, 49.9718382], [26.2407507, 49.9748698]], "closest_point": [26.242317691547964, 49.97365393872775], "angle_difference": null}, {"latitude": 26.23859, "longitude": 49.976677, "time": "06/12/25,13:52:48", "speed": 110, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 8.83, "vehicle_direction": 129, "segment_bearing": 325.1, "nearest_segment": [[26.2385397, 49.9768235], [26.2415708, 49.9744657]], "closest_point": [26.23864203619796, 49.976743895801015], "angle_difference": 16.1}, {"latitude": 26.253637, "longitude": 49.965415, "time": "06/12/25,13:54:58", "speed": 128, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 13.51, "vehicle_direction": 0, "segment_bearing": 54.9, "nearest_segment": [[26.2533959, 49.9652667], [26.2570816, 49.9711229]], "closest_point": [26.25353115906561, 49.96548161280897], "angle_difference": null}, {"latitude": 26.253508, "longitude": 49.965323, "time": "06/12/25,13:54:56", "speed": 168, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 13.67, "vehicle_direction": 324, "segment_bearing": 325.1, "nearest_segment": [[26.2520267, 49.9663318], [26.2533959, 49.9652667]], "closest_point": [26.2533959, 49.9652667], "angle_difference": 1.1}, {"latitude": 26.256337, "longitude": 49.969788, "time": "06/12/25,13:55:28", "speed": 135, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 8.74, "vehicle_direction": 53, "segment_bearing": 54.9, "nearest_segment": [[26.2533959, 49.9652667], [26.2570816, 49.9711229]], "closest_point": [26.2562685650576, 49.96983107070578], "angle_difference": 1.9}, {"latitude": 26.257537, "longitude": 49.971343, "time": "06/12/25,13:55:50", "speed": 123, "speed_limit": 40, "street_name": "", "street_name_ar": "Makkah Road", "distance_to_segment": 16.37, "vehicle_direction": 344, "segment_bearing": 325.4, "nearest_segment": [[26.2574539, 49.9712075], [26.259943, 49.9692922]], "closest_point": [26.2574539, 49.9712075], "angle_difference": 18.6}, {"latitude": 26.281053, "longitude": 49.959268, "time": "06/12/25,13:59:05", "speed": 117, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 12.13, "vehicle_direction": 39, "segment_bearing": 55.0, "nearest_segment": [[26.2808237, 49.9591134], [26.2820599, 49.9610859]], "closest_point": [26.280957931142176, 49.95932758130395], "angle_difference": 16.0}, {"latitude": 26.283655, "longitude": 49.9634, "time": "06/12/25,13:59:20", "speed": 172, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 13.22, "vehicle_direction": 55, "segment_bearing": 235.5, "nearest_segment": [[26.2840583, 49.9638209], [26.280305, 49.9577375]], "closest_point": [26.283759019766535, 49.96333582250226], "angle_difference": 0.5}, {"latitude": 26.28638, "longitude": 49.967448, "time": "06/12/25,13:59:46", "speed": 170, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 12.53, "vehicle_direction": 54, "segment_bearing": 52.8, "nearest_segment": [[26.2838406, 49.9639272], [26.2865401, 49.9678897]], "closest_point": [26.286283823748576, 49.967513521209014], "angle_difference": 1.2}, {"latitude": 26.28974, "longitude": 49.972313, "time": "06/12/25,14:01:09", "speed": 162, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 14.85, "vehicle_direction": 52, "segment_bearing": 235.2, "nearest_segment": [[26.2899862, 49.9724486], [26.2879218, 49.9691315]], "closest_point": [26.289856634343497, 49.972240412517344], "angle_difference": 3.2}, {"latitude": 26.289857, "longitude": 49.972483, "time": "06/12/25,14:01:37", "speed": 112, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 4.98, "vehicle_direction": 12, "segment_bearing": 147.0, "nearest_segment": [[26.2899862, 49.9724486], [26.2897141, 49.9726459]], "closest_point": [26.28988517342358, 49.97252185447824], "angle_difference": null}, {"latitude": 26.289858, "longitude": 49.972303, "time": "06/12/25,14:01:46", "speed": 112, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 3.45, "vehicle_direction": 12, "segment_bearing": 235.2, "nearest_segment": [[26.2899862, 49.9724486], [26.2879218, 49.9691315]], "closest_point": [26.289885092308015, 49.97228613907911], "angle_difference": null}, {"latitude": 26.278318, "longitude": 49.954915, "time": "06/12/25,16:43:24", "speed": 123, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 11.5, "vehicle_direction": 210, "segment_bearing": 55.0, "nearest_segment": [[26.2781302, 49.9548158], [26.2782775, 49.9550508]], "closest_point": [26.278227812911187, 49.95497153003482], "angle_difference": 25.0}, {"latitude": 26.278075, "longitude": 49.954923, "time": "06/12/25,16:43:28", "speed": 110, "speed_limit": 40, "street_name": "", "street_name_ar": "Makkah Road", "distance_to_segment": 5.32, "vehicle_direction": 189, "segment_bearing": 145.3, "nearest_segment": [[26.2781302, 49.9548158], [26.2738992, 49.958087]], "closest_point": [26.27804377801823, 49.954882617203204], "angle_difference": null}, {"latitude": 26.246212, "longitude": 49.979258, "time": "06/12/25,16:47:34", "speed": 127, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 7.01, "vehicle_direction": 199, "segment_bearing": 54.8, "nearest_segment": [[26.2443351, 49.9764113], [26.2462888, 49.9795009]], "closest_point": [26.24615713953079, 49.97929269086571], "angle_difference": null}, {"latitude": 26.243598, "longitude": 49.975003, "time": "06/12/25,16:48:06", "speed": 131, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 6.79, "vehicle_direction": 224, "segment_bearing": 235.0, "nearest_segment": [[26.2444833, 49.9762963], [26.2427566, 49.9735433]], "closest_point": [26.243651203834222, 49.97496963019958], "angle_difference": 11.0}, {"latitude": 26.242683, "longitude": 49.973628, "time": "06/12/25,16:48:23", "speed": 162, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 9.9, "vehicle_direction": 235, "segment_bearing": 54.8, "nearest_segment": [[26.2425987, 49.9736661], [26.2443351, 49.9764113]], "closest_point": [26.24260557673913, 49.97367697193289], "angle_difference": 0.2}, {"latitude": 26.242437, "longitude": 49.973635, "time": "06/12/25,16:48:26", "speed": 124, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 6.06, "vehicle_direction": 182, "segment_bearing": 145.2, "nearest_segment": [[26.2446578, 49.9718382], [26.2407507, 49.9748698]], "closest_point": [26.242401336347445, 49.9735890369914], "angle_difference": null}, {"latitude": 26.23856, "longitude": 49.976705, "time": "06/12/25,16:59:47", "speed": 150, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 8.45, "vehicle_direction": 145, "segment_bearing": 325.1, "nearest_segment": [[26.2385397, 49.9768235], [26.2415708, 49.9744657]], "closest_point": [26.238609775926303, 49.97676899007983], "angle_difference": 0.1}, {"latitude": 26.238575, "longitude": 49.976978, "time": "06/12/25,16:59:50", "speed": 125, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 5.65, "vehicle_direction": 97, "segment_bearing": 55.0, "nearest_segment": [[26.2385397, 49.9768235], [26.2390935, 49.9777054]], "closest_point": [26.238619264905957, 49.97695020330546], "angle_difference": null}, {"latitude": 26.238522, "longitude": 49.97684, "time": "06/12/25,16:59:49", "speed": 123, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 0.22, "vehicle_direction": 119, "segment_bearing": 325.1, "nearest_segment": [[26.2356924, 49.9790383], [26.2385397, 49.9768235]], "closest_point": [26.23852067605322, 49.97683829796205], "angle_difference": 26.1}]; | |
// 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, data) { | |
var lat = data.latitude; | |
var lon = data.longitude; | |
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.device_name) { | |
html += '<tr><td>Vehicle:</td><td>' + data.device_name + '</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) { // This is street_name_en | |
html += '<tr><td>Street (EN):</td><td>' + data.street_name + '</td></tr>'; | |
} | |
if (data.distance_to_segment !== undefined) { | |
html += '<tr><td>Dist to street:</td><td>' + data.distance_to_segment.toFixed(2) + ' m</td></tr>'; | |
} | |
if (data.vehicle_direction !== undefined) { | |
html += '<tr><td>Vehicle Dir:</td><td>' + data.vehicle_direction.toFixed(1) + '°</td></tr>'; | |
} | |
if (data.segment_bearing !== undefined) { | |
html += '<tr><td>Street Bearing:</td><td>' + data.segment_bearing.toFixed(1) + '°</td></tr>'; | |
} | |
if (data.angle_difference !== undefined) { | |
html += '<tr><td>Direction Diff:</td><td>' + data.angle_difference.toFixed(1) + '°</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 < pathData.length; i++) { | |
var iconClass = ''; | |
var icon; | |
var data = pathData[i]; | |
data.device_name = "Testing Live Alerts"; // Add device name to each point's data | |
if (i === 0) { | |
iconClass = 'start-icon'; | |
icon = createNumberedIcon('S', iconClass); | |
} else if (i === latlngs.length - 1) { | |
iconClass = 'end-icon'; // End point is the violation point | |
icon = createNumberedIcon('V', iconClass); | |
} else { | |
icon = createNumberedIcon(i + 1); | |
} | |
var popupContent = createPopupContent(i + 1, data); | |
var vehicleMarker = L.marker([data.latitude, data.longitude], {icon: icon}) | |
.addTo(map) | |
.bindPopup(popupContent); | |
// Draw the nearest street segment for each point if available | |
if (data.nearest_segment && data.nearest_segment.length === 2) { | |
L.polyline(data.nearest_segment, { | |
color: 'red', | |
weight: 6, | |
opacity: 0.8 | |
}).addTo(map).bindPopup('Nearest Street Segment for Point ' + (i + 1)); | |
// Add start and end circles for the segment | |
L.circleMarker(data.nearest_segment[0], { radius: 4, color: 'black', fillColor: 'red', fillOpacity: 1 }).addTo(map); | |
L.circleMarker(data.nearest_segment[1], { radius: 4, color: 'black', fillColor: 'red', fillOpacity: 1 }).addTo(map); | |
} | |
// Draw the closest point on the segment and a line to it | |
if (data.closest_point && data.closest_point.length === 2) { | |
// Draw a small yellow circle at the closest point on the segment | |
L.circleMarker(data.closest_point, { radius: 4, color: 'black', fillColor: 'yellow', fillOpacity: 1 }).addTo(map); | |
// Draw a dashed line from the vehicle to the closest point | |
var line_to_closest = [ | |
[data.latitude, data.longitude], | |
data.closest_point | |
]; | |
L.polyline(line_to_closest, { | |
color: 'grey', | |
weight: 2, | |
opacity: 0.8, | |
dashArray: '5, 5' | |
}).addTo(map); | |
} | |
} | |
// 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: #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="background: #9b59b6; display: inline-block; width: 30px; height: 6px; border-radius: 3px; margin-right: 5px;"></span> Nearest Street Segment</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); | |
var legendContainer = legend.getContainer(); | |
// 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 < pathData.length; i++) { | |
var d = pathData[i]; | |
if (d.speed && d.speed_limit && d.speed > d.speed_limit) { | |
violationCount++; | |
} | |
} | |
div.innerHTML = '<b>Vehicle:</b> Testing Live Alerts<br>' + | |
'<b>Total Points:</b> ' + latlngs.length + '<br>' + | |
'<b>Violations on Path:</b> ' + violationCount; | |
return div; | |
}; | |
info.addTo(map); | |
// Legend toggle logic | |
var toggleButton = document.getElementById('legend-toggle'); | |
var legendVisible = true; | |
toggleButton.addEventListener('click', function() { | |
if (legendVisible) { | |
legendContainer.style.display = 'none'; | |
toggleButton.innerHTML = 'Show Legend'; | |
} else { | |
legendContainer.style.display = 'block'; | |
toggleButton.innerHTML = 'Hide Legend'; | |
} | |
legendVisible = !legendVisible; | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment