From 4dd17ad7261495e38b44fe52bd0dd6eb14c715d9 Mon Sep 17 00:00:00 2001 From: Keith Paterson Date: Mon, 4 Jan 2021 22:18:38 +0100 Subject: [PATCH] #107 Tower position editable --- src/renderer/components/EditBar.vue | 1 + src/renderer/components/LeafletSidebar.vue | 4 +- src/renderer/components/TowerEdit.vue | 85 ++++++++++++++++++++++ src/renderer/components/TowerLayer.vue | 12 ++- src/renderer/components/Upload.vue | 51 +++++++++---- src/renderer/loaders/Tower.js | 19 ++++- src/renderer/loaders/tower_loader.js | 9 +-- src/renderer/loaders/tower_writer.js | 52 +++++++++++++ src/renderer/store/modules/Editable.js | 10 +++ 9 files changed, 215 insertions(+), 28 deletions(-) create mode 100644 src/renderer/components/TowerEdit.vue create mode 100644 src/renderer/loaders/tower_writer.js diff --git a/src/renderer/components/EditBar.vue b/src/renderer/components/EditBar.vue index 929e128..908f50f 100644 --- a/src/renderer/components/EditBar.vue +++ b/src/renderer/components/EditBar.vue @@ -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) diff --git a/src/renderer/components/LeafletSidebar.vue b/src/renderer/components/LeafletSidebar.vue index 967de5b..f225dbc 100644 --- a/src/renderer/components/LeafletSidebar.vue +++ b/src/renderer/components/LeafletSidebar.vue @@ -40,6 +40,7 @@ You should have received a copy of the GNU General Public License along with FG + @@ -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) diff --git a/src/renderer/components/TowerEdit.vue b/src/renderer/components/TowerEdit.vue new file mode 100644 index 0000000..316751a --- /dev/null +++ b/src/renderer/components/TowerEdit.vue @@ -0,0 +1,85 @@ + + + + diff --git a/src/renderer/components/TowerLayer.vue b/src/renderer/components/TowerLayer.vue index aa16b6e..0b0a8b6 100644 --- a/src/renderer/components/TowerLayer.vue +++ b/src/renderer/components/TowerLayer.vue @@ -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) { diff --git a/src/renderer/components/Upload.vue b/src/renderer/components/Upload.vue index 3146762..c3cfb7c 100644 --- a/src/renderer/components/Upload.vue +++ b/src/renderer/components/Upload.vue @@ -7,8 +7,12 @@ E-Mail : {{this.$store.state.Settings.settings.email}}
I agree to release the groundnet under GPL v2
{{message}}
+ + Upload Tower + Upload Groundnet + - {{buttonText}} + {{buttonText}} @@ -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 @@ diff --git a/src/renderer/loaders/Tower.js b/src/renderer/loaders/Tower.js index 819aa7c..81dce99 100644 --- a/src/renderer/loaders/Tower.js +++ b/src/renderer/loaders/Tower.js @@ -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; diff --git a/src/renderer/loaders/tower_loader.js b/src/renderer/loaders/tower_loader.js index f932126..b44932d 100644 --- a/src/renderer/loaders/tower_loader.js +++ b/src/renderer/loaders/tower_loader.js @@ -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 diff --git a/src/renderer/loaders/tower_writer.js b/src/renderer/loaders/tower_writer.js new file mode 100644 index 0000000..14bff2b --- /dev/null +++ b/src/renderer/loaders/tower_writer.js @@ -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); + /** + -1.6286902 + 59.53396633 + 3.05 + */ + return { lon: o.longitude, lat: o.latitude, 'elev-m': o.height}; +} \ No newline at end of file diff --git a/src/renderer/store/modules/Editable.js b/src/renderer/store/modules/Editable.js index 45270bf..947863d 100644 --- a/src/renderer/store/modules/Editable.js +++ b/src/renderer/store/modules/Editable.js @@ -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) } }