Drawing and deleting routes

This commit is contained in:
Jan Kiljanski 2024-06-02 12:12:17 +02:00
parent 34dce12339
commit 99c6e93b4b
4 changed files with 672 additions and 6 deletions

View File

@ -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");

View 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>

View File

@ -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"),
] ]

View File

@ -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))