mirror of
https://github.com/FoggedLens/deflock.git
synced 2026-08-16 07:30:23 +02:00
show field of view, display tags in tabular form
This commit is contained in:
@@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<l-circle-marker :lat-lng="[alpr.lat, alpr.lon]" :radius="7" color="#3f54f3">
|
||||||
|
<l-popup>
|
||||||
|
<DFMapPopup :alpr="alpr" />
|
||||||
|
</l-popup>
|
||||||
|
</l-circle-marker>
|
||||||
|
<l-polygon
|
||||||
|
:lat-lngs="directionIndicatorPolygonCoordinates"
|
||||||
|
:options="{ color: 'red' }"
|
||||||
|
v-if="showFov"
|
||||||
|
>
|
||||||
|
<!-- TODO: use the same popup -->
|
||||||
|
<l-popup>
|
||||||
|
<DFMapPopup :alpr="alpr" />
|
||||||
|
</l-popup>
|
||||||
|
</l-polygon>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { LMarker, LCircleMarker, LFeatureGroup, LPolygon, LPopup } from '@vue-leaflet/vue-leaflet';
|
||||||
|
import DFMapPopup from '@/components/DFMapPopup.vue';
|
||||||
|
import type { ALPR } from '@/types';
|
||||||
|
import type { PropType } from 'vue';
|
||||||
|
import { computed, defineProps } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
alpr: {
|
||||||
|
type: Object as PropType<ALPR>,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
showFov: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const directionIndicatorPolygonCoordinates = computed(() => {
|
||||||
|
const { lat, lon } = props.alpr;
|
||||||
|
const direction = parseInt(props.alpr.tags.direction);
|
||||||
|
const fov = 30; // Field of view in degrees
|
||||||
|
const distance = 0.0004; // Distance for the triangle points
|
||||||
|
|
||||||
|
const toRadians = (degrees: number) => degrees * (Math.PI / 180);
|
||||||
|
|
||||||
|
const pointL = {
|
||||||
|
lat: lat + distance * Math.cos(toRadians(direction - fov / 2)),
|
||||||
|
lon: lon + distance * Math.sin(toRadians(direction - fov / 2))
|
||||||
|
};
|
||||||
|
|
||||||
|
const pointR = {
|
||||||
|
lat: lat + distance * Math.cos(toRadians(direction + fov / 2)),
|
||||||
|
lon: lon + distance * Math.sin(toRadians(direction + fov / 2))
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
[lat, lon],
|
||||||
|
[pointL.lat, pointL.lon],
|
||||||
|
[pointR.lat, pointR.lon]
|
||||||
|
];
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<v-sheet>
|
||||||
|
<v-data-table density="compact" hide-default-footer disable-sort :items="kvTags" />
|
||||||
|
</v-sheet>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { defineProps, computed } from 'vue';
|
||||||
|
import type { PropType } from 'vue';
|
||||||
|
import type { ALPR } from '@/types';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
alpr: {
|
||||||
|
type: Object as PropType<ALPR>,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const valueTransformations: { [key: string]: (value: string) => string } = {
|
||||||
|
direction: (value: string) => `${degreesToCardinal(parseInt(value))} ${value}º`
|
||||||
|
};
|
||||||
|
|
||||||
|
const whitelistedTags = ['brand', 'camera:mount', 'camera:type', 'direction', 'operator'];
|
||||||
|
|
||||||
|
const kvTags = computed(() => {
|
||||||
|
return Object.entries(props.alpr.tags)
|
||||||
|
.filter(([key]) => whitelistedTags.includes(key))
|
||||||
|
.map(([key, value]) => ({ key, value: valueTransformations[key]?.(value) ?? value }));
|
||||||
|
});
|
||||||
|
|
||||||
|
function degreesToCardinal(degrees: number): string {
|
||||||
|
const cardinals = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'];
|
||||||
|
return cardinals[Math.round(degrees / 45) % 8];
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export interface ALPR {
|
||||||
|
id: string;
|
||||||
|
lat: number;
|
||||||
|
lon: number;
|
||||||
|
tags: Record<string, string>;
|
||||||
|
type: string;
|
||||||
|
};
|
||||||
@@ -43,16 +43,7 @@
|
|||||||
name="OpenStreetMap"
|
name="OpenStreetMap"
|
||||||
/>
|
/>
|
||||||
<l-control-zoom position="bottomright" />
|
<l-control-zoom position="bottomright" />
|
||||||
<l-marker
|
<DFMapMarker v-for="alpr in alprsInView" :key="alpr.id" :alpr :show-fov="zoom >= 16" />
|
||||||
v-for="alpr in alprsInView"
|
|
||||||
:key="alpr.id"
|
|
||||||
:lat-lng="[alpr.lat, alpr.lon]"
|
|
||||||
>
|
|
||||||
<l-popup>
|
|
||||||
<p class="mb-0 mt-2" v-if="alpr.tags.brand || alpr.tags.operator"><strong>Brand: </strong><a target="_blank" :href="`https://www.wikidata.org/wiki/${alpr.tags['brand:wikidata'] || alpr.tags['operator:wikidata']}`">{{ alpr.tags.brand || alpr.tags.operator || 'Unknown' }}</a></p>
|
|
||||||
<p class="my-0" v-if="alpr.tags.direction"><strong>Faces: {{ degreesToCardinal(alpr.tags.direction) }} {{ alpr.tags.direction }}°</strong></p>
|
|
||||||
</l-popup>
|
|
||||||
</l-marker>
|
|
||||||
</l-map>
|
</l-map>
|
||||||
<div class="loader" v-else>
|
<div class="loader" v-else>
|
||||||
<span class="mb-4 text-grey">Loading Map</span>
|
<span class="mb-4 text-grey">Loading Map</span>
|
||||||
@@ -70,6 +61,8 @@ import type { Ref } from 'vue';
|
|||||||
import { BoundingBox } from '@/services/apiService';
|
import { BoundingBox } from '@/services/apiService';
|
||||||
import { getALPRs, geocodeQuery } from '@/services/apiService';
|
import { getALPRs, geocodeQuery } from '@/services/apiService';
|
||||||
import { useDisplay } from 'vuetify';
|
import { useDisplay } from 'vuetify';
|
||||||
|
import DFMapMarker from '@/components/DFMapMarker.vue';
|
||||||
|
import type { ALPR } from '@/types';
|
||||||
|
|
||||||
const zoom: Ref<number> = ref(13);
|
const zoom: Ref<number> = ref(13);
|
||||||
const center: Ref<any|null> = ref(null);
|
const center: Ref<any|null> = ref(null);
|
||||||
@@ -81,7 +74,7 @@ const { xs } = useDisplay();
|
|||||||
|
|
||||||
const canRefreshMarkers = computed(() => zoom.value >= 10);
|
const canRefreshMarkers = computed(() => zoom.value >= 10);
|
||||||
|
|
||||||
const alprsInView: Ref<any[]> = ref([]);
|
const alprsInView: Ref<ALPR[]> = ref([]);
|
||||||
const bboxForLastRequest: Ref<BoundingBox|null> = ref(null);
|
const bboxForLastRequest: Ref<BoundingBox|null> = ref(null);
|
||||||
|
|
||||||
function onSearch() {
|
function onSearch() {
|
||||||
@@ -180,11 +173,6 @@ function updateMarkers() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function degreesToCardinal(degrees: number): string {
|
|
||||||
const cardinals = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'];
|
|
||||||
return cardinals[Math.round(degrees / 45) % 8];
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const hash = router.currentRoute.value.hash;
|
const hash = router.currentRoute.value.hash;
|
||||||
if (hash) {
|
if (hash) {
|
||||||
|
|||||||
Reference in New Issue
Block a user