Merge branch 'master' of C:\Users\dikpater\flightgear-airports\flightgear-airports\.git into NodeJS

This commit is contained in:
Paterson
2020-12-18 21:50:51 +01:00
28 changed files with 1217 additions and 333 deletions
+106
View File
@@ -0,0 +1,106 @@
<!--
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 width="100%" v-if="multiarc">
<!--
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="7">
<span class="demo-input-label">Name :</span>
</el-col>
<el-col :span="15">
<el-input placeholder="Please input" v-model="name"></el-input>
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<span class="demo-input-label">Pushback :</span>
</el-col>
<el-col :span="15">
<el-switch v-model="isPushback"></el-switch>
</el-col>
</el-row>
<el-row>
<el-col :span="7">
<span class="demo-input-label">Direction :</span>
</el-col>
<el-col :span="15">
<el-select v-model="direction" placeholder="Select">
<el-option
v-for="type in options"
:key="type.value"
:label="type.label"
:value="type.value"
></el-option>
</el-select>
</el-col>
</el-row>
</div>
</template>
<script lang="js">
export default {
computed: {
multiarc: function () {
return this.$store.state.Editable.type === 'multiarc'
},
// ga (general aviation), cargo (cargo), gate (commercial passenger traffic),
// mil-fighter (military fighter), mil-cargo (military transport)
options: function () {
return [{value: 'bi-directional', label: 'bi-directional'},
{value: 'forward', label: 'forward'},
{value: 'backward', label: 'backward'}
]
},
name: {
// getter
get: function () {
return this.$store.state.Editable.data.multiarc.name
},
// setter
set: function (newValue) {
this.$store.commit('SET_EDIT_ARC_NAME', newValue)
}
},
isPushback: {
// getter
get: function () {
return this.$store.state.Editable.data.multiarc.isPushBackRoute === '1' ||
Number(this.$store.state.Editable.data.multiarc.isPushBackRoute) === Number(1)
},
// setter
set: function (newValue) {
this.$store.commit('SET_EDIT_PUSHBACK', newValue ? '1' : '0')
}
},
direction: {
// getter
get: function () {
return this.$store.state.Editable.data.multiarc.direction
},
// setter
set: function (newValue) {
this.$store.commit('SET_EDIT_DIRECTION', newValue)
}
}
}
}
</script>
+12 -4
View File
@@ -3,7 +3,7 @@
<div class="select-button">
...
</div>
<input type="file" @change="handleFileChange" webkitdirectory directory/>
<input name="hiddenDir" type="file" v-on:change="handleFileChange($event)" webkitdirectory directory tabindex="-1"/>
</label>
</template>
@@ -20,9 +20,15 @@
methods: {
handleFileChange (e) {
var first = e.target.files[0].webkitRelativePath.split("/")[0];
var webkitdirectoryPath = e.target.files[0].path.split(first)[0] + first;
this.$emit('input', webkitdirectoryPath)
try {
if (e.target.files && e.target.files.length>0) {
var first = e.target.files[0].webkitRelativePath.split("/")[0];
var webkitdirectoryPath = e.target.files[0].path.split(first)[0] + first;
this.$emit('input', webkitdirectoryPath)
}
} catch (error) {
console.error(error)
}
}
}
}
@@ -39,6 +45,8 @@
text-align: center;
font-weight: bold;
width: 28px;
height: 28px;
}
.directory-select > input[type="file"] {
+43 -9
View File
@@ -41,11 +41,7 @@ You should have received a copy of the GNU General Public License along with FG
props: [],
created () {
console.log(LMap)
console.log(LMarker)
console.log(L)
console.log(LEdit)
console.log(L2)
[LMap, LMarker, L, LEdit, L2]
console.log('Created Editlayer')
// console.log(LSymbol)
},
@@ -72,6 +68,16 @@ You should have received a copy of the GNU General Public License along with FG
deep: true //add this if u need to watch object properties change etc.
}
);
this.$store.watch(
function (state) {
return state.Editable.data.multiarc;
},
() => { this.editedMultiArc() }
,
{
deep: true //add this if u need to watch object properties change etc.
}
);
this.$store.watch(
function (state) {
return state.Editable.data.parking;
@@ -125,12 +131,18 @@ You should have received a copy of the GNU General Public License along with FG
this.icao = icao
this.groundnetLayerGroup = readGroundnetXML(this.$store.state.Settings.settings.airportsDirectory, icao, force)
if (this.groundnetLayerGroup === undefined) {
console.error('ICAO not loaded ' + icao)
console.warn('Groundnet for ICAO not loaded ' + icao)
return
}
if (this.groundnetLayerGroup.getLayers().length === 0) {
console.warn('Groundnet for ICAO not loaded ' + icao)
}
this.groundnetLayerGroup.eachLayer(l => {
if (l instanceof L.TaxiwaySegment) {
l.addListeners()
l.addListeners()
}
if (l.updateArrows !== undefined) {
l.updateArrows(this.$store.state.Settings.zoom)
}
})
console.log(this.groundnetLayerGroup.maxId)
@@ -659,6 +671,7 @@ You should have received a copy of the GNU General Public License along with FG
!this.editing) {
return;
}
console.debug("Edit Type : " + this.$store.state.type);
var arc = this.groundnetLayerGroup.getLayer(this.$store.state.Editable.index);
if (arc && arc instanceof L.Polyline) {
console.log('Edited Arc : ' + this.$store.state.Editable.index);
@@ -666,6 +679,27 @@ You should have received a copy of the GNU General Public License along with FG
arc.updateStyle();
}
},
editedMultiArc() {
if (!this.groundnetLayerGroup ||
this.$store.state.Editable.data.multiarc === undefined ||
this.$store.state.Editable.data.multiarc.ids === undefined ||
this.featureLookup===undefined ||
!this.editing) {
return;
}
console.debug("Edit Type : " + this.$store.state.Editable.data.multiarc.ids);
this.$store.state.Editable.data.multiarc.ids.forEach(id => {
console.debug(id);
var arc = this.groundnetLayerGroup.getLayer(id);
if (arc && arc instanceof L.Polyline) {
console.log('Edited Arc : ' + this.$store.state.Editable.index);
arc.options.attributes.direction = this.$store.state.Editable.data.multiarc.direction
arc.options.attributes.name = this.$store.state.Editable.data.multiarc.name
arc.options.attributes.isPushBackRoute = this.$store.state.Editable.data.multiarc.isPushBackRoute
arc.updateStyle();
}
});
},
//Update Node
editedNode() {
if (this.$store.state.Editable.index === undefined ||
@@ -825,11 +859,11 @@ You should have received a copy of the GNU General Public License along with FG
this.$parent.mapObject.on('click', this.addParking)
},
removeLayerClick (event) {
console.log(event)
console.debug(event)
this.groundnetLayerGroup.removeLayer(event.target)
},
addParking (event) {
console.log(event.latlng)
console.debug(event.latlng)
if (event.latlng === undefined) {
return
}
+52 -6
View File
@@ -30,8 +30,6 @@ You should have received a copy of the GNU General Public License along with FG
<!--<l-marker :lat-lng="marker"></l-marker>-->
<LeafletSidebar ref="sidebar" @editParking="onEditSidebar" @edit="onEdit($event)"></LeafletSidebar>
<AiLayer ref="aiLayer"></AiLayer>
<PavementLayer ref="pavementLayer"></PavementLayer>
<ThresholdLayer ref="thresholdLayer"></ThresholdLayer>
<l-layer-group layerType="overlay" name="airports" ref="airportLayer">
<l-circle
v-for="(item, index) in this.$store.state.Airports.airports"
@@ -44,6 +42,9 @@ You should have received a copy of the GNU General Public License along with FG
></l-circle>
</l-layer-group>
<EditLayer ref="editLayer"></EditLayer>
<PavementLayer ref="pavementLayer"></PavementLayer>
<ThresholdLayer ref="thresholdLayer"></ThresholdLayer>
<TowerLayer ref="towerLayer"></TowerLayer>
<ToolLayer ref="toolLayer" @select-poly="onSelectedPolygon"></ToolLayer>
<EditBar ref="editBar" @edit="onEdit($event)"></EditBar>
<ToolBar ref="toolBar"></ToolBar>
@@ -60,6 +61,7 @@ You should have received a copy of the GNU General Public License along with FG
import ToolBar from './ToolBar'
import EditLayer from './EditLayer'
import ToolLayer from './ToolLayer'
import TowerLayer from './TowerLayer'
import PavementLayer from './PavementLayer'
import ThresholdLayer from './ThresholdLayer'
@@ -75,7 +77,7 @@ You should have received a copy of the GNU General Public License along with FG
})
export default {
name: 'flightgear-map',
components: { LMap, LTileLayer, LMarker, LCircle, LeafletSidebar, AiLayer, EditBar, ToolBar, EditLayer, PavementLayer, LLayerGroup, LControl, ThresholdLayer, ToolLayer },
components: { LMap, LTileLayer, LMarker, LCircle, LeafletSidebar, AiLayer, EditBar, ToolBar, EditLayer, TowerLayer, PavementLayer, LLayerGroup, LControl, ThresholdLayer, ToolLayer },
props: [],
created () {
this.loadingInstance = null
@@ -85,7 +87,7 @@ You should have received a copy of the GNU General Public License along with FG
},
(newValue, oldValue) => {
// debugger
console.log('setIcaoLoading ' + oldValue + ' => ' + newValue + ' ' + this.groundnetLoaded + ' ' + this.pavementLoaded + ' ' + this.loadingInstance)
console.log('setIcaoLoading ' + oldValue + ' => ' + newValue + ' groundnetLoaded ' + this.groundnetLoaded + ' pavementLoaded ' + this.pavementLoaded + ' ' + this.loadingInstance)
if (newValue !== oldValue && newValue !== '') {
this.groundnetLoaded = newValue
if ((this.loadingInstance === null || this.loadingInstance === undefined)) {
@@ -105,7 +107,7 @@ You should have received a copy of the GNU General Public License along with FG
},
(newValue, oldValue) => {
// debugger
console.log('groundnetLoaded ' + oldValue + ' => ' + newValue + ' ' + this.groundnetLoaded + ' ' + this.pavementLoaded + ' ' + this.loadingInstance)
console.log('groundnetLoaded ' + oldValue + ' => ' + newValue + ' groundnetLoaded ' + this.groundnetLoaded + ' pavementLoaded ' + this.pavementLoaded + ' ' + this.loadingInstance)
if (newValue !== oldValue) {
this.groundnetLoaded = newValue
if (this.groundnetLoaded &&
@@ -160,6 +162,9 @@ You should have received a copy of the GNU General Public License along with FG
this.$refs.pavementLayer.load(airportsToLoad[0])
this.$refs.editLayer.load(airportsToLoad[0])
this.$refs.thresholdLayer.load(airportsToLoad[0])
if (this.$refs.towerLayer) {
this.$refs.towerLayer.load(airportsToLoad[0])
}
this.editingAirport = airportsToLoad[0]
})
}
@@ -169,7 +174,6 @@ You should have received a copy of the GNU General Public License along with FG
if (this.$refs.airportLayer) {
this.$refs.airportLayer.setVisible(this.zoom < 12)
}
// console.log(this.groundnet)
}
})
@@ -208,16 +212,34 @@ You should have received a copy of the GNU General Public License along with FG
if (this.$refs.pavementLayer.getLayer() === e.layer) {
// debugger
var l = this.layersControl._layers.filter(l => l.name === 'APT Layer')
if (l.length > 0 && l[0].layer !== this.$refs.pavementLayer.getLayer()) {
this.layersControl.removeLayer(l[0].layer)
this.layersControl.addOverlay(this.$refs.pavementLayer.getLayer(), 'APT Layer')
}
if (l.length === 0) {
this.layersControl.addOverlay(this.$refs.pavementLayer.getLayer(), 'APT Layer')
}
}
if (this.$refs.thresholdLayer.getLayer() === e.layer) {
l = this.layersControl._layers.filter(l => l.name === 'Threshold Layer')
if (l.length > 0 && l[0].layer !== this.$refs.thresholdLayer.getLayer()) {
this.layersControl.removeLayer(l[0].layer)
this.layersControl.addOverlay(this.$refs.thresholdLayer.getLayer(), 'Threshold Layer')
}
if (l.length === 0) {
this.layersControl.addOverlay(this.$refs.thresholdLayer.getLayer(), 'Threshold Layer')
}
}
if (this.$refs.towerLayer !== undefined && this.$refs.towerLayer.getLayer() === e.layer) {
l = this.layersControl._layers.filter(l => l.name === 'Tower Layer')
if (l.length > 0 && l[0].layer !== this.$refs.towerLayer.getLayer()) {
this.layersControl.removeLayer(l[0].layer)
this.layersControl.addOverlay(this.$refs.towerLayer.getLayer(), 'Tower Layer')
}
if (l.length === 0) {
this.layersControl.addOverlay(this.$refs.towerLayer.getLayer(), 'Tower Layer')
}
}
},
onSelectedPolygon (ring) {
var parkings = this.$refs.editLayer.getParkings(ring)
@@ -234,6 +256,7 @@ You should have received a copy of the GNU General Public License along with FG
this.$refs.map.mapObject.options.minZoom = 1
}
this.$refs.editLayer.enableEdit()
this.$refs.towerLayer.enableEdit()
this.$refs.editBar.setEditing(event)
this.$refs.toolBar.setEditing(event)
this.$refs.sidebar.setEditing(event)
@@ -317,13 +340,36 @@ You should have received a copy of the GNU General Public License along with FG
if (zoom !== this.$store.state.Settings.zoom) {
this.$store.dispatch('setZoom', zoom)
this.$refs.airportLayer.setVisible(zoom < 12)
if (this.$refs.towerLayer) {
this.$refs.towerLayer.setVisible(this.zoom >= 12)
}
if (this.$refs.thresholdLayer) {
this.$refs.thresholdLayer.setVisible(this.zoom >= 12)
}
this.$refs.pavementLayer.setVisible(zoom >= 12)
}
this.$refs.editLayer.groundnetLayerGroup.eachLayer(function (layer) {
if (layer.updateArrows !== undefined) {
layer.updateArrows(zoom)
}
})
if (this.$refs.thresholdLayer) {
this.$refs.thresholdLayer.zoomUpdated()
}
if (this.$refs.towerLayer) {
this.$refs.towerLayer.zoomUpdated()
}
},
async centerUpdated (center) {
if (center !== this.$store.state.Settings.center) {
this.$store.dispatch('setCenter', center)
this.$refs.airportLayer.setVisible(this.zoom < 12)
if (this.$refs.thresholdLayer) {
this.$refs.thresholdLayer.setVisible(this.zoom >= 12)
}
if (this.$refs.towerLayer) {
this.$refs.towerLayer.setVisible(this.zoom >= 12)
}
this.$refs.pavementLayer.setVisible(this.zoom >= 12)
}
},
+20 -9
View File
@@ -1,7 +1,18 @@
<!--
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 class="leaflet-sidebar-pane" id="home">
<h1 class="leaflet-sidebar-header">
Help
{{version}}
<div class="leaflet-sidebar-close"><i class="fa fa-caret-left"></i></div>
</h1>
<h2>Setup</h2>
@@ -15,22 +26,20 @@
<h2>World view</h2>
<p>
When zoomed out you will see circles. Their size corresponds with the number of flights.
Blue means Ok. Yellow to little parking. Red no groundnet.
Blue means Ok. Yellow to little parking in comparison to the number of flights. Red no groundnet.
</p>
<h2>Edit view</h2>
<p>
</p>
<ul>
<li>Button with ICAO code opens the Airport data in the edit tab.</li>
<li>The top 4 buttons in the button bar are for zooming. </li>
<li>Upload sends the current airport to groundweb.</li>
<li>Edit switches into edit mode</li>
<li>Undo undos all changes or all changes during session</li>
<li>Save, saves the groundnet</li>
<li>Draw taxiline</li>
<li>Check triggers the groundnet check.</li>
<li>Draw bi directional taxiline</li>
<li>Draw uni directional taxiline</li>
<li>Draw pushback.</li>
<li>Add parking</li>
<li>Remove element, removes the currently selected element</li>
<li>Check triggers the groundnet check.</li>
</ul>
</div>
</template>
@@ -51,7 +60,9 @@
},
computed: {
version: function () {
return ' Flightgear Airports ' + require('electron').remote.app.getVersion()
}
}
}
</script>
+3 -1
View File
@@ -38,6 +38,7 @@ You should have received a copy of the GNU General Public License along with FG
<div class="leaflet-sidebar-close"><i class="fa fa-caret-left"></i></div>
</h1>
<ParkingEdit></ParkingEdit>
<ArcEditMulti></ArcEditMulti>
<ArcEdit></ArcEdit>
<NodeEdit></NodeEdit>
<ParkingGroupEdit ref="parkingGroupEdit" @editParking="(msg) => $emit('editParking', msg)"></ParkingGroupEdit>
@@ -74,6 +75,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 ArcEditMulti from './ArcEditMulti'
import CheckPanel from './CheckPanel'
import FileSelect from './FileSelect'
import Help from './Help'
@@ -89,7 +91,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, CheckPanel, NodeEdit, ParkingEdit, ParkingGroupEdit, RunScan, FileSelect, SettingsPanel, Search, Upload, WorkInProgress },
components: { Help, AirportEdit, ArcEdit, ArcEditMulti, CheckPanel, NodeEdit, ParkingEdit, ParkingGroupEdit, RunScan, FileSelect, SettingsPanel, Search, Upload, WorkInProgress },
props: [],
created () {
window.addEventListener('keydown', this.doCommand)
+50 -14
View File
@@ -11,17 +11,25 @@
<el-col :span="22" class="label">Airports Directory</el-col>
</el-row>
<el-row>
<el-col :span="20" class="file-label">{{ airports_directory }}</el-col>
<el-col :span="4">
<directory-select @input="airportsDirectorySelect"></directory-select>
<el-col :span="22" v-bind:class="{ invalid: !airports_directory_ok, file_label: airports_directory_ok}">{{ airports_directory }}</el-col>
<el-col :span="2">
<el-popover
placement="top-start"
title="E-Mail"
width="200"
trigger="hover"
content="The work directory. Best is a copy from groundweb"
>
<directory-select @input="airportsDirectorySelect" slot="reference"></directory-select>
</el-popover>
</el-col>
</el-row>
<el-row>
<el-col :span="22" class="label">Flightgear Data Directory</el-col>
</el-row>
<el-row>
<el-col :span="20" class="file-label">{{ flightgear_directory }}</el-col>
<el-col :span="4">
<el-col :span="22" v-bind:class="{ invalid: !flightgear_directory_ok, file_label: flightgear_directory_ok}">{{ flightgear_directory }}</el-col>
<el-col :span="2">
<el-popover
placement="top-start"
title="E-Mail"
@@ -34,20 +42,24 @@
</el-col>
</el-row>
<el-row>
<el-col :span="7" class="label">Traffic Directory</el-col>
<el-col :span="15" v-bind:class="{ invalid: !Traffic_directory_ok}">{{ Traffic_directory }}</el-col>
<el-col :span="22" class="label">Traffic Directory</el-col>
</el-row>
<el-row>
<el-col :span="22" v-bind:class="{ invalid: !Traffic_directory_ok, file_label: Traffic_directory_ok}">{{ Traffic_directory }}</el-col>
<el-col :span="2">
</el-col>
</el-row>
<el-row>
<el-col :span="7" class="label">APT File</el-col>
<el-col :span="15" v-bind:class="{invalid: !apt_file_ok}" >{{ apt_file }}</el-col>
<el-col :span="22" class="label">APT File</el-col>
</el-row>
<el-row>
<el-col :span="22" v-bind:class="{invalid: !apt_file_ok}" >{{ apt_file }}</el-col>
<el-col :span="2">
</el-col>
</el-row>
<el-row>
<el-col :span="7" class="label">Export Directory</el-col>
<el-col :span="15" class="file-label">{{ test_directory }}</el-col>
<el-col :span="15" v-bind:class="{invalid: !test_directory_ok, file_label: test_directory_ok}">{{ test_directory }}</el-col>
<el-col :span="2">
<directory-select @input="testDirectorySelect"></directory-select>
</el-col>
@@ -194,6 +206,14 @@
flightgear_directory: function () {
return this.$store.state.Settings.settings.flightgearDirectory
},
flightgear_directory_ok: function () {
try {
fs.accessSync(this.$store.state.Settings.settings.flightgearDirectory)
return true
} catch (error) {
return false
}
},
AI_directory: function () {
return this.$store.state.Settings.settings.flightgearDirectory_ai
},
@@ -222,9 +242,25 @@
airports_directory: function () {
return this.$store.state.Settings.settings.airportsDirectory
},
airports_directory_ok: function () {
try {
fs.accessSync(this.$store.state.Settings.settings.airportsDirectory)
return true
} catch (error) {
return false
}
},
test_directory: function () {
return this.$store.state.Settings.settings.testDirectory
},
test_directory_ok: function () {
try {
fs.accessSync(this.$store.state.Settings.settings.testDirectory)
return true
} catch (error) {
return false
}
},
scanLogging: {
// getter
get: function () {
@@ -247,14 +283,14 @@
border-radius: 4px;
}
.label {
padding: 10px;
padding: 5px;
font-weight: bold;
}
.file-label {
padding: 10px;
.file_label {
padding: 5px;
}
.invalid {
padding: 10px;
padding: 5px;
background-color: red;
}
+13 -1
View File
@@ -31,6 +31,10 @@
load (icao) {
// Callback for add
this.layerGroup = readThresholdXML(this.$store.state.Settings.settings.airportsDirectory, icao, this.read)
if (!this.layerGroup) {
console.warn('Threshold for ICAO not loaded ' + icao)
return
}
this.layerGroup.addTo(this.$parent.mapObject)
this.visible = true
this.icao = icao
@@ -58,13 +62,21 @@
this.visible = visible
}
}
},
zoomUpdated () {
this.layerGroup.eachLayer(l => {
if (l instanceof L.Threshold) {
l.updateIcon(this.$parent.mapObject)
}
})
}
},
computed: {
edit: function () {
console.log('Zoom : ' + this.$store.state.Settings.zoom)
if (this.$store.state.Settings.zoom > 12) {
console.log()
console.log('Zoom above 12')
}
}
}
+104
View File
@@ -0,0 +1,104 @@
<!--
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">
import { LMap, LMarker } from 'vue2-leaflet'
import L from 'leaflet'
import LEdit from 'leaflet-editable/src/Leaflet.Editable.js'
import {readTowerXML} from '../loaders/tower_loader'
export default {
name: 'tower-layer',
props: [],
created () {
console.debug([LMap, LMarker, L, LEdit])
},
mounted () {
},
beforeDestroy () {
this.remove()
},
data () {
return {
}
},
methods: {
getLayer () {
return this.layerGroup
},
load (icao) {
// Callback for add
this.layerGroup = readTowerXML(this.$store.state.Settings.settings.airportsDirectory, icao, this.read)
if (!this.layerGroup) {
console.warn('Tower for ICAO not loaded ' + icao)
return
}
this.layerGroup.addTo(this.$parent.mapObject)
this.visible = true
this.icao = icao
},
deferredMountedTo (parent) {
},
remove () {
if (this.layerGroup) {
this.$parent.removeLayer(this.layerGroup)
}
},
add () {
if (this.$parent._isMounted) {
this.deferredMountedTo(this.$parent.mapObject)
}
},
enableEdit () {
this.layerGroup.eachLayer(l => {
if (l instanceof L.TowerMarker) {
l.enableEdit(this.$parent.mapObject)
}
})
},
save () {
},
setVisible (visible) {
if (this.layerGroup !== undefined) {
if (visible !== this.visible) {
if (visible) {
this.layerGroup.addTo(this.$parent.mapObject)
} else {
this.layerGroup.removeFrom(this.$parent.mapObject)
}
this.visible = visible
}
}
},
zoomUpdated () {
this.layerGroup.eachLayer(l => {
if (l instanceof L.TowerMarker) {
l.updateIcon(this.$parent.mapObject)
}
})
}
},
computed: {
edit: function () {
console.log('Zoom : ' + this.$store.state.Settings.zoom)
if (this.$store.state.Settings.zoom > 12) {
console.log()
}
}
}
}
</script>
<style scoped lang="scss">
</style>
+276 -153
View File
@@ -4,6 +4,7 @@ const Vue = require('vue');
var L = require('leaflet');
const store = require('../store');
const util = require('util');
const assign = require('core-js/fn/object/assign');
const extendTaxiSegment = function (taxiwaySegment) {
taxiwaySegment.__proto__.begin;
@@ -36,7 +37,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
this.editLayer = editLayer;
this._latlngs[0].glueindex = this.begin;
this._latlngs.slice(-1)[0].glueindex = this.end;
if(this.featureLookup) {
if (this.featureLookup) {
if (typeof this.featureLookup[this.begin] === 'undefined') {
this.featureLookup[this.begin] = new Array();
}
@@ -45,7 +46,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
}
this.featureLookup[this.begin].push(this);
this.featureLookup[this.end].push(this);
this.bidirectional = true;
this.bidirectional = true;
}
};
taxiwaySegment.__proto__.select = function () {
@@ -53,50 +54,50 @@ const extendTaxiSegment = function (taxiwaySegment) {
this.updateStyle();
};
taxiwaySegment.__proto__.selectVertex = function (index) {
this.getLatLngs().forEach( element => {
if (Number(element.glueindex) === index) {
if (element.__vertex._icon != null) {
element.__vertex.__proto__.deselect = function () {
if (this._icon != null) {
this._icon.style.setProperty('background-color','white');
this._icon.style.setProperty('color','white');
} else if (this.icon != null) {
if (this.icon.style != null) {
this.icon.style['background-color'] = 'white';
} else {
this.setStyle({ color: 'white' })
this.getLatLngs().forEach(element => {
if (Number(element.glueindex) === index) {
if (element.__vertex._icon != null) {
element.__vertex.__proto__.deselect = function () {
if (this._icon != null) {
this._icon.style.setProperty('background-color', 'white');
this._icon.style.setProperty('color', 'white');
} else if (this.icon != null) {
if (this.icon.style != null) {
this.icon.style['background-color'] = 'white';
} else {
this.setStyle({ color: 'white' })
}
} else if (this.options.icon != null) {
if (this.options.icon.style != null) {
this.options.icon.style['background-color'] = 'white';
} else {
this.options.icon._setIconStyles({ color: 'white' })
}
}
}
} else if (this.options.icon != null) {
if (this.options.icon.style != null) {
this.options.icon.style['background-color'] = 'white';
element.__vertex._icon.style.setProperty('background-color', 'red');
element.__vertex._icon.style.setProperty('color', 'red');
} else if (element.__vertex !== undefined && element.__vertex.icon != null) {
if (element.__vertex.icon.style != null) {
element.__vertex.icon.style['background-color'] = 'red';
} else {
this.options.icon._setIconStyles({ color: 'white' })
element.__vertex.setStyle({ color: 'red' })
}
}
} else if (element.__vertex.options.icon != null) {
if (element.__vertex.options.icon.style != null) {
element.__vertex.options.icon.style['background-color'] = 'red';
} else {
element.__vertex.options.icon._setIconStyles({ color: 'red' })
}
}
}
element.__vertex._icon.style.setProperty('background-color','red');
element.__vertex._icon.style.setProperty('color','red');
} else if (element.__vertex !== undefined && element.__vertex.icon != null) {
if (element.__vertex.icon.style != null) {
element.__vertex.icon.style['background-color'] = 'red';
} else {
element.__vertex.setStyle({ color: 'red' })
}
} else if (element.__vertex.options.icon != null) {
if (element.__vertex.options.icon.style != null) {
element.__vertex.options.icon.style['background-color'] = 'red';
} else {
element.__vertex.options.icon._setIconStyles({ color: 'red' })
}
}
}
});
});
};
taxiwaySegment.__proto__.deselect = function () {
this.options.attributes.selected = false;
this.updateStyle();
this.getLatLngs().forEach( element => {
if (element.__vertex!==undefined) {
this.getLatLngs().forEach(element => {
if (element.__vertex !== undefined) {
if (element.__vertex._icon != null) {
element.__vertex._icon.style['background-color'] = 'white';
} else if (element.__vertex.icon != null) {
@@ -111,128 +112,170 @@ const extendTaxiSegment = function (taxiwaySegment) {
} else {
element.__vertex.options.icon._setIconStyles({ color: 'white' })
}
}
}
}
});
};
taxiwaySegment.__proto__.addListeners = function () {
this.on('click', function (event) {
if (Number(store.default.state.Editable.index) >= 0 &&
this.featureLookup[store.default.state.Editable.index] !== undefined) {
if (Number(store.default.state.Editable.index) >= 0 &&
this.featureLookup[store.default.state.Editable.index] !== undefined) {
this.featureLookup[store.default.state.Editable.index].forEach(element => {
element.deselect();
});
}
event.target.select();
console.log("Click : " + event.target);
if (store.default.state.Editable.data.arc === undefined ||
store.default.state.Editable.data.arc !== event.target.options.attributes) {
if (event.target.options.attributes === undefined) {
event.target.options.attributes = {};
}
event.target.options.attributes.index = event.target._leaflet_id;
console.debug("Click : " + util.inspect(event.originalEvent));
if (!event.originalEvent.ctrlKey) {
if (store.default.state.Editable.data.arc === undefined ||
store.default.state.Editable.data.arc !== event.target.options.attributes) {
if (event.target.options.attributes === undefined) {
event.target.options.attributes = {};
}
event.target.options.attributes.index = event.target._leaflet_id;
this.editLayer.featureLookup[event.target._leaflet_id] = [];
this.featureLookup[event.target._leaflet_id].push(this);
event.target.options.attributes.selected = true;
store.default.dispatch('setArc', event.target.options.attributes);
}
this.editLayer.featureLookup[event.target._leaflet_id] = [];
this.featureLookup[event.target._leaflet_id].push(this);
event.target.options.attributes.selected = true;
store.default.dispatch('setArc', event.target.options.attributes);
}
} else {
var arcs = event.target.expandArc(event.target.options.attributes);
var multiarc = {name: '', index: 900719925474099, ids: [] ,isPushBackRoute: null, direction: null};
if (store.default.state.Editable.data.multiarc === undefined ||
store.default.state.Editable.data.multiarc !== event.target.options.attributes) {
if (event.target.options.attributes === undefined) {
event.target.options.attributes = {};
}
event.target.options.attributes.index = event.target._leaflet_id;
this.editLayer.featureLookup[event.target._leaflet_id] = [];
this.featureLookup[event.target._leaflet_id].push(this);
event.target.options.attributes.selected = true;
//multiarc.name = JSON.parse(JSON.stringify(event.target.options.attributes.name));
//multiarc.isPushBackRoute = JSON.parse(JSON.stringify(event.target.options.attributes.isPushBackRoute));
//multiarc.direction = JSON.parse(JSON.stringify(event.target.options.attributes.direction));
if(event.target.options.attributes.name!==undefined) {
multiarc.name = assign(event.target.options.attributes.name);
}
multiarc.isPushBackRoute = assign(event.target.options.attributes.isPushBackRoute);
multiarc.direction = assign(event.target.options.attributes.direction);
this.editLayer.featureLookup[900719925474099] = [];
multiarc.ids = [];
//TODO
store.default.dispatch('setMultiArc', multiarc);
}
var editLayer = this.editLayer;
arcs.forEach(id => {
console.debug(id);
var arc = editLayer.groundnetLayerGroup.getLayer(id);
if (arc && arc instanceof L.Polyline) {
editLayer.featureLookup[900719925474099].push(arc);
arc.select();
}
});
store.default.dispatch('setMultiArcIds', arcs);
}
});
this.on('editable:drawing:move', function (event) {
if (dragIndex >= 0) {
this.selectVertex(dragIndex);
console.log('GlueDrag : '+ dragIndex + '\t' + event.target.dragIndex);
console.log('GlueDrag : ' + dragIndex + '\t' + event.target.dragIndex);
this.follow(dragIndex, event);
}
});
this.on('editable:middlemarker:mousedown', event => {
console.debug('editable:middlemarker:mousedown');
} ),
this.on('editable:vertex:new', event => {
console.debug('editable:vertex:new ' + event.vertex.getIndex() + '\t' + event.vertex.getLastIndex() + '\t');
// Find nearest node
let closest = this.editLayer.closestLayerSnap(event.latlng, 5)
let taxiwaySegment = event.latlng.__vertex.editor.feature;
if (taxiwaySegment.options.attributes === undefined) {
taxiwaySegment.options.attributes = { direction: 'bi-directional' };
}
taxiwaySegment.updateStyle();
if(event.vertex.getIndex() !== 0 && event.vertex.getIndex() !== event.vertex.getLastIndex()) {
var nextIndex = ++taxiwaySegment.editLayer.groundnetLayerGroup.maxId;
var splitOffNodes = taxiwaySegment.getLatLngs().splice(-1);
var remainingNodes = taxiwaySegment.getLatLngs();
splitOffNodes.unshift(L.latLng(remainingNodes[1].lat, remainingNodes[1].lng, remainingNodes[1].alt));
remainingNodes[1]['glueindex'] = nextIndex;
remainingNodes[1].attributes = { index: nextIndex, isOnRunway: 0 };
taxiwaySegment.options.attributes.end = nextIndex;
splitOffNodes[0]['glueindex'] = nextIndex;
splitOffNodes[0].attributes = { index: nextIndex, isOnRunway: 0 };
taxiwaySegment.setLatLngs(remainingNodes);
//taxiwaySegment.editor.refresh();
//taxiwaySegment.editor.reset();
if( splitOffNodes.length>1) {
var polyline = new L.Polyline(splitOffNodes, { attributes: {} });
polyline.addTo(taxiwaySegment.editLayer.$parent.$parent.$refs.map.mapObject);
polyline.addTo(taxiwaySegment.editLayer.groundnetLayerGroup);
extendTaxiSegment(polyline);
polyline.addListeners();
polyline.setEditlayer(taxiwaySegment.editLayer);
polyline.enableEdit(taxiwaySegment.editLayer.$parent.$parent.$refs.map.mapObject);
polyline.editor.refresh();
//polyline.editor.reset();
polyline.featureLookup = this.featureLookup;
polyline.options.attributes.name = taxiwaySegment.options.attributes.name;
polyline.options.attributes.direction = taxiwaySegment.options.attributes.direction;
polyline.options.attributes.isPushBackRoute = taxiwaySegment.options.attributes.isPushBackRoute;
polyline.options.attributes.begin = nextIndex;
polyline.options.attributes.end = taxiwaySegment.end;
polyline.updateStyle();
polyline.begin = nextIndex;
polyline.end = taxiwaySegment.end;
taxiwaySegment.end = nextIndex;
this.editLayer.featureLookup[nextIndex] = [];
this.featureLookup[nextIndex].push(taxiwaySegment);
this.featureLookup[nextIndex].push(polyline);
}),
this.on('editable:vertex:new', event => {
console.debug('editable:vertex:new ' + event.vertex.getIndex() + '\t' + event.vertex.getLastIndex() + '\t');
// Find nearest node
let closest = this.editLayer.closestLayerSnap(event.latlng, 5)
let taxiwaySegment = event.latlng.__vertex.editor.feature;
if (taxiwaySegment.options.attributes === undefined) {
taxiwaySegment.options.attributes = { direction: 'bi-directional' };
}
} else {
// Glue to another node
if (closest) {
event.latlng['glueindex'] = Number(closest.glueindex);
event.latlng.__vertex.setLatLng(closest.latlng);
event.latlng.attributes = { index: event.latlng.glueindex, isOnRunway: 0 };
// Push Vertex to lookup
this.editLayer.featureLookup[event.latlng.glueindex].push(event.latlng.__vertex);
if (taxiwaySegment.options.attributes.begin === undefined) {
taxiwaySegment.options.attributes.begin = event.latlng['glueindex']
} else {
taxiwaySegment.options.attributes.end = event.latlng['glueindex']
}
if (taxiwaySegment.getLatLngs().length === 1) {
taxiwaySegment.begin = closest.glueindex;
}
taxiwaySegment.end = closest.glueindex;
console.log(`Closest : ${closest}`)
} else {
event.vertex.latlng['glueindex'] = ++this.editLayer.groundnetLayerGroup.maxId;
event.vertex.latlng.attributes = { index: event.vertex.latlng.glueindex, isOnRunway: 0 };
this.editLayer.featureLookup[event.vertex.latlng.glueindex] = [];
this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(event.vertex);
this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(taxiwaySegment);
// taxiwaySegment.editor.refresh();
taxiwaySegment.updateStyle();
if (event.vertex.getIndex() !== 0 && event.vertex.getIndex() !== event.vertex.getLastIndex()) {
var nextIndex = ++taxiwaySegment.editLayer.groundnetLayerGroup.maxId;
var splitOffNodes = taxiwaySegment.getLatLngs().splice(-1);
var remainingNodes = taxiwaySegment.getLatLngs();
splitOffNodes.unshift(L.latLng(remainingNodes[1].lat, remainingNodes[1].lng, remainingNodes[1].alt));
remainingNodes[1]['glueindex'] = nextIndex;
remainingNodes[1].attributes = { index: nextIndex, isOnRunway: 0 };
taxiwaySegment.options.attributes.end = nextIndex;
splitOffNodes[0]['glueindex'] = nextIndex;
splitOffNodes[0].attributes = { index: nextIndex, isOnRunway: 0 };
taxiwaySegment.setLatLngs(remainingNodes);
//taxiwaySegment.editor.refresh();
//taxiwaySegment.editor.reset();
if (taxiwaySegment.options.attributes.begin === undefined) {
taxiwaySegment.options.attributes.begin = event.vertex.latlng['glueindex']
taxiwaySegment.begin = event.vertex.latlng.glueindex;
} else if (taxiwaySegment.options.attributes.end === undefined ||
(taxiwaySegment.getLatLngs()[taxiwaySegment.getLatLngs().length - 1].glueindex &&
Number(taxiwaySegment.getLatLngs()[taxiwaySegment.getLatLngs().length - 1].glueindex) !== taxiwaySegment.options.attributes.end)) {
taxiwaySegment.options.attributes.end = event.vertex.latlng['glueindex']
taxiwaySegment.end = Number(event.vertex.latlng.glueindex);
if (splitOffNodes.length > 1) {
var polyline = new L.Polyline(splitOffNodes, { attributes: {} });
polyline.addTo(taxiwaySegment.editLayer.$parent.$parent.$refs.map.mapObject);
polyline.addTo(taxiwaySegment.editLayer.groundnetLayerGroup);
extendTaxiSegment(polyline);
polyline.addListeners();
polyline.setEditlayer(taxiwaySegment.editLayer);
polyline.enableEdit(taxiwaySegment.editLayer.$parent.$parent.$refs.map.mapObject);
polyline.editor.refresh();
//polyline.editor.reset();
polyline.featureLookup = this.featureLookup;
polyline.options.attributes.name = taxiwaySegment.options.attributes.name;
polyline.options.attributes.direction = taxiwaySegment.options.attributes.direction;
polyline.options.attributes.isPushBackRoute = taxiwaySegment.options.attributes.isPushBackRoute;
polyline.options.attributes.begin = nextIndex;
polyline.options.attributes.end = taxiwaySegment.end;
polyline.updateStyle();
polyline.begin = nextIndex;
polyline.end = taxiwaySegment.end;
taxiwaySegment.end = nextIndex;
this.editLayer.featureLookup[nextIndex] = [];
this.featureLookup[nextIndex].push(taxiwaySegment);
this.featureLookup[nextIndex].push(polyline);
}
} else {
// Glue to another node
if (closest) {
event.latlng['glueindex'] = Number(closest.glueindex);
event.latlng.__vertex.setLatLng(closest.latlng);
event.latlng.attributes = { index: event.latlng.glueindex, isOnRunway: 0 };
// Push Vertex to lookup
this.editLayer.featureLookup[event.latlng.glueindex].push(event.latlng.__vertex);
if (taxiwaySegment.options.attributes.begin === undefined) {
taxiwaySegment.options.attributes.begin = event.latlng['glueindex']
} else {
taxiwaySegment.options.attributes.end = event.latlng['glueindex']
}
if (taxiwaySegment.getLatLngs().length === 1) {
taxiwaySegment.begin = closest.glueindex;
}
taxiwaySegment.end = closest.glueindex;
console.log(`Closest : ${closest}`)
} else {
event.vertex.latlng['glueindex'] = ++this.editLayer.groundnetLayerGroup.maxId;
event.vertex.latlng.attributes = { index: event.vertex.latlng.glueindex, isOnRunway: 0 };
this.editLayer.featureLookup[event.vertex.latlng.glueindex] = [];
this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(event.vertex);
this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(taxiwaySegment);
// taxiwaySegment.editor.refresh();
//taxiwaySegment.editor.reset();
if (taxiwaySegment.options.attributes.begin === undefined) {
taxiwaySegment.options.attributes.begin = event.vertex.latlng['glueindex']
taxiwaySegment.begin = event.vertex.latlng.glueindex;
} else if (taxiwaySegment.options.attributes.end === undefined ||
(taxiwaySegment.getLatLngs()[taxiwaySegment.getLatLngs().length - 1].glueindex &&
Number(taxiwaySegment.getLatLngs()[taxiwaySegment.getLatLngs().length - 1].glueindex) !== taxiwaySegment.options.attributes.end)) {
taxiwaySegment.options.attributes.end = event.vertex.latlng['glueindex']
taxiwaySegment.end = Number(event.vertex.latlng.glueindex);
}
}
}
}
//this.splitShape(taxiwaySegment.getLatLngs(), )
});
//this.splitShape(taxiwaySegment.getLatLngs(), )
});
this.on('editable:vertex:deleted', event => {
console.debug('editable:vertex:deleted')
});
@@ -251,7 +294,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
if (Number(store.default.state.Editable.index) >= 0 &&
this.featureLookup[store.default.state.Editable.index] !== undefined) {
this.featureLookup[store.default.state.Editable.index].forEach(element => {
if(element.deselect !== undefined) {
if (element.deselect !== undefined) {
element.deselect();
}
});
@@ -268,7 +311,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
this.editLayer.featureLookup[event.vertex.latlng.glueindex].forEach
store.default.dispatch('setNode', event.vertex.latlng)
this.selectVertex(store.default.state.Editable.index)
}
}
}
});
var dragIndex = -1;
@@ -282,7 +325,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
if (Number(store.default.state.Editable.index) >= 0 &&
this.featureLookup[store.default.state.Editable.index] !== undefined) {
this.featureLookup[store.default.state.Editable.index].forEach(element => {
if(element.deselect !== undefined) {
if (element.deselect !== undefined) {
element.deselect();
}
});
@@ -297,7 +340,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
parking[0].selectParking();
} else {
this.selectVertex(Number(dragIndex))
}
}
}
});
this.on('editable:vertex:dragend', function (event) {
@@ -316,29 +359,79 @@ const extendTaxiSegment = function (taxiwaySegment) {
if (parking.length > 0) {
parking[0].selectParking();
} else {
if( Number(event.vertex.latlng.glueindex) !== store.default.state.Editable.index) {
if (Number(event.vertex.latlng.glueindex) !== store.default.state.Editable.index) {
if (Number(store.default.state.Editable.index) >= 0 &&
this.featureLookup[store.default.state.Editable.index] !== undefined) {
this.featureLookup[store.default.state.Editable.index].forEach(element => {
if(element.deselect !== undefined) {
this.featureLookup[store.default.state.Editable.index] !== undefined) {
this.featureLookup[store.default.state.Editable.index].forEach(element => {
if (element.deselect !== undefined) {
element.deselect();
}
});
}
store.default.dispatch('setNode', event.vertex.latlng)
}
store.default.dispatch('setNode', event.vertex.latlng)
}
var lines = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.Polyline);
Vue.default.nextTick(function () {
lines.forEach( line => {
lines.forEach(line => {
line.selectVertex(store.default.state.Editable.index)
});
})
}
}
} catch (error) {
console.error(error);
}
});
};
taxiwaySegment.__proto__.expandArc = function (attributes) {
var isPushBackRoute = attributes.isPushBackRoute;
var ids = [];
var walkedNodes = [];
var segmentIds = [];
console.debug('start Walk');
ids = ids.concat(this.walkPushbackRoute(attributes.begin, walkedNodes, isPushBackRoute));
ids = ids.concat(this.walkPushbackRoute(attributes.end, walkedNodes, isPushBackRoute));
return ids;
}
taxiwaySegment.__proto__.walkPushbackRoute = function (index, walkedNodes, isPushBackRoute) {
console.debug('Walk Level');
walkedNodes.push(index)
var segmentIds = [];
var polyLines = this.featureLookup[index].filter(n => n instanceof L.Polyline);
if (polyLines===undefined || polyLines.length>2) {
console.debug('Walk ' + index + '\t' + polyLines.length);
return;
}
polyLines.forEach(l => {
segmentIds.push(l._leaflet_id);
console.debug('Walk Next ' + index + '\t' +
(walkedNodes.indexOf(index)<0) + '\t'+
l.begin + '\t'+
(walkedNodes.indexOf(Number(l.begin))<0) + '\t'+
l.end + '\t'+
(walkedNodes.indexOf(Number(l.end))<0) + '\t'+
l.options.attributes.direction + '\t' +
l.options.attributes.begin + '\t' +
l.options.attributes.end);
console.debug('Walk isPushBackRoute ' + l.options.attributes.isPushBackRoute + '\t' + isPushBackRoute + '\t' + (l.options.attributes.isPushBackRoute === isPushBackRoute));
if(l.options.attributes.isPushBackRoute === isPushBackRoute ) {
console.debug(Number(l.begin) === index && walkedNodes.indexOf(Number(l.end)) < 0);
if (Number(l.begin) === index && walkedNodes.indexOf(Number(l.end)) < 0) {
console.debug( 'Walk forward ' + l.options.attributes.direction );
segmentIds = segmentIds.concat(this.walkPushbackRoute(Number(l.end), walkedNodes, isPushBackRoute))
}
console.debug(Number(l.end) === index && walkedNodes.indexOf(Number(l.begin)) < 0);
if (Number(l.end) === index && walkedNodes.indexOf(Number(l.begin)) < 0 ) {
console.debug( 'Walk backward ' + l.options.attributes.direction );
segmentIds = segmentIds.concat(this.walkPushbackRoute(Number(l.begin), walkedNodes, isPushBackRoute))
}
}
});
return segmentIds;
}
/**
*
*/
@@ -392,8 +485,38 @@ const extendTaxiSegment = function (taxiwaySegment) {
})
};
taxiwaySegment.__proto__.updateArrows = function (zoom) {
if( this._map === null) {
return;
}
if (this.options.attributes.direction === 'forward') {
this.setText(null);
if (zoom <= 16) {
this.setText(' >', { repeat: true, offset: 6, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 15px serif;' } })
} else if (zoom <= 19 ) {
this.setText(' > ', { repeat: true, offset: 7, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 20px serif;' } })
} else {
this.setText(' > ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } })
}
} else if (this.options.attributes.direction === 'backward') {
this.setText(null);
if (zoom <= 16) {
this.setText(' <', { repeat: true, offset: 6, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 15px serif;' } })
} else if (zoom <= 19 ) {
this.setText(' < ', { repeat: true, offset: 7, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 20px serif;' } })
} else {
this.setText(' < ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } })
}
} else {
this.setText(null);
}
}
taxiwaySegment.__proto__.updateStyle = function () {
var style = {};
if(!this.options.attributes) {
return;
}
if (this.options.attributes.selected) {
style.color = 'red';
} else if (this.options.attributes.isPushBackRoute) {
@@ -403,18 +526,18 @@ const extendTaxiSegment = function (taxiwaySegment) {
style.color = '#3388ff';
}
this.setStyle(style);
if(this._map !== null) {
if (this._map !== null) {
if (this.options.attributes.direction === 'forward') {
this.setText(null);
this.setText(' > ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } })
this.setText(' > ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } })
} else if (this.options.attributes.direction === 'backward') {
this.setText(null);
this.setText(' < ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } })
this.setText(' < ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } })
} else {
this.setText(null);
}
}
}
};
};
+73 -129
View File
@@ -1,141 +1,85 @@
/*
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/.
*/
/* eslint-disable */
const convert = require('geo-coordinates-parser');
const leaflet = require('leaflet');
const turf = require('@turf/turf');
const util = require('util');
const store = require('../store');
const fs = require('fs');
const path = require('path');
var $ = require('jquery');
L.Threshold = L.Circle.extend({
select() {
var style = {};
style['color'] = 'red';
this.setStyle(style);
},
addListeners: function () {
this.on('editable:drawing:move', function (event) {
console.log("Move : ", event);
console.log("Move : ", event.latlng);
// Is it the edit vertex (Middle) moving?
if(event.target.editor._resizeLatLng.__vertex._icon !== event.sourceTarget._element){
event.target.setLatLng(event.latlng);
event.target.updateVertexFromDirection();
this.follow(event.target.id, event);
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
L.Threshold = L.Marker.extend({
options: {
zIndexOffset: 20000,
},
stripSVG: function(fName) {
var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm;
var svg = fs.readFileSync(path.join(__static, '/', fName), 'utf8');
var svg2 = rx.exec(svg);
return svg2[0];
},
updateIcon : function(map) {
console.debug(`Lat Lng Threshold ${this.getLatLng()}`);
if(map !== null) {
var metersPP = this.metersPerPixel(map.getCenter().lat, map.getZoom());
console.debug('Old Meters per pixel ' + this.metersPP);
console.debug('New Meters per pixel ' + metersPP);
if(this._metersPP != metersPP) {
var pixelSize = (this.iconSize/2) / metersPP;
var scale = pixelSize/this.iconSize;
var offset = 0;//-(this.iconSize/2);
this.setIcon(L.divIcon({
iconSize: 64,
className: 'threshold-marker-icon',
html: `<div style=\'transform: translateX(${offset}px) translateY(${offset}px) scale(${scale}) rotate(${this.options.heading}deg); border: 1px red\'>${this.svg}</div>`,
}));
this.update(this.getLatLng());
console.debug();
this.setLatLng(this.getLatLng());
this._metersPP = metersPP;
}
else if(event.target.editor._resizeLatLng.__vertex._icon === event.sourceTarget._element) {
event.target.updateDirectionFromVertex();
event.target.updateVertexFromDirection();
}
});
/*
this.on('editable:vertex:drag', function (event) {
console.log("Drag : ", event);
});
*/
this.on('click', function (event) {
console.log("Click : " + event.target);
store.default.dispatch('setParking', event.target.options.attributes);
this.select();
this.unwatch = store.default.watch(
function (state) {
return state.Editable.data.parking;
},
() => {
if (event.target instanceof L.Threshold) {
event.target.setStyle({color : '#3388ff'});
this.unwatch();
}
}
,
{
deep: true //add this if u need to watch object properties change etc.
}
);
});
this.on('editable:vertex:clicked', function (event) {
console.log(this.featureLookup[event.vertex.glueindex]);
if(event.target.editor._resizeLatLng.__vertex._icon !== event.sourceTarget._element){
event.vertex._icon.style['background-color'] = 'red';
store.default.dispatch('setParking', event.target.options.attributes);
this.unwatch = store.default.watch(
function (state) {
return state.Editable.data.parking;
},
() => {
event.target.setStyle({color : '#3388ff'});
this.unwatch();
}
,
{
deep: true //add this if u need to watch object properties change etc.
}
);
}
},
onAdd : function(map) {
var metersPP = this.metersPerPixel(map.getCenter().lat, map.getZoom());
this.updateIcon(map);
},
metersPerPixel: function (latitude, zoomLevel) {
var earthCircumference = 40075017;
var latitudeRadians = latitude * (Math.PI / 180);
return earthCircumference * Math.cos(latitudeRadians) / Math.pow(2, zoomLevel + 8);
},
}
});
this.on('editable:disable', function (event) {
event.target.removeDirection();
});
},
updateStyle: function () {
},
turfToLatLng: function (turfPoint) {
return {lat: turfPoint.geometry.coordinates[1], lng: turfPoint.geometry.coordinates[0]};
},
extensions: function (editLayer) {
this.createDirection();
if (typeof this.featureLookup[this.id] === 'undefined') {
this.featureLookup[this.id] = [];
}
this.featureLookup[this.id].push(this);
},
_getLatRadius: function () {
return this._mRadius;
},
_getLngRadius: function () {
return this._mRadius;
pixelValue: function (latitude, meters, zoomLevel) {
return meters / metersPerPixel(latitude, zoomLevel);
},
});
var threshold = function (n, layerGroup) {
//console.log(n.attr('lat') + " " + n.attr('lon'));
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
//console.log(latlon.decimalLatitude);
//console.log(convert(n.attr('lat') + " " + n.attr('lon')).decimalLongitude);
const circle = new L.Threshold([latlon.decimalLatitude, latlon.decimalLongitude], { radius: 10, attributes: {} });
circle.on('editable:enable', function (event) {
// event.target.createDirection();
});
/*
<Parking index="2"
type="gate"
name="A6"
number=""
lat="N44 52.799"
lon="W93 11.947"
heading="-147.51"
radius="18"
pushBackRoute="541"
airlineCodes="VIR,KAL,DAL,KLM" />
*/
//circle.attributes = { type: n.attr('type'), name: n.attr('name'), radius: Number(n.attr('radius')), airlineCodes: n.attr('airlineCodes'), heading: Number(n.attr('heading')) };
L.Threshold.addInitHook(function(){
this.svg = this.stripSVG('FGA_THR.svg');
this.iconSize = 500;
});
$.each( n.attrs, function( key, value ) {
console.log( '$', circle.id, key , value);
if(isNaN(value))
circle.options.attributes[ key ] = value;
else
circle.options.attributes[ key ] = Number( value);
});
circle.addTo(layerGroup);
return circle;
//Builds a marker for a ai or multiplayer aircraft
var threshold = function (n, options) {
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
var heading = n.find('hdg-deg/text()').text();
var marker = new L.Threshold([latlon.decimalLatitude, latlon.decimalLongitude], {heading: heading});
return marker;
}
module.exports = threshold;
module.exports = threshold;
+84
View File
@@ -0,0 +1,84 @@
/*
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/.
*/
/* eslint-disable */
const convert = require('geo-coordinates-parser');
const fs = require('fs');
const path = require('path');
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
L.TowerMarker = L.Marker.extend({
options: {
zIndexOffset: 10000,
},
initialize: function (latlng, options) {
L.Marker.prototype.initialize(latlng, options);
L.Util.setOptions(this, options);
this.svg = this.stripSVG('tower.svg');
this.isDragging = false;
},
updateProperties: function(properties) {
this.heading = properties.heading;
this.updateIcon();
},
stripSVG: function(fName) {
var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm;
var svg = fs.readFileSync(path.join(__static, '/', fName), 'utf8');
var svg2 = rx.exec(svg);
return svg2[0];
},
updateIcon : function(map) {
if(map !== null) {
var metersPP = this.metersPerPixel(map.getCenter().lat, map.getZoom());
if(this._metersPP != metersPP) {
console.debug('Meters per pixel ' + metersPP);
var pixelSize = 32 / metersPP;
var scale = pixelSize/64;
var offset = -(64/2);
this.setIcon(L.divIcon({
iconSize: 64,
className: 'tower-marker-icon',
html: `<div style=\'transform: translateX(${offset}px) translateY(${offset}px) scale(${scale}); border: 1px red\'>${this.svg}</div>`,
}));
this._metersPP = metersPP;
}
}
},
onAdd : function(map) {
var metersPP = this.metersPerPixel(map.getCenter().lat, map.getZoom());
console.debug('Meters per pixel ' + metersPP);
this.updateIcon(map);
},
metersPerPixel: function (latitude, zoomLevel) {
var earthCircumference = 40075017;
var latitudeRadians = latitude * (Math.PI / 180);
return earthCircumference * Math.cos(latitudeRadians) / Math.pow(2, zoomLevel + 8);
},
pixelValue: function (latitude, meters, zoomLevel) {
return meters / metersPerPixel(latitude, zoomLevel);
},
});
//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], options);
}
module.exports = tower;
+11 -1
View File
@@ -60,6 +60,11 @@ function walkPushbackRoute (index, walkedNodes, pushBackNodes) {
exports.writeGroundnetXML = function (fDir, icao, featureList) {
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 + '.groundnet.new.xml');
var fBak = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.bak.xml');
@@ -201,7 +206,12 @@ var mapParkings = function (o) {
console.debug(o.options.attributes.airlineCodes);
parking['@airlineCodes'] = o.options.attributes.airlineCodes;
}
if(o.options.attributes.number) {
if(o.options.attributes.number !== undefined &&
typeof o.options.attributes.number === 'number' || (
typeof o.options.attributes.number === 'string' &&
o.options.attributes.number.trim() !== ''
)
) {
console.debug(o.options.attributes.number);
parking['@number'] = o.options.attributes.number;
}
+10 -2
View File
@@ -50,8 +50,16 @@ exports.readThresholdXML = function (fDir, icao, force) {
thresholdNodes.map(n => {
var circle = threshold(n, layerGroup);
features.push(circle);
var icon = threshold(n);
icon.addTo(layerGroup);
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
/*
var marker = new L.Circle([latlon.decimalLatitude, latlon.decimalLongitude], 5);
marker.addTo(layerGroup);
*/
// features.push(circle);
}).sort();
return layerGroup;
+83
View File
@@ -0,0 +1,83 @@
/*
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/.
*/
/* eslint-disable */
const fs = require('fs');
const path = require('path');
var xamel = require('xamel');
const convert = require('geo-coordinates-parser');
const store = require('../store');
const util = require('util');
const tower = require('./Tower.js');
var $ = require('jquery');
exports.readTowerXML = function (fDir, icao, force) {
try {
var layerGroup = L.layerGroup();
layerGroup.maxId = 0;
var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.twr.xml');
var fNew = path.join(fDir, icao[0], icao[1], icao[2], icao + '.twr.new.xml');
if (f == null || !fs.existsSync(f))
return;
if (fNew != null && fs.existsSync(fNew) && !force) {
f = fNew;
}
var features = new Array();
// map.on("editable:vertex:new", function (event) {
// log.console("Add vertex " + event);
// });
var xmlGroundnet = fs.readFileSync(f, 'utf8').toString();
xamel.parse(xmlGroundnet, function (err, xml) {
console.debug("parsed " + path.basename(f));
if (err !== null) {
console.error("Error in " + airline);
throw err;
}
var towerNodes = xml.find('PropertyList/tower/twr');
console.log("Tower " + towerNodes.length);
var merged = new Array();
var nodesLookup = {};
featureLookup = [];
towerNodes.map(n => {
var towerIcon = tower(n, layerGroup);
towerIcon.addTo(layerGroup);
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
/*
var marker = new L.Circle([latlon.decimalLatitude, latlon.decimalLongitude], 5);
marker.addTo(layerGroup);
*/
features.push(towerIcon);
}).sort();
return layerGroup;
});
// var jsonAirports = JSON.parse(geoJSON);
// return jsonAirports;
} catch (error) {
console.error(error);
}
return layerGroup;
};
+63 -4
View File
@@ -1,15 +1,28 @@
/**
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/.
*/
import Vue from 'vue'
const state = {
type: 'none',
index: 'none',
editing: false,
data: {airports: {}, parking: {}, arc: {}, node: {}, runway: {}}
data: {airports: {}, parking: {}, arc: {}, multiarc: {}, node: {}, runway: {}}
}
const SET_EDIT_AIRPORT = 'SET_EDIT_AIRPORT'
const SET_EDIT_PARKING = 'SET_EDIT_PARKING'
const SET_EDIT_ARC = 'SET_EDIT_ARC'
const SET_EDIT_MULTI_ARC = 'SET_EDIT_MULTI_ARC'
const SET_EDIT_RUNWAY = 'SET_EDIT_RUNWAY'
const mutations = {
@@ -62,6 +75,34 @@ const mutations = {
Vue.set(state, 'index', arc.index)
Vue.set(state, 'type', 'arc')
},
SET_EDIT_MULTI_ARC (state, arc) {
if (arc === undefined) {
return
}
if (!state.data || state.type !== 'multiarc') {
Vue.set(state, 'data', {multiarc: {}})
}
Vue.set(state.data.multiarc, 'isPushBackRoute', arc.isPushBackRoute)
Vue.set(state.data.multiarc, 'direction', arc.direction)
if (state.data.multiarc.name === undefined) {
Vue.set(state.data.multiarc, 'name', '')
}
Vue.set(state, 'index', arc.index)
Vue.set(state, 'type', 'multiarc')
},
'SET_EDIT_MULTI_ARC_IDS' (state, arcs) {
if (arcs === undefined) {
return
}
if (!state.data || state.type !== 'multiarc') {
return
}
if (state.data.multiarc.ids === undefined) {
state.data.multiarc.ids = []
}
state.data.multiarc.ids = state.data.multiarc.ids.concat(arcs.filter(n => n).filter((v, i, a) => a.indexOf(v) === i))
},
'SET_EDIT_PARKING_NAME' (state, parkingName) {
Vue.set(state.data.parking, 'name', parkingName)
},
@@ -91,13 +132,25 @@ const mutations = {
Vue.set(state.data.parking, 'coords', coords)
},
'SET_EDIT_ARC_NAME' (state, arcName) {
Vue.set(state.data.arc, 'name', arcName)
if (state.type === 'arc') {
Vue.set(state.data.arc, 'name', arcName)
} else {
Vue.set(state.data.multiarc, 'name', arcName)
}
},
'SET_EDIT_PUSHBACK' (state, isPushBackRoute) {
Vue.set(state.data.arc, 'isPushBackRoute', Number(isPushBackRoute))
if (state.type === 'arc') {
Vue.set(state.data.arc, 'isPushBackRoute', Number(isPushBackRoute))
} else {
Vue.set(state.data.multiarc, 'isPushBackRoute', Number(isPushBackRoute))
}
},
'SET_EDIT_DIRECTION' (state, direction) {
Vue.set(state.data.arc, 'direction', direction)
if (state.type === 'arc') {
Vue.set(state.data.arc, 'direction', direction)
} else {
Vue.set(state.data.multiarc, 'direction', direction)
}
},
'SET_EDIT_HOLDPOINTTYPE' (state, holdPointType) {
Vue.set(state.data.node, 'holdPointType', holdPointType)
@@ -132,6 +185,12 @@ const actions = {
async setArc (context, arc) {
context.commit(SET_EDIT_ARC, arc)
},
async setMultiArc (context, arc) {
context.commit(SET_EDIT_MULTI_ARC, arc)
},
async setMultiArcIds (context, arc) {
context.commit('SET_EDIT_MULTI_ARC_IDS', arc)
},
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))
+6
View File
@@ -31,9 +31,15 @@ const actions = {
context.commit('SET_ICAO_LOADING', p)
},
async setGroundnetLoaded (context, p) {
if (typeof p !== 'boolean') {
console.error('Not Boolean')
}
context.commit('SET_GROUNDNET_LOADED', p)
},
async setPavementLoaded (context, p) {
if (typeof p !== 'boolean') {
console.error('Not Boolean')
}
context.commit('SET_PAVEMENT_LOADED', p)
}
}
+3
View File
@@ -186,6 +186,9 @@ function scanTrafficIntoDB(p, features) {
function traverseDir(dir) {
var result = [];
if(!fs.existsSync(dir)) {
return result;
}
fs.readdirSync(dir).forEach(file => {
let fullPath = path.join(dir, file);
if (fs.lstatSync(fullPath).isDirectory()) {