Zakladni verze planovace

This commit is contained in:
Michal Kváček
2024-04-15 18:13:22 +02:00
parent 338ec13db2
commit cee979fec8
15 changed files with 672 additions and 304 deletions
@@ -0,0 +1,23 @@
<script setup>
import {commonProps} from "src/composables/inputs";
const props = defineProps({
markers: {
type: Array,
required: true
}
});
const swapMarkers = (idx1, idx2) => {
const tmp = markers.value[idx1];
markers.value[idx1] = markers.value[idx2];
markers.value[idx2] = tmp;
};
</script>
<template>
sem prijde ten modal, ve kterem se edituje cela trasa
</template>
@@ -13,7 +13,7 @@ const props = defineProps({
<q-list bordered separator>
<q-item
clickable
:to="{name: 'flightPlan', params: {id: flightPlan.id }}"
:to="{name: 'editFlightPlan', params: {id: flightPlan.id }}"
v-ripple
v-for="flightPlan of items" :key="flightPlan">
<q-item-section avatar>
@@ -0,0 +1,104 @@
import {computed} from "vue";
const markersCenter = computed(() => {
if (markers.value.length === 0) return null;
return {
gpsLatitude: markers.value.map(m => m.gpsLatitude).reduce((a, b) => a + b) / markers.value.length,
gpsLongitude: markers.value.map(m => m.gpsLongitude).reduce((a, b) => a + b) / markers.value.length,
}
});
const calcAngleFromCenter = (pointA, pointB) => {
if (!markersCenter.value) return 0;
const u = vector(markersCenter.value, pointA);
const v = vector(markersCenter.value, pointB);
return Math.acos(
(u[0] * v[0] + u[1] * v[1])
/
(vectorSize(u) * vectorSize(v))
)
}
let targetPosition = null;
let minAngleDiff = Infinity;
let mapPoints = 1;
const handleMapClickNefunkcni = (position) => {
const clickPoint = {gpsLatitude: position.lat, gpsLongitude: position.lng};
const clickAngle = calcAngleFromCenter(clickPoint, markers.value[0]);
for (let i = 1; i < markers.value.length - 1; i++) {
const marker = markers.value[i];
const angle = calcAngleFromCenter(marker, markers.value[0]);
const angleDiff = clickAngle - angle;
console.log("click", i, marker.name, angleDiff);
if (angleDiff < minAngleDiff) {
console.log(" update => ", minAngleDiff, " > ", Math.abs(angleDiff), marker.name, " -> ", markers.value[i + 1].name);
minAngleDiff = angleDiff
targetPosition = Math.max(1, angleDiff < 0 ? i - 1 : i + 1);
}
// console.log(marker.name, angle);
}
console.log("click", clickAngle);
console.log("insert at position", targetPosition);
console.log("---------------")
markers.value.splice(targetPosition, 0, {name: `Bod v mape ${mapPoints}`, type: "mapPoint", ...clickPoint});
mapPoints++;
}
const handleMapClickNefunkcni2 = (position) => {
const clickPoint = {gpsLatitude: position.lat, gpsLongitude: position.lng}
const markersToSort = markers.value.slice(1, -1);
markersToSort.push({name: `Bod v mape ${mapPoints}`, type: "mapPoint", ...clickPoint});
markersToSort.sort(
(a, b) => calcAngleFromCenter(a, markers.value[0]) - calcAngleFromCenter(b, markers.value[0])
);
for (const marker of markersToSort) {
console.log(marker.name, calcAngleFromCenter(marker, markers.value[0]));
}
markers.value = [markers.value[0], ...markersToSort, markers.value[markers.value.length - 1]];
mapPoints++;
}
const calcTotalDistance = (points) => {
let distance = 0;
for (let i = 1; i < points.length; i++) {
distance += vectorDistance(points[i-1], points[i])
}
return distance
}
let minDistance = Infinity;
const handleMapClick = (position) => {
const clickPoint = {gpsLatitude: position.lat, gpsLongitude: position.lng};
const newMarker = {name: `Bod v mape ${mapPoints}`, type: "mapPoint", ...clickPoint}
markers.value.push(newMarker)
for (let i = 1; i < markers.value.length - 1; i++) {
console.log(markers.value[i], clickPoint);
const dist = vectorDistance(markers.value[i], clickPoint);
if (dist < minDistance) {
minDistance = dist;
targetPosition = i;
}
}
targetPosition = Math.min(markers.value.length - 1, Math.max(1, targetPosition));
markers.value.splice(targetPosition, 0, {name: `Bod v mape ${mapPoints}`, type: "mapPoint", ...clickPoint});
mapPoints++;
}
+39 -28
View File
@@ -1,6 +1,7 @@
<script setup>
import {Circle, GoogleMap, Marker, Polygon} from "vue3-google-map";
import {Circle, GoogleMap, CustomMarker, Polygon} from "vue3-google-map";
import {computed, ref, watch} from "vue";
import {useBasicVectorOperations, useVectorUtities} from "src/graphql/fragments/vectorUtilities";
const props = defineProps({
bounds: {
@@ -87,46 +88,56 @@ const atzs = computed(() => {
// TODO: pridat letiste
function isPointInPolygon(clickPoint, polygonCoords) {
var count = 0;
var x = clickPoint.lng, y = clickPoint.lat;
const {isPointInPolygon} = useVectorUtities();
const {vectorDistance} = useBasicVectorOperations();
for (var i = 0; i < polygonCoords.length; i++) {
var iNext = (i + 1) % polygonCoords.length;
const handleLayerClick = (e) => {
const clickCoordinates = {lat: e.latLng.lat(), lng: e.latLng.lng()}
var xi = polygonCoords[i].lng, yi = polygonCoords[i].lat;
var xiNext = polygonCoords[iNext].lng, yiNext = polygonCoords[iNext].lat;
const airspacesUnderClick = []
var test = ((yi > y) !== (yiNext > y)) && (x < (xiNext - xi) * (y - yi) / (yiNext - yi) + xi);
if (test) count++;
for (const atz of atzs.value) {
const distance = vectorDistance(
{gpsLatitude: e.latLng.lat(), gpsLongitude: e.latLng.lng()},
{gpsLatitude: atz.center.lat, gpsLongitude: atz.center.lng},
);
if (distance < 0.079) { // tohle je nejaka bulharska konstanta, +- 5km od stredu letiste
airspacesUnderClick.push(atz);
}
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);
}
}
for (const airspace of airspaces.value) {
if (airspace.path && isPointInPolygon(clickCoordinates, airspace.path)) {
airspacesUnderClick.push(airspace);
}
}
emits("map-click", {airspaces: airspacesUnderClick, clickCoordinates});
}
const emits = defineEmits(["map-click"]);
const handleMapClick = (e) => {
const clickCoordinates = {lat: e.latLng.lat(), lng: e.latLng.lng()}
emits("map-click", {clickCoordinates});
};
</script>
<template>
<GoogleMap :api-key="key" v-bind="$attrs" map-type-id="terrain" :max-zoom="13" ref="mapRef">
<GoogleMap :api-key="key" v-bind="$attrs" @click="handleMapClick" 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"/>
<Polygon :options="airspace" @click=handleLayerClick v-if="airspace.path"/>
<Circle :options="airspace" @click=handleLayerClick v-if="airspace.center && airspace.radius"/>
</template>
<template v-for="atz in atzs" :key="atz">
<Circle :options="atz" @click=handleLayerClick />
<CustomMarker :options="{position: atz.center, anchorPoint: 'CENTER'}" @click="handleLayerClick">
<q-icon name="local_airport" style="font-size: 24px" class="text-primary"/>
</CustomMarker>
</template>
<Circle :options="atz" v-for="atz in atzs" @click=showInfo :key="atz"/>
</GoogleMap>
</template>