mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 09:41:40 -05:00
configurable time threshold
This commit is contained in:
parent
5fa4d953f7
commit
e5075d59d3
4 changed files with 35 additions and 14 deletions
|
|
@ -30,7 +30,7 @@ class Api::V1::SettingsController < ApiController
|
||||||
:time_threshold_minutes, :merge_threshold_minutes, :route_opacity,
|
:time_threshold_minutes, :merge_threshold_minutes, :route_opacity,
|
||||||
:preferred_map_layer, :points_rendering_mode, :live_map_enabled,
|
:preferred_map_layer, :points_rendering_mode, :live_map_enabled,
|
||||||
:immich_url, :immich_api_key, :photoprism_url, :photoprism_api_key,
|
:immich_url, :immich_api_key, :photoprism_url, :photoprism_api_key,
|
||||||
:speed_colored_routes, :speed_color_scale
|
:speed_colored_routes, :speed_color_scale, :fog_of_war_threshold
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ export default class extends BaseController {
|
||||||
this.timezone = this.element.dataset.timezone;
|
this.timezone = this.element.dataset.timezone;
|
||||||
this.userSettings = JSON.parse(this.element.dataset.user_settings);
|
this.userSettings = JSON.parse(this.element.dataset.user_settings);
|
||||||
this.clearFogRadius = parseInt(this.userSettings.fog_of_war_meters) || 50;
|
this.clearFogRadius = parseInt(this.userSettings.fog_of_war_meters) || 50;
|
||||||
|
this.fogLinethreshold = parseInt(this.userSettings.fog_of_war_threshold) || 90;
|
||||||
this.routeOpacity = parseFloat(this.userSettings.route_opacity) || 0.6;
|
this.routeOpacity = parseFloat(this.userSettings.route_opacity) || 0.6;
|
||||||
this.distanceUnit = this.element.dataset.distance_unit || "km";
|
this.distanceUnit = this.element.dataset.distance_unit || "km";
|
||||||
this.pointsRenderingMode = this.userSettings.points_rendering_mode || "raw";
|
this.pointsRenderingMode = this.userSettings.points_rendering_mode || "raw";
|
||||||
|
|
@ -175,13 +176,13 @@ export default class extends BaseController {
|
||||||
// Update event handlers
|
// Update event handlers
|
||||||
this.map.on('moveend', () => {
|
this.map.on('moveend', () => {
|
||||||
if (document.getElementById('fog')) {
|
if (document.getElementById('fog')) {
|
||||||
this.updateFog(this.markers, this.clearFogRadius);
|
this.updateFog(this.markers, this.clearFogRadius, this.fogLinethreshold);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.map.on('zoomend', () => {
|
this.map.on('zoomend', () => {
|
||||||
if (document.getElementById('fog')) {
|
if (document.getElementById('fog')) {
|
||||||
this.updateFog(this.markers, this.clearFogRadius);
|
this.updateFog(this.markers, this.clearFogRadius, this.fogLinethreshold);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -198,7 +199,7 @@ export default class extends BaseController {
|
||||||
if (e.name === 'Fog of War') {
|
if (e.name === 'Fog of War') {
|
||||||
fogEnabled = true;
|
fogEnabled = true;
|
||||||
document.getElementById('fog').style.display = 'block';
|
document.getElementById('fog').style.display = 'block';
|
||||||
this.updateFog(this.markers, this.clearFogRadius);
|
this.updateFog(this.markers, this.clearFogRadius, this.fogLinethreshold);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -212,7 +213,7 @@ export default class extends BaseController {
|
||||||
// Update fog circles on zoom and move
|
// Update fog circles on zoom and move
|
||||||
this.map.on('zoomend moveend', () => {
|
this.map.on('zoomend moveend', () => {
|
||||||
if (fogEnabled) {
|
if (fogEnabled) {
|
||||||
this.updateFog(this.markers, this.clearFogRadius);
|
this.updateFog(this.markers, this.clearFogRadius, this.fogLinethreshold);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -350,7 +351,7 @@ export default class extends BaseController {
|
||||||
|
|
||||||
// Update fog of war if enabled
|
// Update fog of war if enabled
|
||||||
if (this.map.hasLayer(this.fogOverlay)) {
|
if (this.map.hasLayer(this.fogOverlay)) {
|
||||||
this.updateFog(this.markers, this.clearFogRadius);
|
this.updateFog(this.markers, this.clearFogRadius, this.fogLinethreshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the last marker
|
// Update the last marker
|
||||||
|
|
@ -587,7 +588,7 @@ export default class extends BaseController {
|
||||||
|
|
||||||
// Update fog if enabled
|
// Update fog if enabled
|
||||||
if (this.map.hasLayer(this.fogOverlay)) {
|
if (this.map.hasLayer(this.fogOverlay)) {
|
||||||
this.updateFog(this.markers, this.clearFogRadius);
|
this.updateFog(this.markers, this.clearFogRadius, this.fogLinethreshold);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|
@ -623,12 +624,12 @@ export default class extends BaseController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFog(markers, clearFogRadius) {
|
updateFog(markers, clearFogRadius, fogLinethreshold) {
|
||||||
const fog = document.getElementById('fog');
|
const fog = document.getElementById('fog');
|
||||||
if (!fog) {
|
if (!fog) {
|
||||||
initializeFogCanvas(this.map);
|
initializeFogCanvas(this.map);
|
||||||
}
|
}
|
||||||
requestAnimationFrame(() => drawFogCanvas(this.map, markers, clearFogRadius));
|
requestAnimationFrame(() => drawFogCanvas(this.map, markers, clearFogRadius, fogLinethreshold));
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeDrawControl() {
|
initializeDrawControl() {
|
||||||
|
|
@ -724,7 +725,7 @@ export default class extends BaseController {
|
||||||
|
|
||||||
// Form HTML
|
// Form HTML
|
||||||
div.innerHTML = `
|
div.innerHTML = `
|
||||||
<form id="settings-form" class="w-48 h-144 overflow-y-auto">
|
<form id="settings-form" style="overflow-y: auto; height: 36rem; width: 12rem;">
|
||||||
<label for="route-opacity">Route Opacity</label>
|
<label for="route-opacity">Route Opacity</label>
|
||||||
<div class="join">
|
<div class="join">
|
||||||
<input type="number" class="input input-ghost join-item focus:input-ghost input-xs input-bordered w-full max-w-xs" id="route-opacity" name="route_opacity" min="0" max="1" step="0.1" value="${this.routeOpacity}">
|
<input type="number" class="input input-ghost join-item focus:input-ghost input-xs input-bordered w-full max-w-xs" id="route-opacity" name="route_opacity" min="0" max="1" step="0.1" value="${this.routeOpacity}">
|
||||||
|
|
@ -738,6 +739,12 @@ export default class extends BaseController {
|
||||||
<label for="fog_of_war_meters_info" class="btn-xs join-item">?</label>
|
<label for="fog_of_war_meters_info" class="btn-xs join-item">?</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<label for="fog_of_war_threshold">Seconds between Fog of War lines</label>
|
||||||
|
<div class="join">
|
||||||
|
<input type="number" class="join-item input input-ghost focus:input-ghost input-xs input-bordered w-full max-w-xs" id="fog_of_war_threshold" name="fog_of_war_threshold" step="1" value="${this.userSettings.fog_of_war_threshold}">
|
||||||
|
<label for="fog_of_war_threshold_info" class="btn-xs join-item">?</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<label for="meters_between_routes">Meters between routes</label>
|
<label for="meters_between_routes">Meters between routes</label>
|
||||||
<div class="join">
|
<div class="join">
|
||||||
|
|
@ -863,6 +870,7 @@ export default class extends BaseController {
|
||||||
settings: {
|
settings: {
|
||||||
route_opacity: event.target.route_opacity.value,
|
route_opacity: event.target.route_opacity.value,
|
||||||
fog_of_war_meters: event.target.fog_of_war_meters.value,
|
fog_of_war_meters: event.target.fog_of_war_meters.value,
|
||||||
|
fog_of_war_threshold: event.target.fog_of_war_threshold.value,
|
||||||
meters_between_routes: event.target.meters_between_routes.value,
|
meters_between_routes: event.target.meters_between_routes.value,
|
||||||
minutes_between_routes: event.target.minutes_between_routes.value,
|
minutes_between_routes: event.target.minutes_between_routes.value,
|
||||||
time_threshold_minutes: event.target.time_threshold_minutes.value,
|
time_threshold_minutes: event.target.time_threshold_minutes.value,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ export function initializeFogCanvas(map) {
|
||||||
return fog;
|
return fog;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function drawFogCanvas(map, markers, clearFogRadius) {
|
export function drawFogCanvas(map, markers, clearFogRadius, fogLinethreshold) {
|
||||||
const fog = document.getElementById('fog');
|
const fog = document.getElementById('fog');
|
||||||
// Return early if fog element doesn't exist or isn't a canvas
|
// Return early if fog element doesn't exist or isn't a canvas
|
||||||
if (!fog || !(fog instanceof HTMLCanvasElement)) return;
|
if (!fog || !(fog instanceof HTMLCanvasElement)) return;
|
||||||
|
|
@ -42,7 +42,6 @@ export function drawFogCanvas(map, markers, clearFogRadius) {
|
||||||
ctx.globalCompositeOperation = 'destination-out';
|
ctx.globalCompositeOperation = 'destination-out';
|
||||||
|
|
||||||
// 3) Build & sort points
|
// 3) Build & sort points
|
||||||
const thresholdSec = 90; // points will be joined if < 1m30 of time difference
|
|
||||||
const pts = markers
|
const pts = markers
|
||||||
.map(pt => {
|
.map(pt => {
|
||||||
const pixel = map.latLngToContainerPoint(L.latLng(pt[0], pt[1]));
|
const pixel = map.latLngToContainerPoint(L.latLng(pt[0], pt[1]));
|
||||||
|
|
@ -56,7 +55,7 @@ export function drawFogCanvas(map, markers, clearFogRadius) {
|
||||||
// 4) Mark which pts are part of a line
|
// 4) Mark which pts are part of a line
|
||||||
const connected = new Array(pts.length).fill(false);
|
const connected = new Array(pts.length).fill(false);
|
||||||
for (let i = 0; i < pts.length - 1; i++) {
|
for (let i = 0; i < pts.length - 1; i++) {
|
||||||
if (pts[i + 1].time - pts[i].time <= thresholdSec) {
|
if (pts[i + 1].time - pts[i].time <= fogLinethreshold) {
|
||||||
connected[i] = true;
|
connected[i] = true;
|
||||||
connected[i + 1] = true;
|
connected[i + 1] = true;
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +78,7 @@ export function drawFogCanvas(map, markers, clearFogRadius) {
|
||||||
ctx.strokeStyle = 'rgba(255,255,255,1)';
|
ctx.strokeStyle = 'rgba(255,255,255,1)';
|
||||||
|
|
||||||
for (let i = 0; i < pts.length - 1; i++) {
|
for (let i = 0; i < pts.length - 1; i++) {
|
||||||
if (pts[i + 1].time - pts[i].time <= thresholdSec) {
|
if (pts[i + 1].time - pts[i].time <= fogLinethreshold) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.moveTo(pts[i].pixel.x, pts[i].pixel.y);
|
ctx.moveTo(pts[i].pixel.x, pts[i].pixel.y);
|
||||||
ctx.lineTo(pts[i + 1].pixel.x, pts[i + 1].pixel.y);
|
ctx.lineTo(pts[i + 1].pixel.x, pts[i + 1].pixel.y);
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,20 @@
|
||||||
<label class="modal-backdrop" for="fog_of_war_meters_info">Close</label>
|
<label class="modal-backdrop" for="fog_of_war_meters_info">Close</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<input type="checkbox" id="fog_of_war_threshold_info" class="modal-toggle" />
|
||||||
|
<div class="modal focus:z-99" role="dialog">
|
||||||
|
<div class="modal-box">
|
||||||
|
<h3 class="text-lg font-bold">Fog of War Line Threshold</h3>
|
||||||
|
<p class="py-4">
|
||||||
|
Value in seconds.
|
||||||
|
</p>
|
||||||
|
<p class="py-4">
|
||||||
|
Points in the fog are connected by lines. This value is the maximum time between two points to be connected by a line. If the time between two points is greater than this value, they will not be connected.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<label class="modal-backdrop" for="fog_of_war_threshold_info">Close</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<input type="checkbox" id="meters_between_routes_info" class="modal-toggle" />
|
<input type="checkbox" id="meters_between_routes_info" class="modal-toggle" />
|
||||||
<div class="modal focus:z-99" role="dialog">
|
<div class="modal focus:z-99" role="dialog">
|
||||||
<div class="modal-box">
|
<div class="modal-box">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue