Files
app/src/components/map/MapWrapper.vue
T

133 lines
3.2 KiB
Vue

<script setup>
import {Circle, GoogleMap, Marker, Polygon} from "vue3-google-map";
import {computed, ref, watch} from "vue";
const props = defineProps({
bounds: {
type: Array,
required: false
},
airspacesData: {
type: Array,
required: false,
default: () => []
},
});
const key = process.env.GOOGLE_MAPS_API_KEY;
const mapRef = ref(null);
watch(
() => mapRef.value?.ready,
(ready) => {
if (!ready) return;
if (props.bounds) {
const bounds = new mapRef.value.api.LatLngBounds();
for (let i = 0; i < props.bounds.length; i++) {
bounds.extend(props.bounds[i]);
}
mapRef.value.map.fitBounds(bounds);
}
}
);
const airspaces = computed(() => {
const colorsMap = {
C: "#800080",
D: "#800080",
CTR: "#00ff00",
P: "#FF0000",
RMZ: "#FFdd00",
R: "#ff6a00",
Q: "#FFA500",
PGZ: "#008000",
GSEC: "#008000"
}
return props.airspacesData
.filter(airspace => !!colorsMap[airspace.type])
.map(airspace => {
const data = {
name: airspace.name,
strokeColor: colorsMap[airspace.type],
strokeOpacity: 0.2,
strokeWeight: 3,
fillColor: colorsMap[airspace.type],
fillOpacity: 0.1,
};
if (airspace.mapBounds.length > 0) {
data['path'] = airspace.mapBounds;
} else {
data['center'] = airspace.mapCenter;
data['radius'] = airspace.radius
}
return data
});
});
const atzs = computed(() => {
return props.airspacesData
.filter(a => a.type === 'ATZ')
.filter(a => !!a.mapCenter)
.map(airspace => ({
name: airspace.name,
strokeColor: "#4e7cfc",
strokeOpacity: 0.2,
strokeWeight: 1,
fillColor: "#4e7cfc",
fillOpacity: 0.1,
center: airspace.mapCenter,
radius: airspace.radius,
}))
});
// TODO: pridat letiste
function isPointInPolygon(clickPoint, polygonCoords) {
var count = 0;
var x = clickPoint.lng, y = clickPoint.lat;
for (var i = 0; i < polygonCoords.length; i++) {
var iNext = (i + 1) % polygonCoords.length;
var xi = polygonCoords[i].lng, yi = polygonCoords[i].lat;
var xiNext = polygonCoords[iNext].lng, yiNext = polygonCoords[iNext].lat;
var test = ((yi > y) !== (yiNext > y)) && (x < (xiNext - xi) * (y - yi) / (yiNext - yi) + xi);
if (test) count++;
}
return count % 2 === 1; // Lichý počet průsečíků = bod uvnitř
}
const showInfo = (e) => {
for (const airspace of airspaces.value) {
const clickCoords = {lat: e.latLng.lat(), lng: e.latLng.lng()}
if (airspace.path)
console.log(airspace.name, isPointInPolygon(clickCoords, airspace.path));
else {
// console.log(airspace);
}
}
}
</script>
<template>
<GoogleMap :api-key="key" v-bind="$attrs" map-type-id="terrain" :max-zoom="13" ref="mapRef">
<slot/>
<template v-for="airspace in airspaces" :key="airspace">
<Polygon :options="airspace" @click=showInfo v-if="airspace.path"/>
<Circle :options="airspace" @click=showInfo v-if="airspace.center && airspace.radius"/>
</template>
<Circle :options="atz" v-for="atz in atzs" @click=showInfo :key="atz"/>
</GoogleMap>
</template>