#107 Tower position editable

This commit is contained in:
Keith Paterson
2021-01-04 22:18:38 +01:00
parent e6d473c73e
commit 4dd17ad726
9 changed files with 215 additions and 28 deletions
+1
View File
@@ -138,6 +138,7 @@ You should have received a copy of the GNU General Public License along with FG
},
saveDefered () {
this.$parent.$parent.$refs.editLayer.save()
this.$parent.$parent.$refs.towerLayer.save()
this.$parent.$parent.$refs.editLayer.disableEdit()
this.scanGroundnets()
Vue.set(this, 'saveDialogVisible', false)
+3 -1
View File
@@ -40,6 +40,7 @@ You should have received a copy of the GNU General Public License along with FG
<ParkingEdit></ParkingEdit>
<ArcEditMulti></ArcEditMulti>
<ArcEdit></ArcEdit>
<TowerEdit></TowerEdit>
<NodeEdit></NodeEdit>
<ParkingGroupEdit ref="parkingGroupEdit" @editParking="(msg) => $emit('editParking', msg)"></ParkingGroupEdit>
<AirportEdit ref="airportEdit" @edit="$emit('edit', $event)"></AirportEdit>
@@ -75,6 +76,7 @@ You should have received a copy of the GNU General Public License along with FG
import L from 'leaflet'
import AirportEdit from './AirportEdit'
import ArcEdit from './ArcEdit'
import TowerEdit from './TowerEdit'
import ArcEditMulti from './ArcEditMulti'
import CheckPanel from './CheckPanel'
import FileSelect from './FileSelect'
@@ -91,7 +93,7 @@ You should have received a copy of the GNU General Public License along with FG
export default {
name: 'leaflet-sidebar',
components: { Help, AirportEdit, ArcEdit, ArcEditMulti, CheckPanel, NodeEdit, ParkingEdit, ParkingGroupEdit, RunScan, FileSelect, SettingsPanel, Search, Upload, WorkInProgress },
components: { Help, AirportEdit, ArcEdit, ArcEditMulti, CheckPanel, NodeEdit, ParkingEdit, ParkingGroupEdit, RunScan, TowerEdit, FileSelect, SettingsPanel, Search, Upload, WorkInProgress },
props: [],
created () {
window.addEventListener('keydown', this.doCommand)
+85
View File
@@ -0,0 +1,85 @@
<template>
<div width="100%" v-if="tower">
<div>
<el-row>
<el-col :span="7">
<span class="label">Latitude :</span>
</el-col>
<el-col :span="17">
<el-input placeholder="Please input" v-model="latitude" :disabled="!editing"
@focus="coordFocussed = true"
@blur="coordFocussed = false"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<span class="label">Longitude :</span>
</el-col>
<el-col :span="17">
<el-input placeholder="Please input" v-model="longitude" :disabled="!editing"
@focus="coordFocussed = true"
@blur="coordFocussed = false"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<span class="label">Height :</span>
</el-col>
<el-col :span="17">
<el-input placeholder="Please input" v-model="height" :disabled="!editing"
@focus="coordFocussed = true"
@blur="coordFocussed = false"></el-input>
</el-col>
</el-row>
</div>
</div>
</template>
<script lang="js">
/* eslint-disable */
const Coordinates = require('coordinate-parser');
import {writeTowerXML} from '../loaders/tower_writer'
export default {
/*
methods: {
updateIsOnRunway (value) {
this.$store.commit('SET_EDIT_ISONRUNWAY', value)
}
},
*/
data () {
return {
coordFocussed: false
}
},
methods: {
save () {
var o = {latitude: this.latitude, longitude: this.longitude, height: this.height};
writeTowerXML(this.$store.state.Settings.settings.airportsDirectory, this.$parent.$parent.$parent.icao, o)
}
},
computed: {
editing: {
get: function () {
return false //this.$parent.$parent.$parent.$refs.editLayer.editing
}
},
tower: function () {
return this.$store.state.Editable.type === 'tower'
},
// {index: 39, lat: "N58 27.343", lon: "W03 5.153", isOnRunway: 0, holdPointType: "none"}
latitude: function () {
return this.$store.state.Editable.data.tower.coords.latitude;
},
longitude: function () {
return this.$store.state.Editable.data.tower.coords.longitude;
},
height: function () {
return this.$store.state.Editable.data.tower.coords.height;
}
}
}
</script>
+11 -1
View File
@@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License along with FG
import L from 'leaflet'
import LEdit from 'leaflet-editable/src/Leaflet.Editable.js'
import {readTowerXML} from '../loaders/tower_loader'
import {writeTowerXML} from '../loaders/tower_writer'
export default {
name: 'tower-layer',
@@ -72,8 +73,17 @@ You should have received a copy of the GNU General Public License along with FG
}
},
save () {
},
this.layerGroup.eachLayer(l => {
if (l instanceof L.TowerMarker) {
var latitude = l.getLatLng().lat.toFixed(6)
var longitude = l.getLatLng().lng.toFixed(6)
var height = l.elev_m
var o = {latitude: latitude, longitude: longitude, height: height}
writeTowerXML(this.$store.state.Settings.settings.airportsDirectory, l.icao, o)
}
})
},
setVisible (visible) {
if (this.layerGroup !== undefined) {
if (visible !== this.visible) {
+36 -15
View File
@@ -7,8 +7,12 @@
<span class="center">E-Mail : {{this.$store.state.Settings.settings.email}}</span><br/>
<span class="center"><el-checkbox v-model="gplv2" class="center">I agree to release the groundnet under GPL v2</el-checkbox></span><br/>
<span :class="textClass" v-if="message">{{message}}</span><br/>
<el-button @click="handleOkClicked('twr')" :disabled="!tower_comittable" >Upload Tower</el-button>
<el-button @click="handleOkClicked('groundnet')" :disabled="!groundnet_comittable" >Upload Groundnet</el-button>
<span slot="footer" class="dialog-footer">
<el-button @click="handleOkClicked" :disabled="!comittable">{{buttonText}}</el-button>
<el-button @click="closeClicked">{{buttonText}}</el-button>
</span>
</el-dialog>
</template>
@@ -54,7 +58,7 @@
},
data () {
return {
gplv2: false, message: null, error: false, progress: 0, max: 0, azure: false, success: false, uploading: false, buttonText: 'Upload'
gplv2: false, message: null, error: false, progress: 0, max: 0, azure: false, success: false, uploading: false, buttonText: 'Ok'
}
},
methods: {
@@ -90,18 +94,17 @@
this.error = true;
}
},
handleOkClicked () {
if( this.success ) {
// Upload success close
Vue.set(this.$parent, 'uploadVisible', false)
return;
}
closeClicked () {
Vue.set(this.$parent, 'uploadVisible', false)
return;
},
handleOkClicked (type) {
this.uploading = true;
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
this.icao + '.groundnet.new.xml');
this.icao + `.${type}.new.xml`);
if (f == null || !fs.existsSync(f)) {
this.message = 'File doesn\'t exist';
@@ -119,7 +122,7 @@
var formData = new FormData();
formData.append("gpl", this.gplv2 )
formData.append("user_email", this.$store.state.Settings.settings.email)
formData.append('groundnet', blob, this.icao + '.groundnet.xml');
formData.append('groundnet', blob, this.icao + `.${type}.xml`);
var parent = this.$parent;
var messageField = this.message;
@@ -139,15 +142,15 @@
parent.$refs.upload.message == e.srcElement.statusText
} else if(JSON.parse(e.srcElement.response).message.match('[A-Z0-9]* Imported Successfully')) {
parent.$refs.upload.success = true
parent.$refs.upload.message = 'Uploaded Successfully'
parent.$refs.upload.buttonText = 'Ok'
parent.$refs.upload.message = `${type} Uploaded Successfully`
parent.$store.commit('UPLOAD_WIP', parent.$store.state.Airports.currentAirport.icao)
} else if(JSON.parse(e.srcElement.response).message === 'XML Errors') {
var response = JSON.parse(e.srcElement.response);
if (response.validationErrors) {
parent.$refs.upload.message = 'XML Errors : \n';
response.validationErrors.forEach(element => {
parent.$refs.upload.message += element.message + '\r\n';
parent.$refs.upload.message += element.message + '\n';
});
}
} else if(JSON.parse(e.srcElement.response) !== undefined) {
@@ -282,7 +285,7 @@
}
},
textClass: function () {
return !this.error?'center':'error'
return !this.error?'centermessage':'error'
},
title: function () {
return `Upload ${this.icao} to groundweb.`
@@ -302,6 +305,22 @@
console.error('ICAO being set ' + newValue);
}
},
tower_comittable: function () {
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
this.icao + '.twr.new.xml');
return fs.existsSync(f) && this.gplv2 && this.max === 0 && this.azure && !this.uploading;
},
groundnet_comittable: function () {
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
this.icao + '.groundnet.new.xml');
return fs.existsSync(f) && this.$store.state.Check.results.filter(a => a.id>=0).length === 0 && this.gplv2 && this.max === 0 && this.azure && !this.uploading
},
comittable: function () {
return this.$store.state.Check.results.filter(a => a.id>=0).length === 0 && this.gplv2 && this.max === 0 && this.azure && !this.uploading
},
@@ -313,7 +332,9 @@
</script>
<style scoped lang="scss">
.center { text-align: center; vertical-align: middle; padding: 5px; font-size: 12pt; font-weight: normal;}
.el-dialog__body {padding: 10px;}
.center { text-align: center; vertical-align: middle; padding: 5px; font-size: 12pt; font-weight: normal}
.centermessage { text-align: left; vertical-align: middle; padding: 5px; font-size: 12pt; font-weight: normal; white-space: pre-line;}
.error { text-align: center; color: red; padding: 5px; font-size: 12pt; font-weight: normal;}
.el-dialog--center .el-dialog__body { padding: 5px;}
</style>
+15 -4
View File
@@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with FG
const convert = require('geo-coordinates-parser');
const fs = require('fs');
const path = require('path');
const store = require('../store');
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
@@ -60,19 +61,29 @@ L.TowerMarker = L.Marker.extend({
pixelValue: function (latitude, meters, zoomLevel) {
return meters / metersPerPixel(latitude, zoomLevel);
},
});
L.TowerMarker.addInitHook(function(){
this.svg = this.stripSVG('tower.svg');
this.iconSize = 64;
this.on('dragstart', function (event) {
console.debug("Drag Tower : ", event);
});
this.on('dragend', function (event) {
console.debug("DragEnd Tower : ", event);
store.default.dispatch('setTowerCoords',
event.target.getLatLng().lat.toFixed(6) + ' ' +
event.target.getLatLng().lng.toFixed(6) + ' ' +
event.target.elev_m);
});
});
//Builds a marker for a ai or multiplayer aircraft
var tower = function (n, options) {
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
return new L.TowerMarker([latlon.decimalLatitude, latlon.decimalLongitude], {heading: 0, pane: 'tower-pane'});
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
var marker = new L.TowerMarker([latlon.decimalLatitude, latlon.decimalLongitude], {pane: 'tower-pane'});
marker.elev_m = n.find('elev-m/text()').text();
return marker;
}
module.exports = tower;
+2 -7
View File
@@ -52,16 +52,11 @@ exports.readTowerXML = function (fDir, icao, force) {
}
var towerNodes = xml.find('PropertyList/tower/twr');
console.log("Tower " + towerNodes.length);
var merged = new Array();
var nodesLookup = {};
featureLookup = [];
console.log("Towers " + towerNodes.length);
towerNodes.map(n => {
var towerIcon = tower(n, layerGroup);
towerIcon['icao'] = icao
towerIcon.addTo(layerGroup);
/*
//DEBUG Code
+52
View File
@@ -0,0 +1,52 @@
/* eslint-disable */
const fs = require('fs');
const path = require('path');
const store = require('../store');
const util = require('util');
const mathjs = require('mathjs');
var builder = require('xmlbuilder');
var featureLookup = [];
var parkings = [];
var pushBackNodeLookup = [];
exports.writeTowerXML = function (fDir, icao, coordinates) {
try {
try { fs.mkdirSync(path.join(fDir), { recursive: true })} catch (err) { }
try { fs.mkdirSync(path.join(fDir, icao[0]),{ recursive: true })} catch (err) { }
try { fs.mkdirSync(path.join(fDir, icao[0], icao[1]), { recursive: true })} catch (err) { }
try { fs.mkdirSync(path.join(fDir, icao[0], icao[1], icao[2]), { recursive: true })} catch (err) { }
var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.twr.new.xml');
var fBak = path.join(fDir, icao[0], icao[1], icao[2], icao + '.twr.bak.xml');
if( fs.existsSync(f) ) {
fs.copyFileSync(f, fBak);
}
if (f == null)
return;
var xmlObj = { PropertyList: { tower: { twr: map(coordinates)} } };
xmlString = builder.create(xmlObj).end({ pretty: true });
fs.writeFileSync(f, xmlString);
console.debug(xmlString);
} catch (error) {
console.error(error);
}
return;
}
var map = function (o) {
console.debug(o);
/**
<lon>-1.6286902</lon>
<lat>59.53396633</lat>
<elev-m>3.05</elev-m>
*/
return { lon: o.longitude, lat: o.latitude, 'elev-m': o.height};
}
+10
View File
@@ -158,6 +158,13 @@ const mutations = {
'SET_EDIT_NODE_COORDS' (state, coords) {
Vue.set(state.data.node, 'coords', coords)
},
'SET_EDIT_TOWER_COORDS' (state, coords) {
state.type = 'tower'
state.data.tower = { coords: {} }
Vue.set(state.data.tower.coords, 'latitude', coords.split(' ')[0])
Vue.set(state.data.tower.coords, 'longitude', coords.split(' ')[1])
Vue.set(state.data.tower.coords, 'height', coords.split(' ')[2])
},
'SET_EDIT_ISONRUNWAY' (state, isOnRunway) {
Vue.set(state.data.node, 'isOnRunway', isOnRunway)
}
@@ -194,6 +201,9 @@ const actions = {
async setNode (context, node) {
context.commit('SET_EDIT_NODE', node.attributes)
context.commit('SET_EDIT_NODE_COORDS', node.lat.toFixed(6) + ' ' + node.lng.toFixed(6))
},
async setTowerCoords (context, node) {
context.commit('SET_EDIT_TOWER_COORDS', node)
}
}