Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2378cd5eaa | |||
|
|
4fff310d76 | ||
|
|
09b0cba5b0 | ||
|
|
f5930e2039 | ||
|
|
cc80726ec7 | ||
|
|
b73f0bb1a1 | ||
|
|
1ac67e1e18 | ||
|
|
7a58b4bde1 | ||
|
|
ba533e8942 | ||
|
|
8b0afa9fcb | ||
|
|
8a4820d23c | ||
|
|
da597f80e4 | ||
|
|
1bd3b3b2e4 | ||
|
|
b9b6574614 | ||
|
|
089ce029ec | ||
|
|
9e7f41a5c9 | ||
|
|
60881eaf3e | ||
|
|
0f4b82807e | ||
|
|
f9d0469466 | ||
|
|
f56d8ad926 | ||
|
|
b2ddb08374 | ||
|
|
091e7853eb | ||
|
|
e52fcf9572 | ||
|
|
055897c0f6 | ||
|
|
cf2e5150e8 | ||
|
|
d8417c7fd9 | ||
|
|
ed25672448 | ||
|
|
5e0e2c9ea5 | ||
|
|
d7ffe7bcec | ||
|
|
cf1c829c11 | ||
|
|
cfa7a1bf3b | ||
|
|
fd40bc76aa | ||
|
|
281e4b1339 | ||
|
|
77b8d81378 | ||
|
|
21e27bf913 | ||
|
|
92a39591b5 | ||
|
|
ec700c2ed7 | ||
|
|
c161b38664 | ||
|
|
fd2017624b | ||
|
|
41b7b0498f | ||
|
|
737f9a7b56 | ||
|
|
bd4bdd6b51 | ||
|
|
b95a468cdc | ||
|
|
9f6a9a0943 | ||
|
|
bf56736ab9 | ||
|
|
8732819261 | ||
|
|
092d0f2a24 | ||
|
|
1ad43169cc | ||
|
|
828e84e5c1 | ||
|
|
3ed45ee87e | ||
|
|
6ed5da1a99 | ||
|
|
2936559873 | ||
|
|
d3daa87244 | ||
|
|
ba1f5ef2e9 | ||
|
|
bcc5bbb335 | ||
|
|
fbf0e5cbab | ||
|
|
ab32e6849b | ||
|
|
ee5a6a5484 | ||
|
|
44e289f3ae | ||
|
|
7625ea1cf9 | ||
|
|
ac53005c0d | ||
|
|
25e603d15f | ||
|
|
618346d1b1 | ||
|
|
51d114e6d2 | ||
|
|
d317bd049c | ||
|
|
2d94425de5 | ||
|
|
1bba5e2157 | ||
|
|
9b757150d5 | ||
|
|
4dd17ad726 | ||
|
|
e6d473c73e | ||
|
|
84fd39c3b5 |
@@ -54,6 +54,7 @@ jobs:
|
||||
- stage: Deploy
|
||||
install:
|
||||
- pwd
|
||||
- find -name *osx-binaries*
|
||||
- tar -xzf ${CASHER_DIR}/osx-binaries-fetch.tgz
|
||||
- find -name flightgear-airports*
|
||||
- cp ./Users/travis/build/Portree-Kid/flightgear-airports/osx-binaries/*.dmg build/
|
||||
@@ -70,12 +71,12 @@ jobs:
|
||||
skip_cleanup: true
|
||||
overwrite: true
|
||||
draft: true
|
||||
name: '0.0.27'
|
||||
name: '0.0.33'
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: xBF7Jld2WbEXVg5QOxZIC/T2hlKOkajebrNi7kfE8vGVRuZG1cbHWEtBVPxggxmIWvzSyKOACSufFywx8rjgXNP3e310+dp1WuEnOBlkTr6HO3FneTue5gKoPsFB8/r8/BMPWqY50lS2Vei367eINsdNiw4wWv2bzbB6uNBlo9ILRZjbyWnUv+j8+h9gmCg2nHLmHBGhXRMLqYFEHYvq1LrV+tjMNtMBdNiRVYBjpeWI1y7TMsxpdwKvrYF84L7r9IOkjg2DHIACy4SMnIeKi6b7Lr83aK5QwksHByMETxjaNPxgvmg9hPFaRoJsvwOLdgSDU/VpEar8uweOnumt2bdqdwV2t+99A1g41KcvbUI1aATPOWhpGxW+WLBBz40hpDBBwWJ/Il4rMUHfsQ162xoO9NvlKp4IE7pgK3ydGlJx6mYzMx3QB2eKnTFySaIekrkzZPIS3GX50cMclRw6jS3fueUmtNxjIv4hNHgRqE6pQfxhQnaUkHjdP7nglYs0muJotM2Tksyw3YRlLoFzc/siktCDr8ZXxj+rlV3TeoH2vba7f4zr0tYY9vlGAUlcrkBoJ4kDeA8Hm0GnbpWHBsSY4g199jOkgbr/kJ0HDrELv/JJl1c8yp3uSlcN82UgNS15H60D+0zg3Ls4KxvqXslrPh815Se5FqKoEpvZ5VQ=
|
||||
file_glob: true
|
||||
secure: FElxoWQZKIcc9gHFY4yp1CsqvJr76BWdDrp7VsgPN7PuEoZht5Boic3fWbxKyT1fKGr8Yem6CJBXQjaqIZiWWMxuF3KYmsdOK0YRpj6WCePpl0AdZcnWDMsAGuC3ornb1CB3R6x8fx7SMMl8Ghc9/JFDUdjduvT9A0KZ1JrTZLYpP1iOq+aAW0H3byu+tNfTDvee9MzMAtjKriDz0L5z94VQ1lEmuc79qUmNvv9gIJUoNOI58QCDUuOEz2eZPooMz5cOdaupzBK130V7ki/UWbP3meXmzRKN6/iSA9iXiIrBerFtA4wG6hVvKMvKP7d7NalWAtpzOElFivlo7tp+Z1SfjSfZHmZG/PMyndVh1VPmMzX6a76qLyJFGIvOZKOkzzmVyGSVGlUHm8GCkw5wd0S3m6f1eA/YJO5c8aduC7M+qZSuEVdzaAW5xf8Fb1/rs7jELZPxuzio9i+T7vRQ1OFrCBtExQAuO9EyfaIvaVQAImvhOPiza6zkfEkF622LIQZIBL9HZ1OeKKrdWaWG98nUGWDIFXb+B4IBM1cJIPRYmaAbnWVVCBzIGxcb1pMb/zzSocu9poEWCY/CVHuOG7Xg45pghTunPS54E9qxvBx8jDIGz4s3bRwWnBI0DJ5b6aBNqMpghmpKYMCoviT+RwCIKOENlFdrPWH5pk9CmRc=wYHBe6BJtqhkjodvabd6fSX5blecd/y9sSfHV9prk7PRFxkpkp4Fw/sp086SFlunTGmTn359T1mhgr0MD/VDRXu34PEdn47Jpu8CTPfnihiK/3iRaGqW0qLqhmpd6GYc1ecm9sahxYwXgWyCtGZQbdHvrCIiS/Zm1hQtg3Q0O3eYeF+zQXrfCCTIhLLy2egID4Z23RbK620y3dqcSfbWfLzPpXr+2MYVrNZ3gukKiVauf2kBYPNzMTKEtIBfAGHiwQwlCm/fRN5NcL9bwMGmMGktJkIHgpAa2A9nnyw7EadKEKqVw4tI/j1813/FDWlJZBg89RNsZJ0QGSMQcMB0h1XkWZFPV02gqMN2z2eNXsvTJ882g8UkCBzPWYsRQGNKEx9FUFtZO9HAjOnnpAsdTcaQYTow7BiVmPBePtCFKsPyqMgJUsuz6WhUmfJ5FMbMDKn1N6ymyBYmTic5KrT3FRR3s7vFyTNdfNfwd7aNMnZSGb2uHLZyGjrC2QFK3AE/F+jP2bMu/9rcuLcp/CSLpxpN5F6RpVVfqY8X9joEUeXOSd4kO7OPBsg4lxDCqzVmER/X+MEwM57cmyutTtaREZEDTKCoEhWtcMHqLpCojPWbMsKnMh7NRARNWETe76tcwO88K2LqQFvhhILeTXKlWDpNcbGwqSinF62RXG4DxUQ=
|
||||
file_glob: true
|
||||
file: build/*
|
||||
on:
|
||||
branches: '0.0.27'
|
||||
branches: '0.0.33'
|
||||
repo: Portree-Kid/flightgear-airports
|
||||
|
||||
1751
package-lock.json
generated
1751
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "flightgear-airports",
|
||||
"version": "0.0.27",
|
||||
"version": "0.0.34",
|
||||
"author": "portree_kid <keith.paterson@gmx.de>",
|
||||
"description": "An software to design Flightgear groundnets",
|
||||
"license": "GPL v3",
|
||||
"license": "GPL-3.0",
|
||||
"main": "./dist/electron/main.js",
|
||||
"scripts": {
|
||||
"build": "node .electron-vue/build.js && electron-builder",
|
||||
@@ -70,30 +70,35 @@
|
||||
]
|
||||
},
|
||||
"mac": {
|
||||
"icon": "build/icons/icon.icns"
|
||||
"icon": "build/icons/icon.icns",
|
||||
"publish": []
|
||||
},
|
||||
"win": {
|
||||
"icon": "build/icons/icon.ico"
|
||||
"icon": "build/icons/icon.ico",
|
||||
"publish": []
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"perMachine": true,
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"linux": {
|
||||
"icon": "build/icons",
|
||||
"target": "AppImage"
|
||||
"target": "AppImage",
|
||||
"publish": []
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@turf/intersect": "^6.1.3",
|
||||
"@turf/turf": "^5.1.6",
|
||||
"axios": "^0.18.1",
|
||||
"axios": "^0.21.1",
|
||||
"coordinate-parser": "^1.0.3",
|
||||
"dijkstrajs": "^1.0.1",
|
||||
"electron-debug": "^3.0.1",
|
||||
"element-ui": "^2.13.2",
|
||||
"element-ui": "^2.15.1",
|
||||
"file-url": "^3.0.0",
|
||||
"fs": "0.0.1-security",
|
||||
"fs-extra": "^9.0.1",
|
||||
"geo-coordinates-parser": "^1.2.4",
|
||||
"geodesy": "^2.2.0",
|
||||
"idb": "^4.0.5",
|
||||
@@ -101,8 +106,10 @@
|
||||
"leaflet": "^1.5.1",
|
||||
"leaflet-editable": "^1.2.0",
|
||||
"leaflet-polylinedecorator": "^1.6.0",
|
||||
"leaflet-search": "^2.9.9",
|
||||
"leaflet-sidebar-v2": "^3.2.1",
|
||||
"leaflet-textpath": "^1.2.0",
|
||||
"leaflet.pattern": "^0.1.0",
|
||||
"lokijs": "^1.5.8",
|
||||
"mathjs": "^6.2.5",
|
||||
"path": "^0.12.7",
|
||||
@@ -143,7 +150,7 @@
|
||||
"del": "^3.0.0",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "^7.2.4",
|
||||
"electron-builder": "^21.2.0",
|
||||
"electron-builder": "^22.10.4",
|
||||
"electron-devtools-installer": "^2.2.4",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-standard": "^11.0.0",
|
||||
|
||||
@@ -31,6 +31,7 @@ function createWindow () {
|
||||
nodeIntegration: true,
|
||||
nodeIntegrationInWorker: true
|
||||
},
|
||||
closable: true,
|
||||
width: 1000
|
||||
})
|
||||
mainWindow.loadURL(winURL)
|
||||
|
||||
@@ -31,7 +31,7 @@ export function checkMapper(o) {
|
||||
'box': o.box !== undefined ? o.box.getLatLngs() : null
|
||||
};
|
||||
} else if (o instanceof L.RunwayNode) {
|
||||
console.log(o)
|
||||
console.log(o)
|
||||
return { 'index': Number(o['glueindex']), '_leaflet_id': o._leaflet_id, 'lat': o._latlng.lat, 'lng': o._latlng.lng, 'type': 'runway' };
|
||||
} else if (o instanceof L.HoldNode) {
|
||||
console.log(o)
|
||||
@@ -41,6 +41,11 @@ export function checkMapper(o) {
|
||||
'type': 'runway_poly',
|
||||
'pavement': o.getLatLngs()
|
||||
}
|
||||
} else if (o instanceof L.TakeoffPolygon) {
|
||||
return {
|
||||
'type': 'takeoffpad_poly',
|
||||
'pavement': o.getLatLngs()
|
||||
}
|
||||
} else if (o instanceof L.Polyline) {
|
||||
console.log(o)
|
||||
var latLngs = o.getLatLngs().map(l => ({ lat: l.lat, lng: l.lng, index: l.glueindex }));
|
||||
@@ -56,7 +61,7 @@ export function checkMapper(o) {
|
||||
}
|
||||
|
||||
export function groMapper(o) {
|
||||
if (o instanceof L.Polygon) {
|
||||
if (o instanceof L.Polygon) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
100
src/renderer/components/AirlineItem.vue
Normal file
100
src/renderer/components/AirlineItem.vue
Normal file
@@ -0,0 +1,100 @@
|
||||
<!--
|
||||
Copyright 2021 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 :key="airline.label + '-div'">
|
||||
<div v-for="item in traffic" v-bind:key="airline.label + '-' + item.id + '-innerdiv'">
|
||||
<div :key="item.id + '-dep'" v-if="direction == 0">{{ item.departure.time }} {{ item.callsign }} {{ item.departure.port }} --> {{ item.arrival.port }} {{ item['required-aircraft'] }} {{ item.flighttype }}</div>
|
||||
<div :key="item.id + '-arr'" v-if="direction == 1">{{ item.arrival.time }} {{ item.callsign }} {{ item.departure.port }} --> {{ item.arrival.port }} {{ item['required-aircraft'] }} {{ item.flighttype }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import {readTrafficXML} from '../loaders/traffic_loader'
|
||||
import ParkingItem from './ParkingItem'
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
export default {
|
||||
name: 'airline-traffic',
|
||||
components: {ParkingItem},
|
||||
props: {airline: Object},
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
traverseDir (dir, airline) {
|
||||
var result = []
|
||||
if (!fs.existsSync(dir)) {
|
||||
return result
|
||||
}
|
||||
var iaco = airline.label
|
||||
fs.readdirSync(dir).forEach(file => {
|
||||
let fullPath = path.join(dir, file)
|
||||
if (fs.lstatSync(fullPath).isDirectory()) {
|
||||
var children = this.traverseDir(fullPath, airline)
|
||||
result = result.concat(children)
|
||||
} else {
|
||||
if (file.match(new RegExp(`${iaco}.xml`, 'i'))) {
|
||||
result.push(fullPath)
|
||||
}
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
direction: function () {
|
||||
return this.$parent.$parent.$parent.$data.direction
|
||||
},
|
||||
filename: function () {
|
||||
var ret = this.traverseDir(this.$store.state.Settings.settings.flightgearDirectory_traffic, this.airline)
|
||||
if (ret.length > 0) {
|
||||
return ret[0]
|
||||
}
|
||||
},
|
||||
trafficFile: function () {
|
||||
return readTrafficXML(this.filename)
|
||||
},
|
||||
traffic: function () {
|
||||
if (this.filename) {
|
||||
var aircraftLookup = this.trafficFile.filter(a => a['required-aircraft'])
|
||||
.reduce((req, acc) => {
|
||||
req[acc['required-aircraft']] = acc
|
||||
return req
|
||||
}, {})
|
||||
var ret = this.trafficFile.filter(f => f.callsign).filter(f =>
|
||||
(f.departure.port === this.$store.state.Airports.currentAirport.icao && this.direction === 0) ||
|
||||
(f.arrival.port === this.$store.state.Airports.currentAirport.icao && this.direction === 1))
|
||||
.map(obj => ({ ...obj, flighttype: aircraftLookup[obj['required-aircraft']].flighttype }))
|
||||
.filter((v, i, a) => a.findIndex(t => (t.id === v.id)) === i)
|
||||
return ret
|
||||
}
|
||||
},
|
||||
aircraft: function () {
|
||||
if (this.filename) {
|
||||
return this.trafficFile.filter(f => f.registration)
|
||||
}
|
||||
console.debug(this.filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div.row.div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -15,14 +15,14 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
<el-dialog
|
||||
title="Add Airline"
|
||||
:visible.sync="dialogVisible"
|
||||
width="20%"
|
||||
:before-close="handleClose">
|
||||
width="40%"
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<span>Add an selectable airline to {{ icao }} {{ name }}</span>
|
||||
<el-input
|
||||
placeholder="Please input airline"
|
||||
v-model="airlineCode"
|
||||
maxlength="3"
|
||||
></el-input>
|
||||
<el-input
|
||||
placeholder="Please input airline(s)"
|
||||
v-model="airlineCode"
|
||||
></el-input>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">Cancel</el-button>
|
||||
<el-button type="primary" @click="addAirline">Confirm</el-button>
|
||||
@@ -32,116 +32,143 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
title="Import File"
|
||||
:visible.sync="showImportFile"
|
||||
width="20%"
|
||||
:before-close="handleClose">
|
||||
<span>Beware wip will be overwritten</span>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-input
|
||||
placeholder="Please input file"
|
||||
v-model="fileImportName">
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<file-select @input="fileImportFileName"></file-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
:before-close="handleClose"
|
||||
>
|
||||
<span>Beware wip will be overwritten</span>
|
||||
<el-row>
|
||||
<el-col :span="20">
|
||||
<el-input placeholder="Please input file" v-model="fileImportName">
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<file-select @input="fileImportFileName"></file-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="showImportFile = false">Cancel</el-button>
|
||||
<el-button type="primary" @click="importFile">Confirm</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<h1 class="leaflet-sidebar-header">{{ icao }} {{ name }}</h1>
|
||||
<div width="100%" >
|
||||
<el-row>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Description"
|
||||
width="50"
|
||||
trigger="hover"
|
||||
content="Edit"
|
||||
>
|
||||
<el-button @click="edit" v-if="!editing" slot="reference"><i class="fas fa-edit"></i></el-button>
|
||||
</el-popover>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Description"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Import groundnet"
|
||||
>
|
||||
<el-button @click="showImportFile = true" v-if="!editing" slot="reference"><i class="fas fa-file-import"></i></el-button>
|
||||
</el-popover>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Description"
|
||||
width="220"
|
||||
trigger="hover"
|
||||
content="Export groundnet to export directory"
|
||||
>
|
||||
<el-button @click="test" v-if="!editing" slot="reference"><i class="fas fa-file-export"></i></el-button>
|
||||
</el-popover>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Description"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Upload Airport"
|
||||
>
|
||||
<el-button @click="upload" v-if="!editing" slot="reference"><i class="fas fa-upload"></i></el-button>
|
||||
</el-popover>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7"><span class="label"> Airlines :</span></el-col>
|
||||
<el-col :span="15">
|
||||
<el-tag v-for="item in airlines" :key="item.value">{{item.value}}</el-tag>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<el-button @click="dialogVisible = true" v-if="editing" ><i class="fas fa-plus"></i></el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div width="100%">
|
||||
<el-row>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Description"
|
||||
width="50"
|
||||
trigger="hover"
|
||||
content="Edit"
|
||||
>
|
||||
<el-button @click="edit" v-if="!editing" slot="reference"
|
||||
><i class="fas fa-edit"></i
|
||||
></el-button>
|
||||
</el-popover>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Description"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Import groundnet"
|
||||
>
|
||||
<el-button
|
||||
@click="showImportFile = true"
|
||||
v-if="!editing"
|
||||
slot="reference"
|
||||
><i class="fas fa-file-import"></i
|
||||
></el-button>
|
||||
</el-popover>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Description"
|
||||
width="220"
|
||||
trigger="hover"
|
||||
content="Export groundnet to export directory"
|
||||
>
|
||||
<el-button @click="test" v-if="!editing" slot="reference"
|
||||
><i class="fas fa-file-export"></i
|
||||
></el-button>
|
||||
</el-popover>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Description"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Upload Airport"
|
||||
>
|
||||
<el-button @click="upload" v-if="!editing" slot="reference"
|
||||
><i class="fas fa-upload"></i
|
||||
></el-button>
|
||||
</el-popover>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7"><span class="label"> Airlines :</span></el-col>
|
||||
<el-col :span="15">
|
||||
<el-tag v-for="item in airlines" :key="item.value">{{
|
||||
item.value
|
||||
}}</el-tag>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<el-button @click="dialogVisible = true" v-if="editing"
|
||||
><i class="fas fa-plus"></i
|
||||
></el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-tabs v-model="activeTab" >
|
||||
<el-tab-pane label="Frequencies" name="first">
|
||||
<div>
|
||||
<el-row v-for="f in frequencyList" :key="f.index">
|
||||
<Frequency :frequency="f"></Frequency>
|
||||
</el-row>
|
||||
<el-button @click="addFrequency" v-if="editing" >Add</el-button>
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="Frequencies" name="first">
|
||||
<div>
|
||||
<el-row v-for="f in frequencyList" :key="f.index">
|
||||
<Frequency :frequency="f"></Frequency>
|
||||
</el-row>
|
||||
<el-button @click="addFrequency" v-if="editing">Add</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Parkings" name="second">
|
||||
<ParkingList></ParkingList>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Statistics" name="third">
|
||||
<el-row><el-col :span="8"><span class="label">Traffic :</span></el-col></el-row>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Parkings" name="second">
|
||||
<ParkingList></ParkingList>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Statistics" name="third">
|
||||
<el-row
|
||||
><el-col :span="8"
|
||||
><span class="label">Traffic :</span></el-col
|
||||
></el-row
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="8">Flights :</el-col>
|
||||
<el-col :span="4">{{ flights }}</el-col>
|
||||
<el-col :span="8"></el-col>
|
||||
<el-col :span="4"></el-col>
|
||||
</el-row>
|
||||
<el-row><el-col :span="16"><span class="label">GIT/Terrasync :</span></el-col></el-row>
|
||||
<el-row
|
||||
><el-col :span="16"
|
||||
><span class="label">GIT/Terrasync :</span></el-col
|
||||
></el-row
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="8">Parking Positions :</el-col>
|
||||
<el-col :span="4">{{ parking }}</el-col>
|
||||
<el-col :span="8">Groundnet Nodes :</el-col>
|
||||
<el-col :span="4">{{groundnet}}</el-col>
|
||||
<el-col :span="4">{{ groundnet }}</el-col>
|
||||
</el-row>
|
||||
<el-row><el-col :span="8"><span class="label">Work :</span></el-col></el-row>
|
||||
<el-row
|
||||
><el-col :span="8"><span class="label">Work :</span></el-col></el-row
|
||||
>
|
||||
<el-row v-if="wip">
|
||||
<el-col :span="8">Work Parking Positions :</el-col>
|
||||
<el-col :span="4">{{ wipparking }}</el-col>
|
||||
<el-col :span="8">Work Groundnet Nodes :</el-col>
|
||||
<el-col :span="4">{{wipgroundnet}}</el-col>
|
||||
<el-col :span="4">{{ wipgroundnet }}</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="wip">
|
||||
<el-col :span="4">Saved :</el-col>
|
||||
<el-col :span="8" class="text">{{date}}</el-col>
|
||||
<el-col :span="8" class="text">{{ date }}</el-col>
|
||||
<el-col :span="4">Uploaded :</el-col>
|
||||
<el-col :span="8" class="text">{{upload_date}}</el-col>
|
||||
<el-col :span="8" class="text">{{ upload_date }}</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Traffic" name="fourth">
|
||||
<TrafficList></TrafficList>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -150,8 +177,9 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
import FileSelect from './FileSelect'
|
||||
import Frequency from './Frequency'
|
||||
import ParkingList from './ParkingList'
|
||||
import TrafficList from './TrafficList'
|
||||
import Upload from './Upload'
|
||||
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
@@ -160,7 +188,7 @@ export default {
|
||||
return {showImportFile: false, activeTab: 'first', editing: false, uploadVisible: false, dialogVisible: false, airlineCode: '', fileImport: null}
|
||||
},
|
||||
components: {
|
||||
EditButton, FileSelect, Frequency, ParkingList, Upload
|
||||
EditButton, FileSelect, Frequency, ParkingList, TrafficList, Upload
|
||||
},
|
||||
methods: {
|
||||
fileImportFileName (f) {
|
||||
@@ -193,7 +221,11 @@ export default {
|
||||
},
|
||||
addAirline () {
|
||||
this.dialogVisible = false
|
||||
this.$store.dispatch('addAirline', this.airlineCode)
|
||||
this.airlineCode.split(/[ ,]/).forEach(element => {
|
||||
if (element.length === 3) {
|
||||
this.$store.dispatch('addAirline', element)
|
||||
}
|
||||
})
|
||||
},
|
||||
addFrequency () {
|
||||
this.$store.dispatch('addFrequency', {type: 'AWOS', value: 0})
|
||||
@@ -288,10 +320,10 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-row {
|
||||
padding: 0em;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.el-row {
|
||||
padding: 0em;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.label {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
|
||||
@@ -5,24 +5,26 @@
|
||||
<div class="leaflet-sidebar-close">
|
||||
<i class="fa fa-caret-left"></i>
|
||||
</div>
|
||||
</h1>
|
||||
</h1>
|
||||
<div id="panel" width="100%">
|
||||
<el-row v-if="!results || results.length === 0 "><h3>Check not run</h3></el-row>
|
||||
<el-row v-for="(result,idx) in results" :key="idx">
|
||||
<el-col :span="2" v-if="result.id<0"><span class="label"><i class="far fa-check-circle"></i></span></el-col>
|
||||
<el-col :span="2" v-if="result.id>=0"><span class="label"><i class="fas fa-exclamation-triangle"></i></span></el-col>
|
||||
<el-col :span="2" v-if="result.id==-1"><span class="label"><i class="far fa-check-circle"></i></span></el-col>
|
||||
<el-col :span="2" v-if="result.id>=0"><span class="label"><i class="fas fa-exclamation-triangle"></i></span></el-col>
|
||||
<el-col :span="2" v-if="result.id==-2"><span class="label"><i class="fas fa-exclamation-triangle"></i></span></el-col>
|
||||
<el-col :span="15">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Description"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
v-if="result.message"
|
||||
:content=result.message[1]
|
||||
>
|
||||
<span class="label" slot="reference">{{ result.message[0] }}</span>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
<el-col :span="4" v-if="result.id>=0"><el-button v-on:click="show(result.id)" class="button"><i class="fas fa-bullseye"></i></el-button></el-col>
|
||||
<el-col :span="4" v-if="result.id>=0"><el-button v-on:click="show(result.id)" class="button"><i class="fas fa-bullseye"></i></el-button></el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,32 +11,84 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
-->
|
||||
<template>
|
||||
<div id="EditBar">
|
||||
<ZoomButton icon="fas fa-th" v-on:click="zoomin" :show="true" tooltip="Zoomin"></ZoomButton>
|
||||
<ZoomButton icon="fas fa-th-large" v-on:click="zoomout" :show="!editing" tooltip="Zoomout"></ZoomButton>
|
||||
<!--<ZoomButton icon="far fa-eye-slash" v-on:click="hideAPT" :show='true' tooltip="Hide APT"></ZoomButton>-->
|
||||
|
||||
<!--<EditButton icon="fas fa-upload" v-on:click="upload" :show="!editing" tooltip="Upload"></EditButton>-->
|
||||
<!--<EditButton icon="fas fa-edit" v-on:click="edit" :show="!editing" tooltip="Edit"></EditButton>-->
|
||||
<EditButton
|
||||
icon="fas fa-undo"
|
||||
v-on:click="centerDialogVisible = true"
|
||||
:show="editing"
|
||||
tooltip="Undo"
|
||||
></EditButton>
|
||||
<el-dialog title="Reload" :visible.sync="centerDialogVisible" width="30%" center>
|
||||
<span style="center">Reload from last save? You will lose the current edits.</span>
|
||||
<el-dialog
|
||||
title="Checking"
|
||||
width="30%"
|
||||
center
|
||||
:visible.sync="checkDialogVisible"
|
||||
>
|
||||
<el-container direction="vertical">
|
||||
<el-progress
|
||||
:percentage="Number(((progress / max) * 100).toPrecision(3))"
|
||||
v-if="max > 0"
|
||||
></el-progress>
|
||||
</el-container>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
title="Revert"
|
||||
:visible.sync="centerDialogVisible"
|
||||
width="550px"
|
||||
center
|
||||
>
|
||||
<span>
|
||||
Please select the Version to revert to.
|
||||
<el-row v-for="item in saves" :key="item.file">
|
||||
<el-button @click="revert(item.file)">{{item.mtime}}</el-button>
|
||||
</el-row>
|
||||
</span>
|
||||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="undoFirst">Base version (GIT)</el-button>
|
||||
<el-button type="primary" @click="undoLast">Last save</el-button>
|
||||
<el-button type="primary" @click="cancel">Cancel</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-dialog title="Saving" :visible.sync="saveDialogVisible" width="30%" center>
|
||||
<el-dialog
|
||||
title="Saving"
|
||||
:visible.sync="saveDialogVisible"
|
||||
width="30%"
|
||||
center
|
||||
>
|
||||
<span style="center">Saving..</span>
|
||||
</el-dialog>
|
||||
|
||||
<EditButton icon="fas fa-save" v-on:click="save" :show="editing" tooltip="Save"></EditButton>
|
||||
<EditButton icon="far fa-check-square" v-on:click="showCheck" :show="editing" tooltip="Check"></EditButton>
|
||||
<ZoomButton
|
||||
icon="fas fa-th"
|
||||
v-on:click="zoomin"
|
||||
:show="true"
|
||||
tooltip="Zoomin"
|
||||
></ZoomButton>
|
||||
<ZoomButton
|
||||
icon="fas fa-th-large"
|
||||
v-on:click="zoomout"
|
||||
:show="!editing"
|
||||
tooltip="Zoomout"
|
||||
></ZoomButton>
|
||||
|
||||
<EditButton
|
||||
icon="fa fa-window-close"
|
||||
v-on:click="close"
|
||||
:show="editing"
|
||||
tooltip="Close/Save Editing"
|
||||
></EditButton>
|
||||
<EditButton
|
||||
icon="fas fa-undo"
|
||||
v-on:click="openReload"
|
||||
:show="editing"
|
||||
tooltip="Revert to Savepoint"
|
||||
></EditButton>
|
||||
<EditButton
|
||||
icon="fas fa-save"
|
||||
v-on:click="save"
|
||||
:show="editing"
|
||||
tooltip="Save"
|
||||
></EditButton>
|
||||
<EditButton
|
||||
icon="far fa-check-square"
|
||||
v-on:click="showCheck"
|
||||
:show="editing"
|
||||
tooltip="Check"
|
||||
></EditButton>
|
||||
<EditButton
|
||||
icon="fas fa-draw-polygon"
|
||||
v-on:click="drawPolyline"
|
||||
@@ -61,12 +113,12 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
:show="editing"
|
||||
tooltip="Draw Parking"
|
||||
></EditButton>
|
||||
<EditButton icon="fas fa-trash-alt" v-on:click="deleteFeature" :show="editing" tooltip="Remove"></EditButton>
|
||||
<el-dialog title="Checking" width="30%" center :visible.sync="checkDialogVisible">
|
||||
<el-container direction="vertical">
|
||||
<el-progress :percentage="Number(((progress / max)*100).toPrecision(3))" v-if="max>0"></el-progress>
|
||||
</el-container>
|
||||
</el-dialog>
|
||||
<EditButton
|
||||
icon="fas fa-trash-alt"
|
||||
v-on:click="deleteFeature"
|
||||
:show="editing"
|
||||
tooltip="Remove"
|
||||
></EditButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -76,6 +128,8 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
const fs = require('fs');
|
||||
const mapper = require('../check/mapper');
|
||||
|
||||
import {listSaves} from '../loaders/groundnet_loader'
|
||||
|
||||
import EditButton from './EditButton'
|
||||
import ZoomButton from './ZoomButton';
|
||||
import Vue from 'vue'
|
||||
@@ -85,11 +139,14 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
export default {
|
||||
components: { EditButton, ZoomButton },
|
||||
data () {
|
||||
return {isEditing: false, uploadVisible: false, centerDialogVisible: false, saveDialogVisible: false, checkDialogVisible: false, checking: false, progress: 0, max: 0, pavementLayerVisible: true}
|
||||
return {isEditing: false, uploadVisible: false, centerDialogVisible: false, saveDialogVisible: false, checkDialogVisible: false, checking: false, progress: 0, max: 0, pavementLayerVisible: true, saves: [] }
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods: {
|
||||
cancel () {
|
||||
this.centerDialogVisible = false
|
||||
},
|
||||
zoomout() {
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
this.$parent.$parent.zoomUpdated(9)
|
||||
@@ -109,40 +166,52 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
setEditing (editing) {
|
||||
this.isEditing = editing
|
||||
},
|
||||
undoFirst () {
|
||||
revert (file) {
|
||||
this.isEditing = false
|
||||
this.$emit('edit', false)
|
||||
this.centerDialogVisible = false
|
||||
this.$parent.$parent.$refs.map.mapObject.options.minZoom = 1;
|
||||
this.$parent.$parent.$refs.editLayer.disableEdit()
|
||||
this.$parent.$parent.$refs.editLayer.reload(true)
|
||||
this.$parent.$parent.$refs.towerLayer.disableEdit()
|
||||
this.$parent.$parent.$refs.thresholdLayer.disableEdit()
|
||||
this.$parent.$parent.$refs.editLayer.reload(file)
|
||||
},
|
||||
undoLast () {
|
||||
this.isEditing = false
|
||||
this.$emit('edit', false)
|
||||
this.centerDialogVisible = false
|
||||
this.$parent.$parent.$refs.map.mapObject.options.minZoom = 1;
|
||||
this.$parent.$parent.$refs.editLayer.disableEdit()
|
||||
this.$parent.$parent.$refs.editLayer.reload(false)
|
||||
},
|
||||
save () {
|
||||
close () {
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
this.isEditing = false
|
||||
this.$emit('edit', false)
|
||||
this.$parent.$parent.$refs.map.mapObject.options.minZoom = 1;
|
||||
Vue.set(this, 'saveDialogVisible', true)
|
||||
this.$emit('edit', false)
|
||||
Vue.nextTick( function () {
|
||||
setTimeout( this.closeDefered.bind(this), 100);
|
||||
}, this)
|
||||
},
|
||||
closeDefered () {
|
||||
this.$parent.$parent.$refs.editLayer.save()
|
||||
this.$parent.$parent.$refs.towerLayer.save()
|
||||
this.$parent.$parent.$refs.thresholdLayer.save()
|
||||
this.$parent.$parent.$refs.editLayer.disableEdit()
|
||||
this.$parent.$parent.$refs.towerLayer.disableEdit()
|
||||
this.$parent.$parent.$refs.thresholdLayer.disableEdit()
|
||||
this.rescanCurrentGroundnet()
|
||||
Vue.set(this, 'saveDialogVisible', false)
|
||||
},
|
||||
save () {
|
||||
Vue.set(this, 'saveDialogVisible', true)
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
Vue.nextTick( function () {
|
||||
setTimeout( this.saveDefered.bind(this), 100);
|
||||
}, this)
|
||||
},
|
||||
saveDefered () {
|
||||
this.$parent.$parent.$refs.editLayer.save()
|
||||
this.$parent.$parent.$refs.editLayer.disableEdit()
|
||||
this.scanGroundnets()
|
||||
Vue.set(this, 'saveDialogVisible', false)
|
||||
this.$parent.$parent.$refs.towerLayer.save()
|
||||
this.$parent.$parent.$refs.thresholdLayer.save()
|
||||
this.rescanCurrentGroundnet()
|
||||
Vue.set(this, 'saveDialogVisible', false)
|
||||
},
|
||||
scanGroundnets () {
|
||||
rescanCurrentGroundnet () {
|
||||
try {
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/worker.js`
|
||||
@@ -151,7 +220,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
|
||||
var icao = this.$parent.$parent.$refs.editLayer.icao
|
||||
const worker = new Worker(winURL)
|
||||
|
||||
|
||||
var aptDir = path.join(this.$store.state.Settings.settings.airportsDirectory, icao[0], icao[1], icao[2]);
|
||||
worker.postMessage(['scan', aptDir ])
|
||||
// the reply
|
||||
@@ -207,7 +276,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
|
||||
const worker = new Worker(winURL)
|
||||
worker.onerror = function(e) {
|
||||
worker.terminate()
|
||||
worker.terminate()
|
||||
worker.view.max = 0
|
||||
worker.view.checkDialogVisible = false
|
||||
e.preventDefault(); // <-- "Hey browser, I handled it!"
|
||||
@@ -233,9 +302,16 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
console.log(l)
|
||||
pavement.push(l)
|
||||
})
|
||||
var features2 = pavement.map(mapper.checkMapper).filter(n => n)
|
||||
var thresholds = []
|
||||
this.$parent.$parent.$refs.thresholdLayer.getLayer().eachLayer(l => {
|
||||
console.log(l)
|
||||
thresholds.push(l)
|
||||
})
|
||||
var pavementFeatures = pavement.map(mapper.checkMapper).filter(n => n)
|
||||
//TODO
|
||||
var thresholdFeatures = thresholds.map(mapper.checkMapper).filter(n => n)
|
||||
|
||||
worker.postMessage(['check', features.concat(features2) ] )
|
||||
worker.postMessage(['check', features.concat(pavementFeatures).concat(thresholdFeatures) ] )
|
||||
this.pollData()
|
||||
// the reply
|
||||
var store = this.$store
|
||||
@@ -289,6 +365,13 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
Vue.set(this, 'checkDialogVisible', true)
|
||||
this.check()
|
||||
},
|
||||
openReload: function() {
|
||||
this.centerDialogVisible = true
|
||||
var icao = this.$parent.$parent.$refs.editLayer.icao
|
||||
if (icao !== undefined && icao !== '') {
|
||||
this.saves = listSaves(this.$store.state.Settings.settings.airportsDirectory, icao).sort((a, b) => a.mtimeMs - b.mtimeMs)
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -22,7 +22,6 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
import L2 from 'leaflet-textpath'
|
||||
import Vue from 'vue'
|
||||
import { MessageBox } from 'element-ui';
|
||||
import { EventBus } from './event-bus.js';
|
||||
|
||||
const turf = require('@turf/turf')
|
||||
|
||||
@@ -40,14 +39,17 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
components: {},
|
||||
props: [],
|
||||
created () {
|
||||
|
||||
[LMap, LMarker, L, LEdit, L2]
|
||||
console.log('Created Editlayer')
|
||||
console.debug('Created Editlayer')
|
||||
// console.log(LSymbol)
|
||||
},
|
||||
mounted () {
|
||||
this.selectionLayerGroup = L.layerGroup();
|
||||
this.selectionLayerGroup.addTo(this.$parent.mapObject)
|
||||
this.$parent.mapObject.createPane('pushback-pane')
|
||||
this.$parent.mapObject.getPane('pushback-pane').style.zIndex = 512
|
||||
|
||||
this.$parent.mapObject.createPane('route-pane')
|
||||
this.$parent.mapObject.getPane('route-pane').style.zIndex = 511
|
||||
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.node;
|
||||
@@ -104,10 +106,16 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
maxId: 1, icao: String, checking: false, editing: false
|
||||
maxId: 1, icao: '', checking: false, editing: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getLayer () {
|
||||
return this.groundnetLayerGroup;
|
||||
},
|
||||
getIdLayerGroup() {
|
||||
return this.idLayerGroup;
|
||||
},
|
||||
getParkings(ring) {
|
||||
var poly = turf.polygon(ring);
|
||||
var parkings = []
|
||||
@@ -117,19 +125,31 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
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) {
|
||||
load (icao, filename) {
|
||||
if (this.groundnetLayerGroup !== undefined) {
|
||||
this.groundnetLayerGroup.removeFrom(this.$parent.mapObject)
|
||||
}
|
||||
}
|
||||
this.$parent.$parent.setIcao(icao)
|
||||
this.icao = icao
|
||||
this.groundnetLayerGroup = readGroundnetXML(this.$store.state.Settings.settings.airportsDirectory, icao, force)
|
||||
var f = '';
|
||||
if (!filename) {
|
||||
var f = path.join(this.$store.state.Settings.settings.airportsDirectory, icao[0], icao[1], icao[2], icao + '.groundnet.new.xml')
|
||||
if (!fs.existsSync(f)) {
|
||||
f = path.join(this.$store.state.Settings.settings.airportsDirectory, icao[0], icao[1], icao[2], icao + '.groundnet.xml')
|
||||
}
|
||||
} else {
|
||||
f = path.join(this.$store.state.Settings.settings.airportsDirectory, icao[0], icao[1], icao[2], filename)
|
||||
}
|
||||
|
||||
console.info(`Reload from : ${f}`)
|
||||
|
||||
this.groundnetLayerGroup = readGroundnetXML(this.$store.state.Settings.settings.airportsDirectory, icao, f)
|
||||
if (this.groundnetLayerGroup === undefined) {
|
||||
console.warn('Groundnet for ICAO not loaded ' + icao)
|
||||
return
|
||||
@@ -139,18 +159,21 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
}
|
||||
this.groundnetLayerGroup.eachLayer(l => {
|
||||
if (l instanceof L.TaxiwaySegment) {
|
||||
l.addListeners()
|
||||
l.addListeners()
|
||||
}
|
||||
if (l.updateArrows !== undefined) {
|
||||
l.updateArrows(this.$store.state.Settings.zoom)
|
||||
}
|
||||
if (typeof l.setInteractive === 'function') {
|
||||
l.setInteractive(false)
|
||||
}
|
||||
|
||||
})
|
||||
console.log(this.groundnetLayerGroup.maxId)
|
||||
console.debug(`MaxId : ${this.groundnetLayerGroup.maxId}`)
|
||||
this.buildLookup()
|
||||
|
||||
this.groundnetLayerGroup.addTo(this.$parent.mapObject)
|
||||
this.icao = icao
|
||||
console.log(EventBus)
|
||||
EventBus.$emit('i-got-clicked', 1);
|
||||
},
|
||||
visible (feature) {
|
||||
let bounds = this.$store.state.Settings.bounds
|
||||
@@ -192,7 +215,12 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.selection.forEach(element => {
|
||||
element.updateRadius(event.wingspan/2)
|
||||
});
|
||||
break;
|
||||
break;
|
||||
case 'parking-group-type':
|
||||
this.selection.forEach(element => {
|
||||
element.updateType(event.parking_type)
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -202,8 +230,11 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.editable = true
|
||||
this.editing = true
|
||||
this.$store.commit('SET_EDIT', true)
|
||||
|
||||
|
||||
this.featureLookup = [];
|
||||
if(!this.groundnetLayerGroup) {
|
||||
return;
|
||||
}
|
||||
this.groundnetLayerGroup.eachLayer(l => {
|
||||
l.enableEdit()
|
||||
l.featureLookup = this.featureLookup;
|
||||
@@ -220,7 +251,50 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
l.setInteractive(true)
|
||||
}
|
||||
})
|
||||
this.$store.dispatch('addWip', {icao: this.icao}); },
|
||||
this.$store.dispatch('addWip', {icao: this.icao});
|
||||
},
|
||||
showTooltips() {
|
||||
this.groundnetLayerGroup.eachLayer(l => {
|
||||
if (l instanceof L.Polyline) {
|
||||
l.getLatLngs().forEach(l => {
|
||||
if (this.$parent.mapObject.getBounds().contains(l)) {
|
||||
if (l.__vertex && !l.__vertex.getTooltip()) {
|
||||
l.__vertex.bindTooltip(l.glueindex, {permanent: true});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (l instanceof L.ParkingSpot) {
|
||||
if (this.$parent.mapObject.getBounds().contains(l.getLatLng())) {
|
||||
var parkingHub = l.glueindex + " " + l.options.attributes.name + " " + l.options.attributes.number;
|
||||
if(l.box) {
|
||||
l.box.bindTooltip(parkingHub, {permanent: true, direction: 'right'});
|
||||
} else {
|
||||
l.bindTooltip(parkingHub, {permanent: true, direction: 'right'});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
setTimeout(this.closeTooltips.bind(this), 2000);
|
||||
},
|
||||
closeTooltips() {
|
||||
this.groundnetLayerGroup.eachLayer(l => {
|
||||
if (l instanceof L.Polyline) {
|
||||
l.getLatLngs().forEach(l => {
|
||||
if (l.__vertex && l.__vertex.getTooltip()) {
|
||||
l.__vertex.unbindTooltip();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (l instanceof L.ParkingSpot) {
|
||||
if(l.box) {
|
||||
l.box.unbindTooltip();
|
||||
} else {
|
||||
l.unbindTooltip();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
disableEdit () {
|
||||
this.editable = false
|
||||
this.editing = false
|
||||
@@ -250,11 +324,14 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
console.log('Remove : ' + this.$store.state.Editable.type)
|
||||
}
|
||||
},
|
||||
isOnRunway(latlng) {
|
||||
return this.$parent.$parent.$refs.pavementLayer.isOnRunway(latlng)
|
||||
},
|
||||
findRouteToPushback (index) {
|
||||
if (this.featureLookup===undefined || this.featureLookup[index]===undefined) {
|
||||
return
|
||||
}
|
||||
var parking = this.featureLookup[index].filter(n => n instanceof L.ParkingSpot)
|
||||
var parking = this.featureLookup[index].filter(n => n instanceof L.ParkingSpot)
|
||||
var walkedNodes = [index]
|
||||
var pushBackNodes = []
|
||||
this.walkPushbackRoute(index, walkedNodes, pushBackNodes)
|
||||
@@ -280,29 +357,44 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
}
|
||||
});
|
||||
},
|
||||
removeArc (arc) {
|
||||
removeArc (arc) {
|
||||
console.debug('Remove Arc : ' + arc);
|
||||
var arcLayer = this.groundnetLayerGroup.getLayer(this.$store.state.Editable.index);
|
||||
arcLayer.removeFrom(this.groundnetLayerGroup);
|
||||
arcLayer.removeFrom(this.groundnetLayerGroup);
|
||||
},
|
||||
removeParking (index) {
|
||||
if(this.featureLookup[index]===undefined) {
|
||||
console.error("Lookup " + index + " failed ");
|
||||
console.error("Lookup " + index + " failed ");
|
||||
return;
|
||||
}
|
||||
this.featureLookup[index].forEach((element, i) => {
|
||||
if (element instanceof L.ParkingSpot) {
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
}
|
||||
});
|
||||
},
|
||||
show (index) {
|
||||
if(Number.isNaN(index)) {
|
||||
return;
|
||||
}
|
||||
if(this.featureLookup===undefined || this.featureLookup[index]===undefined) {
|
||||
console.error("Lookup " + index + " failed ");
|
||||
this.buildLookup()
|
||||
}
|
||||
if (this.featureLookup===undefined || this.featureLookup[index]===undefined) {
|
||||
var found = false;
|
||||
this.groundnetLayerGroup.eachLayer((layer) => {
|
||||
if (layer instanceof L.Polyline && layer._leaflet_id == index) {
|
||||
layer.select();
|
||||
this.$store.dispatch('setCenter', layer.getCenter());
|
||||
found = true;
|
||||
} else {
|
||||
layer.deselect();
|
||||
}
|
||||
});
|
||||
if (found) {
|
||||
return;
|
||||
} else {
|
||||
console.error("Lookup " + index + " failed ");
|
||||
this.buildLookup();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (Number(this.$store.state.Editable.index) >= 0 &&
|
||||
this.featureLookup[this.$store.state.Editable.index]!==undefined) {
|
||||
@@ -314,7 +406,6 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.featureLookup[index].forEach((element, i) => {
|
||||
if (element instanceof L.Polyline) {
|
||||
element._latlngs.forEach((e1, index1) => {
|
||||
console.log(e1);
|
||||
if (e1.attributes.index===Number(index)) {
|
||||
var latlng = {};
|
||||
latlng.lat = e1.lat;
|
||||
@@ -370,12 +461,12 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.featureLookup[layer.glueindex].push(layer);
|
||||
} else {
|
||||
console.warn(layer)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
getPointCoords (index) {
|
||||
if(this.featureLookup[index]===undefined) {
|
||||
console.error("Lookup " + index + " failed ");
|
||||
console.error("Lookup " + index + " failed ");
|
||||
return;
|
||||
}
|
||||
return this.featureLookup[index].map((element, i) => {
|
||||
@@ -405,14 +496,14 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
}).filter(n => n);
|
||||
},
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
setPointCoords (index, coordinates) {
|
||||
var position = new Coordinates(coordinates);
|
||||
|
||||
var latlng = {lat: position.latitude, lng: position.longitude };
|
||||
if(this.featureLookup[index]===undefined) {
|
||||
console.error("Lookup " + index + " failed ");
|
||||
console.error("Lookup " + index + " failed ");
|
||||
return;
|
||||
}
|
||||
return this.featureLookup[index].map((element, i) => {
|
||||
@@ -435,7 +526,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
else if (element instanceof L.Polyline) {
|
||||
element._latlngs.forEach((e1, index1) => {
|
||||
if (e1.attributes.index===index && (
|
||||
latlng.lat !== element.getLatLngs()[index1].lat ||
|
||||
latlng.lat !== element.getLatLngs()[index1].lat ||
|
||||
latlng.lng !== element.getLatLngs()[index1].lng
|
||||
)
|
||||
) {
|
||||
@@ -460,12 +551,12 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
element.editor.feature.setLatLngs(element.latlngs);
|
||||
element.editor.feature.updateMiddle();
|
||||
*/
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
refreshLookup(index) {
|
||||
//element.__vertex
|
||||
this.featureLookup[index] = this.featureLookup[index].filter(item => {
|
||||
this.featureLookup[index] = this.featureLookup[index].filter(item => {
|
||||
return !(item instanceof L.Editable.VertexMarker && item.editor.__vertex === undefined)
|
||||
}
|
||||
);
|
||||
@@ -478,7 +569,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
},
|
||||
removeNode (index) {
|
||||
if(this.featureLookup[index]===undefined) {
|
||||
console.error("Lookup " + index + " failed ");
|
||||
console.error("Lookup " + index + " failed ");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -496,31 +587,31 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.featureLookup[Number(element.end)] = this.featureLookup[Number(element.end)].filter(item => item !== element);
|
||||
this.refreshLookup(Number(element.end))
|
||||
}
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
element.removeFrom(this.$parent.mapObject);
|
||||
}
|
||||
else {
|
||||
element.getLatLngs().forEach((e1, index1) => {
|
||||
console.debug('Remove Long' + index1 + ' ' + e1);
|
||||
if (e1.attributes.index===index) {
|
||||
var splitOffNodes = element.getLatLngs().splice(index1);
|
||||
var splitOffNodes = element.getLatLngs().splice(index1);
|
||||
element.editor.refresh();
|
||||
element.editor.reset();
|
||||
splitOffNodes.splice(0, 1);
|
||||
if( splitOffNodes.length>1) {
|
||||
var polyline = new L.Polyline(splitOffNodes, { attributes: {} }).addTo(layerGroup);
|
||||
extendTaxiSegment(polyline);
|
||||
polyline.addListeners();
|
||||
polyline.addListeners();
|
||||
polyline.setEditlayer(this);
|
||||
polyline.enableEdit();
|
||||
polyline.editor.refresh();
|
||||
polyline.editor.reset();
|
||||
polyline.addTo(this.groundnetLayerGroup);
|
||||
polyline.addTo(this.groundnetLayerGroup);
|
||||
polyline.end = element.end;
|
||||
// Remove from end lookup
|
||||
this.featureLookup[element.options.attributes.end] = this.featureLookup[element.options.attributes.end].filter(item => item !== element);
|
||||
// push to the end lookup
|
||||
this.featureLookup[element.options.attributes.end].push(polyline);
|
||||
this.featureLookup[element.options.attributes.end].push(polyline);
|
||||
}
|
||||
if(element.getLatLngs().length === 1) {
|
||||
this.featureLookup[index] = this.featureLookup[index].filter(item => item !== element);
|
||||
@@ -537,8 +628,8 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
} else {
|
||||
console.warn('WTF' + element);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
@@ -578,7 +669,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
console.debug(event)
|
||||
event.target.addTo(this.groundnetLayerGroup)
|
||||
})
|
||||
},
|
||||
},
|
||||
drawPushbackPolyline () {
|
||||
var polyLine = this.$parent.mapObject.editTools.startPolyline()
|
||||
polyLine.addTo(this.groundnetLayerGroup)
|
||||
@@ -595,7 +686,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
polyLine.on('editable:drawing:end', event => {
|
||||
console.debug(event)
|
||||
event.target.addTo(this.groundnetLayerGroup)
|
||||
var pt = event.sourceTarget._latlngs[event.sourceTarget._latlngs.length-1];
|
||||
var pt = event.sourceTarget._latlngs[event.sourceTarget._latlngs.length-1];
|
||||
pt.attributes['holdPointType'] = 'PushBack'
|
||||
var nIndex = pt.attributes.index
|
||||
var fa_icon = "<div style='background-color:#4838cc;' class='marker-pin'></div><i class='fas fa-arrows-alt-h'></i>";
|
||||
@@ -621,7 +712,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.featureLookup===undefined) {
|
||||
return
|
||||
}
|
||||
console.log('Edited Parking : ' + this.$store.state.Editable.data.parking)
|
||||
console.debug('Edited Parking : ' + this.$store.state.Editable.data.parking)
|
||||
//Notify list
|
||||
if (this.featureLookup[this.$store.state.Editable.index]===undefined) {
|
||||
return
|
||||
@@ -629,18 +720,18 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.featureLookup[this.$store.state.Editable.index].forEach((element,index) => {
|
||||
if (element instanceof L.ParkingSpot) {
|
||||
element.options.attributes = Object.assign({}, this.$store.state.Editable.data.parking)
|
||||
element.updateVertexFromDirection();
|
||||
element.updateWheelPos();
|
||||
element.updateBox();
|
||||
element.updateVertexFromDirection();
|
||||
element.updateWheelPos();
|
||||
element.updateBox();
|
||||
}
|
||||
})
|
||||
if (this.$store.state.Editable.data.parking.coords) {
|
||||
this.setPointCoords(this.$store.state.Editable.index, this.$store.state.Editable.data.parking.coords)
|
||||
this.setPointCoords(this.$store.state.Editable.index, this.$store.state.Editable.data.parking.coords)
|
||||
}
|
||||
},
|
||||
editedParkings() {
|
||||
if (this.featureLookup===undefined) {
|
||||
console.warn("Lookup undefined");
|
||||
console.warn("Lookup undefined");
|
||||
this.buildLookup()
|
||||
}
|
||||
if (this.featureLookup===undefined) {
|
||||
@@ -648,14 +739,14 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
}
|
||||
console.debug('Edited Parkings : ' + this.$store.state.Parkings.items)
|
||||
this.$store.state.Parkings.items.forEach( newElement => {
|
||||
console.debug(newElement);
|
||||
if(this.featureLookup[newElement.index]) {
|
||||
this.featureLookup[newElement.index].forEach((element,index) => {
|
||||
if (element instanceof L.ParkingSpot) {
|
||||
console.debug(element);
|
||||
element.options.attributes.name = newElement.name
|
||||
element.options.attributes.number = newElement.number
|
||||
element.options.attributes.type = newElement.type
|
||||
//element.updateVertexFromDirection();
|
||||
//element.updateVertexFromDirection();
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -666,10 +757,10 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.featureLookup[this.$store.state.Editable.index].forEach((element,index) => {
|
||||
if (element instanceof L.ParkingSpot) {
|
||||
element.options.attributes = Object.assign({}, this.$store.state.Editable.data.parking)
|
||||
element.updateVertexFromDirection();
|
||||
element.updateVertexFromDirection();
|
||||
}
|
||||
})
|
||||
*/
|
||||
*/
|
||||
},
|
||||
editedArc() {
|
||||
if (!this.groundnetLayerGroup ||
|
||||
@@ -685,7 +776,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
console.log('Edited Arc : ' + this.$store.state.Editable.index);
|
||||
arc.options.attributes = Object.assign({}, this.$store.state.Editable.data.arc)
|
||||
arc.updateStyle();
|
||||
}
|
||||
}
|
||||
},
|
||||
editedMultiArc() {
|
||||
if (!this.groundnetLayerGroup ||
|
||||
@@ -705,7 +796,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
arc.options.attributes.name = String(this.$store.state.Editable.data.multiarc.name)
|
||||
arc.options.attributes.isPushBackRoute = Number(this.$store.state.Editable.data.multiarc.isPushBackRoute)
|
||||
arc.updateStyle();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
//Update Node
|
||||
@@ -715,11 +806,11 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.featureLookup===undefined ||
|
||||
!this.editing) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var isOnRunway = Number(this.$store.state.Editable.data.node.isOnRunway);
|
||||
var isHoldPoint = this.$store.state.Editable.data.node.holdPointType !== 'none' &&
|
||||
this.$store.state.Editable.data.node.holdPointType !== undefined;
|
||||
var nIndex = this.$store.state.Editable.index;
|
||||
var nIndex = this.$store.state.Editable.index;
|
||||
var hasRunwayNode = false;
|
||||
var hasHoldPointNode = false;
|
||||
var latlng;
|
||||
@@ -728,14 +819,14 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
if (isOnRunway === 0) {
|
||||
// We shouldn't have a RunwayNode
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
this.featureLookup[nIndex].splice(index,1);
|
||||
this.featureLookup[nIndex].splice(index,1);
|
||||
}
|
||||
hasRunwayNode = true;
|
||||
} else if (element instanceof L.HoldNode) {
|
||||
if (!isHoldPoint) {
|
||||
// We shouldn't have a RunwayNode
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
this.featureLookup[nIndex].splice(index,1);
|
||||
this.featureLookup[nIndex].splice(index,1);
|
||||
} else {
|
||||
var fa_icon;
|
||||
if (this.$store.state.Editable.data.node.holdPointType === 'PushBack') {
|
||||
@@ -768,33 +859,20 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
latlng = element._latlngs[1];
|
||||
}
|
||||
} else if (element instanceof L.Polyline) {
|
||||
element._latlngs.forEach(element => {
|
||||
if(element.__vertex && Number(element.glueindex) === Number(nIndex)){
|
||||
element._latlngs.forEach(element => {
|
||||
if(element.__vertex && Number(element.glueindex) === Number(nIndex)){
|
||||
if (this.$store.state.Editable.data.node.coords) {
|
||||
this.setPointCoords(this.$store.state.Editable.index, this.$store.state.Editable.data.node.coords)
|
||||
this.setPointCoords(this.$store.state.Editable.index, this.$store.state.Editable.data.node.coords)
|
||||
var position = new Coordinates(this.$store.state.Editable.data.node.coords);
|
||||
latlng = {lat: position.latitude, lng: position.longitude };
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
if (!hasRunwayNode && isOnRunway && latlng !== undefined) {
|
||||
this.$store.state.Editable.data.node.holdPointType
|
||||
const icon = new L.DivIcon({
|
||||
className: 'custom-div-icon',
|
||||
html: "<div style='background-color:#4838cc;' class='marker-pin'></div><i class='fas fa-plane-departure'></i>",
|
||||
iconSize: [30, 42],
|
||||
iconAnchor: [15, 42]
|
||||
});
|
||||
const node = new L.RunwayNode(latlng, { icon: icon });
|
||||
node.glueindex = nIndex;
|
||||
node.addTo(this.groundnetLayerGroup);
|
||||
this.featureLookup[nIndex].push(node);
|
||||
node.featureLookup = this.featureLookup;
|
||||
node.addListeners();
|
||||
node.extensions();
|
||||
this.addRunwayNode(latlng, nIndex)
|
||||
}
|
||||
if (!hasHoldPointNode && isHoldPoint) {
|
||||
var fa_icon = null;
|
||||
@@ -819,6 +897,21 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
node.extensions();
|
||||
}
|
||||
},
|
||||
addRunwayNode (latlng, nIndex) {
|
||||
const icon = new L.DivIcon({
|
||||
className: 'custom-div-icon',
|
||||
html: "<div style='background-color:#4838cc;' class='marker-pin'></div><i class='fas fa-plane-departure'></i>",
|
||||
iconSize: [30, 42],
|
||||
iconAnchor: [15, 42]
|
||||
});
|
||||
const node = new L.RunwayNode(latlng, { icon: icon });
|
||||
node.glueindex = nIndex;
|
||||
node.addTo(this.groundnetLayerGroup);
|
||||
this.featureLookup[nIndex].push(node);
|
||||
node.featureLookup = this.featureLookup;
|
||||
node.addListeners();
|
||||
node.extensions();
|
||||
},
|
||||
// Finde nearest node
|
||||
closestLayerSnap (eventLatlng, snap) {
|
||||
var layers = []
|
||||
@@ -855,7 +948,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
}
|
||||
} else {
|
||||
console.log(layer)
|
||||
}
|
||||
}
|
||||
})
|
||||
layers.sort((l1, l2) => l1.d - l2.d)
|
||||
if (layers.length > 0) {
|
||||
@@ -884,9 +977,9 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
circle.addListeners()
|
||||
circle.enableEdit()
|
||||
circle.extensions()
|
||||
circle.updateVertexFromDirection();
|
||||
circle.updateWheelPos();
|
||||
circle.updateBox();
|
||||
circle.updateVertexFromDirection();
|
||||
circle.updateWheelPos();
|
||||
circle.updateBox();
|
||||
if (Number(this.$store.state.Editable.index) >= 0 &&
|
||||
this.featureLookup[this.$store.state.Editable.index]!==undefined) {
|
||||
this.featureLookup[this.$store.state.Editable.index].forEach(element => {
|
||||
@@ -903,12 +996,12 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.$parent.mapObject.off('click', this.addParking)
|
||||
this.$parent.mapObject._container.style.cursor = ''
|
||||
},
|
||||
reload (force) {
|
||||
this.load(this.icao, force)
|
||||
reload (filename) {
|
||||
this.load(this.icao, filename)
|
||||
},
|
||||
link (index) {
|
||||
var layers = []
|
||||
var centerLatLng = null
|
||||
var centerLatLng = null
|
||||
this.featureLookup[index].forEach(layer => {
|
||||
if (layer instanceof L.Polyline) {
|
||||
// console.log(layer._latlngs)
|
||||
@@ -917,7 +1010,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
if (Number.isNaN(latlng.glueindex)) {
|
||||
console.warn('No glueindex : ' + latlng.__vertex);
|
||||
}
|
||||
|
||||
|
||||
if (Number(latlng.glueindex) === index) {
|
||||
centerLatLng = latlng;
|
||||
}
|
||||
@@ -946,7 +1039,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
nearest.push({d: distance, l: layer, latlng: latlng.__vertex.latlng, glueindex: latlng.glueindex })
|
||||
}
|
||||
} else {
|
||||
console.error("No __Vertex");
|
||||
console.error("No __Vertex", latlng);
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -988,9 +1081,9 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
featureLookup[glueindex] = [];
|
||||
});
|
||||
});
|
||||
},
|
||||
save () {
|
||||
var xml = []
|
||||
@@ -999,7 +1092,6 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
xml.push(l)
|
||||
})
|
||||
writeGroundnetXML(this.$store.state.Settings.settings.airportsDirectory, this.icao, xml)
|
||||
this.load(this.icao, false)
|
||||
},
|
||||
//Copy to test directory
|
||||
test() {
|
||||
@@ -1015,16 +1107,16 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.$message({
|
||||
type: 'info',
|
||||
message: `Copied to ${fNew}`
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: `Copy error : ${error}`
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
setVisible(visible) {
|
||||
if (this.layerGroup) {
|
||||
if (this.layerGroup) {
|
||||
if (visible) {
|
||||
this.layerGroup.addTo(this.$parent.mapObject)
|
||||
} else {
|
||||
|
||||
@@ -29,7 +29,7 @@ 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>
|
||||
<AiLayer ref="aiLayer"></AiLayer>
|
||||
<l-layer-group layerType="overlay" name="airports" ref="airportLayer">
|
||||
<l-circle
|
||||
v-for="(item, index) in this.$store.state.Airports.airports"
|
||||
@@ -42,7 +42,7 @@ 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>
|
||||
<PavementLayer ref="pavementLayer"></PavementLayer>
|
||||
<ThresholdLayer ref="thresholdLayer"></ThresholdLayer>
|
||||
<TowerLayer ref="towerLayer"></TowerLayer>
|
||||
<ToolLayer ref="toolLayer" @select-poly="onSelectedPolygon"></ToolLayer>
|
||||
@@ -53,8 +53,9 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
|
||||
<script lang="js">
|
||||
import 'leaflet/dist/leaflet.css'
|
||||
import 'leaflet-search/dist/leaflet-search.src.css'
|
||||
import '@/assets/button.css'
|
||||
import { LMap, LTileLayer, LMarker, LCircle, LLayerGroup, LControl } from 'vue2-leaflet'
|
||||
import { LMap, LTileLayer, LMarker, LCircle, LLayerGroup, LControl, LTooltip } from 'vue2-leaflet'
|
||||
import LeafletSidebar from './LeafletSidebar'
|
||||
import AiLayer from './AiLayer'
|
||||
import EditBar from './EditBar'
|
||||
@@ -67,6 +68,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
|
||||
import { Loading } from 'element-ui'
|
||||
import L from 'leaflet'
|
||||
import { LeafletSearch } from 'leaflet-search'
|
||||
|
||||
// https://github.com/KoRiGaN/Vue2Leaflet/issues/103
|
||||
delete L.Icon.Default.prototype._getIconUrl
|
||||
@@ -77,7 +79,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, TowerLayer, PavementLayer, LLayerGroup, LControl, ThresholdLayer, ToolLayer },
|
||||
components: { LMap, LTileLayer, LMarker, LCircle, LTooltip, LeafletSidebar, AiLayer, EditBar, ToolBar, EditLayer, TowerLayer, PavementLayer, LLayerGroup, LControl, ThresholdLayer, ToolLayer, LeafletSearch },
|
||||
props: [],
|
||||
created () {
|
||||
this.loadingInstance = null
|
||||
@@ -183,7 +185,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
loadingInstance: Object,
|
||||
groundnetLoaded: false,
|
||||
pavementLoaded: false,
|
||||
url: 'https://a.tile.openstreetmap.de/{z}/{x}/{y}.png',
|
||||
url: 'http://xjsjc.kongjian.xin:4200/tile/{z}/{x}/{y}.png',
|
||||
attribution: '<A href="https://github.com/Portree-Kid/flightgear-airports" target="_blank">Flightgear Airports ' + require('electron').remote.app.getVersion() +
|
||||
'</A> <A href="https://www.electronjs.org/" target="_blank">Electron</A> ' +
|
||||
' <A href="https://element.eleme.io/#/en-US/" target="_blank">element.io</A> ' +
|
||||
@@ -241,6 +243,16 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
}
|
||||
this.$refs.towerLayer.zoomUpdated()
|
||||
}
|
||||
if (this.$refs.editLayer !== undefined && this.searchControl === undefined && this.$refs.editLayer.getLayer() === e.layer) {
|
||||
this.searchControl = new L.Control.Search({
|
||||
layer: this.$refs.editLayer.getLayer(),
|
||||
position: 'topleft',
|
||||
propertyName: 'searchTerm',
|
||||
marker: {animate: false},
|
||||
initial: false
|
||||
})
|
||||
this.searchControl.addTo(this.$refs.map.mapObject)
|
||||
}
|
||||
},
|
||||
onSelectedPolygon (ring) {
|
||||
var parkings = this.$refs.editLayer.getParkings(ring)
|
||||
@@ -258,6 +270,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
}
|
||||
this.$refs.editLayer.enableEdit()
|
||||
this.$refs.towerLayer.enableEdit()
|
||||
this.$refs.thresholdLayer.enableEdit()
|
||||
this.$refs.editBar.setEditing(event)
|
||||
this.$refs.toolBar.setEditing(event)
|
||||
this.$refs.sidebar.setEditing(event)
|
||||
@@ -323,6 +336,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
event.target.airport = item
|
||||
// console.log(event, item)
|
||||
this.normalStyle(event.target)
|
||||
event.target.bindTooltip(event.target.airport.properties.icao + ' ' + event.target.airport.properties.name)
|
||||
},
|
||||
onClick (event, item) {
|
||||
console.log(item)
|
||||
@@ -365,7 +379,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
},
|
||||
async centerUpdated (center) {
|
||||
if (center !== this.$store.state.Settings.center) {
|
||||
this.$store.dispatch('setCenter', center)
|
||||
this.$store.dispatch('setCenter', {lat: Number(center.lat), lng: Number(center.lng)})
|
||||
this.$refs.airportLayer.setVisible(this.zoom < 12)
|
||||
if (this.$refs.thresholdLayer) {
|
||||
this.$refs.thresholdLayer.setVisible(this.zoom >= 12)
|
||||
|
||||
@@ -40,6 +40,8 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
<ParkingEdit></ParkingEdit>
|
||||
<ArcEditMulti></ArcEditMulti>
|
||||
<ArcEdit></ArcEdit>
|
||||
<ThresholdEdit></ThresholdEdit>
|
||||
<TowerEdit></TowerEdit>
|
||||
<NodeEdit></NodeEdit>
|
||||
<ParkingGroupEdit ref="parkingGroupEdit" @editParking="(msg) => $emit('editParking', msg)"></ParkingGroupEdit>
|
||||
<AirportEdit ref="airportEdit" @edit="$emit('edit', $event)"></AirportEdit>
|
||||
@@ -75,11 +77,13 @@ 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'
|
||||
import Help from './Help'
|
||||
import NodeEdit from './NodeEdit'
|
||||
import ThresholdEdit from './ThresholdEdit'
|
||||
import ParkingEdit from './ParkingEdit'
|
||||
import ParkingGroupEdit from './ParkingGroupEdit'
|
||||
// import ParkingList from './ParkingList'
|
||||
@@ -91,7 +95,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, ThresholdEdit, FileSelect, SettingsPanel, Search, Upload, WorkInProgress },
|
||||
props: [],
|
||||
created () {
|
||||
window.addEventListener('keydown', this.doCommand)
|
||||
|
||||
@@ -16,13 +16,21 @@
|
||||
<span class="label">Name :</span>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-input placeholder="Name" v-model="name" :disabled="!editing"></el-input>
|
||||
<el-input
|
||||
placeholder="Name"
|
||||
v-model="name"
|
||||
:disabled="!editing"
|
||||
></el-input>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<span class="label">Number :</span>
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-input placeholder="Number" v-model="number" :disabled="!editing"></el-input>
|
||||
<el-input
|
||||
placeholder="Number"
|
||||
v-model="number"
|
||||
:disabled="!editing"
|
||||
></el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
@@ -40,7 +48,11 @@
|
||||
-->
|
||||
|
||||
<el-radio-group v-model="wingspan" :disabled="!editing">
|
||||
<el-tooltip content="PIPER PA-31/CESSNA 404 Titan" placement="top" effect="light">
|
||||
<el-tooltip
|
||||
content="PIPER PA-31/CESSNA 404 Titan"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-radio :label="15">A (7.5)</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
@@ -48,14 +60,14 @@
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-radio :label="20">- (10)</el-radio>
|
||||
<el-radio :label="20">- (10)</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 (14)</el-radio>
|
||||
<el-radio :label="28">B (14)</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
content="BOEING 737-700/AIRBUS A-320/EMBRAER ERJ 190-100"
|
||||
@@ -64,13 +76,25 @@
|
||||
>
|
||||
<el-radio :label="36">C (18)</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="B767 Series/AIRBUS A-310" placement="top" effect="light">
|
||||
<el-tooltip
|
||||
content="B767 Series/AIRBUS A-310"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-radio :label="52">D (26)</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="B777 Series/B787 Series/A330 Family" placement="top" effect="light">
|
||||
<el-tooltip
|
||||
content="B777 Series/B787 Series/A330 Family"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-radio :label="66">E (33)</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="BOEING 747-8/AIRBUS A-380-800" placement="top" effect="light">
|
||||
<el-tooltip
|
||||
content="BOEING 747-8/AIRBUS A-380-800"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-radio :label="80">F (40)</el-radio>
|
||||
</el-tooltip>
|
||||
</el-radio-group>
|
||||
@@ -80,9 +104,9 @@
|
||||
<el-col :span="7">
|
||||
<span class="label">Aircraft :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">{{type}}</el-col>
|
||||
<el-col :span="17">{{ type }}</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="editing">
|
||||
<el-row v-if="editing">
|
||||
<el-col :span="7">
|
||||
<span class="label">Calculate :</span>
|
||||
</el-col>
|
||||
@@ -91,7 +115,6 @@
|
||||
<el-radio-button label="Nose Wheel"></el-radio-button>
|
||||
<el-radio-button label="Center"></el-radio-button>
|
||||
</el-radio-group>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
@@ -100,14 +123,21 @@
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
placement="bottom-start"
|
||||
title="E-Mail"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="D.DDD, DMS, DM supported"
|
||||
:disabled="!editing || calculate === 'Center'"
|
||||
>
|
||||
<el-input placeholder="Please input" v-model="coordinates" slot="reference" :disabled="!editing || calculate ==='Center'"></el-input>
|
||||
<el-input
|
||||
placeholder="Please input"
|
||||
v-model="coordinates"
|
||||
slot="reference"
|
||||
:disabled="!editing || calculate === 'Center'"
|
||||
@focus="coordFocussed = true"
|
||||
@blur="coordFocussed = false"
|
||||
></el-input>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -124,7 +154,14 @@
|
||||
content="D.DDD, DMS, DM supported"
|
||||
:disabled="!editing || calculate === 'Nose Wheel'"
|
||||
>
|
||||
<el-input placeholder="Please input" v-model="noseCoordinates" slot="reference" :disabled="!editing || calculate === 'Nose Wheel'"></el-input>
|
||||
<el-input
|
||||
placeholder="Please input"
|
||||
v-model="noseCoordinates"
|
||||
slot="reference"
|
||||
:disabled="!editing || calculate === 'Nose Wheel'"
|
||||
@focus="noseCoordFocussed = true"
|
||||
@blur="noseCoordFocussed = false"
|
||||
></el-input>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -132,23 +169,33 @@
|
||||
<el-col :span="7">
|
||||
<span class="label">Heading :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-col :span="13">
|
||||
<el-input-number
|
||||
v-model="heading"
|
||||
:min="-361"
|
||||
:max="720"
|
||||
:step="0.1"
|
||||
:precision="1"
|
||||
:disabled="!editing || calculate ==='Heading'"
|
||||
:disabled="!editing || calculate === 'Heading'"
|
||||
@change="headingChange"
|
||||
></el-input-number>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-button @click="rotate" class="button">
|
||||
<i class="fas fa-ruler-combined"></i>
|
||||
</el-button>
|
||||
</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-select
|
||||
v-model="parking_type"
|
||||
placeholder="Select"
|
||||
:disabled="!editing"
|
||||
>
|
||||
<el-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
@@ -164,7 +211,12 @@
|
||||
<span class="label">Airline :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-select v-model="airlineCodes" multiple placeholder="Select" :disabled="!editing">
|
||||
<el-select
|
||||
v-model="airlineCodes"
|
||||
multiple
|
||||
placeholder="Select"
|
||||
:disabled="!editing"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in airlines"
|
||||
:key="item.value"
|
||||
@@ -178,7 +230,7 @@
|
||||
<el-col :span="7">
|
||||
<span class="label">Pushback Route End :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">{{pushbackEnd}}</el-col>
|
||||
<el-col :span="17">{{ pushbackEnd }}</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
@@ -186,13 +238,64 @@
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
const convert = require('geo-coordinates-parser');
|
||||
|
||||
|
||||
const turf = require('@turf/turf');
|
||||
|
||||
const turfOptions = { units: 'kilometers' };
|
||||
|
||||
export default {
|
||||
mounted() {
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.parking;
|
||||
},
|
||||
() => { this.editedParking() }
|
||||
,
|
||||
{
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
}
|
||||
);
|
||||
},
|
||||
methods: {
|
||||
editedParking() {
|
||||
this.externalChange = true
|
||||
this.heading = Number(this.$store.state.Editable.data.parking.heading);
|
||||
this.externalChange = false
|
||||
},
|
||||
rotate() {
|
||||
var heading = this.$store.state.Editable.data.parking.heading + 90;
|
||||
while (heading>=360) {
|
||||
heading -= 360
|
||||
}
|
||||
while (heading<0) {
|
||||
heading += 360
|
||||
}
|
||||
this.headingChange(heading);
|
||||
},
|
||||
headingChange( newValue ) {
|
||||
while (newValue>=360) {
|
||||
newValue -= 360
|
||||
}
|
||||
while (newValue<0) {
|
||||
newValue += 360
|
||||
}
|
||||
if ( ( Math.abs( this.$store.state.Editable.data.parking.heading - newValue ) >= 0 && Math.abs( this.$store.state.Editable.data.parking.heading - newValue ) <= 0.1 )
|
||||
|| !this.externalChange) {
|
||||
if (Number(this.$store.state.Editable.data.parking.heading) !== newValue) {
|
||||
this.$store.commit('SET_EDIT_PARKING_HEADING', newValue)
|
||||
}
|
||||
if(this.calculate === 'Center') {
|
||||
// we change center
|
||||
const noseWheelLatLng = convert(this.$store.state.Editable.data.parking.nosecoords);
|
||||
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
|
||||
if (parkingSize>=0) {
|
||||
var reverseHeading = this.normalizeAngle(this.$store.state.Editable.data.parking.heading+180);
|
||||
var newCenter = turf.destination(this.latToTurf(noseWheelLatLng), this.validN2M[parkingSize]/1000, reverseHeading, turfOptions);
|
||||
this.$store.commit('SET_EDIT_PARKING_COORDS', this.turfToLatLng(newCenter));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
show (idx) {
|
||||
this.$parent.$parent.$parent.$refs.editLayer.show(idx)
|
||||
},
|
||||
@@ -208,11 +311,41 @@
|
||||
latToTurf (turfPoint) {
|
||||
return [turfPoint.decimalLongitude, turfPoint.decimalLatitude];
|
||||
},
|
||||
turfToLatLng: function (turfPoint) {
|
||||
turfToLatLng (turfPoint) {
|
||||
return '' + turfPoint.geometry.coordinates[1].toFixed(6) + ',' + turfPoint.geometry.coordinates[0].toFixed(6);
|
||||
},
|
||||
beautify (coordString) {
|
||||
var a = coordString.split(' ');
|
||||
if (a.length === 2) {
|
||||
return '' + Number(a[0]).toFixed(6) + ' ' + Number(a[1]).toFixed(6);
|
||||
} else {
|
||||
return coordString;
|
||||
}
|
||||
},
|
||||
calcWheel () {
|
||||
if(this.calculate === 'Nose Wheel') {
|
||||
// we change nosewheel
|
||||
const centerLatLng = convert(this.beautify(this.$store.state.Editable.data.parking.coords));
|
||||
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
|
||||
if (parkingSize>=0) {
|
||||
var newNoseWheel = turf.destination(this.latToTurf(centerLatLng), this.validN2M[parkingSize]/1000, this.$store.state.Editable.data.parking.heading, turfOptions);
|
||||
this.$store.commit('SET_EDIT_PARKING_NOSE_COORDS', this.turfToLatLng(newNoseWheel));
|
||||
}
|
||||
}
|
||||
},
|
||||
calcCenter () {
|
||||
if (this.calculate === 'Center') {
|
||||
// we change center
|
||||
const noseWheelLatLng = convert(this.beautify(this.$store.state.Editable.data.parking.nosecoords));
|
||||
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
|
||||
if (parkingSize>=0) {
|
||||
var newCenter = turf.destination(this.latToTurf(noseWheelLatLng), this.validN2M[parkingSize]/1000, this.$store.state.Editable.data.parking.heading - 180, turfOptions);
|
||||
this.$store.commit('SET_EDIT_PARKING_COORDS', this.turfToLatLng(newCenter));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data () { return {calculate:'Nose Wheel', noseWheel: '', validRadii: [7.5, 10, 14, 18, 26, 33, 40], validN2M: [5, 5, 6, 10, 15, 24, 24] } },
|
||||
data () { return {rotateFocussed: false, externalChange: false, coordFocussed: false, noseCoordFocussed: false, calculateState: 'Nose Wheel', noseWheel: '', validRadii: [7.5, 10, 14, 18, 26, 33, 40], validN2M: [5, 5, 6, 10, 15, 24, 24], heading: 0 }},
|
||||
computed: {
|
||||
editing: {
|
||||
get: function () {
|
||||
@@ -238,16 +371,16 @@
|
||||
},
|
||||
airlineCodes: {
|
||||
// getter
|
||||
get: function () {
|
||||
get: function () {
|
||||
var codes = this.$store.state.Editable.data.parking.airlineCodes
|
||||
if (Array.isArray(codes)) {
|
||||
return codes
|
||||
} else if (codes !== undefined && typeof codes === 'string') {
|
||||
return codes.split(',')
|
||||
return codes.split(',')
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
return
|
||||
return
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
@@ -274,6 +407,19 @@
|
||||
this.$store.commit('SET_EDIT_PARKING_NUMBER', newValue)
|
||||
}
|
||||
},
|
||||
calculate: {
|
||||
get: function () {
|
||||
return this.calculateState;
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.calculateState = newValue;
|
||||
if (newValue==='Center') {
|
||||
this.calcCenter();
|
||||
} else {
|
||||
this.calcWheel();
|
||||
}
|
||||
}
|
||||
},
|
||||
coordinates: {
|
||||
// getter
|
||||
get: function () {
|
||||
@@ -284,78 +430,39 @@
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
if (newValue==='unknown') {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if( newValue.match(/,/g) !== null && newValue.match(/,/g).length === 3) {
|
||||
newValue = newValue.replace(', ', ' ').replace(/,/g, '.').replace(' ', ', ');
|
||||
}
|
||||
this.$store.commit('SET_EDIT_PARKING_COORDS', newValue)
|
||||
}
|
||||
if (this.coordFocussed) {
|
||||
this.$store.commit('SET_EDIT_PARKING_COORDS', newValue)
|
||||
}
|
||||
this.calcWheel();
|
||||
}
|
||||
},
|
||||
noseCoordinates: {
|
||||
// getter
|
||||
get: function () {
|
||||
if(this.$store.state.Editable.index!==undefined) {
|
||||
const center = convert(this.$store.state.Editable.data.parking.coords);
|
||||
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
|
||||
if (parkingSize>=0) {
|
||||
var newWheel = turf.destination(this.latToTurf(center), this.validN2M[parkingSize]/1000, this.normalizeAngle(this.$store.state.Editable.data.parking.heading), turfOptions);
|
||||
var newValue = this.turfToLatLng(newWheel);
|
||||
if( newValue.match(/,/g) !== null && newValue.match(/,/g).length === 1) {
|
||||
newValue = newValue.replace(',', ' ');
|
||||
}
|
||||
this.noseWheel = newValue;
|
||||
return newValue;
|
||||
}
|
||||
if(this.$store.state.Editable.index!==undefined) {
|
||||
if(!this.$store.state.Editable.data.parking.nosecoords && this.calculate === 'Nose Wheel') {
|
||||
this.calcWheel();
|
||||
}
|
||||
return this.$store.state.Editable.data.parking.nosecoords;
|
||||
}
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
if (newValue==='unknown') {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if( newValue.match(/,/g) !== null && newValue.match(/,/g).length === 3) {
|
||||
newValue = newValue.replace(', ', ' ').replace(/,/g, '.').replace(' ', ', ');
|
||||
}
|
||||
this.noseWheel = newValue;
|
||||
var centerCoords = convert(this.$store.state.Editable.data.parking.coords);
|
||||
if(this.calculate === 'Center') {
|
||||
// we change center
|
||||
const noseWheelLatLng = convert(this.noseWheel);
|
||||
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
|
||||
if (parkingSize>=0) {
|
||||
var newCenter = turf.destination(this.latToTurf(noseWheelLatLng), this.validN2M[parkingSize]/1000, this.$store.state.Editable.data.parking.heading, turfOptions);
|
||||
this.$store.commit('SET_EDIT_PARKING_COORDS', this.turfToLatLng(newCenter));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
heading: {
|
||||
// getter
|
||||
get: function () {
|
||||
return Number(this.$store.state.Editable.data.parking.heading)
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
while (newValue>=360) {
|
||||
newValue -= 360
|
||||
}
|
||||
while (newValue<0) {
|
||||
newValue += 360
|
||||
}
|
||||
if (Number(this.$store.state.Editable.data.parking.heading) !== newValue) {
|
||||
this.$store.commit('SET_EDIT_PARKING_HEADING', newValue)
|
||||
}
|
||||
if(this.calculate === 'Center') {
|
||||
// we change center
|
||||
const noseWheelLatLng = convert(this.noseWheel);
|
||||
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
|
||||
if (parkingSize>=0) {
|
||||
var reverseHeading = this.normalizeAngle(this.$store.state.Editable.data.parking.heading+180);
|
||||
var newCenter = turf.destination(this.latToTurf(noseWheelLatLng), this.validN2M[parkingSize]/1000, reverseHeading, turfOptions);
|
||||
this.$store.commit('SET_EDIT_PARKING_COORDS', this.turfToLatLng(newCenter));
|
||||
}
|
||||
if (this.noseCoordFocussed) {
|
||||
this.$store.commit('SET_EDIT_PARKING_NOSE_COORDS', newValue);
|
||||
}
|
||||
this.calcCenter();
|
||||
}
|
||||
},
|
||||
wingspan: {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
radius: 18
|
||||
type: "gate"
|
||||
-->
|
||||
<!--
|
||||
<!--
|
||||
<el-row>
|
||||
<el-col :span="4">
|
||||
<span class="label">Name :</span>
|
||||
@@ -90,13 +90,12 @@
|
||||
</el-button>
|
||||
</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-select v-model="parking_type" @change="typeChange" placeholder="Select" :disabled="!editing">
|
||||
<el-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
@@ -107,6 +106,7 @@
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!--
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Airline :</span>
|
||||
@@ -128,15 +128,15 @@
|
||||
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
import Vue from 'vue'
|
||||
import Vue from 'vue'
|
||||
|
||||
const convert = require('geo-coordinates-parser');
|
||||
const Coordinates = require('coordinate-parser');
|
||||
|
||||
export default {
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
data: Object, avgHeading: 5, editing: Boolean, wingspan: 0
|
||||
data: Object, avgHeading: 5, editing: Boolean, wingspan: 0, parking_type: ''
|
||||
}
|
||||
},
|
||||
|
||||
@@ -153,10 +153,11 @@ const convert = require('geo-coordinates-parser');
|
||||
},
|
||||
show (idx) {
|
||||
this.$parent.$parent.$parent.$refs.editLayer.show(idx)
|
||||
},
|
||||
},
|
||||
setData (data) {
|
||||
this.data = data;
|
||||
this.setAvgHeading();
|
||||
this.setAvgType();
|
||||
},
|
||||
setEditing(editing) {
|
||||
this.editing = editing
|
||||
@@ -164,18 +165,29 @@ const convert = require('geo-coordinates-parser');
|
||||
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);
|
||||
},
|
||||
}, { sum: 0, count: 0, avg: 0 }).avg);
|
||||
},
|
||||
setAvgType() {
|
||||
if( this.data === null || this.data === undefined) {
|
||||
return 0
|
||||
}
|
||||
var types = this.data.map(parking => parking.options.attributes.type).filter((v, i, a) => a.indexOf(v) === i);
|
||||
if (types.length == 1) {
|
||||
this.parking_type = types[0];
|
||||
} else {
|
||||
this.parking_type = '';
|
||||
}
|
||||
},
|
||||
wingspanChange( newValue ) {
|
||||
if ( newValue ) {
|
||||
this.$emit('editParking', {type: 'parking-group-wingspan', wingspan: newValue} )
|
||||
}
|
||||
},
|
||||
},
|
||||
headingChange( newValue ) {
|
||||
while (newValue>=360) {
|
||||
newValue -= 360
|
||||
@@ -186,9 +198,14 @@ const convert = require('geo-coordinates-parser');
|
||||
if ( newValue ) {
|
||||
this.$emit('editParking', {type: 'parking-group-angle', angle: newValue} )
|
||||
}
|
||||
},
|
||||
typeChange( newValue ) {
|
||||
if ( newValue ) {
|
||||
this.$emit('editParking', {type: 'parking-group-type', parking_type: newValue} )
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
computed: {
|
||||
parking: function () {
|
||||
return this.data !== null && this.$store.state.Editable.type === 'parking-group'
|
||||
|
||||
@@ -209,7 +226,7 @@ const convert = require('geo-coordinates-parser');
|
||||
},
|
||||
airlineCodes: {
|
||||
// getter
|
||||
get: function () {
|
||||
get: function () {
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
@@ -271,19 +288,6 @@ const convert = require('geo-coordinates-parser');
|
||||
{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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
<!--
|
||||
Copyright 2021 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>
|
||||
<el-link v-if="!editing" type="primary" @click="show(parking.index)">{{parking.name}} {{number}} {{parking.type}}</el-link>
|
||||
<el-link v-if="!editing" type="primary" @click="show(parking.index)">{{parking.name}} {{number}} {{parking.type}} {{type}}</el-link>
|
||||
<el-input @focus="show(parking.index)" v-if="editing" placeholder="Name" v-model="name" class="wide"></el-input>
|
||||
<el-input @focus="show(parking.index)" v-if="editing" placeholder="Number" v-model="number" class="narrow"></el-input>
|
||||
<el-select @focus="show(parking.index)" v-if="editing" v-model="parking_type" placeholder="Select">
|
||||
@@ -73,7 +84,11 @@
|
||||
number: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.parking.number
|
||||
if (this.parking.number && this.parking.number !== 'undefined') {
|
||||
return this.parking.number
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
@@ -92,8 +107,36 @@
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_PARKING_ITEM_TYPE', [this.parking.index, newValue])
|
||||
}
|
||||
}
|
||||
},
|
||||
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.parking.radius * 2) {
|
||||
case 15:
|
||||
return 'Piper J-3 Cub/Cessna 172'
|
||||
case 20:
|
||||
return 'Beech 200/Cessna 425'
|
||||
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.parking.radius
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import L from 'leaflet'
|
||||
import LEdit from 'leaflet-editable/src/Leaflet.Editable.js'
|
||||
import {readPavement} from '../loaders/pavement_loader'
|
||||
import * as turf from '@turf/turf'
|
||||
|
||||
export default {
|
||||
name: 'edit-layer',
|
||||
@@ -75,6 +76,21 @@
|
||||
this.deferredMountedTo(this.$parent.mapObject)
|
||||
}
|
||||
},
|
||||
isOnRunway (latlng) {
|
||||
var ret = false
|
||||
this.pavement.eachLayer(l => {
|
||||
if (l instanceof L.RunwayPolygon) {
|
||||
console.debug(l)
|
||||
if (turf.booleanContains(l.turfyRunway, this.latToTurf(latlng))) {
|
||||
ret = true
|
||||
}
|
||||
}
|
||||
})
|
||||
return ret
|
||||
},
|
||||
latToTurf (turfPoint) {
|
||||
return turf.point([turfPoint.lng, turfPoint.lat])
|
||||
},
|
||||
setVisible (visible) {
|
||||
if (this.pavement !== undefined) {
|
||||
if (visible !== this.visible) {
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
|
||||
<script lang="js">
|
||||
// import scanner from '../utils/scan'
|
||||
import fileUrl from 'file-url'
|
||||
import {Table, TableColumn} from 'element-ui'
|
||||
|
||||
const path = require('path')
|
||||
|
||||
export default {
|
||||
name: 'search',
|
||||
components: { [Table.name]: Table,
|
||||
@@ -36,7 +33,7 @@
|
||||
},
|
||||
methods: {
|
||||
goto (icao) {
|
||||
console.log(icao)
|
||||
console.debug('Goto : ' + icao)
|
||||
let airports = this.$store.state.Airports.airports
|
||||
.filter(a => a.properties.icao.match(icao))
|
||||
if (airports.length > 0) {
|
||||
@@ -46,87 +43,11 @@
|
||||
formatter (row, column) {
|
||||
console.log('Row ' + row)
|
||||
return row
|
||||
},
|
||||
scanAPT () {
|
||||
try {
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/worker.js`
|
||||
: `file://${__dirname}/worker.js`
|
||||
console.log('make a worker: ', path.resolve(__dirname, 'worker.js'))
|
||||
|
||||
const worker = new Worker(winURL)
|
||||
console.log(fileUrl('src/renderer/utils/worker.js'))
|
||||
|
||||
// var worker = new Worker(fileUrl('src/renderer/utils/worker.js'))
|
||||
worker.postMessage(['scanapt'])
|
||||
// the reply
|
||||
var store = this.$store
|
||||
worker.onmessage = function (e) {
|
||||
if (e.data === 'DONE') {
|
||||
console.log('DONE')
|
||||
store.dispatch('getAirports')
|
||||
worker.terminate()
|
||||
}
|
||||
console.log(e.data)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
scanGroundnets () {
|
||||
try {
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/worker.js`
|
||||
: `file://${__dirname}/worker.js`
|
||||
console.log('make a worker: ', path.resolve(__dirname, 'worker.js'))
|
||||
|
||||
const worker = new Worker(winURL)
|
||||
console.log(fileUrl('src/renderer/utils/worker.js'))
|
||||
|
||||
worker.postMessage(['scan', this.$store.state.Settings.settings.airportsDirectory])
|
||||
// the reply
|
||||
var store = this.$store
|
||||
worker.onmessage = function (e) {
|
||||
if (e.data === 'DONE') {
|
||||
console.log('DONE')
|
||||
store.dispatch('getAirports')
|
||||
worker.terminate()
|
||||
}
|
||||
console.log(e.data)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
scanTraffic () {
|
||||
// let flightgearDirectory = this.$store.state.settings.flightgearDirectory
|
||||
try {
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/worker.js`
|
||||
: `file://${__dirname}/worker.js`
|
||||
console.log('make a worker: ', path.resolve(__dirname, 'worker.js'))
|
||||
|
||||
const worker = new Worker(winURL)
|
||||
console.log(fileUrl('src/renderer/utils/worker.js'))
|
||||
worker.postMessage(['scanai', this.$store.state.Settings.settings.flightgearDirectory])
|
||||
// the reply
|
||||
var store = this.$store
|
||||
worker.onmessage = function (e) {
|
||||
if (e.data === 'DONE') {
|
||||
console.log('DONE')
|
||||
store.dispatch('getAirports')
|
||||
worker.terminate()
|
||||
}
|
||||
console.log(e.data)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
searched: function () {
|
||||
console.log(this.searchterm)
|
||||
console.debug('Search : ' + this.searchterm)
|
||||
if (this.searchterm !== this.lastSearchTerm) {
|
||||
let searchRegex = new RegExp(this.searchterm, 'i')
|
||||
let result = this.$store.state.Airports.airports
|
||||
@@ -136,10 +57,14 @@
|
||||
.filter(a => searchRegex.test(a.properties.icao) || searchRegex.test(a.properties.name))
|
||||
// .map(a => console.log(a.properties))
|
||||
.map(a => ({ icao: a.properties.icao, name: a.properties.name }))
|
||||
.filter((v, i, a) => a.findIndex(t => (t.icao === v.icao)) === i)
|
||||
let icaoResult = result.filter(a => a.icao === this.searchterm).filter((v, i, a) => a.findIndex(t => (t.icao === v.icao)) === i)
|
||||
if (result !== undefined &&
|
||||
result.length === 0 &&
|
||||
icaoResult.length === 0 &&
|
||||
this.searchterm !== undefined &&
|
||||
this.searchterm.length >= 3) {
|
||||
this.searchterm.length >= 3 &&
|
||||
this.searchterm.length <= 4) {
|
||||
// Not found so it might have been excluded due to no traffic
|
||||
this.$store.dispatch('getAirport', this.searchterm)
|
||||
}
|
||||
this.lastResult = result
|
||||
|
||||
@@ -6,135 +6,206 @@
|
||||
<i class="fa fa-caret-left"></i>
|
||||
</div>
|
||||
</h1>
|
||||
<div id="panel" width="100%">
|
||||
<el-row>
|
||||
<el-col :span="22" class="label">Airports Directory</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<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"
|
||||
<el-collapse v-model="activeName" accordion>
|
||||
<el-collapse-item title="General" name="1">
|
||||
<el-row>
|
||||
<el-col :span="12" class="label">Number of saves : </el-col>
|
||||
<el-col :span="12">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Saves"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="How many previous versions should be kept."
|
||||
>
|
||||
<el-input
|
||||
placeholder="Number of versions"
|
||||
slot="reference"
|
||||
v-model="numberOfSaves"
|
||||
></el-input>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Directories" name="2">
|
||||
<el-row>
|
||||
<el-col :span="22" class="label">Airports Directory</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col
|
||||
:span="22"
|
||||
v-bind:class="{
|
||||
invalid: !airports_directory_ok,
|
||||
file_label: airports_directory_ok,
|
||||
}"
|
||||
>{{ airports_directory }}</el-col
|
||||
>
|
||||
<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="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"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="The FGDATA directory."
|
||||
>
|
||||
<directory-select @input="flightgearDirectorySelect" slot="reference"></directory-select>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<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="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" 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>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="22" class="label">Phi Host Url</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24" class="label">
|
||||
<el-input placeholder="Please input a valid Phi URL" v-model="phi_url"></el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
|
||||
<el-col :span="7" class="label">Author E-Mail : </el-col>
|
||||
<el-col :span="17">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="E-Mail"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Only used as a committer/author for Github. This e-mail is only visible via GIT."
|
||||
>
|
||||
<el-input placeholder="Please input your email" slot="reference" v-model="email"></el-input>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
|
||||
<el-col :span="7" class="label">Author Name : </el-col>
|
||||
<el-col :span="17">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Goto"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="This is saved to the file and is therefore distributed via Terrasync."
|
||||
>
|
||||
<el-input placeholder="Please input your Name" slot="reference" v-model="name"></el-input>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Scan logging :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Logging"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Switch on logging for scan. Big performance hit"
|
||||
<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="22"
|
||||
v-bind:class="{
|
||||
invalid: !flightgear_directory_ok,
|
||||
file_label: flightgear_directory_ok,
|
||||
}"
|
||||
>{{ flightgear_directory }}</el-col
|
||||
>
|
||||
<el-switch v-model="scanLogging" slot="reference"></el-switch>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7" class="label"></el-col>
|
||||
<el-col :span="17">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Debug"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Opens the JavaScript Debugger for troubleshooting"
|
||||
>
|
||||
<el-button @click="debug" class="button" slot="reference" >
|
||||
<i class="fas fa-bug"></i> Debugger
|
||||
</el-button>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-col :span="2">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="E-Mail"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="The FGDATA directory."
|
||||
>
|
||||
<directory-select
|
||||
@input="flightgearDirectorySelect"
|
||||
slot="reference"
|
||||
></directory-select>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<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="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"
|
||||
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>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="User" name="3">
|
||||
<el-row>
|
||||
<el-col :span="7" class="label">Author E-Mail : </el-col>
|
||||
<el-col :span="17">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="E-Mail"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Only used as a committer/author for Github. This e-mail is only visible via GIT."
|
||||
>
|
||||
<el-input
|
||||
placeholder="Please input your email"
|
||||
slot="reference"
|
||||
v-model="email"
|
||||
></el-input>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7" class="label">Author Name : </el-col>
|
||||
<el-col :span="17">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Goto"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="This is saved to the file and is therefore distributed via Terrasync."
|
||||
>
|
||||
<el-input
|
||||
placeholder="Please input your Name"
|
||||
slot="reference"
|
||||
v-model="name"
|
||||
></el-input>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Troubleshooting" name="4">
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Scan logging :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Logging"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Switch on logging for scan. Big performance hit"
|
||||
>
|
||||
<el-switch v-model="scanLogging" slot="reference"></el-switch>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7" class="label"></el-col>
|
||||
<el-col :span="17">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Debug"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Opens the JavaScript Debugger for troubleshooting"
|
||||
>
|
||||
<el-button @click="debug" class="button" slot="reference">
|
||||
<i class="fas fa-bug"></i> Debugger
|
||||
</el-button>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="Flightgear" name="5">
|
||||
<el-row>
|
||||
<el-col :span="22" class="label">Phi Host Url</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24" class="label">
|
||||
<el-input
|
||||
placeholder="Please input a valid Phi URL"
|
||||
v-model="phi_url"
|
||||
></el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -148,14 +219,25 @@
|
||||
name: 'settings-panel',
|
||||
components: { DirectorySelect, FileSelect },
|
||||
props: [],
|
||||
mounted () {
|
||||
},
|
||||
|
||||
data () {
|
||||
return { ok: true
|
||||
}
|
||||
return { ok: true, activeName: '0', scanStoreLogging: false }
|
||||
},
|
||||
mounted () {
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Settings.settings
|
||||
},
|
||||
() => { this.loggingChanged() }
|
||||
,
|
||||
{
|
||||
deep: true // add this if u need to watch object properties change etc.
|
||||
}
|
||||
)
|
||||
},
|
||||
methods: {
|
||||
loggingChanged () {
|
||||
this.scanStoreLogging = this.$store.state.Settings.settings.scanLogging === 1
|
||||
},
|
||||
flightgearDirectorySelect: function (flightgearDirectory) {
|
||||
console.log(flightgearDirectory)
|
||||
this.$store.commit('FLIGHTGEAR_DIRECTORY', flightgearDirectory)
|
||||
@@ -173,6 +255,16 @@
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
numberOfSaves: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Settings.settings.numberOfSaves
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_NUMBER_OF_SAVES', newValue)
|
||||
}
|
||||
},
|
||||
email: {
|
||||
// getter
|
||||
get: function () {
|
||||
@@ -264,7 +356,7 @@
|
||||
scanLogging: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Settings.settings.scanLogging === 1
|
||||
return this.scanStoreLogging
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
@@ -293,5 +385,4 @@
|
||||
padding: 5px;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
95
src/renderer/components/ThresholdEdit.vue
Normal file
95
src/renderer/components/ThresholdEdit.vue
Normal file
@@ -0,0 +1,95 @@
|
||||
<!--
|
||||
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="threshold">
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Runway :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-input
|
||||
placeholder="Please input"
|
||||
v-model="runway"
|
||||
:disabled="true"
|
||||
></el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Displacement :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-input-number
|
||||
v-model="displacement"
|
||||
:disabled="!editing"
|
||||
></el-input-number>
|
||||
</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 this.$parent.$parent.$parent.$refs.editLayer.editing
|
||||
}
|
||||
},
|
||||
threshold: function () {
|
||||
return this.$store.state.Editable.type === 'threshold'
|
||||
},
|
||||
//<rwy>07L</rwy>
|
||||
//<hdg-deg>68.77</hdg-deg>
|
||||
//<displ-m>0.0</displ-m>
|
||||
//<stopw-m>160.0</stopw-m>
|
||||
runway: function () {
|
||||
return this.$store.state.Editable.data.threshold.runway;
|
||||
},
|
||||
displacement: {
|
||||
set: function (newValue) {
|
||||
this.$store.dispatch('setDisplacement', newValue);
|
||||
},
|
||||
get: function () {
|
||||
return this.$store.state.Editable.data.threshold.displacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -3,8 +3,10 @@
|
||||
<script lang="js">
|
||||
import { LMap, LMarker } from 'vue2-leaflet'
|
||||
import L from 'leaflet'
|
||||
import leafletPattern from 'leaflet.pattern'
|
||||
import LEdit from 'leaflet-editable/src/Leaflet.Editable.js'
|
||||
import {readThresholdXML} from '../loaders/threshold_loader'
|
||||
import {writeThresholdXML} from '../loaders/threshold_writer'
|
||||
|
||||
export default {
|
||||
name: 'edit-layer',
|
||||
@@ -12,10 +14,19 @@
|
||||
created () {
|
||||
},
|
||||
mounted () {
|
||||
console.log(LMap)
|
||||
console.log(LMarker)
|
||||
console.log(L)
|
||||
console.log(LEdit)
|
||||
console.debug(LMap, LMarker, L, LEdit, leafletPattern)
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.threshold
|
||||
},
|
||||
() => { this.editedThreshold() }
|
||||
,
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
var stripes = new L.StripePattern({color: 'yellow'})
|
||||
stripes.addTo(this.$parent.mapObject)
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.remove()
|
||||
@@ -25,14 +36,33 @@
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
editedThreshold () {
|
||||
if (this.$store.state.Editable.data.threshold) {
|
||||
var rwy = this.$store.state.Editable.data.threshold.runway
|
||||
var displacement = this.$store.state.Editable.data.threshold.displacement
|
||||
this.layerGroup.eachLayer(l => {
|
||||
if (l instanceof L.Threshold) {
|
||||
if (l.rwy === rwy) {
|
||||
l.setDisplacement(displacement)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
getLayer () {
|
||||
return this.layerGroup
|
||||
},
|
||||
load (icao) {
|
||||
this.$parent.mapObject.createPane('threshold-pane')
|
||||
this.$parent.mapObject.getPane('threshold-pane').style.zIndex = 550
|
||||
if (this.layerGroup) {
|
||||
this.layerGroup.removeFrom(this.$parent.mapObject)
|
||||
}
|
||||
var stripes = new L.StripePattern({color: 'yellow'})
|
||||
stripes.addTo(this.$parent.mapObject)
|
||||
|
||||
// Callback for add
|
||||
this.layerGroup = readThresholdXML(this.$store.state.Settings.settings.airportsDirectory, icao, this.read)
|
||||
this.layerGroup = readThresholdXML(this.$store.state.Settings.settings.airportsDirectory, icao, this.read, stripes)
|
||||
if (!this.layerGroup) {
|
||||
console.warn('Threshold for ICAO not loaded ' + icao)
|
||||
return
|
||||
@@ -53,6 +83,24 @@
|
||||
this.deferredMountedTo(this.$parent.mapObject)
|
||||
}
|
||||
},
|
||||
enableEdit () {
|
||||
if (this.layerGroup) {
|
||||
this.layerGroup.eachLayer(l => {
|
||||
if (l instanceof L.Threshold) {
|
||||
l.setInteractive(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
disableEdit () {
|
||||
if (this.layerGroup) {
|
||||
this.layerGroup.eachLayer(l => {
|
||||
if (l instanceof L.Threshold) {
|
||||
l.setInteractive(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
setVisible (visible) {
|
||||
if (this.layerGroup !== undefined) {
|
||||
if (visible !== this.visible) {
|
||||
@@ -65,6 +113,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
save () {
|
||||
if (this.layerGroup) {
|
||||
var list = {}
|
||||
|
||||
this.layerGroup.eachLayer(l => {
|
||||
if (l instanceof L.Threshold) {
|
||||
var latitude = l.originLatLng[0].toFixed(6)
|
||||
var longitude = l.originLatLng[1].toFixed(6)
|
||||
|
||||
if (list[l.index] === undefined) {
|
||||
list[l.index] = []
|
||||
}
|
||||
var o = {latitude: latitude, longitude: longitude, index: l.index, rwy: l.rwy, heading: l.heading, displacement: l.displacement, stopw_m: l.stopw_m}
|
||||
list[l.index].push(o)
|
||||
}
|
||||
})
|
||||
writeThresholdXML(this.$store.state.Settings.settings.airportsDirectory, this.icao, list)
|
||||
}
|
||||
},
|
||||
zoomUpdated () {
|
||||
if (this.layerGroup) {
|
||||
this.layerGroup.eachLayer(l => {
|
||||
|
||||
@@ -11,6 +11,12 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
-->
|
||||
<template>
|
||||
<div id="ToolBar">
|
||||
<ToolButton
|
||||
icon="far fa-eye"
|
||||
v-on:click="showTooltips"
|
||||
:show="editing"
|
||||
tooltip="Show Tooltips"
|
||||
></ToolButton>
|
||||
<ToolButton
|
||||
icon="fas fa-draw-polygon"
|
||||
v-on:click="drawPolyline"
|
||||
@@ -23,7 +29,7 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
<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')
|
||||
@@ -42,6 +48,9 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
this.$parent.$parent.$refs.toolLayer.stopDrawing()
|
||||
this.$parent.$parent.$refs.toolLayer.drawPolyline()
|
||||
},
|
||||
showTooltips () {
|
||||
this.$parent.$parent.$refs.editLayer.showTooltips()
|
||||
},
|
||||
setEditing (edit) {
|
||||
this.isEditing = edit;
|
||||
if(!this.isEditing) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import ToolControl from '../leaflet/ToolControl.js'
|
||||
export default {
|
||||
name: 'edit-bar',
|
||||
components: { ToolControl, L },
|
||||
props: {
|
||||
icon: String,
|
||||
show: Boolean,
|
||||
@@ -22,8 +23,6 @@
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
console.debug(L)
|
||||
console.debug(ToolControl)
|
||||
this.add()
|
||||
},
|
||||
beforeDestroy () {
|
||||
|
||||
@@ -58,11 +58,11 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
var polyLine = this.$parent.mapObject.editTools.startPolygon(undefined, {color: 'green'})
|
||||
var layerGroup = this.toolLayerGroup;
|
||||
polyLine.addTo(this.toolLayerGroup)
|
||||
polyLine.on('editable:drawing:click', event => {
|
||||
//polyLine.removeFrom(layerGroup);
|
||||
polyLine.on('click', event => {
|
||||
polyLine.removeFrom(layerGroup);
|
||||
});
|
||||
polyLine.on('editable:drawing:end', event => {
|
||||
console.debug(event)
|
||||
console.debug('editable:drawing:end', event)
|
||||
var latLngs = event.target.getLatLngs()[0].map( latLng => ([latLng.lat, latLng.lng]));
|
||||
|
||||
|
||||
|
||||
93
src/renderer/components/TowerEdit.vue
Normal file
93
src/renderer/components/TowerEdit.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<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="true"
|
||||
@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="true"
|
||||
@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-number placeholder="Please input" @change="handleChange" v-model="height" :disabled="!editing" :step="0.01"
|
||||
@focus="coordFocussed = true"
|
||||
@blur="coordFocussed = false"></el-input-number>
|
||||
</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)
|
||||
},
|
||||
handleChange (newValue) {
|
||||
this.$store.dispatch('setTowerHeight', newValue);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
editing: {
|
||||
get: function () {
|
||||
return 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: {
|
||||
get: function () {
|
||||
return this.$store.state.Editable.data.tower.height;
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.$store.dispatch('setTowerHeight', newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -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',
|
||||
@@ -24,7 +25,16 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
console.debug([LMap, LMarker, L, LEdit])
|
||||
},
|
||||
mounted () {
|
||||
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.tower
|
||||
},
|
||||
() => { this.editedTower() }
|
||||
,
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.remove()
|
||||
@@ -34,12 +44,25 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
editedTower () {
|
||||
if (this.$store.state.Editable.data.tower) {
|
||||
this.layerGroup.eachLayer(l => {
|
||||
if (l instanceof L.TowerMarker) {
|
||||
l.setTowerHeight(this.$store.state.Editable.data.tower.height)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
getLayer () {
|
||||
return this.layerGroup
|
||||
},
|
||||
load (icao) {
|
||||
this.$parent.mapObject.createPane('tower-pane')
|
||||
this.$parent.mapObject.getPane('tower-pane').style.zIndex = 550
|
||||
if (this.layerGroup !== undefined) {
|
||||
this.layerGroup.removeFrom(this.$parent.mapObject)
|
||||
}
|
||||
|
||||
// Callback for add
|
||||
this.layerGroup = readTowerXML(this.$store.state.Settings.settings.airportsDirectory, icao, this.read)
|
||||
if (!this.layerGroup) {
|
||||
@@ -66,14 +89,34 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
if (this.layerGroup) {
|
||||
this.layerGroup.eachLayer(l => {
|
||||
if (l instanceof L.TowerMarker) {
|
||||
l.enableEdit(this.$parent.mapObject)
|
||||
l.setInteractive(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
disableEdit () {
|
||||
if (this.layerGroup) {
|
||||
this.layerGroup.eachLayer(l => {
|
||||
if (l instanceof L.TowerMarker) {
|
||||
l.setInteractive(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
save () {
|
||||
},
|
||||
if (this.layerGroup) {
|
||||
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) {
|
||||
|
||||
97
src/renderer/components/TrafficList.vue
Normal file
97
src/renderer/components/TrafficList.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<!--
|
||||
Copyright 2021 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>
|
||||
<el-radio-group v-model="direction">
|
||||
<el-radio :label="departure"
|
||||
><i class="fas fa-plane-departure"></i
|
||||
></el-radio>
|
||||
<el-radio :label="arrival"><i class="fas fa-plane-arrival"></i></el-radio>
|
||||
</el-radio-group>
|
||||
<el-collapse v-model="activeName" accordion ref="collapse">
|
||||
<el-collapse-item
|
||||
v-for="a in airlines"
|
||||
v-bind:key="a.index"
|
||||
class="row"
|
||||
:title="a.label"
|
||||
:name="a.label"
|
||||
>
|
||||
<AirlineItem :airline="a" ref="airline"></AirlineItem>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Add Test Traffic"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Generate Testtraffic"
|
||||
>
|
||||
<el-button @click="generate" class="button" slot="reference">
|
||||
<i class="fas fa-notes-medical"></i>
|
||||
</el-button>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import AirlineItem from './AirlineItem'
|
||||
import {writeTrafficXML} from '../loaders/traffic_writer'
|
||||
|
||||
export default {
|
||||
name: 'traffic-list',
|
||||
components: {AirlineItem},
|
||||
props: [],
|
||||
data () {
|
||||
return {
|
||||
activeName: '',
|
||||
departure: 0,
|
||||
arrival: 1,
|
||||
direction: 0,
|
||||
activeIndex: '1',
|
||||
activeIndex2: '1'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
generate () {
|
||||
// .filter((f) => f.$children[0])
|
||||
var aircraft = this.$refs.airline.flatMap((f) => {
|
||||
console.debug(f.aircraft)
|
||||
return f.aircraft
|
||||
}
|
||||
).filter(f => f)
|
||||
|
||||
writeTrafficXML(this.$store.state.Settings.settings.flightgearDirectory_traffic, this.$store.state.Parkings.items, aircraft)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
airlines: function () {
|
||||
var airlineCodes = []
|
||||
if (this.$store.state.Airports.currentAirport !== undefined && this.$store.state.Airports.currentAirport.airlines) {
|
||||
var storedairlineCodes = this.$store.state.Airports.currentAirport.airlines
|
||||
storedairlineCodes.forEach(element => {
|
||||
airlineCodes.push({value: element, label: element})
|
||||
})
|
||||
}
|
||||
return airlineCodes.filter((v, i, a) => a.indexOf(v) === i)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div.row.div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
<!--
|
||||
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>
|
||||
<el-dialog :title.sync="title" :visible.sync="visible" width="30%" center>
|
||||
<span v-if="max>0">
|
||||
@@ -7,8 +19,13 @@
|
||||
<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>
|
||||
<el-button @click="handleOkClicked('threshold')" :disabled="!threshold_comittable" >Upload Threshold</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>
|
||||
@@ -30,8 +47,8 @@
|
||||
function (state) {
|
||||
return state.Loading.groundnetLoaded;
|
||||
},
|
||||
() => { if(this.$store.state.Loading.groundnetLoaded &&
|
||||
this.$store.state.Loading.pavementLoaded &&
|
||||
() => { if(this.$store.state.Loading.groundnetLoaded &&
|
||||
this.$store.state.Loading.pavementLoaded &&
|
||||
this.visible) this.check() }
|
||||
,
|
||||
{
|
||||
@@ -42,8 +59,8 @@
|
||||
function (state) {
|
||||
return state.Loading.pavementLoaded;
|
||||
},
|
||||
() => { if(this.$store.state.Loading.groundnetLoaded &&
|
||||
this.$store.state.Loading.pavementLoaded &&
|
||||
() => { if(this.$store.state.Loading.groundnetLoaded &&
|
||||
this.$store.state.Loading.pavementLoaded &&
|
||||
this.visible) this.check() }
|
||||
,
|
||||
{
|
||||
@@ -54,18 +71,22 @@
|
||||
},
|
||||
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: {
|
||||
reqListener(e) {
|
||||
if(JSON.parse(e.srcElement.response).status==='OK') {
|
||||
this.message = null;
|
||||
this.azure = true;
|
||||
this.error = false;
|
||||
} else {
|
||||
this.message = 'Azure down';
|
||||
}
|
||||
try {
|
||||
if(JSON.parse(e.srcElement.response).status==='OK') {
|
||||
this.message = null;
|
||||
this.azure = true;
|
||||
this.error = false;
|
||||
} else {
|
||||
this.message = 'Azure down';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
},
|
||||
status () {
|
||||
@@ -79,29 +100,28 @@
|
||||
if (xhr.status !== 200){
|
||||
parent.$refs.upload.message = 'Azure down';
|
||||
parent.$refs.upload.error = true;
|
||||
console.error(xhr);
|
||||
console.error(xhr);
|
||||
}
|
||||
}
|
||||
xhr.addEventListener("load", this.reqListener);
|
||||
xhr.addEventListener("load", this.reqListener);
|
||||
try {
|
||||
xhr.send();
|
||||
xhr.send();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.error = true;
|
||||
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');
|
||||
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
|
||||
this.icao[0],
|
||||
this.icao[1],
|
||||
this.icao[2],
|
||||
this.icao + `.${type}.new.xml`);
|
||||
|
||||
if (f == null || !fs.existsSync(f)) {
|
||||
this.message = 'File doesn\'t exist';
|
||||
@@ -119,8 +139,8 @@
|
||||
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;
|
||||
// action after uploading happens
|
||||
@@ -128,7 +148,7 @@
|
||||
if (xhr.status !== 200){
|
||||
parent.$refs.upload.message = 'Upload Error'
|
||||
parent.$refs.upload.error = true;
|
||||
console.error(xhr);
|
||||
console.error(xhr);
|
||||
}
|
||||
}
|
||||
xhr.onload = function(e) {
|
||||
@@ -139,21 +159,21 @@
|
||||
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) {
|
||||
var response = JSON.parse(e.srcElement.response);
|
||||
parent.$refs.upload.message = response.err;
|
||||
} else {
|
||||
} else {
|
||||
parent.$refs.upload.message = response.message;
|
||||
}
|
||||
};
|
||||
@@ -161,7 +181,7 @@
|
||||
|
||||
// do the uploading
|
||||
console.log("File uploading started!");
|
||||
xhr.send(formData);
|
||||
xhr.send(formData);
|
||||
},
|
||||
pollData () {
|
||||
var workery = this.worker
|
||||
@@ -177,7 +197,7 @@
|
||||
},
|
||||
check () {
|
||||
try {
|
||||
if(!(this.$store.state.Loading.groundnetLoaded &&
|
||||
if(!(this.$store.state.Loading.groundnetLoaded &&
|
||||
this.$store.state.Loading.pavementLoaded)) {
|
||||
return
|
||||
}
|
||||
@@ -220,7 +240,7 @@
|
||||
console.log(l)
|
||||
pavement.push(l)
|
||||
})
|
||||
var features2 = pavement.map(mapper.checkMapper).filter(n => n)
|
||||
var features2 = pavement.map(mapper.checkMapper).filter(n => n)
|
||||
|
||||
worker.postMessage(['check', features.concat(features2) ] )
|
||||
this.pollData()
|
||||
@@ -235,7 +255,7 @@
|
||||
worker.terminate()
|
||||
worker.view.max = 0
|
||||
worker.view.checkDialogVisible = false
|
||||
clearInterval(this.polling)
|
||||
clearInterval(this.polling)
|
||||
this.checking = false
|
||||
} else if (e.data.length > 0) {
|
||||
if (e.data[0] === 'max') {
|
||||
@@ -259,7 +279,7 @@
|
||||
return parent.$refs.editLayer;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
pavementLayer () {
|
||||
var parent = this.$parent;
|
||||
while (!parent.icao||parent.$refs.pavementLayer==undefined) {
|
||||
@@ -268,7 +288,7 @@
|
||||
return parent.$refs.pavementLayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
visible: {
|
||||
@@ -282,9 +302,9 @@
|
||||
}
|
||||
},
|
||||
textClass: function () {
|
||||
return !this.error?'center':'error'
|
||||
return !this.error?'centermessage':'error'
|
||||
},
|
||||
title: function () {
|
||||
title: function () {
|
||||
return `Upload ${this.icao} to groundweb.`
|
||||
},
|
||||
icao: {
|
||||
@@ -302,6 +322,30 @@
|
||||
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
|
||||
},
|
||||
threshold_comittable: function () {
|
||||
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
|
||||
this.icao[0],
|
||||
this.icao[1],
|
||||
this.icao[2],
|
||||
this.icao + '.threshold.new.xml');
|
||||
return fs.existsSync(f) && 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 +357,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>
|
||||
|
||||
@@ -12,14 +12,30 @@ You should have received a copy of the GNU General Public License along with FG
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
const turf = require('@turf/turf')
|
||||
|
||||
L.RunwayPolygon = L.Polygon.extend({
|
||||
turfyRunway: [],
|
||||
|
||||
setTurfy: function (runwayPoints) {
|
||||
var latLngs = runwayPoints.map(this.turfToLatLng);
|
||||
latLngs.push(latLngs[0]);
|
||||
this.turfyRunway = turf.polygon([latLngs]);
|
||||
},
|
||||
|
||||
turfToLatLng: function (turfPoint) {
|
||||
return [turfPoint.lng, turfPoint.lat];
|
||||
}
|
||||
});
|
||||
|
||||
var runwayPoly = function (runwayPoints) {
|
||||
var runwayPoly = new L.RunwayPolygon(runwayPoints);
|
||||
runwayPoly.setStyle({ color: 'grey', fillColor: 'grey', opacity: 0.5, fillOpacity: 0.5, interactive: false });
|
||||
|
||||
runwayPoly.setTurfy(runwayPoints);
|
||||
console.debug(runwayPoints);
|
||||
return runwayPoly;
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = runwayPoly;
|
||||
41
src/renderer/leaflet/TakeoffPad.js
Normal file
41
src/renderer/leaflet/TakeoffPad.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright 2021 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 turf = require('@turf/turf')
|
||||
|
||||
L.TakeoffPolygon = L.Polygon.extend({
|
||||
turfyRunway: [],
|
||||
|
||||
setTurfy: function (padPoints) {
|
||||
var latLngs = padPoints.map(this.turfToLatLng);
|
||||
latLngs.push(latLngs[0]);
|
||||
this.turfyRunway = turf.polygon([latLngs]);
|
||||
},
|
||||
|
||||
turfToLatLng: function (turfPoint) {
|
||||
return [turfPoint.lng, turfPoint.lat];
|
||||
}
|
||||
});
|
||||
|
||||
var takeoffPadPoly = function (padPoints) {
|
||||
var takeoffPadPoly = new L.TakeoffPolygon(padPoints);
|
||||
takeoffPadPoly.setStyle({ color: 'black', fillColor: '', opacity: 1.0, fillOpacity: 0.0, interactive: false });
|
||||
takeoffPadPoly.setTurfy(padPoints);
|
||||
console.debug(padPoints);
|
||||
return takeoffPadPoly;
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = takeoffPadPoly;
|
||||
@@ -11,7 +11,7 @@ L.HoldNode = L.Marker.extend({
|
||||
if(this._icon!==null) {
|
||||
this._icon.childNodes[0].style['background-color'] = 'red';
|
||||
}
|
||||
},
|
||||
},
|
||||
deselect() {
|
||||
if(this._icon!==null) {
|
||||
this._icon.childNodes[0].style['background-color'] = '#4838cc';
|
||||
@@ -31,7 +31,7 @@ L.HoldNode = L.Marker.extend({
|
||||
this.featureLookup[this.glueindex].push(this);
|
||||
},
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
follow(dragIndex, event) {
|
||||
@@ -61,18 +61,18 @@ L.HoldNode = L.Marker.extend({
|
||||
element.updateEndVertex(event.latlng);
|
||||
element.updateMiddle();
|
||||
}
|
||||
} else if (element instanceof L.Editable.VertexMarker) {
|
||||
} else if (element instanceof L.Editable.VertexMarker) {
|
||||
console.log(element);
|
||||
element.setLatLng(event.latlng);
|
||||
element.latlngs.forEach((latlng, index) => {
|
||||
console.log(latlng);
|
||||
console.log(latlng);
|
||||
if(latlng.__vertex === element) {
|
||||
latlng.update(event.latlng);
|
||||
}
|
||||
});
|
||||
element.editor.feature.setLatLngs(element.latlngs);
|
||||
element.editor.feature.updateMiddle();
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -80,7 +80,7 @@ L.HoldNode = L.Marker.extend({
|
||||
|
||||
var holdNode = function (n, layerGroup) {
|
||||
//console.log(n.attr('lat') + " " + n.attr('lon'));
|
||||
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
|
||||
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
|
||||
var fa_icon = null;
|
||||
if (n.attr('holdPointType') === 'PushBack') {
|
||||
fa_icon = "<div style='background-color:#4838cc;' class='marker-pin'></div><i class='fas fa-arrows-alt-h'></i>";
|
||||
@@ -93,8 +93,9 @@ var holdNode = function (n, layerGroup) {
|
||||
iconSize: [30, 42],
|
||||
iconAnchor: [15, 42]
|
||||
});
|
||||
const node = new L.HoldNode([latlon.decimalLatitude, latlon.decimalLongitude], { icon: icon });
|
||||
const node = new L.HoldNode([latlon.decimalLatitude, latlon.decimalLongitude], { icon: icon });
|
||||
node.glueindex = n.attr('index');
|
||||
node.feature = { properties: { searchTerm: n.attr('index')}};
|
||||
node.holdPointType = n.attr('holdPointType');
|
||||
node.addTo(layerGroup);
|
||||
node.addListeners();
|
||||
|
||||
@@ -25,10 +25,10 @@ L.ParkingSpot = L.Circle.extend({
|
||||
if (this.direction === undefined ) {
|
||||
var center = this._latlng;
|
||||
var options = { units: 'kilometers' };
|
||||
|
||||
|
||||
var start = turf.destination([center.lng, center.lat], this.options.attributes.radius / 1000, this.normalizeAngle(this.options.attributes.heading+180), options);
|
||||
var end = turf.destination([center.lng, center.lat], this.options.attributes.radius / 1000, this.normalizeAngle(this.options.attributes.heading), options);
|
||||
// Resize, since leaflet is wrong
|
||||
// Resize, since leaflet is wrong
|
||||
var rad2 = center.distanceTo(this.turfToLatLng(end), options);
|
||||
console.debug('Dist ', center, [center.lng, center.lat], end.geometry.coordinates, this.options.attributes.radius, rad2);
|
||||
this.setRadius(rad2);
|
||||
@@ -53,7 +53,7 @@ L.ParkingSpot = L.Circle.extend({
|
||||
try {
|
||||
console.debug("Update Middle ", this.editor.editLayer._layers[0]);
|
||||
var o = this.editor.editLayer._layers;
|
||||
|
||||
|
||||
console.debug(o);
|
||||
for (var key in o) {
|
||||
if (o.hasOwnProperty(key)) {
|
||||
@@ -63,7 +63,7 @@ L.ParkingSpot = L.Circle.extend({
|
||||
console.debug(o[key] == this.direction);
|
||||
if (this.editor._resizeLatLng.__vertex!=o[key] &&
|
||||
o[key] != this.direction &&
|
||||
o[key] != this.frontWheel &&
|
||||
o[key] != this.frontWheel &&
|
||||
o[key] != this.box) {
|
||||
o[key].setLatLng(this.getLatLng());
|
||||
}
|
||||
@@ -72,9 +72,9 @@ L.ParkingSpot = L.Circle.extend({
|
||||
//Object.values(o);
|
||||
/*
|
||||
.forEach(vertex => {
|
||||
console.debug(this.editor._resizeLatLng.__vertex==vertex);
|
||||
console.debug(this.editor._resizeLatLng.__vertex==vertex);
|
||||
});
|
||||
*/
|
||||
*/
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
@@ -85,17 +85,21 @@ L.ParkingSpot = L.Circle.extend({
|
||||
},
|
||||
updateHeading(heading) {
|
||||
this.options.attributes.heading = heading;
|
||||
this.updateVertexFromDirection();
|
||||
this.updateWheelPos();
|
||||
this.updateVertexFromDirection();
|
||||
this.updateWheelPos();
|
||||
this.updateBox();
|
||||
},
|
||||
updateRadius(radius) {
|
||||
this._mRadius = radius;
|
||||
this.updateDirectionFromVertex();
|
||||
this.updateVertexFromDirection();
|
||||
this.updateWheelPos();
|
||||
this.updateDirectionFromVertex();
|
||||
this.updateVertexFromDirection();
|
||||
this.updateWheelPos();
|
||||
this.updateBox();
|
||||
},
|
||||
updateType(type) {
|
||||
this.options.attributes.type = type;
|
||||
this.deselect();
|
||||
},
|
||||
// Update the direction vertex from the direction
|
||||
updateVertexFromDirection() {
|
||||
if (this.editEnabled()) {
|
||||
@@ -131,14 +135,15 @@ L.ParkingSpot = L.Circle.extend({
|
||||
updateWheelPos() {
|
||||
var start = this._latlng;
|
||||
var options = { units: 'kilometers' };
|
||||
const parkingSize = validRadii.indexOf(this.options.attributes.radius);
|
||||
const parkingSize = validRadii.indexOf(this.options.attributes.radius);
|
||||
if (parkingSize>=0) {
|
||||
var frontWheelEnd = turf.destination([start.lng, start.lat], validN2M[parkingSize] / 1000, this.options.attributes.heading, options);
|
||||
|
||||
if(this.frontWheel!==undefined) {
|
||||
this.frontWheel.setLatLng(this.turfToLatLng(frontWheelEnd));
|
||||
return this.turfToLatLng(frontWheelEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
updateBox() {
|
||||
var start = [this._latlng.lng, this._latlng.lat];
|
||||
@@ -176,7 +181,7 @@ L.ParkingSpot = L.Circle.extend({
|
||||
var latlngs = [leftBack, rightBack, rightMiddle, rightIntermediate, rightFront, leftFront, leftIntermediate, leftMiddle].map(l => this.turfToLatLng(l));
|
||||
this.box = L.polygon(latlngs);
|
||||
//this.box.addTo(this.editor.editLayer);
|
||||
this.box._parkingSpot = this;
|
||||
this.box._parkingSpot = this;
|
||||
this.box.on('click', function (event) {
|
||||
console.debug("Click Parking Box : " + event.target);
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
@@ -188,7 +193,7 @@ L.ParkingSpot = L.Circle.extend({
|
||||
}
|
||||
});
|
||||
}
|
||||
event.target._parkingSpot.select();
|
||||
event.target._parkingSpot.select();
|
||||
});
|
||||
if(this.editor && this.editor.editLayer) {
|
||||
this.box.addTo(this.editor.editLayer);
|
||||
@@ -199,7 +204,7 @@ L.ParkingSpot = L.Circle.extend({
|
||||
console.debug(latlngs);
|
||||
this.box.setLatLngs(latlngs);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
normalizeAngle( angle ) {
|
||||
if(angle >= 180) {
|
||||
@@ -217,21 +222,37 @@ L.ParkingSpot = L.Circle.extend({
|
||||
style['color'] = 'red';
|
||||
this.setStyle(style);
|
||||
if(this.direction) {
|
||||
this.direction.setStyle(style);
|
||||
this.direction.setStyle(style);
|
||||
this.frontWheel.setStyle(style);
|
||||
}
|
||||
this.updateWheelPos();
|
||||
var wheelPos = this.updateWheelPos();
|
||||
if(wheelPos) {
|
||||
store.default.dispatch('setParkingNoseCoords', wheelPos.lat.toFixed(6) + ' ' + wheelPos.lng.toFixed(6));
|
||||
}
|
||||
|
||||
this.updateBox();
|
||||
if(this.box) {
|
||||
if(this.box) {
|
||||
this.box.setStyle(style);
|
||||
}
|
||||
},
|
||||
},
|
||||
deselect() {
|
||||
var style = {};
|
||||
style['color'] = '#3388ff';
|
||||
if(this.options.attributes.type == 'ga') {
|
||||
style['color'] = 'green';
|
||||
} else if(this.options.attributes.type == 'cargo') {
|
||||
style['color'] = 'yellow';
|
||||
} else if(this.options.attributes.type == 'gate') {
|
||||
style['color'] = '#3388ff';
|
||||
} else if(this.options.attributes.type == 'mil-fighter') {
|
||||
style['color'] = 'red';
|
||||
} else if(this.options.attributes.type == 'mil-cargo') {
|
||||
style['color'] = 'DarkRed';
|
||||
} else {
|
||||
style['color'] = '#3388ff';
|
||||
}
|
||||
this.setStyle(style);
|
||||
if(this.direction) {
|
||||
this.direction.setStyle(style);
|
||||
this.direction.setStyle(style);
|
||||
this.frontWheel.setStyle(style);
|
||||
}
|
||||
this.updateWheelPos();
|
||||
@@ -239,7 +260,24 @@ L.ParkingSpot = L.Circle.extend({
|
||||
if(this.box) {
|
||||
this.box.setStyle(style);
|
||||
}
|
||||
},
|
||||
},
|
||||
setInteractive(interactive) {
|
||||
if (interactive) {
|
||||
if(this.direction&&this.direction._path) {
|
||||
L.DomUtil.addClass(this.direction._path, 'leaflet-interactive');
|
||||
}
|
||||
if(this.box&&this.box._path) {
|
||||
L.DomUtil.addClass(this.box._path, 'leaflet-interactive');
|
||||
}
|
||||
} else {
|
||||
if(this.direction&&this.direction._path) {
|
||||
L.DomUtil.removeClass(this.direction._path, 'leaflet-interactive');
|
||||
}
|
||||
if(this.box&&this.box._path) {
|
||||
L.DomUtil.removeClass(this.box._path, 'leaflet-interactive');
|
||||
}
|
||||
}
|
||||
},
|
||||
addListeners: function () {
|
||||
this.on('editable:drawing:move', function (event) {
|
||||
console.debug("Move Parking Spot: ", event);
|
||||
@@ -250,36 +288,38 @@ L.ParkingSpot = L.Circle.extend({
|
||||
event.target.updateVertexFromDirection();
|
||||
event.target.updateWheelPos();
|
||||
event.target.updateBox();
|
||||
this.follow(event.target.id, event);
|
||||
this.follow(event.target.id, event);
|
||||
}
|
||||
else if(event.target.editor._resizeLatLng.__vertex._icon === event.sourceTarget._element) {
|
||||
event.target.updateDirectionFromVertex();
|
||||
event.target.updateVertexFromDirection();
|
||||
event.target.updateDirectionFromVertex();
|
||||
event.target.updateVertexFromDirection();
|
||||
event.target.updateWheelPos();
|
||||
event.target.updateBox();
|
||||
}
|
||||
});
|
||||
this.on('add', function (event) {
|
||||
console.log(event);
|
||||
console.debug(event);
|
||||
event.target.updateBox();
|
||||
if(event.target.box !== undefined) {
|
||||
event.target.box.addTo(event.target._map);
|
||||
}
|
||||
event.target.setInteractive(false);
|
||||
});
|
||||
this.on('remove', function (event) {
|
||||
console.log(event);
|
||||
console.debug(event);
|
||||
if(event.target.box !== undefined) {
|
||||
event.target.box.removeFrom(event.target._map);
|
||||
}
|
||||
});
|
||||
this.on('editable:vertex:drag', function (event) {
|
||||
this.on('editable:vertex:drag', function (event) {
|
||||
console.debug("Drag Parking : ", event);
|
||||
});
|
||||
this.on('editable:vertex:dragend', function (event) {
|
||||
console.debug("DragEnd Parking : ", event);
|
||||
store.default.dispatch('setParking', event.target.options.attributes);
|
||||
store.default.dispatch('setParkingCoords', event.target.getLatLng().lat.toFixed(6) + ' ' + event.target.getLatLng().lng.toFixed(6));
|
||||
event.target.updateWheelPos();
|
||||
var wheelPos = event.target.updateWheelPos();
|
||||
store.default.dispatch('setParkingNoseCoords', wheelPos.lat.toFixed(6) + ' ' + wheelPos.lng.toFixed(6));
|
||||
event.target.updateBox();
|
||||
/*
|
||||
store.default.dispatch('setParkingHeading', this.options.attributes.heading)
|
||||
@@ -296,8 +336,8 @@ L.ParkingSpot = L.Circle.extend({
|
||||
}
|
||||
});
|
||||
}
|
||||
event.target.select();
|
||||
});
|
||||
event.target.select();
|
||||
});
|
||||
this.on('editable:vertex:clicked', function (event) {
|
||||
console.debug(this.featureLookup[event.vertex.glueindex]);
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
@@ -312,14 +352,14 @@ L.ParkingSpot = L.Circle.extend({
|
||||
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.select();
|
||||
this.select();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this.on('editable:disable', function (event) {
|
||||
event.target.removeDirection();
|
||||
});
|
||||
});
|
||||
},
|
||||
updateStyle: function () {
|
||||
|
||||
@@ -333,24 +373,20 @@ L.ParkingSpot = L.Circle.extend({
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
store.default.dispatch('setParking', this.options.attributes);
|
||||
store.default.dispatch('setParkingCoords', this.getLatLng().lat.toFixed(6) + ' ' + this.getLatLng().lng.toFixed(6));
|
||||
|
||||
this.select();
|
||||
},
|
||||
turfToLatLng: function (turfPoint) {
|
||||
return {lat: turfPoint.geometry.coordinates[1], lng: turfPoint.geometry.coordinates[0]};
|
||||
},
|
||||
extensions: function (editLayer) {
|
||||
this.createDirection();
|
||||
this.createDirection();
|
||||
if (typeof this.featureLookup[this.id] === 'undefined') {
|
||||
this.featureLookup[this.id] = [];
|
||||
}
|
||||
this.featureLookup[this.id].push(this);
|
||||
},
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
follow (dragIndex, event) {
|
||||
@@ -396,7 +432,7 @@ L.ParkingSpot = L.Circle.extend({
|
||||
});
|
||||
element.editor.feature.setLatLngs(element.latlngs);
|
||||
element.editor.feature.updateMiddle();
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -416,12 +452,14 @@ var parkingSpot = function (n, layerGroup) {
|
||||
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
|
||||
//console.log(latlon.decimalLatitude);
|
||||
//console.log(convert(n.attr('lat') + " " + n.attr('lon')).decimalLongitude);
|
||||
const circle = new L.ParkingSpot([latlon.decimalLatitude, latlon.decimalLongitude], { radius: n.attr('radius'), attributes: {} });
|
||||
circle.on('editable:enable', function (event) {
|
||||
const parking = new L.ParkingSpot([latlon.decimalLatitude, latlon.decimalLongitude], { radius: n.attr('radius'), attributes: {} });
|
||||
parking.on('editable:enable', function (event) {
|
||||
// event.target.createDirection();
|
||||
});
|
||||
circle.id = n.attr('index');
|
||||
circle.glueindex = n.attr('index');
|
||||
parking.id = n.attr('index');
|
||||
parking.glueindex = n.attr('index');
|
||||
parking.feature = { properties: { searchTerm: n.attr('index') + ' ' + n.attr('name')}};
|
||||
|
||||
/*
|
||||
<Parking index="2"
|
||||
type="gate"
|
||||
@@ -431,23 +469,24 @@ lat="N44 52.799"
|
||||
lon="W93 11.947"
|
||||
heading="-147.51"
|
||||
radius="18"
|
||||
pushBackRoute="541"
|
||||
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')) };
|
||||
|
||||
$.each( n.attrs, function( key, value ) {
|
||||
console.debug( '$', circle.id, key , value);
|
||||
|
||||
console.debug( '$', parking.id, key , value);
|
||||
|
||||
if(isNaN(value))
|
||||
circle.options.attributes[ key ] = value;
|
||||
parking.options.attributes[ key ] = value;
|
||||
else
|
||||
circle.options.attributes[ key ] = Number( value);
|
||||
parking.options.attributes[ key ] = Number( value);
|
||||
});
|
||||
circle.addListeners();
|
||||
|
||||
circle.addTo(layerGroup);
|
||||
return circle;
|
||||
parking.addListeners();
|
||||
|
||||
parking.addTo(layerGroup);
|
||||
parking.deselect();
|
||||
return parking;
|
||||
}
|
||||
|
||||
module.exports = parkingSpot;
|
||||
@@ -26,21 +26,35 @@ L.RunwayNode = L.Marker.extend({
|
||||
store.default.dispatch('setRunway', event.target.options.attributes);
|
||||
}
|
||||
});
|
||||
this.on('add', function (event) {
|
||||
event.target.setInteractive(false);
|
||||
});
|
||||
},
|
||||
setInteractive(interactive) {
|
||||
if (interactive) {
|
||||
if(this._icon) {
|
||||
L.DomUtil.addClass(this._icon, 'leaflet-interactive');
|
||||
}
|
||||
} else {
|
||||
if(this._icon) {
|
||||
L.DomUtil.removeClass(this._icon, 'leaflet-interactive');
|
||||
}
|
||||
}
|
||||
},
|
||||
select() {
|
||||
try {
|
||||
this._icon.style['color'] = 'red';
|
||||
this._icon.style['color'] = 'red';
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
},
|
||||
deselect() {
|
||||
try {
|
||||
this._icon.style['color'] = 'black';
|
||||
this._icon.style['color'] = 'black';
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
},
|
||||
extensions: function (editLayer) {
|
||||
this.options.attributes = {};
|
||||
if (typeof this.featureLookup[this.glueindex] === 'undefined') {
|
||||
@@ -49,7 +63,7 @@ L.RunwayNode = L.Marker.extend({
|
||||
this.featureLookup[this.glueindex].push(this);
|
||||
},
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
follow(dragIndex, event) {
|
||||
@@ -79,18 +93,18 @@ L.RunwayNode = L.Marker.extend({
|
||||
element.updateEndVertex(event.latlng);
|
||||
element.updateMiddle();
|
||||
}
|
||||
} else if (element instanceof L.Editable.VertexMarker) {
|
||||
} else if (element instanceof L.Editable.VertexMarker) {
|
||||
console.log(element);
|
||||
element.setLatLng(event.latlng);
|
||||
element.latlngs.forEach((latlng, index) => {
|
||||
console.log(latlng);
|
||||
console.log(latlng);
|
||||
if(latlng.__vertex === element) {
|
||||
latlng.update(event.latlng);
|
||||
}
|
||||
});
|
||||
element.editor.feature.setLatLngs(element.latlngs);
|
||||
element.editor.feature.updateMiddle();
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -106,7 +120,9 @@ var runwayNode = function (n, layerGroup) {
|
||||
});
|
||||
var node = new L.RunwayNode([latlon.decimalLatitude, latlon.decimalLongitude], { icon: icon, attributes: {} });
|
||||
node.glueindex = n.attr('index');
|
||||
$.each( n.attrs, function( key, value ) {
|
||||
node.feature = n.attr('index');
|
||||
|
||||
$.each( n.attrs, function( key, value ) {
|
||||
if(isNaN(value))
|
||||
node.options.attributes[ key ] = value;
|
||||
else
|
||||
|
||||
@@ -10,11 +10,13 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
taxiwaySegment.__proto__.begin;
|
||||
taxiwaySegment.__proto__.end;
|
||||
taxiwaySegment.__proto__.bidirectional;
|
||||
|
||||
taxiwaySegment.__proto__.updateBeginVertex = function (latlng) {
|
||||
if (this._latlngs[0].__vertex) {
|
||||
this._latlngs[0].__vertex.setLatLng(latlng);
|
||||
this.selectVertex(Number(this._latlngs[0].glueindex));
|
||||
}
|
||||
|
||||
};
|
||||
taxiwaySegment.__proto__.updateEndVertex = function (latlng) {
|
||||
if (this._latlngs[1].__vertex) {
|
||||
@@ -56,7 +58,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
taxiwaySegment.__proto__.selectVertex = function (index) {
|
||||
this.getLatLngs().forEach(element => {
|
||||
if (Number(element.glueindex) === index) {
|
||||
if (element.__vertex._icon != null) {
|
||||
if (element.__vertex !== undefined && element.__vertex._icon != null) {
|
||||
element.__vertex.__proto__.deselect = function () {
|
||||
if (this._icon != null) {
|
||||
this._icon.style.setProperty('background-color', 'white');
|
||||
@@ -141,7 +143,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
}
|
||||
} else {
|
||||
var arcs = event.target.expandArc(event.target.options.attributes);
|
||||
var multiarc = {name: '', index: 900719925474099, ids: [] ,isPushBackRoute: null, direction: null};
|
||||
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) {
|
||||
@@ -152,18 +154,22 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
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) {
|
||||
if (event.target.options.attributes.name !== undefined) {
|
||||
multiarc.name = assign(event.target.options.attributes.name);
|
||||
}
|
||||
multiarc.isPushBackRoute = assign(event.target.options.attributes.isPushBackRoute);
|
||||
if (event.target.options.attributes.isPushBackRoute) {
|
||||
multiarc.isPushBackRoute = assign(event.target.options.attributes.isPushBackRoute);
|
||||
} else {
|
||||
multiarc.isPushBackRoute = false;
|
||||
}
|
||||
multiarc.direction = assign(event.target.options.attributes.direction);
|
||||
|
||||
|
||||
this.editLayer.featureLookup[900719925474099] = [];
|
||||
|
||||
|
||||
multiarc.ids = [];
|
||||
|
||||
//TODO
|
||||
@@ -175,11 +181,11 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
var arc = editLayer.groundnetLayerGroup.getLayer(id);
|
||||
if (arc && arc instanceof L.Polyline) {
|
||||
editLayer.featureLookup[900719925474099].push(arc);
|
||||
arc.select();
|
||||
}
|
||||
arc.select();
|
||||
}
|
||||
});
|
||||
store.default.dispatch('setMultiArcIds', arcs);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.on('editable:drawing:move', function (event) {
|
||||
if (dragIndex >= 0) {
|
||||
@@ -190,92 +196,117 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
});
|
||||
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' };
|
||||
});
|
||||
this.on('editable:vertex:new', event => {
|
||||
console.debug('editable:vertex:new ' + event.vertex.getIndex() + '\t' + event.vertex.getLastIndex() + '\t');
|
||||
// Find nearest node
|
||||
let isOnRunway = this.editLayer.isOnRunway(event.latlng)
|
||||
let closest = this.editLayer.closestLayerSnap(event.latlng, 5)
|
||||
let taxiwaySegment = event.vertex.editor.feature;
|
||||
if (taxiwaySegment.options.attributes === undefined) {
|
||||
taxiwaySegment.options.attributes = { direction: 'bi-directional' };
|
||||
}
|
||||
var isOnRunwayNum = 0;
|
||||
if (isOnRunway) {
|
||||
isOnRunwayNum = 1;
|
||||
}
|
||||
taxiwaySegment.updateStyle();
|
||||
if (event.vertex.getIndex() !== 0 && event.vertex.getIndex() !== event.vertex.getLastIndex()) {
|
||||
var x = taxiwaySegment.getLatLngs().filter(l => l === event.vertex.latlng);
|
||||
// Somehow the latlng is not in our Segment!?
|
||||
if (taxiwaySegment.getLatLngs().length < 3 && x.length === 0) {
|
||||
var fixed = taxiwaySegment.getLatLngs();
|
||||
fixed.splice(1, 0, event.vertex.latlng);
|
||||
taxiwaySegment.setLatLngs(fixed);
|
||||
}
|
||||
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);
|
||||
}
|
||||
var nextIndex = ++taxiwaySegment.editLayer.groundnetLayerGroup.maxId;
|
||||
var splitOffNodes = taxiwaySegment.getLatLngs().splice(-1);
|
||||
var remainingNodes = taxiwaySegment.getLatLngs();
|
||||
if (remainingNodes.length <= 1 || !remainingNodes[1]) {
|
||||
console.error('Not enough remaining nodes', remainingNodes);
|
||||
}
|
||||
splitOffNodes.unshift(L.latLng(remainingNodes[1].lat, remainingNodes[1].lng, remainingNodes[1].alt));
|
||||
remainingNodes[1]['glueindex'] = nextIndex;
|
||||
remainingNodes[1].attributes = { index: nextIndex, isOnRunway: isOnRunwayNum };
|
||||
taxiwaySegment.options.attributes.end = nextIndex;
|
||||
splitOffNodes[0]['glueindex'] = nextIndex;
|
||||
splitOffNodes[0].attributes = { index: nextIndex, isOnRunway: isOnRunwayNum };
|
||||
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.feature = { properties: {searchTerm: 'Arc ' + nextIndex + '-' + taxiwaySegment.end}};
|
||||
|
||||
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}`)
|
||||
console.error('SplitoffNodes Short ', splitOffNodes);
|
||||
}
|
||||
} 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: isOnRunwayNum };
|
||||
// Push Vertex to lookup
|
||||
this.editLayer.featureLookup[event.latlng.glueindex].push(event.latlng.__vertex);
|
||||
if (isOnRunwayNum == 1) {
|
||||
this.editLayer.addRunwayNode(event.latlng, event.latlng['glueindex'])
|
||||
}
|
||||
if (taxiwaySegment.options.attributes.begin === undefined) {
|
||||
taxiwaySegment.options.attributes.begin = event.latlng['glueindex']
|
||||
} 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);
|
||||
}
|
||||
taxiwaySegment.options.attributes.end = event.latlng['glueindex']
|
||||
}
|
||||
if (taxiwaySegment.getLatLngs().length === 1) {
|
||||
taxiwaySegment.begin = closest.glueindex;
|
||||
}
|
||||
taxiwaySegment.end = closest.glueindex;
|
||||
console.debug(`Closest : ${closest}`)
|
||||
} else {
|
||||
event.vertex.latlng['glueindex'] = ++this.editLayer.groundnetLayerGroup.maxId;
|
||||
event.vertex.latlng.attributes = { index: event.vertex.latlng.glueindex, isOnRunway: isOnRunwayNum };
|
||||
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);
|
||||
if (isOnRunwayNum == 1) {
|
||||
this.editLayer.addRunwayNode(event.latlng, event.vertex.latlng['glueindex'])
|
||||
}
|
||||
// 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')
|
||||
});
|
||||
@@ -287,8 +318,8 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
console.debug('editable:vertex:click')
|
||||
});
|
||||
this.on('editable:vertex:rawclick', event => {
|
||||
event.cancel()
|
||||
console.debug('editable:vertex:rawclick')
|
||||
event.cancel()
|
||||
});
|
||||
this.on('editable:vertex:clicked', function (event) {
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
@@ -355,6 +386,9 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
});
|
||||
}
|
||||
dragIndex = -1;
|
||||
if (!event.vertex.latlng.glueindex) {
|
||||
console.error('GlueIndex not found : ', event.vertex);
|
||||
}
|
||||
var parking = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.ParkingSpot);
|
||||
if (parking.length > 0) {
|
||||
parking[0].selectParking();
|
||||
@@ -379,6 +413,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error(event.vertex.latlng.glueindex);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -394,46 +429,46 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
return ids;
|
||||
}
|
||||
|
||||
taxiwaySegment.__proto__.walkPushbackRoute = function (index, walkedNodes, isPushBackRoute) {
|
||||
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) {
|
||||
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))
|
||||
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))
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
taxiwaySegment.__proto__.follow = function (dragIndex, event) {
|
||||
@@ -486,30 +521,30 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
};
|
||||
|
||||
taxiwaySegment.__proto__.updateArrows = function (zoom) {
|
||||
if( this._map === null) {
|
||||
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;' } })
|
||||
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;' } })
|
||||
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;' } })
|
||||
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;' } })
|
||||
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__.setInteractive = function (interactive) {
|
||||
@@ -522,9 +557,9 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
if (!this._path) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.options.interactive = interactive;
|
||||
|
||||
|
||||
if (interactive) {
|
||||
L.DomUtil.addClass(this._path, 'leaflet-interactive');
|
||||
} else {
|
||||
@@ -534,7 +569,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
|
||||
taxiwaySegment.__proto__.updateStyle = function () {
|
||||
var style = {};
|
||||
if(!this.options.attributes) {
|
||||
if (!this.options.attributes) {
|
||||
return;
|
||||
}
|
||||
if (this.options.attributes.selected) {
|
||||
@@ -545,7 +580,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
else {
|
||||
style.color = '#3388ff';
|
||||
}
|
||||
if(this.editEnabled()) {
|
||||
if (this.editEnabled()) {
|
||||
style.interactive = true;
|
||||
} else {
|
||||
style.interactive = false;
|
||||
@@ -554,10 +589,10 @@ const extendTaxiSegment = function (taxiwaySegment) {
|
||||
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; 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);
|
||||
}
|
||||
|
||||
@@ -14,14 +14,20 @@ 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');
|
||||
const turf = require('@turf/turf');
|
||||
|
||||
|
||||
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
|
||||
|
||||
|
||||
L.Threshold = L.Marker.extend({
|
||||
options: {
|
||||
zIndexOffset: 20000,
|
||||
},
|
||||
heading: 0,
|
||||
displacement: 0,
|
||||
stopw_m: 0,
|
||||
originLatLng: null,
|
||||
rwy: '',
|
||||
interactive: false,
|
||||
stripSVG: function(fName) {
|
||||
var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm;
|
||||
var svg = fs.readFileSync(path.join(__static, '/', fName), 'utf8');
|
||||
@@ -32,7 +38,7 @@ L.Threshold = L.Marker.extend({
|
||||
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('Old Meters per pixel ' + this._metersPP);
|
||||
console.debug('New Meters per pixel ' + metersPP);
|
||||
if(this._metersPP != metersPP) {
|
||||
var pixelSize = (this.iconSize/2) / metersPP;
|
||||
@@ -41,16 +47,28 @@ L.Threshold = L.Marker.extend({
|
||||
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>`,
|
||||
html: `<div style=\'transform: translateX(${offset}px) translateY(${offset}px) scale(${scale}) rotate(${this.heading}deg); border: 1px red\'>${this.svg}</div>`,
|
||||
}));
|
||||
this.setInteractive(this.interactive);
|
||||
|
||||
this.update(this.getLatLng());
|
||||
console.debug();
|
||||
this.setLatLng(this.getLatLng());
|
||||
this._metersPP = metersPP;
|
||||
}
|
||||
}
|
||||
},
|
||||
setInteractive(interactive) {
|
||||
if (interactive) {
|
||||
if(this._icon) {
|
||||
L.DomUtil.addClass(this._icon, 'leaflet-interactive');
|
||||
}
|
||||
} else {
|
||||
if(this._icon) {
|
||||
L.DomUtil.removeClass(this._icon, 'leaflet-interactive');
|
||||
}
|
||||
}
|
||||
this.interactive = interactive;
|
||||
},
|
||||
metersPerPixel: function (latitude, zoomLevel) {
|
||||
var earthCircumference = 40075017;
|
||||
var latitudeRadians = latitude * (Math.PI / 180);
|
||||
@@ -60,21 +78,86 @@ L.Threshold = L.Marker.extend({
|
||||
pixelValue: function (latitude, meters, zoomLevel) {
|
||||
return meters / metersPerPixel(latitude, zoomLevel);
|
||||
},
|
||||
|
||||
setOrigin (originLatLng) {
|
||||
this.originLatLng = originLatLng;
|
||||
},
|
||||
setHeading (heading) {
|
||||
this.heading = Number(heading);
|
||||
},
|
||||
setRunway (rwy) {
|
||||
this.rwy = Number(rwy);
|
||||
},
|
||||
setStopW (stopw_m) {
|
||||
this.stopw_m = stopw_m;
|
||||
},
|
||||
setDisplacement(displacement) {
|
||||
const turfOptions = { units: 'kilometers' };
|
||||
this.displacement = Number(displacement);
|
||||
|
||||
var newPos = turf.destination([this.originLatLng[1], this.originLatLng[0]], displacement/1000, this.normalizeAngle(this.heading), turfOptions);
|
||||
var newValue = {lat: newPos.geometry.coordinates[1].toFixed(6),
|
||||
lng: newPos.geometry.coordinates[0].toFixed(6) };
|
||||
console.debug(`Threshold Old : ${this.originLatLng} -> ${this.turfToLatLng(newPos)}`);
|
||||
this.setLatLng(newValue);
|
||||
},
|
||||
normalizeAngle( angle ) {
|
||||
if(angle >= 180) {
|
||||
return angle - 360;
|
||||
}
|
||||
if(angle <= -180) {
|
||||
return angle + 360;
|
||||
}
|
||||
return angle;
|
||||
},
|
||||
latToTurf (turfPoint) {
|
||||
return [turfPoint.lng, turfPoint.lat];
|
||||
},
|
||||
latLngToTurf (turfPoint) {
|
||||
return [turfPoint.decimalLongitude, turfPoint.decimalLatitude];
|
||||
},
|
||||
turfToLatLng: function (turfPoint) {
|
||||
return '' + turfPoint.geometry.coordinates[1].toFixed(6) + ',' + turfPoint.geometry.coordinates[0].toFixed(6);
|
||||
}
|
||||
});
|
||||
|
||||
L.Threshold.addInitHook(function(){
|
||||
this.svg = this.stripSVG('FGA_THR.svg');
|
||||
this.iconSize = 500;
|
||||
|
||||
this.on('click', function (event) {
|
||||
console.debug("Click Threshold : ", event);
|
||||
store.default.dispatch('setThreshold', {rwy: event.target.rwy, displacement: event.target.displacement});
|
||||
});
|
||||
this.on('add', function (event) {
|
||||
event.target.setInteractive(false);
|
||||
});
|
||||
});
|
||||
|
||||
//Builds a marker for a ai or multiplayer aircraft
|
||||
//Builds a marker for a threshold
|
||||
/*
|
||||
<threshold>
|
||||
<lon>13.517142</lon>
|
||||
<lat>52.380125</lat>
|
||||
<rwy>07L</rwy>
|
||||
<hdg-deg>68.77</hdg-deg>
|
||||
<displ-m>0.0</displ-m>
|
||||
<stopw-m>160.0</stopw-m>
|
||||
</threshold>
|
||||
*/
|
||||
var threshold = function (n, options) {
|
||||
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
|
||||
var rwy = n.find('rwy/text()').text();
|
||||
var heading = n.find('hdg-deg/text()').text();
|
||||
var displ_m = n.find('displ-m/text()').text();
|
||||
var stopw_m = n.find('stopw-m/text()').text();
|
||||
|
||||
var marker = new L.Threshold([latlon.decimalLatitude, latlon.decimalLongitude], {heading: heading, pane: 'threshold-pane'});
|
||||
var marker = new L.Threshold([latlon.decimalLatitude, latlon.decimalLongitude],
|
||||
{pane: 'threshold-pane'});
|
||||
marker.setOrigin([latlon.decimalLatitude, latlon.decimalLongitude]);
|
||||
marker.setHeading(heading);
|
||||
marker.setDisplacement(displ_m);
|
||||
marker.setRunway(rwy);
|
||||
marker.setStopW(stopw_m);
|
||||
return marker;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,13 +14,14 @@ 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*/
|
||||
|
||||
|
||||
L.TowerMarker = L.Marker.extend({
|
||||
options: {
|
||||
zIndexOffset: 10000,
|
||||
zIndexOffset: 10000, draggable: 'true'
|
||||
},
|
||||
stripSVG: function(fName) {
|
||||
var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm;
|
||||
@@ -29,20 +30,21 @@ L.TowerMarker = L.Marker.extend({
|
||||
return svg2[0];
|
||||
},
|
||||
updateIcon : function(map) {
|
||||
console.debug(`Lat Lng Threshold ${this.getLatLng()}`);
|
||||
console.debug(`Lat Lng Tower ${this.getLatLng()}`);
|
||||
if(map !== null) {
|
||||
var metersPP = this.metersPerPixel(map.getCenter().lat, map.getZoom());
|
||||
console.debug('Old Meters per pixel ' + this.metersPP);
|
||||
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;
|
||||
if(this._metersPP != metersPP) {
|
||||
var pixelSize = this.iconSize / metersPP;
|
||||
var scale = pixelSize/this.iconSize;
|
||||
var offset = 0;//-(this.iconSize/2);
|
||||
var offset = 0;//-(this.iconSize/2);
|
||||
this.setIcon(L.divIcon({
|
||||
iconSize: 64,
|
||||
iconSize: 32,
|
||||
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>`,
|
||||
}));
|
||||
html: `<div style=\'transform: translateX(${offset}px) translateY(${offset}px) scale(${scale}); border: 1px red\'>${this.svg}</div>`,
|
||||
}));
|
||||
this.setInteractive(this.interactive);
|
||||
|
||||
this.update(this.getLatLng());
|
||||
console.debug();
|
||||
@@ -50,29 +52,65 @@ L.TowerMarker = L.Marker.extend({
|
||||
this._metersPP = metersPP;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
setInteractive(interactive) {
|
||||
if (interactive) {
|
||||
if(this._icon) {
|
||||
L.DomUtil.addClass(this._icon, 'leaflet-interactive');
|
||||
}
|
||||
} else {
|
||||
if(this._icon) {
|
||||
L.DomUtil.removeClass(this._icon, 'leaflet-interactive');
|
||||
}
|
||||
}
|
||||
this.interactive = interactive;
|
||||
},
|
||||
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);
|
||||
},
|
||||
|
||||
|
||||
setTowerHeight: function (height) {
|
||||
this.elev_m = height;
|
||||
}
|
||||
});
|
||||
|
||||
L.TowerMarker.addInitHook(function(){
|
||||
this.svg = this.stripSVG('tower.svg');
|
||||
this.iconSize = 64;
|
||||
this.iconSize = 32;
|
||||
this.on('click', function (event) {
|
||||
store.default.dispatch('setTowerCoords',
|
||||
event.target.getLatLng().lat.toFixed(6) + ' ' +
|
||||
event.target.getLatLng().lng.toFixed(6) + ' ' +
|
||||
event.target.elev_m);
|
||||
store.default.dispatch('setTowerHeight', event.target.elev_m );
|
||||
});
|
||||
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);
|
||||
store.default.dispatch('setTowerHeight', event.target.elev_m );
|
||||
});
|
||||
this.on('add', function (event) {
|
||||
event.target.setInteractive(false);
|
||||
});
|
||||
});
|
||||
|
||||
//Builds a marker for a ai or multiplayer aircraft
|
||||
var tower = function (n, options) {
|
||||
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 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;
|
||||
|
||||
@@ -23,28 +23,44 @@ function addFrequencies (type, value) {
|
||||
value.split(' ').forEach(frequencyValue => {
|
||||
if( value.length > 0) {
|
||||
var frequency = {type: type, value: frequencyValue};
|
||||
frequencies.push(frequency);
|
||||
frequencies.push(frequency);
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
exports.addFeature = function (feature) {
|
||||
featureLookup[feature.id] = new Array();
|
||||
featureLookup[feature.id] = [];
|
||||
}
|
||||
|
||||
exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
exports.listSaves = function (fDir, icao) {
|
||||
var directory = path.join(fDir, icao[0], icao[1], icao[2]);
|
||||
var files = fs.readdirSync(directory);
|
||||
var ret = files
|
||||
.filter(f => f.includes(icao) )
|
||||
.filter(f => f.includes('groundnet') )
|
||||
.map(f => {
|
||||
try {
|
||||
var fileDate = fs.lstatSync(path.join(directory, f));
|
||||
return {file: f, mtime: `${fileDate.mtime}`, mtimeMs: `${fileDate.mtimeMs}`};
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
ret.forEach( f => {
|
||||
console.debug(f);
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
exports.readGroundnetXML = function (fDir, icao, f) {
|
||||
try {
|
||||
store.default.dispatch('setGroundnetLoaded', false);
|
||||
var layerGroup = L.layerGroup();
|
||||
layerGroup.minId = 9999999999;
|
||||
layerGroup.maxId = 0;
|
||||
var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.xml');
|
||||
var fNew = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.new.xml');
|
||||
|
||||
if (f == null || (!fs.existsSync(f) && force)|| (!fs.existsSync(f) && !fs.existsSync(fNew) ))
|
||||
if (f == null || (!fs.existsSync(f) ))
|
||||
return layerGroup;
|
||||
if (fNew != null && fs.existsSync(fNew) && !force) {
|
||||
f = fNew;
|
||||
}
|
||||
|
||||
var features = new Array();
|
||||
|
||||
@@ -83,7 +99,7 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
addFrequencies('UNICOM', unicom);
|
||||
|
||||
store.default.dispatch('setFrequencies', frequencies);
|
||||
|
||||
|
||||
var parkingNodes = xml.find('groundnet/parkingList/Parking');
|
||||
console.debug("Parking Nodes length" + parkingNodes.length);
|
||||
|
||||
@@ -98,12 +114,13 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
nodesLookup[n.attr('index')] = n;
|
||||
featureLookup[n.attr('index')] = new Array();
|
||||
featureLookup[n.attr('index')].push(circle);
|
||||
layerGroup.minId = Math.min(layerGroup.minId, Number(n.attr('index')))
|
||||
layerGroup.maxId = Math.max(layerGroup.maxId, Number(n.attr('index')))
|
||||
features.push(circle);
|
||||
}).sort();
|
||||
|
||||
store.default.dispatch('setParkings', parkingNodes.map(
|
||||
p => ({index: Number(p.attrs.index), name: String(p.attrs.name), number: String(p.attrs.number), type: String(p.attrs.type)}
|
||||
|
||||
store.default.dispatch('setParkings', parkingNodes.map(
|
||||
p => ({index: Number(p.attrs.index), radius: Number(p.attrs.radius), name: String(p.attrs.name), number: String(p.attrs.number), type: String(p.attrs.type)}
|
||||
)).sort((p1, p2) => {
|
||||
if (p1.name === p2.name) {
|
||||
return p1.number?p1.number.localeCompare(p2.number):-1;
|
||||
@@ -117,14 +134,16 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
//attrs.lat
|
||||
//console.log(n.attr('lat') + " " + n.attr('lon'));
|
||||
try {
|
||||
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
|
||||
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
|
||||
} catch (error) {
|
||||
console.warn(n.attr('lat') + " " + n.attr('lon'));
|
||||
convert(n.attr('lat') + " " + n.attr('lon'));
|
||||
}
|
||||
//console.log(latlon.decimalLatitude);
|
||||
|
||||
layerGroup.minId = Math.min(layerGroup.minId, Number(n.attr('index')))
|
||||
layerGroup.maxId = Math.max(layerGroup.maxId, Number(n.attr('index')))
|
||||
console.debug(`Min Id : ${layerGroup.minId} Max Id : ${layerGroup.maxId} `);
|
||||
|
||||
nodesLookup[n.attr('index')] = n;
|
||||
if (n.attr('isOnRunway') === '1') {
|
||||
@@ -167,7 +186,7 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
if (element instanceof L.Polyline && element.end === n.attr('begin') && element.begin === n.attr('end')) {
|
||||
element.bidirectional = true;
|
||||
element.options.attributes.direction = 'bi-directional'
|
||||
bidirectional = true;
|
||||
bidirectional = true;
|
||||
element.updateStyle();
|
||||
}
|
||||
});
|
||||
@@ -175,8 +194,13 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
if (!bidirectional) {
|
||||
var beginlatlon = convert(beginNode.attr('lat') + " " + beginNode.attr('lon'));
|
||||
var endlatlon = convert(endNode.attr('lat') + " " + endNode.attr('lon'));
|
||||
|
||||
var polyline = new L.Polyline([[beginlatlon.decimalLatitude, beginlatlon.decimalLongitude], [endlatlon.decimalLatitude, endlatlon.decimalLongitude]], { attributes: {} }).addTo(layerGroup);
|
||||
|
||||
var pane = 'route-pane';
|
||||
if(n.attr('isPushBackRoute') === '1') {
|
||||
pane = 'pushback-pane';
|
||||
}
|
||||
|
||||
var polyline = new L.Polyline([[beginlatlon.decimalLatitude, beginlatlon.decimalLongitude], [endlatlon.decimalLatitude, endlatlon.decimalLongitude]], { pane: pane, attributes: {} }).addTo(layerGroup);
|
||||
extendTaxiSegment(polyline);
|
||||
polyline.addListeners();
|
||||
polyline._latlngs[0].attributes = {};
|
||||
@@ -210,6 +234,8 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
|
||||
polyline.begin = beginNode.attr('index');
|
||||
polyline.end = endNode.attr('index');
|
||||
polyline.feature = { properties: { searchTerm: 'Arc ' + beginNode.attr('index') + '-' + endNode.attr('index')}};
|
||||
|
||||
// polyline.enableEdit();
|
||||
|
||||
// polyline.on('dblclick', function (event) { L.DomEvent.stop; polyline.toggleEdit; });
|
||||
|
||||
@@ -14,13 +14,13 @@ const mathjs = require('mathjs');
|
||||
|
||||
var builder = require('xmlbuilder');
|
||||
|
||||
var featureLookup = [];
|
||||
var featureLookup = [];
|
||||
var parkings = [];
|
||||
var pushBackNodeLookup = [];
|
||||
|
||||
/**
|
||||
* Walk nodes until the pushback node is found.
|
||||
* @param {*} index
|
||||
* Walk nodes until the pushback node is found.
|
||||
* @param {*} index
|
||||
*/
|
||||
|
||||
function findRouteToPushback (index) {
|
||||
@@ -57,6 +57,12 @@ function walkPushbackRoute (index, walkedNodes, pushBackNodes) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} fDir The directory
|
||||
* @param {*} icao
|
||||
* @param {*} featureList
|
||||
*/
|
||||
|
||||
exports.writeGroundnetXML = function (fDir, icao, featureList) {
|
||||
try {
|
||||
@@ -65,33 +71,46 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
|
||||
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 fileNames = [];
|
||||
for (let index = 1; index <= store.default.state.Settings.settings.numberOfSaves; index++) {
|
||||
fileNames.push(path.join(fDir, icao[0], icao[1], icao[2], icao + `.groundnet.bak.${index}.xml`));
|
||||
}
|
||||
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');
|
||||
|
||||
if( fs.existsSync(f) ) {
|
||||
fs.copyFileSync(f, fBak);
|
||||
var previous = '';
|
||||
fileNames.reverse().forEach(fBak => {
|
||||
if (fs.existsSync(fBak) && previous !== '') {
|
||||
console.debug( `Copy ${fBak} to ${previous}`);
|
||||
fs.copyFileSync(fBak, previous);
|
||||
}
|
||||
previous = fBak;
|
||||
});
|
||||
fs.copyFileSync(f, previous);
|
||||
}
|
||||
if (f == null)
|
||||
return;
|
||||
pushBackNodeLookup = [];
|
||||
pushBackNodeLookup = [];
|
||||
|
||||
console.debug(featureList);
|
||||
|
||||
var parkings = featureList.map(mapParkings).filter(n => n);
|
||||
var runwayNodes = featureList.map(mapRunwayNodes).filter(n => n);
|
||||
var holdNodes = featureList.map(mapHoldPoint).filter(n => n);
|
||||
|
||||
|
||||
holdNodes.forEach(n => {
|
||||
pushBackNodeLookup[n['@index']] = n;
|
||||
});
|
||||
|
||||
|
||||
var nodes = [];
|
||||
var arcList = [];
|
||||
var frequencies = [];
|
||||
|
||||
var version = new Date().toUTCString() + ' by FlightgearAirports ' + require('electron').remote.app.getVersion();
|
||||
var name = store.default.state.Settings.settings.name;
|
||||
var name = store.default.state.Settings.settings.name;
|
||||
|
||||
featureLookup = [];
|
||||
featureLookup = [];
|
||||
// Loaded segments
|
||||
featureList.filter(o => o instanceof L.TaxiwaySegment).filter(n => n).forEach(element => {
|
||||
var begin = mapBeginNode(element);
|
||||
@@ -103,9 +122,9 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
|
||||
console.warn("End missing");
|
||||
nodes[end['@index']] = end;
|
||||
});
|
||||
// New segments
|
||||
// New segments
|
||||
featureList.filter(o => o instanceof L.Polyline).filter(n => n).forEach(arcElement => {
|
||||
// element._latlngs.forEach(latlng => { nodes[latlng.glueindex] = mapVertexNode(latlng) });
|
||||
// element._latlngs.forEach(latlng => { nodes[latlng.glueindex] = mapVertexNode(latlng) });
|
||||
var startIndex = -1;
|
||||
console.debug(arcElement.options.attributes);
|
||||
var currentArc = arcElement.options.attributes;
|
||||
@@ -123,7 +142,7 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
|
||||
arc = { '@begin': startIndex, '@end': String(latlng.glueindex) };
|
||||
styleArc(currentArc, arc);
|
||||
arcList.push(arc);
|
||||
featureLookup[startIndex][latlng.glueindex] = arc;
|
||||
featureLookup[startIndex][latlng.glueindex] = arc;
|
||||
}
|
||||
if( currentArc.direction === 'bi-directional' || currentArc.direction === 'backward' ){
|
||||
arc = { '@begin': String(latlng.glueindex), '@end': startIndex };
|
||||
@@ -132,7 +151,7 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
|
||||
featureLookup[latlng.glueindex][startIndex] = arc;
|
||||
}
|
||||
if (currentArc.direction === '' || !currentArc.direction) {
|
||||
console.error( "Arc without direction " + util.inspect(currentArc) );
|
||||
console.error( "Arc without direction " + util.inspect(currentArc) );
|
||||
}
|
||||
}
|
||||
startIndex = latlng.glueindex;
|
||||
@@ -143,12 +162,12 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
|
||||
});
|
||||
runwayNodes.forEach(element => {
|
||||
if (nodes[element['@index']] != undefined) {
|
||||
nodes[element['@index']]['@isOnRunway'] = "1";
|
||||
nodes[element['@index']]['@isOnRunway'] = "1";
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Find the index of the pushback node
|
||||
// Find the index of the pushback node
|
||||
parkings.forEach(n => {
|
||||
nodes[n['@index']] = null;
|
||||
var pushBackNode = findRouteToPushback(Number(n['@index']))[0];
|
||||
@@ -178,7 +197,54 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
|
||||
|
||||
var unicomList = store.default.state.Frequencies.items.filter(f => f.type === 'UNICOM').map(mapFrequency);
|
||||
|
||||
var xmlObj = { groundnet: { version: 1, fgaversion: version, name: name,
|
||||
|
||||
var gapStart = -1;
|
||||
var gapEnd = -1;
|
||||
|
||||
do {
|
||||
gapStart = -1;
|
||||
gapEnd = -1;
|
||||
var allIds = parkings.map(n => Number(n['@index']))
|
||||
.concat(uniqueNodes.map(n => Number(n['@index'])))
|
||||
.sort((a, b) => a - b);
|
||||
|
||||
allIds.forEach((element, index, array) => {
|
||||
if (index > 0 && array[index-1] + 1 != element && gapStart == -1 ) {
|
||||
gapStart = array[index-1];
|
||||
gapEnd = element;
|
||||
}
|
||||
});
|
||||
var gap = gapEnd - gapStart -1;
|
||||
if ( gap >= 0 ) {
|
||||
parkings = parkings.map(n => {
|
||||
if (n['@index']>gapStart) {
|
||||
n['@index'] = String(n['@index'] - gap);
|
||||
}
|
||||
if (n['@pushbackRoute']>gapStart) {
|
||||
n['@pushbackRoute'] = String(n['@pushbackRoute'] - gap);
|
||||
}
|
||||
return n;
|
||||
});
|
||||
uniqueNodes = uniqueNodes.map(n => {
|
||||
if (n['@index']>gapStart) {
|
||||
n['@index'] = String(n['@index'] - gap);
|
||||
}
|
||||
return n;
|
||||
});
|
||||
arcList = arcList.map(n => {
|
||||
if (n['@begin']>gapStart) {
|
||||
n['@begin'] = String(n['@begin'] - gap);
|
||||
}
|
||||
if (n['@end']>gapStart) {
|
||||
n['@end'] = String(n['@end'] - gap);
|
||||
}
|
||||
return n;
|
||||
});
|
||||
}
|
||||
|
||||
} while( gapStart > 0 && gapEnd > 0);
|
||||
|
||||
var xmlObj = { groundnet: { version: 1, fgaversion: version, name: name,
|
||||
'frequencies': { APPROACH: approachList, DEPARTURE: departureList, AWOS: awosList, CLEARANCE: clearanceList, GROUND: groundList, TOWER: towerList, UNICOM: unicomList },
|
||||
parkingList: { Parking: parkings }, TaxiNodes: { node: uniqueNodes }, TaxiWaySegments: { arc: arcList } } };
|
||||
|
||||
@@ -209,7 +275,7 @@ var mapParkings = function (o) {
|
||||
console.debug(o.options.attributes.airlineCodes);
|
||||
parking['@airlineCodes'] = o.options.attributes.airlineCodes;
|
||||
}
|
||||
if(o.options.attributes.number !== undefined &&
|
||||
if(o.options.attributes.number !== undefined &&
|
||||
typeof o.options.attributes.number === 'number' || (
|
||||
typeof o.options.attributes.number === 'string' &&
|
||||
o.options.attributes.number.trim() !== ''
|
||||
@@ -226,10 +292,10 @@ var mapParkings = function (o) {
|
||||
var mapRunwayNodes = function (o) {
|
||||
console.debug(o);
|
||||
if (o instanceof L.RunwayNode) {
|
||||
var runwayNode = { '@index': String(o['glueindex']),
|
||||
'@lat': convertLat(o._latlng),
|
||||
'@lon': convertLon(o._latlng),
|
||||
'@isOnRunway': '1',
|
||||
var runwayNode = { '@index': String(o['glueindex']),
|
||||
'@lat': convertLat(o._latlng),
|
||||
'@lon': convertLon(o._latlng),
|
||||
'@isOnRunway': '1',
|
||||
'@holdPointType': 'none' };
|
||||
return runwayNode;
|
||||
}
|
||||
@@ -299,7 +365,7 @@ var styleArc = function (attributes, arc) {
|
||||
arc['@isPushBackRoute'] = "0";
|
||||
}
|
||||
if ( attributes.name !== '' && attributes.name !== 'undefined') {
|
||||
arc['@name'] = attributes.name;
|
||||
arc['@name'] = attributes.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,22 @@
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
var xamel = require('xamel');
|
||||
const xamel = require('xamel');
|
||||
const convert = require('geo-coordinates-parser');
|
||||
const LatLonEllipsoidal = require('geodesy/latlon-ellipsoidal-vincenty.js').default;
|
||||
|
||||
const store = require('../store');
|
||||
|
||||
const util = require('util');
|
||||
|
||||
const takeoffPadPoly = require('../leaflet/TakeoffPad.js');
|
||||
|
||||
const threshold = require('./Threshold.js');
|
||||
|
||||
|
||||
var $ = require('jquery');
|
||||
|
||||
exports.readThresholdXML = function (fDir, icao, force) {
|
||||
exports.readThresholdXML = function (fDir, icao, force, stripes) {
|
||||
try {
|
||||
var layerGroup = L.layerGroup();
|
||||
layerGroup.maxId = 0;
|
||||
@@ -40,26 +43,39 @@ exports.readThresholdXML = function (fDir, icao, force) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
var thresholdNodes = xml.find('PropertyList/runway/threshold');
|
||||
console.log("Threshold Nodes" + thresholdNodes.length);
|
||||
var runwayNodes = xml.find('PropertyList/runway');
|
||||
console.log("Threshold Nodes" + runwayNodes.length);
|
||||
|
||||
var merged = new Array();
|
||||
|
||||
var nodesLookup = {};
|
||||
featureLookup = [];
|
||||
|
||||
var index = 0;
|
||||
runwayNodes.map(r => {
|
||||
var thresholds = r.find('threshold');
|
||||
thresholds.map(n => {
|
||||
var icon = threshold(n);
|
||||
icon.index = index;
|
||||
icon.addTo(layerGroup);
|
||||
// Width in m
|
||||
var runwayWidth = 20;
|
||||
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
|
||||
var displ_m = Number(n.find('displ-m/text()').text());
|
||||
var pointMiddle = new LatLonEllipsoidal(latlon.decimalLatitude, latlon.decimalLongitude);
|
||||
var heading = Number(n.find('hdg-deg/text()').text());
|
||||
var point1 = pointMiddle.destinationPoint(displ_m, heading);
|
||||
var point2 = pointMiddle.destinationPoint(displ_m + 80, heading);
|
||||
|
||||
thresholdNodes.map(n => {
|
||||
var icon = threshold(n);
|
||||
icon.addTo(layerGroup);
|
||||
var runwayPoints = [];
|
||||
runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (heading + 90)));
|
||||
runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (heading + 90)));
|
||||
runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (heading - 90)));
|
||||
runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (heading - 90)));
|
||||
|
||||
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);
|
||||
*/
|
||||
var runwayPoly = takeoffPadPoly(runwayPoints);
|
||||
runwayPoly.addTo(layerGroup);
|
||||
}
|
||||
)
|
||||
|
||||
// features.push(circle);
|
||||
index+=1;
|
||||
}).sort();
|
||||
|
||||
return layerGroup;
|
||||
@@ -70,4 +86,4 @@ exports.readThresholdXML = function (fDir, icao, force) {
|
||||
console.error(error);
|
||||
}
|
||||
return layerGroup;
|
||||
};
|
||||
};
|
||||
|
||||
120
src/renderer/loaders/threshold_writer.js
Normal file
120
src/renderer/loaders/threshold_writer.js
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 2021 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');
|
||||
|
||||
const store = require('../store');
|
||||
|
||||
const util = require('util');
|
||||
|
||||
const mathjs = require('mathjs');
|
||||
|
||||
var builder = require('xmlbuilder');
|
||||
|
||||
|
||||
|
||||
var writeThresholdXML = 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 + '.threshold.new.xml');
|
||||
var fBak = path.join(fDir, icao[0], icao[1], icao[2], icao + '.threshold.bak.xml');
|
||||
|
||||
if( fs.existsSync(f) ) {
|
||||
fs.copyFileSync(f, fBak);
|
||||
}
|
||||
if (f == null)
|
||||
return;
|
||||
var xmlObj = { PropertyList: { runway: 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);
|
||||
|
||||
/**
|
||||
<?xml version='1.0' encoding='ISO-8859-1'?>
|
||||
<PropertyList>
|
||||
<runway>
|
||||
<threshold>
|
||||
<lon>13.485025</lon>
|
||||
<lat>52.367689</lat>
|
||||
<rwy>07</rwy>
|
||||
<hdg-deg>68.75</hdg-deg>
|
||||
<displ-m>0.0</displ-m>
|
||||
<stopw-m>300.0</stopw-m>
|
||||
</threshold>
|
||||
<threshold>
|
||||
<lon>13.526097</lon>
|
||||
<lat>52.377431</lat>
|
||||
<rwy>25</rwy>
|
||||
<hdg-deg>248.78</hdg-deg>
|
||||
<displ-m>0.0</displ-m>
|
||||
<stopw-m>300.0</stopw-m>
|
||||
</threshold>
|
||||
</runway>
|
||||
<runway>
|
||||
<threshold>
|
||||
<lon>13.517142</lon>
|
||||
<lat>52.380125</lat>
|
||||
<rwy>07L</rwy>
|
||||
<hdg-deg>68.77</hdg-deg>
|
||||
<displ-m>0.0</displ-m>
|
||||
<stopw-m>160.0</stopw-m>
|
||||
</threshold>
|
||||
<threshold>
|
||||
<lon>13.554253</lon>
|
||||
<lat>52.388919</lat>
|
||||
<rwy>25R</rwy>
|
||||
<hdg-deg>248.80</hdg-deg>
|
||||
<displ-m>0.0</displ-m>
|
||||
<stopw-m>300.0</stopw-m>
|
||||
</threshold>
|
||||
</runway>
|
||||
</PropertyList>
|
||||
*/
|
||||
var ret = [];
|
||||
Object.keys(o).forEach(key => {
|
||||
ret.push({ threshold: mapThreshold(o[key])});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* <latitude>58.106924</latitude>
|
||||
<longitude>6.610419</longitude>
|
||||
<index>0</index>
|
||||
<rwy>14</rwy>
|
||||
<heading>131.16</heading>
|
||||
<displacement>273</displacement>
|
||||
<stopw_m>0.0</stopw_m>
|
||||
|
||||
* @param {*} t
|
||||
*/
|
||||
|
||||
var mapThreshold = function (t) {
|
||||
return t.map( t => {return {lon: t.longitude, lat: t.latitude, rwy: t.rwy, 'hdg-deg': t.heading, 'displ-m': t.displacement, 'stopw-m': t.stopw_m}});
|
||||
}
|
||||
|
||||
export { writeThresholdXML };
|
||||
@@ -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
|
||||
|
||||
63
src/renderer/loaders/tower_writer.js
Normal file
63
src/renderer/loaders/tower_writer.js
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright 2021 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');
|
||||
|
||||
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};
|
||||
}
|
||||
123
src/renderer/loaders/traffic_loader.js
Normal file
123
src/renderer/loaders/traffic_loader.js
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright 2021 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 store = require('../store');
|
||||
|
||||
const util = require('util');
|
||||
|
||||
exports.readTrafficXML = function (f) {
|
||||
try {
|
||||
var ret = [];
|
||||
var xmlTraffic = fs.readFileSync(f, 'utf8').toString();
|
||||
xamel.parse(xmlTraffic, function (err, xml) {
|
||||
console.debug("parsed " + path.basename(f));
|
||||
if (err !== null) {
|
||||
console.error("Error in " + airline);
|
||||
throw err;
|
||||
}
|
||||
|
||||
var requiredAircraft = xml.find('trafficlist/aircraft');
|
||||
console.log("Aircraft " + requiredAircraft.length);
|
||||
|
||||
ret.concat(requiredAircraft);
|
||||
var flights = xml.find('trafficlist/flight');
|
||||
console.log("Flights " + flights.length);
|
||||
ret.concat(flights);
|
||||
console.log(ret.length);
|
||||
ret = ret.concat(flights.map(flightMapper)).concat(requiredAircraft.map(aircraftMapper))
|
||||
return ret;
|
||||
});
|
||||
return ret;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* <flight>
|
||||
<callsign>Hebridean_1047</callsign>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>EGPU</port>
|
||||
<time>4/14:50:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>EGEO</port>
|
||||
<time>4/15:50:00</time>
|
||||
</arrival>
|
||||
<repeat>WEEK</repeat>
|
||||
</flight>
|
||||
*/
|
||||
|
||||
function flightMapper(params) {
|
||||
return {
|
||||
id: `${btoa(buildId(params))}`,
|
||||
callsign: params.find('callsign').text(),
|
||||
'required-aircraft': params.find('required-aircraft').text(),
|
||||
arrival: {
|
||||
port: params.find('arrival/port').text(),
|
||||
time: params.find('arrival/time').text()
|
||||
},
|
||||
departure: {
|
||||
port: params.find('departure/port').text(),
|
||||
time: params.find('departure/time').text()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function buildId(params) {
|
||||
return `${params.find('callsign').text()}_`+
|
||||
`${params.find('arrival/port').text()}_`+
|
||||
`${params.find('arrival/time').text()}_`+
|
||||
`${params.find('departure/port').text()}_` +
|
||||
`${params.find('departure/time').text()}`;
|
||||
}
|
||||
|
||||
/*
|
||||
<aircraft>
|
||||
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
|
||||
<livery>HBR</livery>
|
||||
<airline>HBR</airline>
|
||||
<home-port>EGEO</home-port>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<actype>BN2</actype>
|
||||
<offset>0</offset>
|
||||
<radius>8</radius>
|
||||
<flighttype>gate</flighttype>
|
||||
<performance-class>turboprop_transport</performance-class>
|
||||
<registration>G-HEBO</registration>
|
||||
<heavy>false</heavy>
|
||||
</aircraft>
|
||||
*/
|
||||
|
||||
function aircraftMapper(params) {
|
||||
return {
|
||||
model: params.find('model').text(),
|
||||
livery: params.find('livery').text(),
|
||||
airline: params.find('airline').text(),
|
||||
'home-port': params.find('home-port').text(),
|
||||
'required-aircraft': params.find('required-aircraft').text(),
|
||||
actype: params.find('actype').text(),
|
||||
offset: params.find('offset').text(),
|
||||
radius: params.find('radius').text(),
|
||||
flighttype: params.find('flighttype').text(),
|
||||
'performance-class': params.find('performance-class').text(),
|
||||
'registration': params.find('registration').text(),
|
||||
'heavy': params.find('heavy').text(),
|
||||
};
|
||||
}
|
||||
180
src/renderer/loaders/traffic_writer.js
Normal file
180
src/renderer/loaders/traffic_writer.js
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
Copyright 2021 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');
|
||||
|
||||
const store = require('../store');
|
||||
|
||||
const util = require('util');
|
||||
|
||||
const mathjs = require('mathjs');
|
||||
|
||||
var builder = require('xmlbuilder');
|
||||
|
||||
var parkingStats = (acc, cur) => {
|
||||
if (!acc[cur.radius]) {
|
||||
acc[cur.radius] = { count: 0, radius: cur.radius }
|
||||
}
|
||||
acc[cur.radius].count += 1
|
||||
return acc
|
||||
};
|
||||
|
||||
/**
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<trafficlist xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="traffic.xsd">
|
||||
<aircraft>
|
||||
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
|
||||
<livery>HBR</livery>
|
||||
<airline>HBR</airline>
|
||||
<home-port>EGEO</home-port>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<actype>BN2</actype>
|
||||
<offset>0</offset>
|
||||
<radius>8</radius>
|
||||
<flighttype>gate</flighttype>
|
||||
<performance-class>turboprop_transport</performance-class>
|
||||
<registration>G-HEBS</registration>
|
||||
<heavy>false</heavy>
|
||||
</aircraft>
|
||||
<flight>
|
||||
<callsign>Hebridean_1047</callsign>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>EGPU</port>
|
||||
<time>4/14:50:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>EGEO</port>
|
||||
<time>4/15:50:00</time>
|
||||
</arrival>
|
||||
<repeat>WEEK</repeat>
|
||||
</flight>
|
||||
</trafficlist>
|
||||
*/
|
||||
|
||||
var writeTrafficXML = function (fDir, parkings, aircraft) {
|
||||
try {
|
||||
var icao = store.default.state.Airports.currentAirport.icao;
|
||||
var aircraftList = aircraft;
|
||||
|
||||
try { fs.mkdirSync(path.join(fDir), { recursive: true }) } catch (err) { }
|
||||
try { fs.mkdirSync(path.join(fDir, 'TST'), { recursive: true }) } catch (err) { }
|
||||
|
||||
var f = path.join(fDir, 'TST', icao + '.xml');
|
||||
|
||||
|
||||
var parkingData = parkings.reduce(parkingStats, {});
|
||||
|
||||
/*
|
||||
*
|
||||
<flight>
|
||||
<callsign>Hebridean_1001</callsign>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>EGEO</port>
|
||||
<time>2/14:10:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>EGEY</port>
|
||||
<time>2/15:20:00</time>
|
||||
</arrival>
|
||||
<repeat>WEEK</repeat>
|
||||
</flight>
|
||||
*/
|
||||
|
||||
var flightMapper = function (pStat) {
|
||||
var ret = [];
|
||||
var blockSize = Math.min( pStat[1].count/6, 6);
|
||||
for (let index = 0; index < pStat[1].count; index++) {
|
||||
var aircraft = this[index];
|
||||
var minutes = `${Math.floor(index/blockSize)}`.padStart(2, '0');
|
||||
var seconds = `${index}`.padStart(2, '0');
|
||||
for (let weekday = 0; weekday < 7; weekday++) {
|
||||
ret.push({
|
||||
callsign: `Test_${index}_${weekday}`,
|
||||
'required-aircraft': aircraft['required-aircraft'],
|
||||
fltrules: 'VFR',
|
||||
departure: {
|
||||
port: icao,
|
||||
time: `${weekday}/12:${minutes}:${seconds}`
|
||||
},
|
||||
'cruise-alt': 50,
|
||||
arrival: {
|
||||
port: icao,
|
||||
time: `${weekday}/13:${minutes}:${seconds}`
|
||||
},
|
||||
repeat: 'WEEK'
|
||||
});
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
<aircraft>
|
||||
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
|
||||
<livery>HBR</livery>
|
||||
<airline>HBR</airline>
|
||||
<home-port>EGEO</home-port>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<actype>BN2</actype>
|
||||
<offset>0</offset>
|
||||
<radius>8</radius>
|
||||
<flighttype>gate</flighttype>
|
||||
<performance-class>turboprop_transport</performance-class>
|
||||
<registration>G-HEBO</registration>
|
||||
<heavy>false</heavy>
|
||||
</aircraft>
|
||||
|
||||
*/
|
||||
var aircraftMapper = function (pStat) {
|
||||
var ret = [];
|
||||
if (typeof this === 'undefined') {
|
||||
return;
|
||||
}
|
||||
var possibleAircraft = this.filter(a => a.radius <= pStat[1].radius);
|
||||
|
||||
for (let index = 0; index < pStat[1].count; index++) {
|
||||
var aircraft = possibleAircraft[Math.floor(Math.random() * possibleAircraft.length)];
|
||||
aircraft['required-aircraft'] = `GG-${index}`;
|
||||
aircraft.registration = `GG-${index}`;
|
||||
aircraft['home-port'] = icao;
|
||||
ret.push(aircraft);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
var aircraftList = Object.entries(parkingData).flatMap(aircraftMapper, aircraft).sort();
|
||||
var flightList = Object.entries(parkingData).flatMap(flightMapper, aircraftList).sort();
|
||||
|
||||
var xmlObj = { trafficList: { aircraft: aircraftList, flight: flightList } };
|
||||
|
||||
var xmlString = builder.create(xmlObj).end({ pretty: true });
|
||||
fs.writeFileSync(f, xmlString);
|
||||
console.debug(xmlString);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
export { writeTrafficXML as writeTrafficXML };
|
||||
@@ -14,6 +14,10 @@ Vue.config.productionTip = false
|
||||
|
||||
Vue.use(ElementUI)
|
||||
|
||||
Vue.config.errorHandler = (err, vm, info) => {
|
||||
console.error(err)
|
||||
}
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
components: { App },
|
||||
|
||||
@@ -16,7 +16,7 @@ const state = {
|
||||
type: 'none',
|
||||
index: 'none',
|
||||
editing: false,
|
||||
data: {airports: {}, parking: {}, arc: {}, multiarc: {}, node: {}, runway: {}}
|
||||
data: {airports: {}, parking: {}, arc: {}, multiarc: {}, node: {}, runway: {}, threshold: {}, tower: {}}
|
||||
}
|
||||
|
||||
const SET_EDIT_AIRPORT = 'SET_EDIT_AIRPORT'
|
||||
@@ -38,7 +38,6 @@ const mutations = {
|
||||
state.type = 'airport'
|
||||
},
|
||||
SET_EDIT_PARKING (state, parking) {
|
||||
Vue.set(state, 'data', {})
|
||||
var p = Object.assign({}, parking)
|
||||
Vue.set(state.data, 'parking', p)
|
||||
Vue.set(state, 'index', p.index)
|
||||
@@ -48,15 +47,11 @@ const mutations = {
|
||||
if (node === undefined) {
|
||||
return
|
||||
}
|
||||
if (!state.data || state.type !== 'node') {
|
||||
Vue.set(state, 'data', {})
|
||||
}
|
||||
Vue.set(state.data, 'node', node)
|
||||
Vue.set(state, 'index', node.index)
|
||||
Vue.set(state, 'type', 'node')
|
||||
},
|
||||
SET_EDIT_RUNWAY (state, runway) {
|
||||
Vue.set(state, 'data', {})
|
||||
Vue.set(state.data, 'node', runway)
|
||||
Vue.set(state, 'index', runway.index)
|
||||
Vue.set(state, 'type', 'runway')
|
||||
@@ -65,9 +60,6 @@ const mutations = {
|
||||
if (arc === undefined) {
|
||||
return
|
||||
}
|
||||
if (!state.data || state.type !== 'arc') {
|
||||
Vue.set(state, 'data', {})
|
||||
}
|
||||
Vue.set(state.data, 'arc', arc)
|
||||
if (state.data.arc.name === undefined) {
|
||||
Vue.set(state.data.arc, 'name', '')
|
||||
@@ -79,9 +71,6 @@ const mutations = {
|
||||
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) {
|
||||
@@ -131,6 +120,9 @@ const mutations = {
|
||||
'SET_EDIT_PARKING_COORDS' (state, coords) {
|
||||
Vue.set(state.data.parking, 'coords', coords)
|
||||
},
|
||||
'SET_EDIT_PARKING_NOSE_COORDS' (state, coords) {
|
||||
Vue.set(state.data.parking, 'nosecoords', coords)
|
||||
},
|
||||
'SET_EDIT_ARC_NAME' (state, arcName) {
|
||||
if (state.type === 'arc') {
|
||||
Vue.set(state.data.arc, 'name', arcName)
|
||||
@@ -158,6 +150,28 @@ const mutations = {
|
||||
'SET_EDIT_NODE_COORDS' (state, coords) {
|
||||
Vue.set(state.data.node, 'coords', coords)
|
||||
},
|
||||
'SET_EDIT_TOWER_COORDS' (state, coords) {
|
||||
state.type = 'tower'
|
||||
if (!state.data.tower) {
|
||||
state.data.tower = {}
|
||||
}
|
||||
if (!state.data.tower.coords) {
|
||||
state.data.tower.coords = {}
|
||||
}
|
||||
Vue.set(state.data.tower.coords, 'latitude', coords.split(' ')[0])
|
||||
Vue.set(state.data.tower.coords, 'longitude', coords.split(' ')[1])
|
||||
},
|
||||
'SET_EDIT_TOWER_HEIGHT' (state, height) {
|
||||
Vue.set(state.data.tower, 'height', height)
|
||||
},
|
||||
'SET_EDIT_THRESHOLD_COORDS' (state, threshold) {
|
||||
state.type = 'threshold'
|
||||
Vue.set(state.data.threshold, 'runway', threshold.rwy)
|
||||
Vue.set(state.data.threshold, 'displacement', threshold.displacement)
|
||||
},
|
||||
'SET_EDIT_THRESHOLD_DISPLACEMENT' (state, displacement) {
|
||||
Vue.set(state.data.threshold, 'displacement', displacement)
|
||||
},
|
||||
'SET_EDIT_ISONRUNWAY' (state, isOnRunway) {
|
||||
Vue.set(state.data.node, 'isOnRunway', isOnRunway)
|
||||
}
|
||||
@@ -182,6 +196,9 @@ const actions = {
|
||||
async setParkingCoords (context, coords) {
|
||||
context.commit('SET_EDIT_PARKING_COORDS', coords)
|
||||
},
|
||||
async setParkingNoseCoords (context, coords) {
|
||||
context.commit('SET_EDIT_PARKING_NOSE_COORDS', coords)
|
||||
},
|
||||
async setArc (context, arc) {
|
||||
context.commit(SET_EDIT_ARC, arc)
|
||||
},
|
||||
@@ -194,6 +211,18 @@ 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)
|
||||
},
|
||||
async setTowerHeight (context, height) {
|
||||
context.commit('SET_EDIT_TOWER_HEIGHT', height)
|
||||
},
|
||||
async setThreshold (context, node) {
|
||||
context.commit('SET_EDIT_THRESHOLD_COORDS', node)
|
||||
},
|
||||
async setDisplacement (context, displacement) {
|
||||
context.commit('SET_EDIT_THRESHOLD_DISPLACEMENT', displacement)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ const mutations = {
|
||||
|
||||
const actions = {
|
||||
async addParking (context, p) {
|
||||
context.commit('ADD_FREADD_PARKINGQUENCY', p)
|
||||
context.commit('ADD_PARKING', p)
|
||||
},
|
||||
async updatedParking (context, p) {
|
||||
context.commit('UPDATE_PARKING', p)
|
||||
|
||||
@@ -3,7 +3,7 @@ const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const state = {
|
||||
settings: { flightgearDirectory: '.', testDirectory: '.', email: 'flightgearairports@example.org', name: 'unknown', phi_url: 'http://localhost:8080' },
|
||||
settings: { numberOfSaves: 1, flightgearDirectory: '.', testDirectory: '.', email: 'flightgearairports@example.org', name: 'unknown', phi_url: 'http://localhost:8080' },
|
||||
zoom: 14,
|
||||
center: [47.413220, -1.219482],
|
||||
bounds: undefined,
|
||||
@@ -50,6 +50,9 @@ const mutations = {
|
||||
'SET_NAME'(state, name) {
|
||||
state.settings.name = name
|
||||
},
|
||||
'SET_NUMBER_OF_SAVES'(state, numberOfSaves) {
|
||||
state.settings.numberOfSaves = numberOfSaves
|
||||
},
|
||||
'SET_PHI_URL'(state, phi_url) {
|
||||
state.settings.phi_url = phi_url
|
||||
},
|
||||
|
||||
@@ -43,22 +43,22 @@ onmessage = function (event) {
|
||||
).catch(result => {
|
||||
console.error('Crashed');
|
||||
console.error(result);
|
||||
postMessage(['DONE', [{id: -1, message: ['Crashed', result ]}]]);
|
||||
postMessage(['DONE', [{ id: -1, message: ['Crashed', result] }]]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements the checks of the groundnet
|
||||
* @param {*} data
|
||||
* @param {*} data
|
||||
*/
|
||||
|
||||
async function checkGroundnet(data) {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
try {
|
||||
const fName = process.env.NODE_ENV === 'development'
|
||||
? './src/renderer/utils/check_msg.json'
|
||||
: path.join(`${process.resourcesPath}`, 'workers','check_msg.json');
|
||||
? './src/renderer/utils/check_msg.json'
|
||||
: path.join(`${process.resourcesPath}`, 'workers', 'check_msg.json');
|
||||
check_msg = JSON.parse(fs.readFileSync(fName, 'utf8').toString());
|
||||
//debugger;
|
||||
var parkings = data.map(mapParkings).filter(n => n !== undefined);
|
||||
@@ -68,9 +68,9 @@ async function checkGroundnet(data) {
|
||||
var edges = data.map(mapEdges).filter(n => n !== undefined);
|
||||
|
||||
var normalNodes = data.map(mapEdges).filter(n => n !== undefined)
|
||||
.flatMap(m => m.latLngs).filter(n => runwayNodeIDs.indexOf(Number(n.index)) < 0);
|
||||
.flatMap(m => m.latLngs).filter(n => runwayNodeIDs.indexOf(Number(n.index)) < 0);
|
||||
|
||||
var runways = data.map(mapRunways).filter(n => n !== undefined);
|
||||
var takeoffPads = data.map(mapTakeoffPads).filter(n => n !== undefined);
|
||||
|
||||
this.max = 30;
|
||||
this.postMessage(['max', this.max]);
|
||||
@@ -87,7 +87,7 @@ async function checkGroundnet(data) {
|
||||
var directionalGraph = {};
|
||||
var bidirectionalGraph = {};
|
||||
|
||||
console.log(parkings);
|
||||
console.debug(parkings);
|
||||
parkings.forEach(element => {
|
||||
directionalGraph[element] = {};
|
||||
bidirectionalGraph[element] = {};
|
||||
@@ -99,12 +99,13 @@ async function checkGroundnet(data) {
|
||||
var notOkNodes = [];
|
||||
//debugger;
|
||||
|
||||
console.log(edges);
|
||||
console.debug(edges);
|
||||
if (edges === undefined) {
|
||||
resolve([{ id: -1, message: check_msg.NO_EDGES }]);
|
||||
}
|
||||
this.postMessage(['progress', 1]);
|
||||
if (runways.length === 0) {
|
||||
//debugger;
|
||||
if (takeoffPads.length === 0) {
|
||||
resolve([{ id: -1, message: check_msg.NO_RUNWAYS }]);
|
||||
}
|
||||
this.postMessage(['progress', 1]);
|
||||
@@ -135,7 +136,7 @@ async function checkGroundnet(data) {
|
||||
var node2 = directionalGraph[element.end];
|
||||
if (element.direction === undefined) {
|
||||
notOkNodes.push({ id: Number(element._leaflet_id), message: check_msg.EDGE_MISSING_DIRECTION });
|
||||
}
|
||||
}
|
||||
if (element.direction === 'bi-directional' || element.direction === 'forward') {
|
||||
node1[Number(element.end)] = 1;
|
||||
}
|
||||
@@ -150,6 +151,9 @@ async function checkGroundnet(data) {
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
var isLegitEnd = function (v) {
|
||||
if (bidirectionalGraph[v] === undefined) {
|
||||
debugger;
|
||||
}
|
||||
if (Object.keys(bidirectionalGraph[v]).length <= 1) {
|
||||
return true;
|
||||
}
|
||||
@@ -158,7 +162,7 @@ async function checkGroundnet(data) {
|
||||
runwayNodeIDs = runwayNodeIDs.filter(
|
||||
(v, i) => isLegitEnd(v)
|
||||
);
|
||||
// Check if there is a route from every parking to every runway node
|
||||
// Check if there is a route from every parking to every runway node
|
||||
var okNodes = [];
|
||||
logger('info', directionalGraph);
|
||||
parkings.forEach(parkingNode => {
|
||||
@@ -170,7 +174,7 @@ async function checkGroundnet(data) {
|
||||
} else {
|
||||
console.log(`No route from Parking ${parkingNode} to Runwaynode ${runwayNode}`);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
// Build pushback directionalGraph
|
||||
@@ -203,7 +207,7 @@ async function checkGroundnet(data) {
|
||||
if (numRoutes === 0) {
|
||||
if (multiplePushbackRoutes[parkingNode] === undefined &&
|
||||
Object.keys(noPushbackGraph[parkingNode]) > 0) {
|
||||
// Only when there is a edge leaving
|
||||
// Only when there is a edge leaving
|
||||
multiplePushbackRoutes[parkingNode] = [];
|
||||
}
|
||||
} else if (numRoutes === 1) {
|
||||
@@ -219,37 +223,41 @@ async function checkGroundnet(data) {
|
||||
multiplePushbackRoutes[parkingNode].push(pushbackNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
var notConnectedToPushback = pushbackNodes.map(
|
||||
id => {
|
||||
var normalRoutes = bidirectionalGraph[id];
|
||||
var pushbackRoutes = noPushbackGraph[id];
|
||||
if (Object.keys(pushbackRoutes).length < 1)
|
||||
return { id: id, message: check_msg.PUSHBACK_NOT_CONNECTED }
|
||||
}).filter(n => n !== undefined);
|
||||
var normalRoutes = bidirectionalGraph[id];
|
||||
var pushbackRoutes = noPushbackGraph[id];
|
||||
if (Object.keys(pushbackRoutes).length < 1)
|
||||
return { id: id, message: check_msg.PUSHBACK_NOT_CONNECTED }
|
||||
}).filter(n => n !== undefined);
|
||||
this.postMessage(['progress', 1]);
|
||||
var multipleTaxiRoutes = pushbackNodes.map(
|
||||
id => {
|
||||
var normalRoutes = bidirectionalGraph[id];
|
||||
var pushbackRoutes = noPushbackGraph[id];
|
||||
var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined);
|
||||
if (nonPushbackRoutes.length > 1)
|
||||
return { id: id, message: check_msg.TO_MANY_PUSHBACK_TAXI_ROUTES }
|
||||
}).filter(n => n !== undefined);
|
||||
var normalRoutes = bidirectionalGraph[id];
|
||||
var pushbackRoutes = noPushbackGraph[id];
|
||||
if (normalRoutes !== undefined) {
|
||||
var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined);
|
||||
if (nonPushbackRoutes.length > 1)
|
||||
return { id: id, message: check_msg.TO_MANY_PUSHBACK_TAXI_ROUTES }
|
||||
}
|
||||
}).filter(n => n !== undefined);
|
||||
this.postMessage(['progress', 1]);
|
||||
var pushbackExitNotBidirectional = pushbackNodes.map(
|
||||
id => {
|
||||
var normalRoutes = bidirectionalGraph[id];
|
||||
var pushbackRoutes = noPushbackGraph[id];
|
||||
var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined);
|
||||
if(nonPushbackRoutes.length > 0) {
|
||||
var returnRoute = Object.keys(bidirectionalGraph[nonPushbackRoutes[0]]).map(id => Number(id)).filter(retId =>id === retId);
|
||||
if (returnRoute.length === 0)
|
||||
return { id: id, message: check_msg.PUSHBACK_EXIT_NOT_BIDRECTIONAL }
|
||||
}
|
||||
}).filter(n => n !== undefined);
|
||||
var normalRoutes = bidirectionalGraph[id];
|
||||
var pushbackRoutes = noPushbackGraph[id];
|
||||
if (normalRoutes !== undefined) {
|
||||
var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined);
|
||||
if(nonPushbackRoutes.length > 0) {
|
||||
var returnRoute = Object.keys(bidirectionalGraph[nonPushbackRoutes[0]]).map(id => Number(id)).filter(retId =>id === retId);
|
||||
if (returnRoute.length === 0)
|
||||
return { id: id, message: check_msg.PUSHBACK_EXIT_NOT_BIDRECTIONAL }
|
||||
}
|
||||
}
|
||||
}).filter(n => n !== undefined);
|
||||
this.postMessage(['progress', 1]);
|
||||
var rogueHoldPoints = pushbackNodes.map(
|
||||
id => {
|
||||
@@ -290,16 +298,16 @@ async function checkGroundnet(data) {
|
||||
var notOkNodesRunways = runwayNodeIDs.filter(
|
||||
(v, i) => okNodes.indexOf(v) < 0
|
||||
).map(
|
||||
id => { return { id: id, message: check_msg.NO_RUNWAY_ROUTE } }
|
||||
id => { return { id: id, message: check_msg.NO_PARKING_ROUTE } }
|
||||
);
|
||||
this.postMessage(['progress', 1]);
|
||||
|
||||
if (parkings.length === 0) {
|
||||
notOkNodes.push({ id: 0, message: check_msg.NO_PARKINGS });
|
||||
notOkNodes.push({ id: -2, message: check_msg.NO_PARKINGS });
|
||||
}
|
||||
this.postMessage(['progress', 1]);
|
||||
if (runwayNodeIDs.length === 0) {
|
||||
notOkNodes.push({ id: 0, message: check_msg.NO_RUNWAY_NODES });
|
||||
notOkNodes.push({ id: -2, message: check_msg.NO_RUNWAY_NODES });
|
||||
}
|
||||
this.postMessage(['progress', 1]);
|
||||
var allEnds = Object.entries(bidirectionalGraph).filter(
|
||||
@@ -344,7 +352,7 @@ async function checkGroundnet(data) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
@@ -353,14 +361,14 @@ async function checkGroundnet(data) {
|
||||
parkingNodes.forEach(parkingNode => {
|
||||
if (!parkingNode.name || /^\s*$/.test(parkingNode.name)) {
|
||||
invalidParkings.push({ id: parkingNode.index, message: check_msg.NAME_EMPTY });
|
||||
|
||||
|
||||
}
|
||||
if (!parkingNode.type) {
|
||||
invalidParkings.push({ id: parkingNode.index, message: check_msg.TYPE_EMPTY });
|
||||
|
||||
|
||||
}
|
||||
if (['ga', 'cargo', 'gate', 'mil-fighter', 'mil-cargo'].indexOf(parkingNode.parkingType) < 0) {
|
||||
invalidParkings.push({ id: parkingNode.index, message: check_msg.PARKING_TYPE_INVALID });
|
||||
invalidParkings.push({ id: parkingNode.index, message: check_msg.PARKING_TYPE_INVALID });
|
||||
}
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
@@ -375,21 +383,29 @@ async function checkGroundnet(data) {
|
||||
this.postMessage(['progress', 1]);
|
||||
//Check if runwaynodes are on runway
|
||||
runwayNodes.forEach(runwayNode => {
|
||||
if( runways.filter(r => turf.booleanContains(r, latToTurf(runwayNode))).length === 0 ) {
|
||||
// debugger;
|
||||
if (takeoffPads.filter(r => turf.booleanContains(r, latToTurf(runwayNode))).length === 0) {
|
||||
notOkNodes.push({ id: runwayNode.index, message: check_msg.RUNWAY_NODE_NOT_ON_RUNWAY });
|
||||
}
|
||||
}
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
|
||||
//Check if nodes no normal nodes are on runway
|
||||
normalNodes.forEach(normalNode => {
|
||||
//debugger;
|
||||
if( runways.filter(r => turf.booleanContains(r, latToTurf(normalNode))).length > 0 ) {
|
||||
if (takeoffPads.filter(r => turf.booleanContains(r, latToTurf(normalNode))).length > 0) {
|
||||
notOkNodes.push({ id: normalNode.index, message: check_msg.NON_RUNWAYNODE_ON_RUNWAY });
|
||||
}
|
||||
}
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
|
||||
var doubleEdges = edges.filter((v, i, a) => a.findIndex(t => (t.start === v.start && t.end === v.end) ) !== i);
|
||||
doubleEdges.forEach(e => {
|
||||
notOkNodes.push({ id: e.id, message: check_msg.DOUBLE_EDGE });
|
||||
});
|
||||
|
||||
// debugger;
|
||||
|
||||
notOkNodes = notOkNodes.concat(invalidParkings);
|
||||
if (invalidParkings.length === 0) {
|
||||
notOkNodes.push({ id: -1, message: check_msg.PARKINGS_VALID });
|
||||
@@ -415,8 +431,8 @@ async function checkGroundnet(data) {
|
||||
notOkNodes = notOkNodes.concat(notConnectedToPushback);
|
||||
notOkNodes = notOkNodes.concat(multipleTaxiRoutes);
|
||||
notOkNodes = notOkNodes.concat(pushbackExitNotBidirectional);
|
||||
if (wrongPushbackRoutes.length === 0 &&
|
||||
notConnectedToPushback.length === 0 &&
|
||||
if (wrongPushbackRoutes.length === 0 &&
|
||||
notConnectedToPushback.length === 0 &&
|
||||
multipleTaxiRoutes.length === 0 &&
|
||||
pushbackExitNotBidirectional.length === 0
|
||||
) {
|
||||
@@ -496,12 +512,12 @@ var mapRunwayNodeId = function (o) {
|
||||
|
||||
var mapRunwayNode = function (o) {
|
||||
if (o.type === 'runway') {
|
||||
return {index:o.index, lat: o.lat, lng: o.lng};
|
||||
return { index: o.index, lat: o.lat, lng: o.lng };
|
||||
}
|
||||
}
|
||||
|
||||
var mapRunways = function (o) {
|
||||
if (o.type === 'runway_poly') {
|
||||
var mapTakeoffPads = function (o) {
|
||||
if (o.type === 'takeoffpad_poly') {
|
||||
var pts = o.pavement[0].map(latLngToArray);
|
||||
pts.push(pts[0]);
|
||||
return turf.polygon([pts]);
|
||||
@@ -510,12 +526,10 @@ var mapRunways = function (o) {
|
||||
|
||||
var mapEdges = function (o) {
|
||||
if (o.type === 'poly')
|
||||
// debugger;
|
||||
return {
|
||||
start: o.start, end: o.end, isPushBackRoute: o.isPushBackRoute !== undefined &&
|
||||
id: o._leaflet_id, start: o.start, end: o.end, isPushBackRoute: o.isPushBackRoute !== undefined &&
|
||||
o.isPushBackRoute !== 0, direction: o.direction, latLngs: o.latLngs
|
||||
};
|
||||
console.debug(o);
|
||||
}
|
||||
|
||||
var latToTurf = function (turfPoint) {
|
||||
|
||||
@@ -1,32 +1,33 @@
|
||||
{
|
||||
"LONG_ROUTE_START" : ["Start of long route", "Route segments of >2km are Taxidraw artefacts"],
|
||||
"LONG_ROUTE_END": ["End of long route", "Route segments of >2km are Taxidraw artefacts"],
|
||||
"EDGE_MISSING_DIRECTION": ["Edge missing direction", ""],
|
||||
"NO_RUNWAY_ROUTE": ["No way from parking to each runway", ""],
|
||||
"NO_PARKING_ROUTE": ["No way from runway to each parking", ""],
|
||||
"EDGE_MISSING_DIRECTION": ["Edge missing direction", "Each edge must have a direction (forward, backward, bi-directional)"],
|
||||
"NO_RUNWAY_ROUTE": ["No way from parking to each runway", "There must be a route from each parking to each runway."],
|
||||
"NO_PARKING_ROUTE": ["No way from runway to each parking", "There must be a route from each runway to each parking."],
|
||||
"NO_PARKINGS": ["No parkings", ""],
|
||||
"NO_RUNWAYNODES": ["No Runwaynodes", ""],
|
||||
"NO_RUNWAY_NODES": ["No Runwaynodes", "Fine for parking only"],
|
||||
"NOT_LEGIT_END": ["Node not a legimate end", "Taxiroutes must end either at a parking or on a runway"],
|
||||
"UNKNOWN_RADIUS" :["Unknown radius", "Radii must be one from the list"],
|
||||
"OVERLAPPING_PARKINGS" :["Overlapping parkings", ""],
|
||||
"NAME_EMPTY" :["Name empty", ""],
|
||||
"TYPE_EMPTY" :["Parking type empty", ""],
|
||||
"PARKING_TYPE_INVALID" :["Parking type not valid", ""],
|
||||
"OVERLAPPING_PARKINGS" :["Overlapping parkings", "Parkings must not overlap"],
|
||||
"NAME_EMPTY" :["Name empty", "Name of parking must not be empty"],
|
||||
"TYPE_EMPTY" :["Parking type empty", "The parking type must not be empty"],
|
||||
"PARKING_TYPE_INVALID" :["Parking type not valid", "The type of parking must be one of ()"],
|
||||
"DUAL_PUSHBACK": ["Dual runway/ pushback node", "A runway node can not be a hold node at the same time"],
|
||||
"RUNWAY_NODE_NOT_ON_RUNWAY" : ["Runwaynode not on runway", ""],
|
||||
"NON_RUNWAYNODE_ON_RUNWAY": ["Non Runwaynode on runway", ""],
|
||||
"PARKINGS_VALID": ["Parkings valid", ""],
|
||||
"NO_OVERLAPPING_PARKINGS": ["No parkings overlapping", ""],
|
||||
"RUNWAY_NODE_NOT_ON_RUNWAY" : ["Runwaynode not in takeoff pad", ""],
|
||||
"NON_RUNWAYNODE_ON_RUNWAY": ["Non Runwaynode in takeoff pad", ""],
|
||||
"PARKINGS_VALID": ["Parkings valid", "All Ok"],
|
||||
"NO_OVERLAPPING_PARKINGS": ["No parkings overlapping", "Parking positions may not overlap. Reduce the radius or move."],
|
||||
"NO_INVALID_ENDS": ["No invalid ends", ""],
|
||||
"ROUTES_FROM_PARKINGS_OK": ["Routes from parkings OK", ""],
|
||||
"ROUTES_FROM_RUNWAYS_OK": ["Routes from runways OK", ""],
|
||||
"PUSHBACK_ROUTES_OK": ["Pushback routes OK", ""],
|
||||
"UNCONNECTED_PUSHBACK": ["Unconnected Pushbacknode", ""],
|
||||
"NO_WAY_TO_HOLDPOINT":["No way to pushback holdpoint", ""],
|
||||
"MULTIPLE_PUSHBACK": ["Multiple connected pushback points", ""],
|
||||
"NO_WAY_TO_HOLDPOINT":["No way to pushback holdpoint", "There is no route from the parking to the pushback hold point-"],
|
||||
"MULTIPLE_PUSHBACK": ["Multiple connected pushback points", "There are more than one possible pushback holdpoint routes."],
|
||||
"PUSHBACK_NOT_CONNECTED": ["Pushback Holding Point not Connected to Pushback Route", ""],
|
||||
"TO_MANY_PUSHBACK_TAXI_ROUTES": ["Too many Taxi routes from Pushback Holding Point", ""],
|
||||
"TO_MANY_PUSHBACK_TAXI_ROUTES": ["Too many Taxi routes from Pushback Holding Point", "There must be only one pushback point reachable from the parking."],
|
||||
"PUSHBACK_EXIT_NOT_BIDRECTIONAL": ["Pushback Holding Point Exit route is not bidirectional", ""],
|
||||
"NO_EDGES": ["No Edges", "No checks are run if there are no edges present"],
|
||||
"NO_RUNWAYS": ["No Runways", "No checks are run if there are no runways present. APT layer visible?"]
|
||||
"NO_RUNWAYS": ["No Runways", "No checks are run if there are no runways present. APT layer visible?"],
|
||||
"DOUBLE_EDGE": ["No Double Edges", "This edge is doubled"]
|
||||
}
|
||||
@@ -1,29 +1,40 @@
|
||||
var util = require("util");
|
||||
/* eslint-disable no-unused-vars */
|
||||
var util = require('util');
|
||||
|
||||
const d = new Date();
|
||||
|
||||
const fName = 'scan_' + d.getFullYear()
|
||||
+ d.getMonth()
|
||||
+ d.getDay()
|
||||
+ d.getHours()
|
||||
+ d.getMinutes()
|
||||
+ d.getSeconds()
|
||||
+ d.getMilliseconds() + '.log';
|
||||
const fName = 'scan_' + d.getFullYear() +
|
||||
d.getMonth() +
|
||||
d.getDay() +
|
||||
d.getHours() +
|
||||
d.getMinutes() +
|
||||
d.getSeconds() +
|
||||
d.getMilliseconds() + '.log';
|
||||
|
||||
var logStream = null;
|
||||
|
||||
var loggerInit = function (logging) {
|
||||
if (logging) {
|
||||
logStream = require('fs').createWriteStream( fName, {autoClose: true});
|
||||
try {
|
||||
const homedir = require('os').homedir();
|
||||
const logFileName = require('path').join(homedir, fName);
|
||||
logStream = require('fs').createWriteStream( logFileName, {autoClose: true});
|
||||
} catch (error) {
|
||||
console.error('Logging not possible ' + error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var logger = function (level, msg, o) {
|
||||
var d = new Date();
|
||||
if(logStream!==null) {
|
||||
var d = new Date();
|
||||
try {
|
||||
if (logStream !== null) {
|
||||
logStream.write(d.toUTCString() + '|' + level + ' | ' + msg + '\r\n');
|
||||
}
|
||||
if (o != undefined && logStream!==null) {
|
||||
logStream.write( util.inspect(o,{depth: 2}) + '\r\n');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Logging not possible ' + error);
|
||||
}
|
||||
}
|
||||
174
static/tower.svg
174
static/tower.svg
@@ -1,6 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
@@ -9,40 +7,15 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 16.933333 16.933334"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.1 r15371"
|
||||
sodipodi:docname="tower.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="12.8125"
|
||||
inkscape:cx="31.843902"
|
||||
inkscape:cy="32"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1013"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4489" />
|
||||
</sodipodi:namedview>
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||
sodipodi:docname="FGA Tower Icon.svg"
|
||||
viewBox="0 0 248.26501 249.26443"
|
||||
height="32"
|
||||
width="32"
|
||||
id="svg833"
|
||||
version="1.1">
|
||||
<metadata
|
||||
id="metadata5">
|
||||
id="metadata839">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
@@ -53,26 +26,121 @@
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs837" />
|
||||
<sodipodi:namedview
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:cy="131.18309"
|
||||
inkscape:cx="130.09189"
|
||||
inkscape:zoom="2.8284272"
|
||||
fit-margin-bottom="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-top="0"
|
||||
showgrid="false"
|
||||
id="namedview835"
|
||||
inkscape:window-height="1361"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
guidetolerance="10"
|
||||
gridtolerance="10"
|
||||
objecttolerance="10"
|
||||
borderopacity="1"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
inkscape:document-rotation="0"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-global="true" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Background" />
|
||||
<g
|
||||
transform="translate(7.706459,7.9160461)"
|
||||
inkscape:label="Headset"
|
||||
id="layer1"
|
||||
transform="translate(0,-280.06665)">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.47822458px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0.37724475,288.43079 3.66477855,-8.09956 h 8.9225597 l 3.569025,8.20209 -3.569025,8.20208 H 4.0420233 Z"
|
||||
id="path4487"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 2.6458333,288.53332 2.9104166,-5.55625 h 5.8208331 l 2.645833,5.55625 -2.381249,5.82083 H 5.2916666 Z"
|
||||
id="path4503"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 7.6729166,286.94582 -0.79375,1.5875 0.79375,1.32291 h 1.5875 l 0.7937504,-1.32291 -0.7937504,-1.5875 z"
|
||||
id="path4505"
|
||||
inkscape:connector-curvature="0" />
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="g962">
|
||||
<circle
|
||||
r="124.1325"
|
||||
cy="116.21645"
|
||||
cx="116.42604"
|
||||
id="path1622"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="sccsccs"
|
||||
d="m 88.489103,214.89893 c 0,-5.21922 4.23103,-9.45026 9.450184,-9.45033 l 36.986813,-6e-5 c 5.20585,0 9.43688,4.23103 9.43688,9.45026 0,5.21922 -4.23103,9.45026 -9.43688,9.45012 l -36.986813,7e-5 c -5.219154,2e-4 -9.450184,-4.23083 -9.450184,-9.45006 z"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#00a8b2;stroke-width:0.0994765;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path849-5" />
|
||||
<g
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
transform="translate(-3.4175518e-4)"
|
||||
id="g1992">
|
||||
<path
|
||||
id="path849-5-5"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#00a8b2;stroke-width:0.150978;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 226.14123,79.658933 c -7.92132,0 -14.34375,6.421246 -14.34375,14.322266 v 56.134771 c 1e-4,7.92121 6.42243,14.34377 14.34375,14.34375 1.77942,0 3.47461,-0.33935 5.04687,-0.93164 a 124.1325,124.1325 0 0 0 9.29492,-43.01367 v -8.59961 a 124.1325,124.1325 0 0 0 -4.2207,-28.076179 c -2.59403,-2.582096 -6.16991,-4.179688 -10.12109,-4.179688 z" />
|
||||
<path
|
||||
id="path849-5-5-8"
|
||||
style="fill:#000000;fill-opacity:1;stroke:#00a8b2;stroke-width:0.150978;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 6.711542,79.658933 c -3.950201,0 -7.5252386,1.596784 -10.1191409,4.177734 A 124.1325,124.1325 0 0 0 -7.6302551,111.8855 v 8.66211 a 124.1325,124.1325 0 0 0 9.2949219,42.98047 c 1.5722702,0.59229 3.2674492,0.93164 5.0468752,0.93164 7.92132,0 14.34406,-6.42254 14.34375,-14.34375 V 93.981199 c 2.1e-4,-7.901011 -6.42245,-14.322266 -14.34375,-14.322266 z" />
|
||||
</g>
|
||||
<g
|
||||
id="g916"
|
||||
style="stroke:#00989a;stroke-opacity:1">
|
||||
<path
|
||||
id="rect1605"
|
||||
style="fill:none;fill-opacity:1;stroke:#00989a;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 53.844354,143.81714 v 79.60352 a 124.1325,124.1325 0 0 0 62.582026,16.92773 124.1325,124.1325 0 0 0 63.28907,-17.34766 v -79.18359 z" />
|
||||
<polygon
|
||||
style="fill:#00989a;fill-opacity:1;stroke:#00989a;stroke-opacity:1"
|
||||
id="polygon986"
|
||||
points="89.486,243.876 71.941,139.481 26.677,139.481 61.767,243.876 "
|
||||
transform="matrix(0.75835957,0,0,0.75835957,6.0968618,-47.492855)" />
|
||||
<polygon
|
||||
style="fill:#00989a;fill-opacity:1;stroke:#00989a;stroke-opacity:1"
|
||||
id="polygon988"
|
||||
points="151.484,139.481 151.484,243.876 189.314,243.876 206.859,139.481 "
|
||||
transform="matrix(0.75835957,0,0,0.75835957,6.0968618,-47.492855)" />
|
||||
<polygon
|
||||
style="fill:#00989a;fill-opacity:1;stroke:#00989a;stroke-opacity:1"
|
||||
id="polygon990"
|
||||
points="84.109,139.481 101.654,243.876 139.484,243.876 139.484,139.481 "
|
||||
transform="matrix(0.75835957,0,0,0.75835957,6.0968618,-47.492855)" />
|
||||
<polygon
|
||||
style="fill:#00989a;fill-opacity:1;stroke:#00989a;stroke-opacity:1"
|
||||
id="polygon992"
|
||||
points="201.482,243.876 229.201,243.876 264.291,139.481 219.027,139.481 "
|
||||
transform="matrix(0.75835957,0,0,0.75835957,6.0968618,-47.492855)" />
|
||||
<rect
|
||||
y="42.483017"
|
||||
x="44.615604"
|
||||
height="9.8302555"
|
||||
width="143.62088"
|
||||
id="rect1605-7"
|
||||
style="fill:#00989a;fill-opacity:1;stroke:#00989a;stroke-width:2.50089;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
id="path1761"
|
||||
d="m 221.22133,163.59357 c -16.80353,25.19128 -43.642,43.64367 -76.66957,51.11645"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path913"
|
||||
d="M 6.8856252,81.848629 C 21.611214,33.687043 66.066978,0.7936943 116.42946,0.79583065 c 50.36251,0.00213 94.81547,32.89923835 109.537,81.06206135"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 6.6 KiB |
Reference in New Issue
Block a user