2024-12-19 13:39:50 -05:00
|
|
|
import { formatDate } from "../maps/helpers";
|
2024-10-20 14:23:58 -04:00
|
|
|
import { formatDistance } from "../maps/helpers";
|
|
|
|
|
import { getUrlParameter } from "../maps/helpers";
|
|
|
|
|
import { minutesToDaysHoursMinutes } from "../maps/helpers";
|
|
|
|
|
import { haversineDistance } from "../maps/helpers";
|
|
|
|
|
|
2024-12-05 17:14:56 -05:00
|
|
|
export function addHighlightOnHover(polyline, map, polylineCoordinates, userSettings, distanceUnit) {
|
2024-10-20 14:23:58 -04:00
|
|
|
const originalStyle = { color: "blue", opacity: userSettings.routeOpacity, weight: 3 };
|
|
|
|
|
const highlightStyle = { color: "yellow", opacity: 1, weight: 5 };
|
|
|
|
|
|
|
|
|
|
polyline.setStyle(originalStyle);
|
|
|
|
|
|
|
|
|
|
const startPoint = polylineCoordinates[0];
|
|
|
|
|
const endPoint = polylineCoordinates[polylineCoordinates.length - 1];
|
|
|
|
|
|
2024-12-19 13:39:50 -05:00
|
|
|
const firstTimestamp = formatDate(startPoint[4], userSettings.timezone);
|
|
|
|
|
const lastTimestamp = formatDate(endPoint[4], userSettings.timezone);
|
2024-10-20 14:23:58 -04:00
|
|
|
|
|
|
|
|
const minutes = Math.round((endPoint[4] - startPoint[4]) / 60);
|
|
|
|
|
const timeOnRoute = minutesToDaysHoursMinutes(minutes);
|
|
|
|
|
|
|
|
|
|
const totalDistance = polylineCoordinates.reduce((acc, curr, index, arr) => {
|
|
|
|
|
if (index === 0) return acc;
|
|
|
|
|
const dist = haversineDistance(arr[index - 1][0], arr[index - 1][1], curr[0], curr[1]);
|
|
|
|
|
return acc + dist;
|
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
|
|
const startIcon = L.divIcon({ html: "🚥", className: "emoji-icon" });
|
|
|
|
|
const finishIcon = L.divIcon({ html: "🏁", className: "emoji-icon" });
|
|
|
|
|
|
|
|
|
|
const isDebugMode = getUrlParameter("debug") === "true";
|
|
|
|
|
|
|
|
|
|
let popupContent = `
|
|
|
|
|
<strong>Start:</strong> ${firstTimestamp}<br>
|
|
|
|
|
<strong>End:</strong> ${lastTimestamp}<br>
|
|
|
|
|
<strong>Duration:</strong> ${timeOnRoute}<br>
|
2024-12-05 17:14:56 -05:00
|
|
|
<strong>Total Distance:</strong> ${formatDistance(totalDistance, distanceUnit)}<br>
|
2024-10-20 14:23:58 -04:00
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
if (isDebugMode) {
|
|
|
|
|
const prevPoint = polylineCoordinates[0];
|
|
|
|
|
const nextPoint = polylineCoordinates[polylineCoordinates.length - 1];
|
|
|
|
|
const distanceToPrev = haversineDistance(prevPoint[0], prevPoint[1], startPoint[0], startPoint[1]);
|
|
|
|
|
const distanceToNext = haversineDistance(endPoint[0], endPoint[1], nextPoint[0], nextPoint[1]);
|
|
|
|
|
|
|
|
|
|
const timeBetweenPrev = Math.round((startPoint[4] - prevPoint[4]) / 60);
|
|
|
|
|
const timeBetweenNext = Math.round((endPoint[4] - nextPoint[4]) / 60);
|
|
|
|
|
const pointsNumber = polylineCoordinates.length;
|
|
|
|
|
|
|
|
|
|
popupContent += `
|
|
|
|
|
<strong>Prev Route:</strong> ${Math.round(distanceToPrev)}m and ${minutesToDaysHoursMinutes(timeBetweenPrev)} away<br>
|
|
|
|
|
<strong>Next Route:</strong> ${Math.round(distanceToNext)}m and ${minutesToDaysHoursMinutes(timeBetweenNext)} away<br>
|
|
|
|
|
<strong>Points:</strong> ${pointsNumber}<br>
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const startMarker = L.marker([startPoint[0], startPoint[1]], { icon: startIcon }).bindPopup(`Start: ${firstTimestamp}`);
|
|
|
|
|
const endMarker = L.marker([endPoint[0], endPoint[1]], { icon: finishIcon }).bindPopup(popupContent);
|
|
|
|
|
|
|
|
|
|
let hoverPopup = null;
|
|
|
|
|
|
|
|
|
|
polyline.on("mouseover", function (e) {
|
|
|
|
|
polyline.setStyle(highlightStyle);
|
|
|
|
|
startMarker.addTo(map);
|
|
|
|
|
endMarker.addTo(map);
|
|
|
|
|
|
|
|
|
|
const latLng = e.latlng;
|
|
|
|
|
if (hoverPopup) {
|
|
|
|
|
map.closePopup(hoverPopup);
|
|
|
|
|
}
|
|
|
|
|
hoverPopup = L.popup()
|
|
|
|
|
.setLatLng(latLng)
|
|
|
|
|
.setContent(popupContent)
|
|
|
|
|
.openOn(map);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
polyline.on("mouseout", function () {
|
|
|
|
|
polyline.setStyle(originalStyle);
|
|
|
|
|
map.closePopup(hoverPopup);
|
|
|
|
|
map.removeLayer(startMarker);
|
|
|
|
|
map.removeLayer(endMarker);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
polyline.on("click", function () {
|
|
|
|
|
map.fitBounds(polyline.getBounds());
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Close the popup when clicking elsewhere on the map
|
|
|
|
|
map.on("click", function () {
|
|
|
|
|
map.closePopup(hoverPopup);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-05 17:14:56 -05:00
|
|
|
export function createPolylinesLayer(markers, map, timezone, routeOpacity, userSettings, distanceUnit) {
|
2024-10-20 14:23:58 -04:00
|
|
|
const splitPolylines = [];
|
|
|
|
|
let currentPolyline = [];
|
|
|
|
|
const distanceThresholdMeters = parseInt(userSettings.meters_between_routes) || 500;
|
|
|
|
|
const timeThresholdMinutes = parseInt(userSettings.minutes_between_routes) || 60;
|
|
|
|
|
|
|
|
|
|
for (let i = 0, len = markers.length; i < len; i++) {
|
|
|
|
|
if (currentPolyline.length === 0) {
|
|
|
|
|
currentPolyline.push(markers[i]);
|
|
|
|
|
} else {
|
|
|
|
|
const lastPoint = currentPolyline[currentPolyline.length - 1];
|
|
|
|
|
const currentPoint = markers[i];
|
|
|
|
|
const distance = haversineDistance(lastPoint[0], lastPoint[1], currentPoint[0], currentPoint[1]);
|
|
|
|
|
const timeDifference = (currentPoint[4] - lastPoint[4]) / 60;
|
|
|
|
|
|
|
|
|
|
if (distance > distanceThresholdMeters || timeDifference > timeThresholdMinutes) {
|
|
|
|
|
splitPolylines.push([...currentPolyline]);
|
|
|
|
|
currentPolyline = [currentPoint];
|
|
|
|
|
} else {
|
|
|
|
|
currentPolyline.push(currentPoint);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (currentPolyline.length > 0) {
|
|
|
|
|
splitPolylines.push(currentPolyline);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return L.layerGroup(
|
|
|
|
|
splitPolylines.map((polylineCoordinates) => {
|
|
|
|
|
const latLngs = polylineCoordinates.map((point) => [point[0], point[1]]);
|
2024-12-25 07:05:42 -05:00
|
|
|
const polyline = L.polyline(latLngs, {
|
|
|
|
|
color: "blue",
|
|
|
|
|
opacity: 0.6,
|
|
|
|
|
weight: 3,
|
2025-01-07 08:31:06 -05:00
|
|
|
zIndexOffset: 400,
|
|
|
|
|
pane: 'overlayPane'
|
2024-12-25 07:05:42 -05:00
|
|
|
});
|
2024-10-20 14:23:58 -04:00
|
|
|
|
2024-12-05 17:14:56 -05:00
|
|
|
addHighlightOnHover(polyline, map, polylineCoordinates, userSettings, distanceUnit);
|
2024-10-20 14:23:58 -04:00
|
|
|
|
|
|
|
|
return polyline;
|
|
|
|
|
})
|
|
|
|
|
).addTo(map);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function updatePolylinesOpacity(polylinesLayer, opacity) {
|
|
|
|
|
polylinesLayer.eachLayer((layer) => {
|
|
|
|
|
if (layer instanceof L.Polyline) {
|
|
|
|
|
layer.setStyle({ opacity: opacity });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|