Skip to content

Instantly share code, notes, and snippets.

@youssef22222
Created June 12, 2025 14:02
Show Gist options
  • Save youssef22222/cd26d8b86d8c18ef4f26c15133780223 to your computer and use it in GitHub Desktop.
Save youssef22222/cd26d8b86d8c18ef4f26c15133780223 to your computer and use it in GitHub Desktop.
Speed Violation Map - 3181 BBD (CTS-OBD) - 1749736966
<!DOCTYPE html>
<html>
<head>
<title>Speed Violation Path - 3181 BBD (CTS-OBD)</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.22720955555555, 50.1873295], 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 and the detailed path data
var latlngs = [
[26.19293, 50.18789],
[26.193282, 50.188703],
[26.193307, 50.188125],
[26.1932, 50.188888],
[26.19337, 50.188308],
[26.193098, 50.188882],
[26.192238, 50.188272],
[26.191133, 50.188208],
[26.190352, 50.188242],
[26.182173, 50.18314],
[26.18267, 50.183473],
[26.181877, 50.182935],
[26.183195, 50.18382],
[26.181488, 50.182677],
[26.181035, 50.182613],
[26.18082, 50.182403],
[26.180887, 50.182523],
[26.181928, 50.1831],
[26.183125, 50.183933],
[26.216203, 50.196748],
[26.21806, 50.196538],
[26.218507, 50.196487],
[26.250717, 50.196963],
[26.28882, 50.180422],
[26.288353, 50.179485],
[26.287117, 50.179393],
[26.288757, 50.1809],
[26.287975, 50.17935],
[26.288588, 50.18138],
[26.288225, 50.182495],
[26.284733, 50.194095],
[26.285047, 50.193007],
[26.284468, 50.194607],
[26.284882, 50.193568],
[26.284322, 50.194932],
[26.282662, 50.197357]
];
var pathData = [{"latitude": 26.19293, "longitude": 50.18789, "time": "06/12/25,12:27:41", "speed": 107, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 6.52, "vehicle_direction": 118, "segment_bearing": 40.0, "nearest_segment": [[26.1924107, 50.1873188], [26.1934325, 50.1882757]], "closest_point": [26.1929723505454, 50.18784477710598], "angle_difference": null}, {"latitude": 26.193282, "longitude": 50.188703, "time": "06/12/25,16:50:14", "speed": 132, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 10.35, "vehicle_direction": 68, "segment_bearing": 127.1, "nearest_segment": [[26.1932545, 50.1885724], [26.193127, 50.1887602]], "closest_point": [26.19320248447077, 50.18864901581482], "angle_difference": null}, {"latitude": 26.193307, "longitude": 50.188125, "time": "06/12/25,16:50:13", "speed": 122, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 2.55, "vehicle_direction": 52, "segment_bearing": 40.0, "nearest_segment": [[26.1924107, 50.1873188], [26.1934325, 50.1882757]], "closest_point": [26.19329045005788, 50.18814267241181], "angle_difference": 12.0}, {"latitude": 26.1932, "longitude": 50.188888, "time": "06/12/25,16:50:14", "speed": 132, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 14.7, "vehicle_direction": 107, "segment_bearing": 132.8, "nearest_segment": [[26.193127, 50.1887602], [26.1930344, 50.1888718]], "closest_point": [26.193093962880017, 50.188800015794705], "angle_difference": 25.8}, {"latitude": 26.19337, "longitude": 50.188308, "time": "06/12/25,16:50:13", "speed": 131, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 6.98, "vehicle_direction": 57, "segment_bearing": 40.0, "nearest_segment": [[26.1924107, 50.1873188], [26.1934325, 50.1882757]], "closest_point": [26.193415317535088, 50.188259608885616], "angle_difference": 17.0}, {"latitude": 26.193098, "longitude": 50.188882, "time": "06/12/25,16:50:18", "speed": 105, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 5.92, "vehicle_direction": 105, "segment_bearing": 132.8, "nearest_segment": [[26.193127, 50.1887602], [26.1930344, 50.1888718]], "closest_point": [26.193055320614835, 50.18884658681841], "angle_difference": 27.8}, {"latitude": 26.192238, "longitude": 50.188272, "time": "06/12/25,16:50:31", "speed": 135, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 5.73, "vehicle_direction": 210, "segment_bearing": 30.0, "nearest_segment": [[26.1918386, 50.1880805], [26.1922287, 50.188332]], "closest_point": [26.192207944542954, 50.18831861882224], "angle_difference": 0.0}, {"latitude": 26.191133, "longitude": 50.188208, "time": "06/12/25,16:50:49", "speed": 126, "speed_limit": 40, "street_name": "", "street_name_ar": "", "distance_to_segment": 1.91, "vehicle_direction": 212, "segment_bearing": 121.5, "nearest_segment": [[26.1913841, 50.1877874], [26.1908701, 50.1887233]], "closest_point": [26.1911484459296, 50.188216482965935], "angle_difference": null}, {"latitude": 26.190352, "longitude": 50.188242, "time": "06/12/25,16:51:00", "speed": 124, "speed_limit": 100, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "distance_to_segment": 11.69, "vehicle_direction": 200, "segment_bearing": 210.9, "nearest_segment": [[26.1908701, 50.1887233], [26.190293, 50.188339]], "closest_point": [26.190293, 50.188339], "angle_difference": 10.9}, {"latitude": 26.182173, "longitude": 50.18314, "time": "06/12/25,16:52:03", "speed": 180, "speed_limit": 110, "street_name": "", "street_name_ar": "", "distance_to_segment": 9.02, "vehicle_direction": 209, "segment_bearing": 207.6, "nearest_segment": [[26.1822474, 50.1830818], [26.1815841, 50.1826953]], "closest_point": [26.18221717501753, 50.183064188126444], "angle_difference": 1.4}, {"latitude": 26.18267, "longitude": 50.183473, "time": "06/12/25,16:52:03", "speed": 185, "speed_limit": 100, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "distance_to_segment": 12.3, "vehicle_direction": 211, "segment_bearing": 208.2, "nearest_segment": [[26.183082, 50.1835795], [26.1822474, 50.1830818]], "closest_point": [26.182731229338042, 50.18337032367786], "angle_difference": 2.8}, {"latitude": 26.181877, "longitude": 50.182935, "time": "06/12/25,16:52:03", "speed": 175, "speed_limit": 110, "street_name": "", "street_name_ar": "", "distance_to_segment": 6.13, "vehicle_direction": 209, "segment_bearing": 207.6, "nearest_segment": [[26.1822474, 50.1830818], [26.1815841, 50.1826953]], "closest_point": [26.181907027595088, 50.18288346751922], "angle_difference": 1.4}, {"latitude": 26.183195, "longitude": 50.18382, "time": "06/12/25,16:52:03", "speed": 156, "speed_limit": 100, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "distance_to_segment": 13.24, "vehicle_direction": 213, "segment_bearing": 31.0, "nearest_segment": [[26.1820841, 50.1832309], [26.1867518, 50.1863531]], "closest_point": [26.183123843617924, 50.1839263790419], "angle_difference": 2.0}, {"latitude": 26.181488, "longitude": 50.182677, "time": "06/12/25,16:52:03", "speed": 168, "speed_limit": 110, "street_name": "", "street_name_ar": "", "distance_to_segment": 3.47, "vehicle_direction": 210, "segment_bearing": 208.3, "nearest_segment": [[26.1815841, 50.1826953], [26.1813499, 50.1825549]], "closest_point": [26.181505336006268, 50.182648081961055], "angle_difference": 1.7}, {"latitude": 26.181035, "longitude": 50.182613, "time": "06/12/25,16:52:15", "speed": 108, "speed_limit": 100, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "distance_to_segment": 3.44, "vehicle_direction": 66, "segment_bearing": 25.9, "nearest_segment": [[26.1808962, 50.1825761], [26.181726, 50.1830249]], "closest_point": [26.18101902766467, 50.18264253173765], "angle_difference": null}, {"latitude": 26.18082, "longitude": 50.182403, "time": "06/12/25,16:52:14", "speed": 114, "speed_limit": 110, "street_name": "", "street_name_ar": "", "distance_to_segment": 14.59, "vehicle_direction": 159, "segment_bearing": 104.9, "nearest_segment": [[26.1809607, 50.1823573], [26.1809511, 50.1823976]], "closest_point": [26.1809511, 50.1823976], "angle_difference": null}, {"latitude": 26.180887, "longitude": 50.182523, "time": "06/12/25,16:52:14", "speed": 110, "speed_limit": 100, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "distance_to_segment": 4.81, "vehicle_direction": 109, "segment_bearing": 16.3, "nearest_segment": [[26.18068, 50.1825057], [26.1808962, 50.1825761]], "closest_point": [26.180872248907786, 50.182568300939444], "angle_difference": null}, {"latitude": 26.181928, "longitude": 50.1831, "time": "06/12/25,16:52:15", "speed": 124, "speed_limit": 110, "street_name": "", "street_name_ar": "", "distance_to_segment": 0.82, "vehicle_direction": 41, "segment_bearing": 36.9, "nearest_segment": [[26.1817345, 50.1829483], [26.182046, 50.183209]], "closest_point": [26.18192295827839, 50.18310602415145], "angle_difference": 4.1}, {"latitude": 26.183125, "longitude": 50.183933, "time": "06/12/25,16:52:21", "speed": 164, "speed_limit": 100, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "distance_to_segment": 0.5, "vehicle_direction": 26, "segment_bearing": 31.0, "nearest_segment": [[26.1820841, 50.1832309], [26.1867518, 50.1863531]], "closest_point": [26.183127702280554, 50.183928960081055], "angle_difference": 5.0}, {"latitude": 26.216203, "longitude": 50.196748, "time": "06/12/25,16:55:07", "speed": 185, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "distance_to_segment": 1.48, "vehicle_direction": 353, "segment_bearing": 354.4, "nearest_segment": [[26.2161013, 50.1967442], [26.217554, 50.1965849]], "closest_point": [26.21620137985479, 50.196733225455446], "angle_difference": 1.4}, {"latitude": 26.21806, "longitude": 50.196538, "time": "06/12/25,16:55:15", "speed": 181, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "distance_to_segment": 0.9, "vehicle_direction": 355, "segment_bearing": 354.3, "nearest_segment": [[26.217554, 50.1965849], [26.2182769, 50.196505]], "closest_point": [26.218059014348228, 50.19652908225699], "angle_difference": 0.7}, {"latitude": 26.218507, "longitude": 50.196487, "time": "06/12/25,16:55:18", "speed": 189, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "distance_to_segment": 0.71, "vehicle_direction": 354, "segment_bearing": 354.4, "nearest_segment": [[26.2182769, 50.196505], [26.221408, 50.1961629]], "closest_point": [26.21850622904858, 50.1964799438001], "angle_difference": 0.4}, {"latitude": 26.250717, "longitude": 50.196963, "time": "06/12/25,16:57:25", "speed": 201, "speed_limit": 110, "street_name": "King Khaled Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u0627\u0644\u0645\u0644\u0643 \u062e\u0627\u0644\u062f", "distance_to_segment": 0.02, "vehicle_direction": 345, "segment_bearing": 344.6, "nearest_segment": [[26.249619, 50.1973004], [26.25072, 50.1969619]], "closest_point": [26.2507169500969, 50.196962837685916], "angle_difference": 0.4}, {"latitude": 26.28882, "longitude": 50.180422, "time": "06/12/25,17:00:44", "speed": 153, "speed_limit": 80, "street_name": "Custodian of the Two Holly Mosques Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u062e\u0627\u062f\u0645 \u0627\u0644\u062d\u0631\u0645\u064a\u0646 \u0627\u0644\u0634\u0631\u064a\u0641\u064a\u0646", "distance_to_segment": 5.58, "vehicle_direction": 30, "segment_bearing": 286.7, "nearest_segment": [[26.2881951, 50.1829464], [26.2888942, 50.1803403]], "closest_point": [26.28886877374481, 50.180435083812974], "angle_difference": null}, {"latitude": 26.288353, "longitude": 50.179485, "time": "06/12/25,17:00:44", "speed": 160, "speed_limit": 50, "street_name": "", "street_name_ar": "", "distance_to_segment": 13.16, "vehicle_direction": 5, "segment_bearing": 47.1, "nearest_segment": [[26.2882788, 50.1795879], [26.2883792, 50.1797086]], "closest_point": [26.2882788, 50.1795879], "angle_difference": null}, {"latitude": 26.287117, "longitude": 50.179393, "time": "06/12/25,17:00:44", "speed": 171, "speed_limit": 50, "street_name": "", "street_name_ar": "", "distance_to_segment": 1.22, "vehicle_direction": 340, "segment_bearing": 0.1, "nearest_segment": [[26.2867917, 50.1793801], [26.287269, 50.179381]], "closest_point": [26.28711702316763, 50.17938071343149], "angle_difference": 20.1}, {"latitude": 26.288757, "longitude": 50.1809, "time": "06/12/25,17:00:44", "speed": 152, "speed_limit": 80, "street_name": "Custodian of the Two Holly Mosques Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u062e\u0627\u062f\u0645 \u0627\u0644\u062d\u0631\u0645\u064a\u0646 \u0627\u0644\u0634\u0631\u064a\u0641\u064a\u0646", "distance_to_segment": 1.38, "vehicle_direction": 63, "segment_bearing": 286.7, "nearest_segment": [[26.2881951, 50.1829464], [26.2888942, 50.1803403]], "closest_point": [26.28874492636729, 50.18089676118467], "angle_difference": null}, {"latitude": 26.287975, "longitude": 50.17935, "time": "06/12/25,17:00:44", "speed": 162, "speed_limit": 50, "street_name": "", "street_name_ar": "", "distance_to_segment": 1.92, "vehicle_direction": 355, "segment_bearing": 26.4, "nearest_segment": [[26.287936, 50.1793498], [26.2880332, 50.1794037]], "closest_point": [26.287965912740255, 50.1793663874146], "angle_difference": null}, {"latitude": 26.288588, "longitude": 50.18138, "time": "06/12/25,17:00:48", "speed": 150, "speed_limit": 80, "street_name": "Custodian of the Two Holly Mosques Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u062e\u0627\u062f\u0645 \u0627\u0644\u062d\u0631\u0645\u064a\u0646 \u0627\u0644\u0634\u0631\u064a\u0641\u064a\u0646", "distance_to_segment": 2.91, "vehicle_direction": 85, "segment_bearing": 286.7, "nearest_segment": [[26.2881951, 50.1829464], [26.2888942, 50.1803403]], "closest_point": [26.28861346270106, 50.181386830503165], "angle_difference": 21.7}, {"latitude": 26.288225, "longitude": 50.182495, "time": "06/12/25,17:00:48", "speed": 168, "speed_limit": 80, "street_name": "Custodian of the Two Holly Mosques Road", "street_name_ar": "\u0637\u0631\u064a\u0642 \u062e\u0627\u062f\u0645 \u0627\u0644\u062d\u0631\u0645\u064a\u0646 \u0627\u0644\u0634\u0631\u064a\u0641\u064a\u0646", "distance_to_segment": 7.45, "vehicle_direction": 102, "segment_bearing": 106.4, "nearest_segment": [[26.2884678, 50.1813137], [26.287895, 50.1834783]], "closest_point": [26.288159770152483, 50.182477738770835], "angle_difference": 4.4}, {"latitude": 26.284733, "longitude": 50.194095, "time": "06/12/25,17:01:49", "speed": 167, "speed_limit": 90, "street_name": "", "street_name_ar": "", "distance_to_segment": 3.65, "vehicle_direction": 108, "segment_bearing": 112.3, "nearest_segment": [[26.2848734, 50.1938096], [26.2844541, 50.1949488]], "closest_point": [26.284764136090175, 50.19410646011465], "angle_difference": 4.3}, {"latitude": 26.285047, "longitude": 50.193007, "time": "06/12/25,17:01:49", "speed": 178, "speed_limit": 80, "street_name": "Custodian of the Two Holy Mosques Road", "street_name_ar": "\u0637\u0631\u0642 \u062e\u0627\u062f\u0645 \u0627\u0644\u062d\u0631\u0645\u064a\u0646 \u0627\u0644\u0634\u0631\u064a\u0641\u064a\u0646", "distance_to_segment": 6.56, "vehicle_direction": 108, "segment_bearing": 108.1, "nearest_segment": [[26.2860426, 50.1898255], [26.2848734, 50.1938096]], "closest_point": [26.285104025087513, 50.19302373495453], "angle_difference": 0.1}, {"latitude": 26.284468, "longitude": 50.194607, "time": "06/12/25,17:01:49", "speed": 164, "speed_limit": 60, "street_name": "", "street_name_ar": "", "distance_to_segment": 0.81, "vehicle_direction": 110, "segment_bearing": 109.6, "nearest_segment": [[26.2847807, 50.1936532], [26.2843171, 50.1951032]], "closest_point": [26.28447502862629, 50.19460924722148], "angle_difference": 0.4}, {"latitude": 26.284882, "longitude": 50.193568, "time": "06/12/25,17:01:49", "speed": 172, "speed_limit": 80, "street_name": "Custodian of the Two Holy Mosques Road", "street_name_ar": "\u0637\u0631\u0642 \u062e\u0627\u062f\u0645 \u0627\u0644\u062d\u0631\u0645\u064a\u0646 \u0627\u0644\u0634\u0631\u064a\u0641\u064a\u0646", "distance_to_segment": 6.6, "vehicle_direction": 107, "segment_bearing": 108.1, "nearest_segment": [[26.2860426, 50.1898255], [26.2848734, 50.1938096]], "closest_point": [26.284939361400355, 50.19358483365109], "angle_difference": 1.1}, {"latitude": 26.284322, "longitude": 50.194932, "time": "06/12/25,17:01:49", "speed": 164, "speed_limit": 60, "street_name": "", "street_name_ar": "", "distance_to_segment": 5.23, "vehicle_direction": 113, "segment_bearing": 109.6, "nearest_segment": [[26.2847807, 50.1936532], [26.2843171, 50.1951032]], "closest_point": [26.284367214760262, 50.19494645625025], "angle_difference": 3.4}, {"latitude": 26.282662, "longitude": 50.197357, "time": "06/12/25,17:02:22", "speed": 120, "speed_limit": 60, "street_name": "Riyadh Street", "street_name_ar": "\u0634\u0627\u0631\u0639 \u0627\u0644\u0631\u064a\u0627\u0636", "distance_to_segment": 4.58, "vehicle_direction": 182, "segment_bearing": 190.9, "nearest_segment": [[26.2827536, 50.1973299], [26.2823688, 50.1972474]], "closest_point": [26.282671580288365, 50.19731231521255], "angle_difference": 8.9}];
// 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 = "3181 BBD (CTS-OBD)"; // 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> 3181 BBD (CTS-OBD)<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