Multiediting for Parkings

This commit is contained in:
portree_kid 2020-06-30 16:34:14 +02:00
parent 94779a1686
commit 57b83daa51
9 changed files with 446 additions and 136 deletions

View File

@ -1,3 +1,14 @@
<!--
Copyright 2020 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
-->
<template>
<div id="EditBar">
<Upload :visible.sync="uploadVisible" ref="upload"></Upload>

View File

@ -1,3 +1,14 @@
<!--
Copyright 2020 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
-->
<template></template>
<script lang="js">
@ -11,6 +22,8 @@
import L2 from 'leaflet-textpath'
import Vue from 'vue'
import { MessageBox } from 'element-ui';
const turf = require('@turf/turf')
const Coordinates = require('coordinate-parser');
const path = require('path')
@ -87,6 +100,21 @@
}
},
methods: {
getParkings(ring) {
var poly = turf.polygon(ring);
var parkings = []
this.groundnetLayerGroup.eachLayer(l => {
//console.log(l)
if (l instanceof L.ParkingSpot) {
var tp = turf.point([l.getLatLng().lat, l.getLatLng().lng]);
if (turf.booleanPointInPolygon(tp, poly)) {
parkings.push(l);
}
}
})
this.selection = parkings;
return parkings;
},
load (icao, force) {
if (this.groundnetLayerGroup !== undefined) {
this.groundnetLayerGroup.removeFrom(this.$parent.mapObject)
@ -151,6 +179,23 @@
getEditing () {
return this.editing;
},
onEdit (event) {
switch (event.type) {
case 'parking-group-angle':
this.selection.forEach(element => {
element.updateHeading(event.angle)
});
break;
case 'parking-group-wingspan':
this.selection.forEach(element => {
element.updateRadius(event.wingspan/2)
});
break;
default:
break;
}
},
enableEdit () {
this.editable = true
this.editing = true
@ -407,6 +452,7 @@
}
});
},
/*
getParkings (){
var parkings = []
this.groundnetLayerGroup.eachLayer(l => {
@ -416,6 +462,7 @@
})
return parkings
},
*/
refreshLookup(index) {
//element.__vertex
this.featureLookup[index] = this.featureLookup[index].filter(item => {

View File

@ -1,3 +1,14 @@
<!--
Copyright 2020 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
-->
<template>
<l-map
:zoom="zoom"
@ -16,7 +27,7 @@
</l-control>
-->
<!--<l-marker :lat-lng="marker"></l-marker>-->
<LeafletSidebar></LeafletSidebar>
<LeafletSidebar ref="sidebar" @edit="onEditSidebar"></LeafletSidebar>
<AiLayer ref="aiLayer"></AiLayer>
<PavementLayer ref="pavementLayer"></PavementLayer>
<!--<ThresholdLayer ref="thresholdLayer"></ThresholdLayer>-->
@ -32,7 +43,7 @@
></l-circle>
</l-layer-group>
<EditLayer ref="editLayer"></EditLayer>
<ToolLayer ref="toolLayer"></ToolLayer>
<ToolLayer ref="toolLayer" @select-poly="onSelectedPolygon"></ToolLayer>
<EditBar ref="editBar" @edit="onEdit"></EditBar>
<ToolBar ref="toolBar"></ToolBar>
</l-map>
@ -105,10 +116,20 @@
}
},
methods: {
onSelectedPolygon (ring) {
var parkings = this.$refs.editLayer.getParkings(ring)
console.log(ring)
console.log(parkings)
this.$refs.sidebar.setData(parkings)
},
onEdit (event) {
this.$refs.map.mapObject.options.minZoom = 13
this.$refs.editLayer.enableEdit()
this.$refs.toolBar.setEdit(this.$refs.editBar.isEditing)
this.$refs.sidebar.setEditing(this.$refs.editBar.isEditing)
},
onEditSidebar (event) {
this.$refs.editLayer.onEdit(event)
},
editAirport () {
if (this.editingAirport) {

View File

@ -1,128 +0,0 @@
<template>
<div id="wrapper">
<img id="logo" src="~@/assets/logo.png" alt="electron-vue">
<main>
<div class="left-side">
<span class="title">
Welcome to your new project!
</span>
<system-information></system-information>
</div>
<div class="right-side">
<div class="doc">
<div class="title">Getting Started</div>
<p>
electron-vue comes packed with detailed documentation that covers everything from
internal configurations, using the project structure, building your application,
and so much more.
</p>
<button @click="open('https://simulatedgreg.gitbooks.io/electron-vue/content/')">Read the Docs</button><br><br>
</div>
<div class="doc">
<div class="title alt">Other Documentation</div>
<button class="alt" @click="open('https://electron.atom.io/docs/')">Electron</button>
<button class="alt" @click="open('https://vuejs.org/v2/guide/')">Vue.js</button>
</div>
</div>
</main>
</div>
</template>
<script>
import SystemInformation from './LandingPage/SystemInformation'
export default {
name: 'landing-page',
components: { SystemInformation },
methods: {
open (link) {
this.$electron.shell.openExternal(link)
}
}
}
</script>
<style>
@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro');
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body { font-family: 'Source Sans Pro', sans-serif; }
#wrapper {
background:
radial-gradient(
ellipse at top left,
rgba(255, 255, 255, 1) 40%,
rgba(229, 229, 229, .9) 100%
);
height: 100vh;
padding: 60px 80px;
width: 100vw;
}
#logo {
height: auto;
margin-bottom: 20px;
width: 420px;
}
main {
display: flex;
justify-content: space-between;
}
main > div { flex-basis: 50%; }
.left-side {
display: flex;
flex-direction: column;
}
.welcome {
color: #555;
font-size: 23px;
margin-bottom: 10px;
}
.title {
color: #2c3e50;
font-size: 20px;
font-weight: bold;
margin-bottom: 6px;
}
.title.alt {
font-size: 18px;
margin-bottom: 10px;
}
.doc p {
color: black;
margin-bottom: 10px;
}
.doc button {
font-size: .8em;
cursor: pointer;
outline: none;
padding: 0.75em 2em;
border-radius: 2em;
display: inline-block;
color: #fff;
background-color: #4fc08d;
transition: all 0.15s ease;
box-sizing: border-box;
border: 1px solid #4fc08d;
}
.doc button.alt {
color: #42b983;
background-color: transparent;
}
</style>

View File

@ -1,3 +1,14 @@
<!--
Copyright 2020 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
-->
<template>
<div id="sidebar" class="leaflet-sidebar collapsed">
<!-- Nav tabs -->
@ -28,6 +39,7 @@
<ParkingEdit></ParkingEdit>
<ArcEdit></ArcEdit>
<NodeEdit></NodeEdit>
<ParkingGroupEdit ref="parkingGroupEdit" @edit="(msg) => $emit('edit', msg)"></ParkingGroupEdit>
<AirportEdit></AirportEdit>
</div>
<!--
@ -66,6 +78,7 @@
import Help from './Help'
import NodeEdit from './NodeEdit'
import ParkingEdit from './ParkingEdit'
import ParkingGroupEdit from './ParkingGroupEdit'
// import ParkingList from './ParkingList'
import RunScan from './RunScan'
import SettingsPanel from './SettingsPanel'
@ -74,7 +87,7 @@
export default {
name: 'leaflet-sidebar',
components: { Help, AirportEdit, ArcEdit, CheckPanel, NodeEdit, ParkingEdit, RunScan, FileSelect, SettingsPanel, Search, WorkInProgress },
components: { Help, AirportEdit, ArcEdit, CheckPanel, NodeEdit, ParkingEdit, ParkingGroupEdit, RunScan, FileSelect, SettingsPanel, Search, WorkInProgress },
props: [],
mounted () {
this.add()
@ -122,6 +135,15 @@
this.deferredMountedTo(this.$parent.mapObject)
}
},
setEditing (editing) {
this.$refs.parkingGroupEdit.setEditing(editing)
},
setData (data) {
if (data.length > 0) {
this.sidebar.open('edit')
this.$refs.parkingGroupEdit.setData(data)
}
},
scan () {
}
},

View File

@ -0,0 +1,300 @@
<template>
<div v-if="parking">
<!--
airlineCodes: 0
heading: 341.34
index: 13
lat: "N59 52.610885"
lon: "W1 17.855144"
name: "Western_Apron_Hanger"
pushBackRoute: 27
radius: 18
type: "gate"
-->
<!--
<el-row>
<el-col :span="4">
<span class="label">Name :</span>
</el-col>
<el-col :span="8">
<el-input placeholder="Name" v-model="name" :disabled="!editing"></el-input>
</el-col>
</el-row>
-->
<el-row>
<el-col :span="7">
<span class="label">Size :</span>
</el-col>
<el-col :span="17">
<!--
* Cat Models FG Radii N2M Radii
* B Small Regionals ERJ CRJ ATR 14 6
* C A319 A320 A321 B737 18 10
* D B757, B767 26 15
* E B777 B787 A330 A340 A360 33 24
* F A380 40 24
-->
<el-radio-group v-model="wingspan" :disabled="!editing" @change="wingspanChange">
<el-tooltip content="PIPER PA-31/CESSNA 404 Titan" placement="top" effect="light">
<el-radio :label="15">A</el-radio>
</el-tooltip>
<el-tooltip
content="BOMBARDIER Regional Jet CRJ-200/DE HAVILLAND CANADA DHC-6"
placement="top"
effect="light"
>
<el-radio :label="28">B</el-radio>
</el-tooltip>
<el-tooltip
content="BOEING 737-700/AIRBUS A-320/EMBRAER ERJ 190-100"
placement="top"
effect="light"
>
<el-radio :label="36">C</el-radio>
</el-tooltip>
<el-tooltip content="B767 Series/AIRBUS A-310" placement="top" effect="light">
<el-radio :label="52">D</el-radio>
</el-tooltip>
<el-tooltip content="B777 Series/B787 Series/A330 Family" placement="top" effect="light">
<el-radio :label="66">E</el-radio>
</el-tooltip>
<el-tooltip content="BOEING 747-8/AIRBUS A-380-800" placement="top" effect="light">
<el-radio :label="80">F</el-radio>
</el-tooltip>
</el-radio-group>
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<span class="label">Aircraft :</span>
</el-col>
<el-col :span="17" class="value">{{type}}</el-col>
</el-row>
<el-row>
<el-col :span="7">
<span class="label">Heading :</span>
</el-col>
<el-col :span="17">
<el-input-number
v-model="avgHeading" @change="headingChange"
:min="-361"
:max="720"
:step="0.1"
:precision="1"
:disabled="!editing"
></el-input-number>
</el-col>
</el-row>
<!--
<el-row>
<el-col :span="7">
<span class="label">Parking Type :</span>
</el-col>
<el-col :span="17">
<el-select v-model="parking_type" placeholder="Select" :disabled="!editing">
<el-option
v-for="type in options"
:key="type.value"
:label="type.label"
:value="type.value"
:disabled="type.disabled"
></el-option>
</el-select>
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<span class="label">Airline :</span>
</el-col>
<el-col :span="17">
<el-select v-model="airlineCodes" multiple placeholder="Select" :disabled="!editing">
<el-option
v-for="item in airlines"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-col>
</el-row>
-->
</div>
</template>
<script lang="js">
/* eslint-disable */
import Vue from 'vue'
const convert = require('geo-coordinates-parser');
const Coordinates = require('coordinate-parser');
export default {
data () {
return {
data: Object, avgHeading: 5, editing: Boolean, wingspan: 0
}
},
methods: {
show (idx) {
this.$parent.$parent.$parent.$refs.editLayer.show(idx)
},
setData (data) {
this.data = data;
this.setAvgHeading();
},
setEditing(editing) {
this.editing = editing
},
setAvgHeading() {
if( this.data === null || this.data === undefined) {
return 0
}
this.avgHeading = Number( this.data.reduce(function (r, parking) {
r.sum = r.sum + parking.options.attributes.heading;
r.avg = r.sum / ++r.count;
return r;
}, { sum: 0, count: 0, avg: 0 }).avg);
},
wingspanChange( newValue ) {
if ( newValue ) {
this.$emit('edit', {type: 'parking-group-wingspan', wingspan: newValue} )
}
},
headingChange( newValue ) {
while (newValue>=360) {
newValue -= 360
}
while (newValue<0) {
newValue += 360
}
if ( newValue ) {
this.$emit('edit', {type: 'parking-group-angle', angle: newValue} )
}
}
},
computed: {
parking: function () {
return this.data !== null
},
airlines: function () {
var airlineCodes = [];
var storedairlineCodes = this.$store.state.Airports.currentAirport.airlines;
// return [{value: 'bi-directional', label: 'bi-directional'},
// {value: 'forward', label: 'forward'},
// {value: 'backward', label: 'backward'}
// ]
if(storedairlineCodes) {
storedairlineCodes.forEach(element => {
airlineCodes.push({value: element, label: element});
});
}
return airlineCodes
},
airlineCodes: {
// getter
get: function () {
},
// setter
set: function (newValue) {
}
},
name: {
// getter
get: function () {
},
// setter
set: function (newValue) {
}
},
number: {
// getter
get: function () {
},
// setter
set: function (newValue) {
}
},
pushbackEnd: function () {
return this.$parent.$parent.$parent.$refs.editLayer.findRouteToPushback(this.$store.state.Editable.index)
},
type: function () {
/**
* Cat Models FG Radii N2M Radii
* B Small Regionals ERJ CRJ ATR 14 6
* C A319 A320 A321 B737 18 10
* D B757, B767 26 15
* E B777 B787 A330 A340 A360 33 24
* F A380 40 24
*/
switch (this.wingspan) {
case 15:
return 'PIPER PA-31/CESSNA 404 Titan'
case 28:
return 'BOMBARDIER Regional Jet CRJ-200/DE HAVILLAND CANADA DHC-6'
case 36:
return 'BOEING 737-700/AIRBUS A-320/EMBRAER ERJ 190-100'
case 52:
return 'B767 Series/AIRBUS A-310'
case 66:
return 'B777 Series/B787 Series/A330 Family'
case 80:
return 'BOEING 747-8/AIRBUS A-380-800'
default:
return 'Unknown radius : ' + this.wingspan
}
},
// ga (general aviation), cargo (cargo), gate (commercial passenger traffic),
// mil-fighter (military fighter), mil-cargo (military transport)
options: function () {
return [{value: 'none', label: 'none', disabled: true},
{value: 'ga', label: 'general aviation'},
{value: 'cargo', label: 'cargo'},
{value: 'gate', label: 'commercial passenger traffic'},
{value: 'mil-fighter', label: 'military fighter'},
{value: 'mil-cargo', label: 'military cargo'}
]
},
parking_type: {
// getter
get: function () {
if (this.$store.state.Editable.data.parking.type === undefined) {
return 'none'
}
return this.$store.state.Editable.data.parking.type
},
// setter
set: function (newValue) {
this.$store.commit('SET_EDIT_PARKING_TYPE', newValue)
}
}
}
}
</script>
<style>
.el-row {
margin: 1px;
}
.el-col {
padding-left: 2pt;
}
.label {
display: flex;
justify-content: left;
align-items: center;
font-weight: bold;
}
.value {
display: flex;
justify-content: left;
align-items: center;
}
.el-popover--plain {
padding: 10px 10px;
}
.el-popover__title {
display: none;
}
</style>

View File

@ -1,10 +1,21 @@
<!--
Copyright 2020 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
-->
<template>
<div id="ToolBar">
<ToolButton
icon="fas fa-draw-polygon"
v-on:click="drawPolyline"
:show="editing"
tooltip="Draw Guidline"
tooltip="Draw Guideline"
></ToolButton>
</div>
</template>
@ -12,11 +23,12 @@
<script lang="js">
/* eslint-disable */
import ToolButton from './ToolButton'
import Vue from 'vue'
import Vue from 'vue'
import fileUrl from 'file-url'
const path = require('path')
const fs = require('fs');
const fs = require('fs')
export default {
components: { ToolButton },

View File

@ -16,6 +16,8 @@ You should have received a copy of the GNU General Public License along with FG
import {LMap, LMarker} from 'vue2-leaflet'
import L from 'leaflet'
import LEdit from 'leaflet-editable/src/Leaflet.Editable.js'
const turf = require('@turf/turf')
export default {
name: 'tool-layer',
@ -53,9 +55,21 @@ You should have received a copy of the GNU General Public License along with FG
});
},
drawPolyline () {
var polyLine = this.$parent.mapObject.editTools.startPolyline(undefined, {color: 'green'})
var polyLine = this.$parent.mapObject.editTools.startPolygon(undefined, {color: 'green'})
polyLine.addTo(this.toolLayerGroup)
polyLine.toolLayerGroup = this.toolLayerGroup;
polyLine.on('editable:drawing:end', event => {
console.log(event)
var latLngs = event.target.getLatLngs()[0].map( latLng => ([latLng.lat, latLng.lng]));
// turf rings must start/end with the same point
latLngs.push(latLngs[0]);
var ring = [latLngs];
this.$emit('select-poly', ring);
})
},
},

View File

@ -75,6 +75,17 @@ L.ParkingSpot = L.Circle.extend({
removeDirection() {
this.direction = undefined;
},
updateHeading(heading) {
this.options.attributes.heading = heading;
this.updateVertexFromDirection();
this.updateWheelPos();
},
updateRadius(radius) {
this._mRadius = radius;
this.updateDirectionFromVertex();
this.updateVertexFromDirection();
this.updateWheelPos();
},
// Update the direction vertex from the direction
updateVertexFromDirection() {
if (this.editEnabled()) {