better map markers

This commit is contained in:
Will Freeman
2024-12-12 13:19:50 -07:00
parent 6dff9cb2c8
commit a0f743b432
5 changed files with 82 additions and 51 deletions
+14 -49
View File
@@ -1,28 +1,25 @@
<template>
<l-circle-marker :lat-lng="[alpr.lat, alpr.lon]" :radius="7" :color="markerColor">
<l-marker-rotate v-if="showFov && hasDirection" :lat-lng="[alpr.lat, alpr.lon]" rotationOrigin="center center" :rotationAngle>
<l-popup>
<DFMapPopup :alpr="alpr" />
</l-popup>
<l-icon :icon-url :icon-size :icon-anchor />
</l-marker-rotate>
<l-circle-marker v-else :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 && hasDirection"
>
<!-- TODO: use the same popup -->
<l-popup>
<DFMapPopup :alpr="alpr" />
</l-popup>
</l-polygon>
</template>
<script setup lang="ts">
import { LCircleMarker, LPolygon, LPopup } from '@vue-leaflet/vue-leaflet';
import { LIcon, LPopup, LCircleMarker } from '@vue-leaflet/vue-leaflet';
import { LMarkerRotate } from 'vue-leaflet-rotate-marker';
import DFMapPopup from '@/components/DFMapPopup.vue';
import type { ALPR } from '@/types';
import type { PropType } from 'vue';
import { computed, defineProps } from 'vue';
import { type PointExpression } from 'leaflet';
const props = defineProps({
alpr: {
@@ -35,41 +32,9 @@ const props = defineProps({
}
});
const markerColor = computed(() => {
if (props.alpr.tags.brand === 'Avigilon') {
return '#ff5722';
}
return '#3f54f3';
});
const iconSize: PointExpression = [60, 60];
const iconAnchor: PointExpression = [30, 30];
const hasDirection = computed(() => props.alpr.tags.direction !== undefined);
const directionIndicatorPolygonCoordinates = computed(() => {
if (!hasDirection.value) {
console.warn('ALPR does not have direction tag');
return [];
}
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]
];
});
const rotationAngle = computed(() => parseInt(props.alpr.tags.direction) || undefined);
const iconUrl = computed(() => props.showFov ? `/map-icon.svg` : '/map-icon-simple.svg');
</script>
+6 -2
View File
@@ -5,13 +5,13 @@
<v-icon start>mdi-face-recognition</v-icon> <b>Face Recognition</b>
</v-list-item>
<v-list-item>
<v-icon start>mdi-car</v-icon> <b>License Plate</b>
<v-icon start>mdi-cctv</v-icon> <b>License Plate Reader</b>
</v-list-item>
<v-list-item v-if="isFaceRecognition">
<v-icon start>mdi-adjust</v-icon> <b>Omnidirectional</b>
</v-list-item>
<v-list-item v-else>
<v-icon start>mdi-cctv</v-icon> <b>Directional {{ alpr.tags.direction ? `(${degreesToCardinal(parseInt(alpr.tags.direction))})` : '' }}</b>
<v-icon start>mdi-compass-outline</v-icon> <b>{{ cardinalDirection }}</b>
</v-list-item>
<v-list-item>
<v-icon start>mdi-domain</v-icon> <b>
@@ -75,6 +75,10 @@ const kvTags = computed(() => {
.map(([key, value]) => ({ key, value: valueTransformations[key]?.(value) ?? value }));
});
const cardinalDirection = computed(() =>
props.alpr.tags.direction === undefined ? 'Unknown' : degreesToCardinal(parseInt(props.alpr.tags.direction))
);
function degreesToCardinal(degrees: number): string {
const cardinals = ['North', 'Northeast', 'East', 'Southeast', 'South', 'Southwest', 'West', 'Northwest'];
return cardinals[Math.round(degrees / 45) % 8];