Drawing and deleting routes
This commit is contained in:
parent
34dce12339
commit
99c6e93b4b
|
|
@ -8,6 +8,8 @@
|
||||||
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
|
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<!-- Leaflet CSS -->
|
<!-- Leaflet CSS -->
|
||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
|
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/leaflet-draw/dist/leaflet.draw.css" />
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.css" />
|
||||||
<style>
|
<style>
|
||||||
body, html {
|
body, html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
@ -45,11 +47,21 @@
|
||||||
<input type="file" id="fileInput" class="d-none" webkitdirectory mozdirectory>
|
<input type="file" id="fileInput" class="d-none" webkitdirectory mozdirectory>
|
||||||
<button class="list-group-item list-group-item-action" onclick="document.getElementById('fileInput').click();">Load GTFS from computer</button>
|
<button class="list-group-item list-group-item-action" onclick="document.getElementById('fileInput').click();">Load GTFS from computer</button>
|
||||||
<button class="list-group-item list-group-item-action" onclick="importGTFS()">Import existing GTFS</button>
|
<button class="list-group-item list-group-item-action" onclick="importGTFS()">Import existing GTFS</button>
|
||||||
<div id="currentGTFS">
|
|
||||||
<h6>Current GTFS</h6>
|
|
||||||
<!-- Route IDs will be inserted here -->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<h5 id="currentGTFS">
|
||||||
|
Current GTFS
|
||||||
|
<h6 id="newShape">
|
||||||
|
<button class="list-group-item list-group-item-action" onclick="addNewShape()">Add New Shape</button>
|
||||||
|
</h6>
|
||||||
|
<h6 id="chosenShape">
|
||||||
|
Chosen Shape
|
||||||
|
<!-- Shape options will be inserted here -->
|
||||||
|
</h6>
|
||||||
|
<h6 id="currentRoutes">
|
||||||
|
Current GTFS
|
||||||
|
<!-- Route IDs will be inserted here -->
|
||||||
|
</h6>
|
||||||
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|
@ -81,6 +93,10 @@
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
||||||
<!-- Leaflet JS -->
|
<!-- Leaflet JS -->
|
||||||
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
||||||
|
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
||||||
|
<script src="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.js"></script>
|
||||||
|
<script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>
|
||||||
|
<script src="https://unpkg.com/leaflet-draw/dist/leaflet.draw.js"></script>
|
||||||
<script>
|
<script>
|
||||||
// Initialize the map centered on Toruń, Poland
|
// Initialize the map centered on Toruń, Poland
|
||||||
var map = L.map('map').setView([53.0138, 18.5984], 13);
|
var map = L.map('map').setView([53.0138, 18.5984], 13);
|
||||||
|
|
@ -89,9 +105,246 @@
|
||||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
maxZoom: 19,
|
maxZoom: 19,
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
|
||||||
|
// Assuming route is an array of objects with lon and lat properties
|
||||||
|
// Given route coordinates
|
||||||
|
// Given route coordinates
|
||||||
|
const route = [
|
||||||
|
{ lat: 53.015498, lon: 18.548179, stop: true },
|
||||||
|
{ lat: 53.0155061509397, lon: 18.5483665019274, stop: false },
|
||||||
|
{ lat: 53.0154795263022, lon: 18.5488848388195, stop: false },
|
||||||
|
{ lat: 53.0153786752536, lon: 18.5508066415787, stop: false },
|
||||||
|
{ lat: 53.0152608809305, lon: 18.5528719425201, stop: false },
|
||||||
|
{ lat: 53.0152253812084, lon: 18.5534271597862, stop: false },
|
||||||
|
{ lat: 53.0150269049514, lon: 18.5555809736252, stop: false },
|
||||||
|
{ lat: 53.014975, lon: 18.55602, stop: false },
|
||||||
|
{ lat: 53.0149397687454, lon: 18.5565304756165, stop: false },
|
||||||
|
{ lat: 53.0148816778436, lon: 18.5571071505547, stop: false },
|
||||||
|
{ lat: 53.0148155186657, lon: 18.5575430095196, stop: false },
|
||||||
|
{ lat: 53.014707404669, lon: 18.558078110218, stop: false },
|
||||||
|
{ lat: 53.0145960631056, lon: 18.5584764182568, stop: false },
|
||||||
|
{ lat: 53.0144782666461, lon: 18.5588613152504, stop: false },
|
||||||
|
{ lat: 53.0143330376918, lon: 18.559333384037, stop: false },
|
||||||
|
{ lat: 53.0141047045143, lon: 18.5600320994854, stop: false },
|
||||||
|
{ lat: 53.0140401578139, lon: 18.5602413117886, stop: false },
|
||||||
|
{ lat: 53.013946968345, lon: 18.5605558007956, stop: false },
|
||||||
|
{ lat: 53.01379, lon: 18.56118, stop: false },
|
||||||
|
{ lat: 53.0137287186281, lon: 18.5616239905357, stop: false },
|
||||||
|
{ lat: 53.0136657850481, lon: 18.5622046887875, stop: false },
|
||||||
|
{ lat: 53.0136310908558, lon: 18.5627853870392, stop: false },
|
||||||
|
{ lat: 53.0136302840138, lon: 18.5634854435921, stop: false },
|
||||||
|
{ lat: 53.0136294771718, lon: 18.5643585026264, stop: false },
|
||||||
|
{ lat: 53.0136359319076, lon: 18.5656929016113, stop: false },
|
||||||
|
{ lat: 53.013623, lon: 18.566067, stop: false },
|
||||||
|
{ lat: 53.0136472276929, lon: 18.5697859525681, stop: false },
|
||||||
|
{ lat: 53.013666, lon: 18.570766, stop: false },
|
||||||
|
{ lat: 53.0136940244864, lon: 18.5711324214935, stop: false },
|
||||||
|
{ lat: 53.0137174228641, lon: 18.5718646645546, stop: false },
|
||||||
|
{ lat: 53.0137279117879, lon: 18.5728490352631, stop: false },
|
||||||
|
{ lat: 53.0137569580252, lon: 18.5748016834259, stop: false },
|
||||||
|
{ lat: 53.0138279598562, lon: 18.5799622535706, stop: false },
|
||||||
|
{ lat: 53.0138271530179, lon: 18.5806059837341, stop: false },
|
||||||
|
{ lat: 53.013829, lon: 18.581098, stop: false },
|
||||||
|
{ lat: 53.0138465171337, lon: 18.5817566514015, stop: false },
|
||||||
|
{ lat: 53.0138731427787, lon: 18.5820704698563, stop: false },
|
||||||
|
{ lat: 53.013915905144, lon: 18.5823293030262, stop: false },
|
||||||
|
{ lat: 53.0139990092421, lon: 18.5826712846756, stop: false },
|
||||||
|
{ lat: 53.0141377846607, lon: 18.5830146074295, stop: false },
|
||||||
|
{ lat: 53.0143023781834, lon: 18.5833364725113, stop: false },
|
||||||
|
{ lat: 53.0147412911747, lon: 18.5841679573059, stop: false },
|
||||||
|
{ lat: 53.0149058823955, lon: 18.5845327377319, stop: false },
|
||||||
|
{ lat: 53.0149736550686, lon: 18.5848170518875, stop: false },
|
||||||
|
{ lat: 53.0150059277327, lon: 18.5851013660431, stop: false },
|
||||||
|
{ lat: 53.0149768823361, lon: 18.5854822397232, stop: false },
|
||||||
|
{ lat: 53.0149381551103, lon: 18.5858201980591, stop: false },
|
||||||
|
{ lat: 53.0148832914808, lon: 18.5861045122147, stop: false },
|
||||||
|
{ lat: 53.0147412911747, lon: 18.5865873098373, stop: false },
|
||||||
|
{ lat: 53.0144766529938, lon: 18.5873705148697, stop: false },
|
||||||
|
{ lat: 53.0143185147695, lon: 18.5879445075989, stop: false },
|
||||||
|
{ lat: 53.0142475137456, lon: 18.588320016861, stop: false },
|
||||||
|
{ lat: 53.0142216951625, lon: 18.5889208316803, stop: false },
|
||||||
|
{ lat: 53.014231377133, lon: 18.5903531312943, stop: false },
|
||||||
|
{ lat: 53.014179739932, lon: 18.591029047966, stop: false },
|
||||||
|
{ lat: 53.014093, lon: 18.591931, stop: false },
|
||||||
|
{ lat: 53.0140635560039, lon: 18.5925793647766, stop: false },
|
||||||
|
{ lat: 53.0138634607279, lon: 18.5950094461441, stop: false },
|
||||||
|
{ lat: 53.0137860042429, lon: 18.5960957407951, stop: false },
|
||||||
|
{ lat: 53.0137884247602, lon: 18.5964578390121, stop: false },
|
||||||
|
{ lat: 53.013811016248, lon: 18.5968963801861, stop: false },
|
||||||
|
{ lat: 53.013823118826, lon: 18.5972410440445, stop: false },
|
||||||
|
{ lat: 53.0138626538902, lon: 18.5976192355156, stop: false },
|
||||||
|
{ lat: 53.0138743530349, lon: 18.5977774858475, stop: false },
|
||||||
|
{ lat: 53.0138929102925, lon: 18.5980108380318, stop: false },
|
||||||
|
{ lat: 53.0139522127793, lon: 18.5982844233513, stop: false },
|
||||||
|
{ lat: 53.0140054639226, lon: 18.5985177755356, stop: false },
|
||||||
|
{ lat: 53.0141829672589, lon: 18.5990703105927, stop: false },
|
||||||
|
{ lat: 53.0145186079356, lon: 18.5998964309692, stop: false },
|
||||||
|
{ lat: 53.014776791295, lon: 18.600577712059, stop: false },
|
||||||
|
{ lat: 53.0149026551227, lon: 18.6009210348129, stop: false },
|
||||||
|
{ lat: 53.0150091549978, lon: 18.6013180017471, stop: false },
|
||||||
|
{ lat: 53.015039, lon: 18.601521, stop: false },
|
||||||
|
{ lat: 53.0150914501758, lon: 18.601650595665, stop: false },
|
||||||
|
{ lat: 53.0151769724494, lon: 18.6019402742386, stop: false },
|
||||||
|
{ lat: 53.0153157440799, lon: 18.6025303602219, stop: false },
|
||||||
|
{ lat: 53.0159063253302, lon: 18.6050033569336, stop: false },
|
||||||
|
{ lat: 53.0159595740621, lon: 18.6051052808762, stop: false },
|
||||||
|
{ lat: 53.016212908038, lon: 18.6057087779045, stop: false },
|
||||||
|
{ lat: 53.016392015875, lon: 18.6062023043633, stop: false },
|
||||||
|
{ lat: 53.0167034358397, lon: 18.6071813106537, stop: false },
|
||||||
|
{ lat: 53.0168970637, lon: 18.6077579855919, stop: false },
|
||||||
|
{ lat: 53.0172342968156, lon: 18.6090561747551, stop: false },
|
||||||
|
{ lat: 53.0178200112259, lon: 18.6114004254341, stop: false },
|
||||||
|
{ lat: 53.017955, lon: 18.61257, stop: false },
|
||||||
|
{ lat: 53.0180571990971, lon: 18.6132296919823, stop: false },
|
||||||
|
{ lat: 53.0180975370407, lon: 18.6134120821953, stop: false },
|
||||||
|
{ lat: 53.0182330722551, lon: 18.6135971546173, stop: false },
|
||||||
|
{ lat: 53.0183702205505, lon: 18.6136749386787, stop: false },
|
||||||
|
{ lat: 53.0185638409312, lon: 18.6137366294861, stop: false },
|
||||||
|
{ lat: 53.018813932637, lon: 18.61372590065, stop: false },
|
||||||
|
{ lat: 53.0190462746003, lon: 18.6136186122894, stop: false },
|
||||||
|
{ lat: 53.0198610750697, lon: 18.6131680011749, stop: false },
|
||||||
|
{ lat: 53.0206968346139, lon: 18.6127656698227, stop: false },
|
||||||
|
{ lat: 53.020924326204, lon: 18.6126691102982, stop: false },
|
||||||
|
{ lat: 53.021166337217, lon: 18.6126852035522, stop: false },
|
||||||
|
{ lat: 53.0213776923911, lon: 18.6128380894661, stop: false },
|
||||||
|
{ lat: 53.021561, lon: 18.61306, stop: false },
|
||||||
|
{ lat: 53.0225732010204, lon: 18.6140289902687, stop: false },
|
||||||
|
{ lat: 53.0226667751966, lon: 18.6141550540924, stop: false },
|
||||||
|
{ lat: 53.0227329223366, lon: 18.6142757534981, stop: false },
|
||||||
|
{ lat: 53.0228281095064, lon: 18.6145010590553, stop: false },
|
||||||
|
{ lat: 53.0231007631186, lon: 18.6154532432556, stop: false },
|
||||||
|
{ lat: 53.0233121088159, lon: 18.6160218715668, stop: false },
|
||||||
|
{ lat: 53.0233766416468, lon: 18.616236448288, stop: false },
|
||||||
|
{ lat: 53.0236105723499, lon: 18.617859184742, stop: false },
|
||||||
|
{ lat: 53.023596, lon: 18.617925, stop: false },
|
||||||
|
{ lat: 53.0236589716473, lon: 18.6182025074959, stop: false },
|
||||||
|
{ lat: 53.0240042183936, lon: 18.6206004023552, stop: false },
|
||||||
|
{ lat: 53.0243446225271, lon: 18.6229392886162, stop: false },
|
||||||
|
{ lat: 53.024355, lon: 18.623137, stop: false },
|
||||||
|
{ lat: 53.0244172202175, lon: 18.6234569549561, stop: false },
|
||||||
|
{ lat: 53.0245866143533, lon: 18.6245834827423, stop: false },
|
||||||
|
{ lat: 53.0248173119636, lon: 18.6261793971062, stop: false },
|
||||||
|
{ lat: 53.0248770027528, lon: 18.6267426609993, stop: false },
|
||||||
|
{ lat: 53.0249044282228, lon: 18.6272844672203, stop: false },
|
||||||
|
{ lat: 53.0248866823325, lon: 18.6278986930847, stop: false },
|
||||||
|
{ lat: 53.0248657099071, lon: 18.6282339692116, stop: false },
|
||||||
|
{ lat: 53.0248156986979, lon: 18.6286067962646, stop: false },
|
||||||
|
{ lat: 53.024689863786, lon: 18.629746735096, stop: false },
|
||||||
|
{ lat: 53.0245382160966, lon: 18.6309456825256, stop: false },
|
||||||
|
{ lat: 53.0243494623769, lon: 18.632450401783, stop: false },
|
||||||
|
{ lat: 53.0243284896904, lon: 18.6327347159386, stop: false },
|
||||||
|
{ lat: 53.0243510756601, lon: 18.6329787969589, stop: false },
|
||||||
|
{ lat: 53.0244285131806, lon: 18.6332631111145, stop: false },
|
||||||
|
{ lat: 53.0245382160966, lon: 18.6334374547005, stop: false },
|
||||||
|
{ lat: 53.0248818425429, lon: 18.6338827013969, stop: false },
|
||||||
|
{ lat: 53.0249608923709, lon: 18.6340570449829, stop: false },
|
||||||
|
{ lat: 53.0252238530014, lon: 18.6343467235565, stop: false },
|
||||||
|
{ lat: 53.0255368224599, lon: 18.6348643898964, stop: false },
|
||||||
|
{ lat: 53.0261401695438, lon: 18.6358863115311, stop: false },
|
||||||
|
{ lat: 53.0273194144766, lon: 18.6379784345627, stop: false },
|
||||||
|
{ lat: 53.0284873352723, lon: 18.6399900913239, stop: false },
|
||||||
|
{ lat: 53.0290357954512, lon: 18.640918135643, stop: false },
|
||||||
|
{ lat: 53.0293326062866, lon: 18.6414679884911, stop: false },
|
||||||
|
{ lat: 53.029613, lon: 18.642062, stop: false },
|
||||||
|
{ lat: 53.0297358786052, lon: 18.6422833800316, stop: false },
|
||||||
|
{ lat: 53.0298875080216, lon: 18.6425060033798, stop: false },
|
||||||
|
{ lat: 53.030047202256, lon: 18.6426830291748, stop: false },
|
||||||
|
{ lat: 53.0304585331672, lon: 18.6433508992195, stop: false },
|
||||||
|
{ lat: 53.0312456966792, lon: 18.6447349190712, stop: false },
|
||||||
|
{ lat: 53.0326973949821, lon: 18.6473366618156, stop: false },
|
||||||
|
{ lat: 53.0329312751379, lon: 18.6478275060654, stop: false },
|
||||||
|
{ lat: 53.033373224521, lon: 18.6488091945648, stop: false },
|
||||||
|
{ lat: 53.0337700073347, lon: 18.6497667431831, stop: false },
|
||||||
|
{ lat: 53.034585, lon: 18.652202, stop: false },
|
||||||
|
{ lat: 53.0348103351817, lon: 18.6528244614601, stop: false },
|
||||||
|
{ lat: 53.0350071075487, lon: 18.6533984541893, stop: false },
|
||||||
|
{ lat: 53.0355458076316, lon: 18.6549916863441, stop: false },
|
||||||
|
{ lat: 53.0360490183959, lon: 18.6564803123474, stop: false },
|
||||||
|
{ lat: 53.0363490066345, lon: 18.6574995517731, stop: false },
|
||||||
|
{ lat: 53.036634477375, lon: 18.658752143383, stop: false },
|
||||||
|
{ lat: 53.036779631264, lon: 18.6595916748047, stop: false },
|
||||||
|
{ lat: 53.036913494973, lon: 18.6604714393616, stop: false },
|
||||||
|
{ lat: 53.0369796202662, lon: 18.6611768603325, stop: false },
|
||||||
|
{ lat: 53.037042, lon: 18.662501, stop: false },
|
||||||
|
{ lat: 53.037087678454, lon: 18.6630356311798, stop: false },
|
||||||
|
{ lat: 53.0370844528404, lon: 18.6644732952118, stop: false },
|
||||||
|
{ lat: 53.0370650991536, lon: 18.6653906106949, stop: false },
|
||||||
|
{ lat: 53.0370538094989, lon: 18.6655354499817, stop: false },
|
||||||
|
{ lat: 53.0369957483712, lon: 18.6657473444939, stop: false },
|
||||||
|
{ lat: 53.0368941412094, lon: 18.6659109592438, stop: false },
|
||||||
|
{ lat: 53.0367812440823, lon: 18.6660236120224, stop: false },
|
||||||
|
{ lat: 53.0366635081919, lon: 18.6660584807396, stop: false },
|
||||||
|
{ lat: 53.03626836484, lon: 18.6660531163216, stop: false },
|
||||||
|
{ lat: 53.0360667596939, lon: 18.6660772562027, stop: false },
|
||||||
|
{ lat: 53.035969988889, lon: 18.666130900383, stop: false },
|
||||||
|
{ lat: 53.0359119263018, lon: 18.6662194132805, stop: false },
|
||||||
|
{ lat: 53.0358716050147, lon: 18.666318655014, stop: false },
|
||||||
|
{ lat: 53.0358522507835, lon: 18.6664044857025, stop: false },
|
||||||
|
{ lat: 53.0358425736646, lon: 18.666487634182, stop: false },
|
||||||
|
{ lat: 53.0358457993711, lon: 18.6665761470795, stop: false },
|
||||||
|
{ lat: 53.0358490250774, lon: 18.6666512489319, stop: false },
|
||||||
|
{ lat: 53.0358828949789, lon: 18.6667665839195, stop: false },
|
||||||
|
{ lat: 53.0359409576052, lon: 18.6668872833252, stop: false },
|
||||||
|
{ lat: 53.0360135357781, lon: 18.6669623851776, stop: false },
|
||||||
|
{ lat: 53.0360909523612, lon: 18.6669918894768, stop: false },
|
||||||
|
{ lat: 53.0361586917574, lon: 18.6669918894768, stop: false },
|
||||||
|
{ lat: 53.0362425594339, lon: 18.6669623851776, stop: false },
|
||||||
|
{ lat: 53.0363183627703, lon: 18.6668953299522, stop: false },
|
||||||
|
{ lat: 53.0367167313055, lon: 18.6663025617599, stop: true },
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
const stops = route.filter(point => point.stop).map(point => [point.lat, point.lon]);
|
||||||
|
|
||||||
|
/*if (stops.length < 2) {
|
||||||
|
console.error('Not enough stops to calculate route');
|
||||||
|
} else {
|
||||||
|
const coordinates = stops.map(stop => stop.join(',')).join(';');
|
||||||
|
|
||||||
|
axios.get(`http://router.project-osrm.org/route/v1/driving/${coordinates}?overview=full&geometries=geojson`)
|
||||||
|
.then(response => {
|
||||||
|
const route = response.data.routes[0];
|
||||||
|
const routeLine = L.geoJSON(route.geometry).addTo(map);
|
||||||
|
map.fitBounds(routeLine.getBounds());
|
||||||
|
|
||||||
|
stops.forEach(stop => {
|
||||||
|
L.marker(stop).addTo(map);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error fetching route from OSRM', error);
|
||||||
|
});
|
||||||
|
}*/
|
||||||
|
|
||||||
let routesData = [];
|
let routesData = [];
|
||||||
let tripsData = [];
|
let tripsData = [];
|
||||||
|
// Holder of currently inspected shape ID value
|
||||||
|
let currentShapeID = null;
|
||||||
|
// Create empty dictionary for shapes to be displayed.
|
||||||
|
let shapes = {};
|
||||||
|
// Total number of newly defined Shapes
|
||||||
|
// In a mature version the indexing has to be changed.
|
||||||
|
let numNewShapes = 0;
|
||||||
|
// Current layer that can be saved or discarded
|
||||||
|
let currentLayer = null;
|
||||||
|
|
||||||
|
// Setting up the drawing control
|
||||||
|
|
||||||
|
// FeatureGroup to store editable layers
|
||||||
|
var drawnItems = new L.FeatureGroup();
|
||||||
|
map.addLayer(drawnItems);
|
||||||
|
|
||||||
|
// Set up the drawing control
|
||||||
|
var drawControl = new L.Control.Draw({
|
||||||
|
position: 'topright', // Adds the drawing control on the right
|
||||||
|
edit: {
|
||||||
|
featureGroup: drawnItems
|
||||||
|
},
|
||||||
|
draw: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// Polyline drawer that will be used
|
||||||
|
let polylineDrawer = new L.Draw.Polyline(map, drawControl.options.polyline);
|
||||||
|
|
||||||
document.getElementById('fileInput').addEventListener('change', handleFileSelect, false);
|
document.getElementById('fileInput').addEventListener('change', handleFileSelect, false);
|
||||||
|
|
||||||
|
|
@ -117,6 +370,21 @@
|
||||||
tripsReader.readAsText(tripsFile);
|
tripsReader.readAsText(tripsFile);
|
||||||
} else {
|
} else {
|
||||||
alert('Please select a valid GTFS folder containing routes.txt and trips.txt.');
|
alert('Please select a valid GTFS folder containing routes.txt and trips.txt.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle shapes file
|
||||||
|
let shapesFile;
|
||||||
|
for (let file of files) {
|
||||||
|
if (file.name === 'shapes.txt') {
|
||||||
|
shapesFile = file;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shapesFile) {
|
||||||
|
// Parse shapes.txt file and draw on the map
|
||||||
|
parseShapesFile(shapesFile);
|
||||||
|
} else {
|
||||||
|
alert('shapes.txt file not found in the selected folder.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,7 +401,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayRouteIds(routes) {
|
function displayRouteIds(routes) {
|
||||||
const currentGTFS = document.getElementById('currentGTFS');
|
const currentRoutes = document.getElementById('currentRoutes');
|
||||||
const routeList = document.createElement('div');
|
const routeList = document.createElement('div');
|
||||||
routeList.className = 'list-group';
|
routeList.className = 'list-group';
|
||||||
routes.forEach(route => {
|
routes.forEach(route => {
|
||||||
|
|
@ -143,7 +411,7 @@
|
||||||
routeItem.onclick = () => showTrips(route.route_id);
|
routeItem.onclick = () => showTrips(route.route_id);
|
||||||
routeList.appendChild(routeItem);
|
routeList.appendChild(routeItem);
|
||||||
});
|
});
|
||||||
currentGTFS.appendChild(routeList);
|
currentRoutes.appendChild(routeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showTrips(routeId) {
|
function showTrips(routeId) {
|
||||||
|
|
@ -181,6 +449,383 @@
|
||||||
|
|
||||||
$('#tripsModal').modal('show');
|
$('#tripsModal').modal('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to parse shapes.txt file and draw shapes on the map
|
||||||
|
function parseShapesFile(file) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = function(event) {
|
||||||
|
const text = event.target.result;
|
||||||
|
const lines = text.split('\n');
|
||||||
|
const headers = lines[0].split(',');
|
||||||
|
const shapeIdIndex = headers.indexOf('shape_id');
|
||||||
|
const shapePtSequenceIndex = headers.indexOf('shape_pt_sequence');
|
||||||
|
const shapePtLatIndex = headers.indexOf('shape_pt_lat');
|
||||||
|
const shapePtLonIndex = headers.indexOf('shape_pt_lon');
|
||||||
|
|
||||||
|
for (let i = 1; i < lines.length; i++) {
|
||||||
|
const line = lines[i].trim();
|
||||||
|
if (line) {
|
||||||
|
const columns = line.split(',');
|
||||||
|
const shape_id = columns[shapeIdIndex];
|
||||||
|
const shape_pt_sequence = parseInt(columns[shapePtSequenceIndex], 10);
|
||||||
|
const shape_pt_lat = parseFloat(columns[shapePtLatIndex]);
|
||||||
|
const shape_pt_lon = parseFloat(columns[shapePtLonIndex]);
|
||||||
|
|
||||||
|
if (!shapes[shape_id]) {
|
||||||
|
shapes[shape_id] = [];
|
||||||
|
}
|
||||||
|
shapes[shape_id].push({
|
||||||
|
sequence: shape_pt_sequence,
|
||||||
|
lat: shape_pt_lat,
|
||||||
|
lon: shape_pt_lon
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the shape points by sequence and draw them with click listeners
|
||||||
|
for (let shape_id in shapes) {
|
||||||
|
if (shapes.hasOwnProperty(shape_id)) {
|
||||||
|
shapes[shape_id].sort((a, b) => a.sequence - b.sequence);
|
||||||
|
const latlngs = shapes[shape_id].map(point => [point.lat, point.lon]);
|
||||||
|
|
||||||
|
addClickableShape (latlngs, shape_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addClickableShape (latlngs, shape_id) {
|
||||||
|
// Create polyline and add to map
|
||||||
|
const polyline = L.polyline(latlngs, { color: 'blue', weight: 5 }).addTo(map);
|
||||||
|
|
||||||
|
// Add click event listener to polyline
|
||||||
|
polyline.on('click', function (e) {
|
||||||
|
// Reset previous polyline to blue
|
||||||
|
if (currentShapeID !== null) {
|
||||||
|
shapes[currentShapeID].polyline.setStyle({ color: 'blue' });
|
||||||
|
}
|
||||||
|
// Set new currentShapeID value
|
||||||
|
currentShapeID = shape_id;
|
||||||
|
|
||||||
|
// Highlight the clicked polyline
|
||||||
|
polyline.setStyle({ color: 'red' }).bringToFront();
|
||||||
|
|
||||||
|
displayShapeOptions(shape_id, shapes);
|
||||||
|
|
||||||
|
console.log('Shape clicked:', shape_id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Store polyline reference in shapes object for reset purpose
|
||||||
|
shapes[shape_id].polyline = polyline;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNewShape() {
|
||||||
|
shapeStops = [];
|
||||||
|
cancelShapeEdit();
|
||||||
|
|
||||||
|
// Create a container div for the buttons
|
||||||
|
const buttonContainer = document.createElement('div');
|
||||||
|
buttonContainer.className = 'button-container mt-3 p-3 border rounded';
|
||||||
|
|
||||||
|
// Create Toggle OSM router machine button
|
||||||
|
const editButton = document.createElement('button');
|
||||||
|
editButton.className = 'btn btn-primary btn-block my-2';
|
||||||
|
editButton.textContent = 'Toggle OSM router machine';
|
||||||
|
editButton.onclick = () => {
|
||||||
|
// Open route editing tool
|
||||||
|
shapeToOSRM(shapes[shapeID].polyline);
|
||||||
|
};
|
||||||
|
buttonContainer.appendChild(editButton);
|
||||||
|
|
||||||
|
// Create Save button
|
||||||
|
const saveButton = document.createElement('button');
|
||||||
|
saveButton.className = 'btn btn-secondary btn-block my-2';
|
||||||
|
saveButton.textContent = 'Save Shape';
|
||||||
|
saveButton.setAttribute('ready-to-save', 'false');
|
||||||
|
saveButton.onclick = () => {
|
||||||
|
if (saveButton.getAttribute('ready-to-save') === 'true') {
|
||||||
|
// Append coordinates to stops list
|
||||||
|
var latlngs = currentLayer.getLatLngs();
|
||||||
|
latlngs.forEach(function(latlng) {
|
||||||
|
stops.push([latlng.lat, latlng.lng]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Transform the polyline into the specified format in the shapes dictionary
|
||||||
|
shape_id = "n_" + numNewShapes;
|
||||||
|
numNewShapes += 1;
|
||||||
|
shapes[shape_id] = [];
|
||||||
|
latlngs.forEach(function(latlng, index) {
|
||||||
|
shapes[shape_id].push({
|
||||||
|
sequence: index + 1,
|
||||||
|
lat: latlng.lat,
|
||||||
|
lon: latlng.lng
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete the layer with the drawn polyline
|
||||||
|
map.removeLayer(currentLayer);
|
||||||
|
|
||||||
|
// Create polyline and add to map
|
||||||
|
addClickableShape (latlngs, shape_id);
|
||||||
|
|
||||||
|
// Log the results
|
||||||
|
console.log('Stops:', stops);
|
||||||
|
console.log('Shapes:', shapes);
|
||||||
|
|
||||||
|
// Change button esthetics to default
|
||||||
|
saveButton.style.backgroundColor = '';
|
||||||
|
saveButton.style.color = '';
|
||||||
|
|
||||||
|
cancelShapeEdit();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
buttonContainer.appendChild(saveButton);
|
||||||
|
|
||||||
|
// Create Cancel button
|
||||||
|
const cancelButton = document.createElement('button');
|
||||||
|
cancelButton.className = 'btn btn-secondary btn-block my-2';
|
||||||
|
cancelButton.textContent = 'Cancel';
|
||||||
|
cancelButton.onclick = () => {
|
||||||
|
cancelShapeEdit();
|
||||||
|
};
|
||||||
|
buttonContainer.appendChild(cancelButton);
|
||||||
|
|
||||||
|
// Append the button container to the chosenShape element
|
||||||
|
chosenShape.appendChild(buttonContainer);
|
||||||
|
|
||||||
|
polylineDrawer.enable();
|
||||||
|
|
||||||
|
// Add created polylines to the map
|
||||||
|
map.on(L.Draw.Event.CREATED, function (event) {
|
||||||
|
var layer = event.layer;
|
||||||
|
currentLayer = layer;
|
||||||
|
drawnItems.addLayer(layer);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add created shapes to the map and handle the polyline
|
||||||
|
map.on(L.Draw.Event.CREATED, function (event) {
|
||||||
|
var layer = event.layer;
|
||||||
|
|
||||||
|
// Check if the drawn shape is a polyline
|
||||||
|
if (layer instanceof L.Polyline && !(layer instanceof L.Polygon)) {
|
||||||
|
// Disable the drawing control
|
||||||
|
map.removeControl(drawControl);
|
||||||
|
|
||||||
|
saveButton.style.backgroundColor = 'green';
|
||||||
|
saveButton.style.color = 'white'; // Ensure the text is readable
|
||||||
|
saveButton.setAttribute('ready-to-save', 'true');
|
||||||
|
} else {
|
||||||
|
// Add the drawn layer to the map if it's not a polyline
|
||||||
|
drawnItems.addLayer(layer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayShapeOptions(shapeID, shapes) {
|
||||||
|
const chosenShape = document.getElementById('chosenShape');
|
||||||
|
|
||||||
|
// Clear any existing content inside chosenShape
|
||||||
|
while (chosenShape.firstChild) {
|
||||||
|
chosenShape.removeChild(chosenShape.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add text content at the top
|
||||||
|
const textContent = document.createElement('div');
|
||||||
|
textContent.textContent = "Shape " + shapeID;
|
||||||
|
chosenShape.appendChild(textContent);
|
||||||
|
|
||||||
|
// Create a container div for the buttons
|
||||||
|
const buttonContainer = document.createElement('div');
|
||||||
|
buttonContainer.className = 'button-container mt-3 p-3 border rounded';
|
||||||
|
|
||||||
|
// Create Edit button
|
||||||
|
const editButton = document.createElement('button');
|
||||||
|
editButton.className = 'btn btn-primary btn-block my-2';
|
||||||
|
editButton.textContent = 'Edit Shape';
|
||||||
|
editButton.onclick = () => {
|
||||||
|
// Open route editing tool
|
||||||
|
shapeToOSRM(shapes[shapeID].polyline);
|
||||||
|
};
|
||||||
|
buttonContainer.appendChild(editButton);
|
||||||
|
|
||||||
|
// Create Delete button
|
||||||
|
const deleteButton = document.createElement('button');
|
||||||
|
deleteButton.className = 'btn btn-danger btn-block my-2';
|
||||||
|
deleteButton.textContent = 'Delete Shape';
|
||||||
|
deleteButton.onclick = () => {
|
||||||
|
|
||||||
|
// Cancel the edit view for the current shape
|
||||||
|
cancelShapeEdit();
|
||||||
|
// Delete the current shape and its representation from the map
|
||||||
|
deleteShape(shapeID);
|
||||||
|
};
|
||||||
|
buttonContainer.appendChild(deleteButton);
|
||||||
|
|
||||||
|
// Create Cancel button
|
||||||
|
const cancelButton = document.createElement('button');
|
||||||
|
cancelButton.className = 'btn btn-secondary btn-block my-2';
|
||||||
|
cancelButton.textContent = 'Cancel';
|
||||||
|
cancelButton.onclick = () => {
|
||||||
|
cancelShapeEdit();
|
||||||
|
};
|
||||||
|
buttonContainer.appendChild(cancelButton);
|
||||||
|
|
||||||
|
// Append the button container to the chosenShape element
|
||||||
|
chosenShape.appendChild(buttonContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelShapeEdit () {
|
||||||
|
// Define reference to the chosenShape field
|
||||||
|
const chosenShape = document.getElementById('chosenShape');
|
||||||
|
|
||||||
|
// Remove any existing routing control (if needed)
|
||||||
|
if (window.routingControl) {
|
||||||
|
map.removeControl(window.routingControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable the current drawing
|
||||||
|
polylineDrawer.disable();
|
||||||
|
|
||||||
|
// Clear all drawn items
|
||||||
|
drawnItems.clearLayers();
|
||||||
|
|
||||||
|
// Clear any existing content inside chosenShape
|
||||||
|
while (chosenShape.firstChild) {
|
||||||
|
chosenShape.removeChild(chosenShape.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add text content at the top
|
||||||
|
const textContent = document.createElement('div');
|
||||||
|
textContent.textContent = "Chosen Shape";
|
||||||
|
chosenShape.appendChild(textContent);
|
||||||
|
|
||||||
|
// Reset previous polyline to blue
|
||||||
|
if (currentShapeID !== null) {
|
||||||
|
shapes[currentShapeID].polyline.setStyle({ color: 'blue' });
|
||||||
|
}
|
||||||
|
// Set currentShapeID to null
|
||||||
|
currentShapeID = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteShape(shapeID) {
|
||||||
|
if (shapes[shapeID] && shapes[shapeID].polyline) {
|
||||||
|
map.removeLayer(shapes[shapeID].polyline); // Remove the polyline from the map
|
||||||
|
delete shapes[shapeID]; // Delete the shape from the shapes object
|
||||||
|
console.log('Shape deleted:', shapeID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function that takes a shape of a route and draws an OSRM path along it
|
||||||
|
function shapeToOSRM (polyline) {
|
||||||
|
if (!polyline) {
|
||||||
|
console.error('Invalid polyline');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the latlngs array from the polyline
|
||||||
|
const latlngs = polyline.getLatLngs();
|
||||||
|
|
||||||
|
if (latlngs.length < 2) {
|
||||||
|
console.error('Polyline should have at least two points');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define start and end points
|
||||||
|
const startPoint = latlngs[0];
|
||||||
|
const endPoint = latlngs[latlngs.length - 1];
|
||||||
|
|
||||||
|
const initialWaypoints = [
|
||||||
|
L.latLng(startPoint.lat, startPoint.lng),
|
||||||
|
L.latLng(endPoint.lat, endPoint.lng)
|
||||||
|
];
|
||||||
|
|
||||||
|
console.log('initialWaypoints', initialWaypoints[0]);
|
||||||
|
|
||||||
|
const routingControl = L.Routing.control({
|
||||||
|
waypoints: initialWaypoints,
|
||||||
|
routeWhileDragging: false,
|
||||||
|
createMarker: () => null // Don't create markers for initial route
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
console.log('Added routingControl.');
|
||||||
|
|
||||||
|
routingControl.on('routesfound', function (e) {
|
||||||
|
const routes = e.routes;
|
||||||
|
const routePolyline = routes[0].coordinates;
|
||||||
|
|
||||||
|
console.log('routePolyline[0]: ', routePolyline[0]);
|
||||||
|
|
||||||
|
// Find the furthest point from the original polyline to the generated polyline
|
||||||
|
const furthestPoint = findFurthestPoint(latlngs, routePolyline);
|
||||||
|
|
||||||
|
console.log('furthestPoint: ', furthestPoint);
|
||||||
|
|
||||||
|
// Create new waypoints with the furthest point added
|
||||||
|
const newWaypoints = [
|
||||||
|
L.latLng(startPoint.lat, startPoint.lng),
|
||||||
|
L.latLng(furthestPoint.lat, furthestPoint.lng),
|
||||||
|
L.latLng(endPoint.lat, endPoint.lng)
|
||||||
|
];
|
||||||
|
|
||||||
|
// Generate the new route with the updated waypoints
|
||||||
|
generateNewRoute(newWaypoints);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateNewRoute(waypoints) {
|
||||||
|
if (window.finalRoutingControl) {
|
||||||
|
map.removeControl(window.finalRoutingControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.finalRoutingControl = L.Routing.control({
|
||||||
|
waypoints: waypoints,
|
||||||
|
routeWhileDragging: false
|
||||||
|
}).addTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findFurthestPoint(originalPolyline, generatedPolyline) {
|
||||||
|
let maxDistance = -1;
|
||||||
|
let furthestPoint = null;
|
||||||
|
|
||||||
|
originalPolyline.forEach(point => {
|
||||||
|
const latlngPoint = L.latLng(point.lat, point.lng);
|
||||||
|
const distance = findDistanceToPolyline(latlngPoint, generatedPolyline);
|
||||||
|
|
||||||
|
if (distance > maxDistance) {
|
||||||
|
maxDistance = distance;
|
||||||
|
furthestPoint = point;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return furthestPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findDistanceToPolyline(point, polyline) {
|
||||||
|
let minDistance = Infinity;
|
||||||
|
|
||||||
|
polyline.forEach((segmentPoint, index) => {
|
||||||
|
if (index === 0) return;
|
||||||
|
const prevPoint = polyline[index - 1];
|
||||||
|
console.log('Current shapefile point: ', point);
|
||||||
|
console.log('Current generated polyline point: ', segment);
|
||||||
|
const segmentDistance = L.GeometryUtil.distanceSegment(map, point, prevPoint, segmentPoint);
|
||||||
|
minDistance = Math.min(minDistance, segmentDistance);
|
||||||
|
});
|
||||||
|
|
||||||
|
return minDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to write "Hello World!" to the console when the map is clicked
|
||||||
|
function onMapClick(event) {
|
||||||
|
// Check if the click event is not on a shape
|
||||||
|
if (!event.originalEvent.target.closest('.leaflet-interactive')) {
|
||||||
|
cancelShapeEdit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the map click event listener
|
||||||
|
map.on('click', onMapClick);
|
||||||
|
|
||||||
function importGTFS() {
|
function importGTFS() {
|
||||||
alert("Import existing GTFS clicked");
|
alert("Import existing GTFS clicked");
|
||||||
|
|
|
||||||
12
transport_accessibility/pt_map/templates/testing.html
Normal file
12
transport_accessibility/pt_map/templates/testing.html
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{% for x in fruits %}
|
||||||
|
<h1>{{ x }}</h1>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<p>In views.py you can see what the fruits variable looks like.</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -3,4 +3,5 @@ from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.index, name="index"),
|
path("", views.index, name="index"),
|
||||||
|
path("testing/", views.testing, name="testing"),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,16 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
from django.template import loader
|
||||||
from .models import Agency, Stop, Route, Trip, StopTime, Calendar, CalendarDate, FareAttribute, FareRule, Shape, Frequency, Transfer, FeedInfo
|
from .models import Agency, Stop, Route, Trip, StopTime, Calendar, CalendarDate, FareAttribute, FareRule, Shape, Frequency, Transfer, FeedInfo
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
|
|
||||||
return HttpResponse("Test")
|
return HttpResponse("Test")
|
||||||
|
|
||||||
|
def testing(request):
|
||||||
|
template = loader.get_template('testing.html')
|
||||||
|
context = {
|
||||||
|
'fruits': ['Apple', 'Banana', 'Cherry'],
|
||||||
|
}
|
||||||
|
return HttpResponse(template.render(context, request))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user