Compare commits
310 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4363dd2a6 | ||
|
|
92009bfce0 | ||
|
|
98b92ef308 | ||
|
|
5fc343a7c1 | ||
|
|
92f0b72456 | ||
|
|
5c01f2a656 | ||
|
|
956e347517 | ||
|
|
5aa33c6814 | ||
|
|
a9b2558cf2 | ||
|
|
0bb3021e3c | ||
|
|
8274fb882e | ||
|
|
9e82084e52 | ||
|
|
edf0e23f8b | ||
|
|
f4bc2f47ce | ||
|
|
91c1d93fd3 | ||
|
|
3a9c1cd3c2 | ||
|
|
a43a6c476b | ||
|
|
56284283bf | ||
|
|
41376bb130 | ||
|
|
e13127de4b | ||
|
|
60903eb3e5 | ||
|
|
e8b0c3c923 | ||
|
|
d0361b0e76 | ||
|
|
9c5f7f58f7 | ||
|
|
062dec2303 | ||
|
|
5130503153 | ||
|
|
7c57323daf | ||
|
|
71c8a6f8e0 | ||
|
|
eeaaca03f4 | ||
|
|
0f9f95c09d | ||
|
|
300d243ef8 | ||
|
|
bf8f7002ae | ||
|
|
dbb60162a7 | ||
|
|
715f3c968e | ||
|
|
0146ee8623 | ||
|
|
4d5a4f4ff7 | ||
|
|
217d3d7a8e | ||
|
|
939322471d | ||
|
|
2ff284df5c | ||
|
|
67c8814691 | ||
|
|
a1fca579af | ||
|
|
63e08cacbf | ||
|
|
54fc153feb | ||
|
|
dc480ad25d | ||
|
|
7c8cc0e705 | ||
|
|
00132e46fb | ||
|
|
0172b49450 | ||
|
|
ec718a54ff | ||
|
|
07b9d3efee | ||
|
|
a2bd53637b | ||
|
|
8a328a1707 | ||
|
|
02433ac77c | ||
|
|
0499ee82c2 | ||
|
|
2178061b55 | ||
|
|
c569e45a6e | ||
|
|
1075e8d466 | ||
|
|
ed35aab63b | ||
|
|
febd720588 | ||
|
|
93a5c954e5 | ||
|
|
d6acedb384 | ||
|
|
6770b52f89 | ||
|
|
9fe7322c7b | ||
|
|
c26c123088 | ||
|
|
d3d4d91faf | ||
|
|
30d6bce2d8 | ||
|
|
3ecace714e | ||
|
|
a52b3c3b67 | ||
|
|
a4f00b8a22 | ||
|
|
9f1420309b | ||
|
|
a28c7cdddf | ||
|
|
df28183232 | ||
|
|
ec03754c95 | ||
|
|
4fac546e90 | ||
|
|
6f3b1dd936 | ||
|
|
9865ce0e9e | ||
|
|
a7fb534c2e | ||
|
|
82f88d159b | ||
|
|
d61dc7c955 | ||
|
|
d372170fe9 | ||
|
|
7e032e73b2 | ||
|
|
d4aa4b09a0 | ||
|
|
79631004f8 | ||
|
|
29355c63da | ||
|
|
176fbeed08 | ||
|
|
6c052c16e2 | ||
|
|
d6f1204dd1 | ||
|
|
9a8e03f9cf | ||
|
|
8b360beaf1 | ||
|
|
9dfd4320fe | ||
|
|
dc874ff9f5 | ||
|
|
bed38277ce | ||
|
|
4c01775ccf | ||
|
|
8a167dc991 | ||
|
|
d9ab69a29e | ||
|
|
a71d95cb74 | ||
|
|
760c7e4fd0 | ||
|
|
70926ed2ff | ||
|
|
4b7183c428 | ||
|
|
8fcd1f64fb | ||
|
|
64685aa1d1 | ||
|
|
fad6b3de84 | ||
|
|
3c315c4f0c | ||
|
|
3cc8f1e34a | ||
|
|
3416333b42 | ||
|
|
6de8d22381 | ||
|
|
87750d0826 | ||
|
|
ba1fa6cb4f | ||
|
|
8a646490c8 | ||
|
|
921321d3b0 | ||
|
|
7a75e4f392 | ||
|
|
af4d3b7143 | ||
|
|
463c6d9feb | ||
|
|
05a54a2d2f | ||
|
|
233362b2fa | ||
|
|
ec9b5be879 | ||
|
|
234ec5eb69 | ||
|
|
d9cc35f2c2 | ||
|
|
78f86d41ee | ||
|
|
b4003c3c06 | ||
|
|
72dc611764 | ||
|
|
57b83daa51 | ||
|
|
94779a1686 | ||
|
|
b9a34df117 | ||
|
|
7b7afb357b | ||
|
|
1d048c0d28 | ||
|
|
98ff3a92aa | ||
|
|
594b4f5411 | ||
|
|
71432255f5 | ||
|
|
38c380a433 | ||
|
|
1463427b97 | ||
|
|
952d2834b0 | ||
|
|
eea409a087 | ||
|
|
afc0790b81 | ||
|
|
a05c96be61 | ||
|
|
d5071c4333 | ||
|
|
cb5e641bbc | ||
|
|
7191b41dc6 | ||
|
|
d18cfed7e9 | ||
|
|
29d02be3ad | ||
|
|
484d0673c1 | ||
|
|
5287576c9c | ||
|
|
0387719195 | ||
|
|
df6501d06e | ||
|
|
a28f7d685d | ||
|
|
4503bf3dba | ||
|
|
70dddc2299 | ||
|
|
c8fdec8cb5 | ||
|
|
3a22487fb9 | ||
|
|
e4f2a62224 | ||
|
|
0acc30fa18 | ||
|
|
5058cc705b | ||
|
|
399b567497 | ||
|
|
bc8a99a996 | ||
|
|
589d7c28d8 | ||
|
|
fe7fbd433e | ||
|
|
8394e46add | ||
|
|
d8438c331a | ||
|
|
2515649b55 | ||
|
|
01f3db55dd | ||
|
|
55df912131 | ||
|
|
a9019340a4 | ||
|
|
c221699b16 | ||
|
|
4b1ee70da5 | ||
|
|
063fd049f0 | ||
|
|
b841b8560d | ||
|
|
50e3806d12 | ||
|
|
2f50bf1782 | ||
|
|
4923b467f4 | ||
|
|
e122bbbb08 | ||
|
|
474e8bf113 | ||
|
|
77bf06f764 | ||
|
|
33421e5aab | ||
|
|
bd7530a9a1 | ||
|
|
fb4d518c6c | ||
|
|
ac0879b7b8 | ||
|
|
dea6a9bf19 | ||
|
|
d4c0e59779 | ||
|
|
3f9183439f | ||
|
|
228f16994b | ||
|
|
d9eed59de7 | ||
|
|
32c0cbd33b | ||
|
|
46091aa7db | ||
|
|
743b5c6e8d | ||
|
|
0f890d1593 | ||
|
|
3aea131727 | ||
|
|
66687bb35f | ||
|
|
23cc742c93 | ||
|
|
2a7c8a735f | ||
|
|
93d6328dea | ||
|
|
7c643b209a | ||
|
|
9a3f473949 | ||
|
|
37e97e84e2 | ||
|
|
4090519e51 | ||
|
|
9f381dea12 | ||
|
|
e3da808f5c | ||
|
|
d80a308f4d | ||
|
|
c144aab56c | ||
|
|
294abffcc4 | ||
|
|
3ee9ec60e3 | ||
|
|
7142373c2a | ||
|
|
1f395e2157 | ||
|
|
315cb8b1f0 | ||
|
|
7f9c5b5457 | ||
|
|
eb69b0cdb2 | ||
|
|
49165227af | ||
|
|
0938ab8780 | ||
|
|
f3703d1ef8 | ||
|
|
26726df251 | ||
|
|
fc25b62737 | ||
|
|
503dacd54a | ||
|
|
07042d92e7 | ||
|
|
f9f9256ffe | ||
|
|
3b9ab26035 | ||
|
|
00bdd6c558 | ||
|
|
de0267ac7d | ||
|
|
079a56abfd | ||
|
|
a4d048c116 | ||
|
|
6e87c3428b | ||
|
|
b06b1b6a03 | ||
|
|
9ce9e54c26 | ||
|
|
d8093c323c | ||
|
|
8d13cf3d35 | ||
|
|
be078ecced | ||
|
|
d8ad1ffcc4 | ||
|
|
c7fae2427a | ||
|
|
ffc7109ea5 | ||
|
|
2ec5ab4512 | ||
|
|
f312dc5998 | ||
|
|
ad8bc5d3f3 | ||
|
|
94b3e8995e | ||
|
|
b4ba826fd3 | ||
|
|
2713d2cbfa | ||
|
|
0a112fe76a | ||
|
|
ead320bdb5 | ||
|
|
da9c89d762 | ||
|
|
59d58b05ab | ||
|
|
cb2f9c69ab | ||
|
|
eaae16c291 | ||
|
|
0756f377b3 | ||
|
|
fb72f8d760 | ||
|
|
90740751dd | ||
|
|
e08238c64d | ||
|
|
4cc5e1913d | ||
|
|
bd0e45440c | ||
|
|
4d87ac16b8 | ||
|
|
9065ae75f9 | ||
|
|
af2578cc36 | ||
|
|
98c29b8b62 | ||
|
|
4b908f57ce | ||
|
|
826781647e | ||
|
|
304269b996 | ||
|
|
05318a7782 | ||
|
|
7092441d3b | ||
|
|
677695d0ba | ||
|
|
4c76d30010 | ||
|
|
41214581fd | ||
|
|
a4baeee2ea | ||
|
|
70a0f5a7de | ||
|
|
2956bfbddb | ||
|
|
3a6fdab354 | ||
|
|
fd15052c1c | ||
|
|
28dd9a1b63 | ||
|
|
1af687fd2c | ||
|
|
69a0e849a6 | ||
|
|
cb8a49fc9d | ||
|
|
61d9145dd8 | ||
|
|
1650b44628 | ||
|
|
26a935997b | ||
|
|
ffc8d76d1f | ||
|
|
5be00f012f | ||
|
|
2d5f2f0063 | ||
|
|
f515d6249f | ||
|
|
bf59d025f6 | ||
|
|
d5f68613a1 | ||
|
|
4b564798ab | ||
|
|
1e43d973b2 | ||
|
|
0870422875 | ||
|
|
c7ebaccb3f | ||
|
|
41463dedff | ||
|
|
ebf82c09e9 | ||
|
|
a4239d385b | ||
|
|
821da07c4e | ||
|
|
3c98a0720b | ||
|
|
686cabb635 | ||
|
|
4ed58fc7fa | ||
|
|
62f24201b2 | ||
|
|
918cfd750c | ||
|
|
6d6c065793 | ||
|
|
ec629a7ef4 | ||
|
|
ffca8da053 | ||
|
|
c2b0fe2a7b | ||
|
|
1f6fc221f9 | ||
|
|
84989714e5 | ||
|
|
45980c3abe | ||
|
|
43f8aeb9d6 | ||
|
|
7d6be33150 | ||
|
|
56e23da410 | ||
|
|
fe1db57414 | ||
|
|
62823feedd | ||
|
|
aba6ac6df5 | ||
|
|
5f60c46dc9 | ||
|
|
06f630afab | ||
|
|
76db33a686 | ||
|
|
2f86bed0bf | ||
|
|
9eb92fb13d | ||
|
|
ae680eb994 | ||
|
|
034c132347 | ||
|
|
8fccc23009 | ||
|
|
a76f7d6209 | ||
|
|
b4206d3a53 |
@@ -125,6 +125,18 @@ let rendererConfig = {
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: path.resolve(__dirname, '../src/index.ejs'),
|
||||
templateParameters(compilation, assets, options) {
|
||||
return {
|
||||
compilation: compilation,
|
||||
webpack: compilation.getStats().toJson(),
|
||||
webpackConfig: compilation.options,
|
||||
htmlWebpackPlugin: {
|
||||
files: assets,
|
||||
options: options
|
||||
},
|
||||
process,
|
||||
};
|
||||
},
|
||||
minify: {
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true,
|
||||
|
||||
@@ -97,7 +97,18 @@ let webConfig = {
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: path.resolve(__dirname, '../src/index.ejs'),
|
||||
minify: {
|
||||
templateParameters(compilation, assets, options) {
|
||||
return {
|
||||
compilation: compilation,
|
||||
webpack: compilation.getStats().toJson(),
|
||||
webpackConfig: compilation.options,
|
||||
htmlWebpackPlugin: {
|
||||
files: assets,
|
||||
options: options
|
||||
},
|
||||
process,
|
||||
};
|
||||
}, minify: {
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true,
|
||||
removeComments: true
|
||||
|
||||
92
.travis.yml
@@ -1,32 +1,86 @@
|
||||
osx_image: xcode8.3
|
||||
sudo: required
|
||||
dist: trusty
|
||||
dist: xenial
|
||||
language: node_js
|
||||
node_js:
|
||||
- 10.15.3
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
- os: windows
|
||||
- os: linux
|
||||
workspaces:
|
||||
use:
|
||||
- binaries
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
- "$HOME/.electron"
|
||||
- "$HOME/.cache"
|
||||
- "$HOME/.cache"
|
||||
addons:
|
||||
before_install:
|
||||
install:
|
||||
- source ~/.bashrc
|
||||
- npm install -g xvfb-maybe
|
||||
- npm install
|
||||
script:
|
||||
- npm run build
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: Xm3z86gQmpSajvlXSVgG7mxcaS5K7GfE4HrARIDR4pQ4UguQ3/fFOenRyKAQImmH0kLCSIbVE21NMAQ3YI2F9El9I6GU7Wirccsg14TZZiBQAzKOTXZ+JsBloeBxuTOsR84SkO6pV8OT/pRnQd9frqyc1W7wzoX+0sQykMztXCNfI+1MXXGOAgMzlKuDMO1PVENz0V63mWipL/Mae/SyrHa1Bws+4LJKvv42m0HMKdN7ekt41vxcSUvLmN+YLlqUEVr/eUhQXUNCaWlmM0KxmfuzTedca5/1yzLvN8smEt2I2b0DFRM3Mi/QdI22fVRHs6XGpm8yqZRKmhySDXFspXKWBiuCF6AezX6NiIe/ZUh10gIukjkyLtrNk/o29qhj2WE9HJz4xhsGMAx3632cLSMPku5ALN7jv5scWjwCGNHs4ZeZyyePMeGM6Y6pje1uJPbxWGjwoV6iI4Y4esP+z3KcXvZdnzkpYMy2mzdT4gf7A7zieax1YwB6U/MEanXYKFBH4yzYK9+hx3ck2eLT3LcV/ChHN2bKmERJdf18h+zI8e5YKTzd3/kHLiUUv19N2a4TUYloGOyzrLwn2VD1Xm4jJVVLTIQvWbH5YK7cNkHYa4+PnsB+JppSoby7HiBcothw4OLpJO8eCMqXcPRU1n+cRAZTB7VOS7pWh8e8LFE=
|
||||
file: build/flightgear-airports*.*
|
||||
draft: true
|
||||
on:
|
||||
repo: Portree-Kid/flightgear-airports
|
||||
node_js:
|
||||
- 10.15.3
|
||||
jobs:
|
||||
include:
|
||||
- stage: Build binaries
|
||||
os: windows
|
||||
script:
|
||||
- npm run build
|
||||
- mkdir windows-binaries
|
||||
- mv -v build/flightgear-airports* windows-binaries/
|
||||
- ls -l windows-binaries
|
||||
workspaces:
|
||||
create:
|
||||
name: windows-binaries
|
||||
paths: windows-binaries
|
||||
- os: linux
|
||||
script:
|
||||
- npm run build
|
||||
- mkdir linux-binaries
|
||||
- mv -v build/flightgear-airports* linux-binaries/
|
||||
- ls -l linux-binaries
|
||||
workspaces:
|
||||
create:
|
||||
name: linux-binaries
|
||||
paths: linux-binaries
|
||||
- os: osx
|
||||
script:
|
||||
- npm run build
|
||||
- mkdir osx-binaries
|
||||
- mv -v build/flightgear-airports* osx-binaries/
|
||||
- ls -l osx-binaries
|
||||
workspaces:
|
||||
create:
|
||||
name: osx-binaries
|
||||
paths: osx-binaries
|
||||
- stage: Deploy
|
||||
install:
|
||||
- pwd
|
||||
- tar -xzf ${CASHER_DIR}/osx-binaries-fetch.tgz
|
||||
- find -name flightgear-airports*
|
||||
# - find -name windows-binaries
|
||||
# - find -name osx-binaries
|
||||
# - find -name linux-binaries
|
||||
# - ls -l | grep "^d"
|
||||
# - ls -l "C:"
|
||||
- cp ./Users/travis/build/Portree-Kid/flightgear-airports/osx-binaries/*.dmg build/
|
||||
- cp ./C:/Users/travis/build/Portree-Kid/flightgear-airports/windows-binaries/*.exe build/
|
||||
- cp ./linux-binaries/*.AppImage build/
|
||||
- ls -l "build/"
|
||||
script: skip
|
||||
workspaces:
|
||||
use:
|
||||
- windows-binaries
|
||||
- linux-binaries
|
||||
- osx-binaries
|
||||
deploy:
|
||||
skip_cleanup: true
|
||||
overwrite: true
|
||||
draft: true
|
||||
name: '0.0.28'
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: JnHZdzg4AsEcRn4uQkn15ELd8KqSQBgC3cOPRAEFVsOCRhh8aH8WFwAG0uZIjwU1F4qinK0sAayYllc5WrjHZ4/93FNDES3H4hEE1K3WDXG0cVxAt1JiDWVq6meEQWKRNO8zoT4aZa6vigOQhnaS5PE3KcdsaD5N6tkHxI+W7a4qBIUtbMjceKSFVDflJLLBWmMibuQ1JZ9gT1FES4yN18wj/bMM8x8V3xM6m7FPKfiVtnD0IpJKYNDVPQOdw7nJpzvVIzYVEgUTiRY2nVbslJkB8Lllh6zAC4B5vc8UTACf/S+j2z1ofAGajY8x8b0K3UDhg7b7vfTmPpmTJl1ZBGB5scyhRDneIOMr15QiAyKfStHpwdCz8MLV7H/tugPM348riT+JqecARjk/rIgc18/tL6lKQA4P4FG4mGp5s+eq+AAg2fdhyj7rL6kLw+z5J9170ch+ot7Ju6BUJVmvRAWxAg+yXCzyKdfen8RL+R7tdwJ0nFawtnkxwwZwLnr0792mchjl4JK+Q0sEb5J8DmBR1WVL+L3TN6G9HwUrFsm2eVCHAi0k5ExJLYoHV54kg+7uD8upACh3LRFIIFcvQWu52a7VTTwY+5Gsz91o8sAcJImo4E8Ii0wmFhcDPQ3HHa1dUGOofhpMcgPG15lsgdumUeulPz6fUQ3IxzBc8Uo=
|
||||
file_glob: true
|
||||
file: build/*
|
||||
on:
|
||||
branches: '0.0.28'
|
||||
repo: Portree-Kid/flightgear-airports
|
||||
|
||||
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"C_Cpp.default.configurationProvider": "go2sh.cmake-integration"
|
||||
}
|
||||
13
I.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
I
|
||||
1050 Generated by WorldEditor 2.0.0r4
|
||||
|
||||
1 0 1 0 ABCD BezierTest
|
||||
120 Linear Feature 4
|
||||
111 58.21662712 -005.33381019
|
||||
116 58.21536335 -005.33388344 58.21539229 -005.33536672
|
||||
120 Linear Feature 2
|
||||
111 58.21649206 -005.33161294
|
||||
112 58.21619300 -005.33166788 58.21620265 -005.33296805
|
||||
112 58.21572029 -005.33166789 58.21573959 -005.33263844
|
||||
115 58.21535371 -005.33172282
|
||||
99
|
||||
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 9.0 KiB |
8
build/installer.nsh
Normal file
@@ -0,0 +1,8 @@
|
||||
!macro preInit
|
||||
SetRegView 64
|
||||
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$PROGRAMFILES64\flightgear-airports"
|
||||
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$PROGRAMFILES64\flightgear-airports"
|
||||
SetRegView 32
|
||||
WriteRegExpandStr HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation "$PROGRAMFILES32\flightgear-airports"
|
||||
WriteRegExpandStr HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation "$PROGRAMFILES32\flightgear-airports"
|
||||
!macroend
|
||||
693
package-lock.json
generated
47
package.json
@@ -1,16 +1,15 @@
|
||||
{
|
||||
"name": "flightgear-airports",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.28",
|
||||
"author": "portree_kid <keith.paterson@gmx.de>",
|
||||
"description": "An software to design Flightgear groundnets",
|
||||
"license": null,
|
||||
"license": "GPL v3",
|
||||
"main": "./dist/electron/main.js",
|
||||
"scripts": {
|
||||
"build": "node .electron-vue/build.js && electron-builder",
|
||||
"build:dir": "node .electron-vue/build.js && electron-builder --dir",
|
||||
"build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
|
||||
"build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
|
||||
"dev": "node .electron-vue/dev-runner.js",
|
||||
"dev": "SET NODE_ENV=development&& node .electron-vue/dev-runner.js",
|
||||
"e2e": "npm run pack && mocha test/e2e",
|
||||
"lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src test",
|
||||
"lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter --fix src test",
|
||||
@@ -18,6 +17,7 @@
|
||||
"pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
|
||||
"pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
|
||||
"test": "npm run unit && npm run e2e",
|
||||
"mocha": "SET NODE_ENV=mocha&& mocha test/mocha/**/*.js",
|
||||
"unit": "karma start test/unit/karma.conf.js",
|
||||
"postinstall": ""
|
||||
},
|
||||
@@ -35,7 +35,22 @@
|
||||
"filter": [
|
||||
"**/*"
|
||||
]
|
||||
}],
|
||||
},
|
||||
{
|
||||
"from": "node_modules/dijkstrajs",
|
||||
"to": "workers",
|
||||
"filter": [
|
||||
"**/dijkstra.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"from": "node_modules/@turf",
|
||||
"to": "workers/node_modules/@turf",
|
||||
"filter": [
|
||||
"**"
|
||||
]
|
||||
}
|
||||
],
|
||||
"files": [
|
||||
"dist/electron/**/*"
|
||||
],
|
||||
@@ -60,19 +75,26 @@
|
||||
"win": {
|
||||
"icon": "build/icons/icon.ico"
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"linux": {
|
||||
"icon": "build/icons"
|
||||
"icon": "build/icons",
|
||||
"target": "AppImage"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@turf/intersect": "^6.1.3",
|
||||
"@turf/turf": "^5.1.6",
|
||||
"axios": "^0.18.0",
|
||||
"axios": "^0.18.1",
|
||||
"coordinate-parser": "^1.0.3",
|
||||
"dijkstrajs": "^1.0.1",
|
||||
"electron-debug": "^3.0.1",
|
||||
"element-ui": "^2.12.0",
|
||||
"element-ui": "^2.13.2",
|
||||
"file-url": "^3.0.0",
|
||||
"fs": "0.0.1-security",
|
||||
"geo-coordinates-parser": "^1.2.3",
|
||||
"geo-coordinates-parser": "^1.2.4",
|
||||
"geodesy": "^2.2.0",
|
||||
"idb": "^4.0.5",
|
||||
"jquery": "^3.4.1",
|
||||
@@ -84,6 +106,7 @@
|
||||
"lokijs": "^1.5.8",
|
||||
"mathjs": "^6.2.5",
|
||||
"path": "^0.12.7",
|
||||
"tiny-worker": "^2.3.0",
|
||||
"vue": "^2.5.16",
|
||||
"vue-electron": "^1.0.6",
|
||||
"vue-idb": "^0.2.0",
|
||||
@@ -112,14 +135,14 @@
|
||||
"babel-register": "^6.26.0",
|
||||
"babili-webpack-plugin": "^0.1.2",
|
||||
"cfonts": "^2.1.2",
|
||||
"chai": "^4.1.2",
|
||||
"chai": "^4.2.0",
|
||||
"chalk": "^2.4.1",
|
||||
"copy-webpack-plugin": "^4.5.1",
|
||||
"cross-env": "^5.1.6",
|
||||
"css-loader": "^0.28.11",
|
||||
"del": "^3.0.0",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "^4.2.12",
|
||||
"electron": "^7.2.4",
|
||||
"electron-builder": "^21.2.0",
|
||||
"electron-devtools-installer": "^2.2.4",
|
||||
"eslint": "^4.19.1",
|
||||
@@ -146,7 +169,7 @@
|
||||
"mocha": "^5.2.0",
|
||||
"multispinner": "^0.2.1",
|
||||
"node-loader": "^0.6.0",
|
||||
"node-sass": "^4.9.2",
|
||||
"node-sass": "^4.14.1",
|
||||
"require-dir": "^1.0.0",
|
||||
"sass-loader": "^7.0.3",
|
||||
"spectron": "^3.8.0",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<% if (htmlWebpackPlugin.options.nodeModules) { %>
|
||||
<!-- Add `node_modules/` to global paths so `require` works properly in development -->
|
||||
<script>
|
||||
require('module').globalPaths.push('<%= htmlWebpackPlugin.options.nodeModules.replace(/\\/g, '\\\\') %>')
|
||||
require('module').globalPaths.push('<%= htmlWebpackPlugin.options.nodeModules.replace(/\\/g, "\\\\") %>')
|
||||
</script>
|
||||
<% } %>
|
||||
</head>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
import { app, BrowserWindow } from 'electron'
|
||||
import { app, BrowserWindow, Menu } from 'electron'
|
||||
|
||||
const { ipcMain } = require('electron')
|
||||
ipcMain.on('OpenDebugger', (event, arg) => {
|
||||
mainWindow.webContents.openDevTools()
|
||||
})
|
||||
/**
|
||||
* Set `__static` path to static files in production
|
||||
* https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
|
||||
@@ -16,6 +20,7 @@ const winURL = process.env.NODE_ENV === 'development'
|
||||
: `file://${__dirname}/index.html`
|
||||
|
||||
function createWindow () {
|
||||
Menu.setApplicationMenu(null)
|
||||
/**
|
||||
* Initial window options
|
||||
*/
|
||||
@@ -29,7 +34,6 @@ function createWindow () {
|
||||
width: 1000
|
||||
})
|
||||
mainWindow.loadURL(winURL)
|
||||
mainWindow.webContents.openDevTools()
|
||||
|
||||
mainWindow.onerror = function (message, source, lineno, colno, error) {
|
||||
console.error(error)
|
||||
|
||||
2
src/renderer/assets/aircraft/FGA_ACT_A_GA.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="150mm" height="150mm" version="1.1" viewBox="0 0 150 150" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-1.6394e-5 -147)"><g transform="translate(-512.5 -153)"><path d="m587.5 347.75c-0.32736 0-0.75863 2.023-0.97757 3.043 0 0-8.7023-0.47356-8.7023 0.14107 0 0.61461 8.733 0.36873 8.733 0.36873 0.0812 0.14151 0.22163 0.15914 0.368 0.18528v0.21306c-0.57176 0.16009-1.4739 0.31231-2.5099 0.41186-1.036 0.0995-1.1332 0.93371-1.1332 0.93371-0.70455 4.8918-0.96276 10.026-1.2071 14.632-0.012 0.0118-0.0165 1.6e-4 -0.0369 9e-3l-20.112 2e-3 -27.221 1.9869c-2.1208 0.16639-2.2014 1.5529-2.2014 3.2272v8.0906l29.858 3.5196 19.67 0.0146c1.2567 9.6974 3.6713 28.109 3.6713 28.109l-12.803 2.1075c-0.75926 0.18181-1.8746 0.23703-2.1181 1.0313-0.3756 1.9795-0.35641 4.2182-0.24741 6.0605 0.0369 0.68858 0.16248 1.2114 0.8672 1.354l13.439 2.401c0.39078 0.0865 0.49893-0.13326 0.58873-0.48422l1.3408-4.2669s-0.081 7.3888 0.73272 9.0111c0.81369-1.6224 0.73271-9.0111 0.73271-9.0111l1.3412 4.2669c0.0898 0.35096 0.19795 0.57077 0.58874 0.48422l13.439-2.401c0.70472-0.14253 0.83032-0.6654 0.8672-1.354 0.10899-1.8424 0.12819-4.081-0.24741-6.0605-0.24351-0.79425-1.3589-0.84947-2.1181-1.0313l-12.803-2.1075s2.4149-18.412 3.6716-28.109l19.67-0.0146 29.859-3.5196v-8.0906c5.8e-4 -1.6743-0.081-3.0608-2.2018-3.2272l-27.221-1.9869-20.112-2e-3c-0.0204-9e-3 -0.0249 3e-3 -0.0369-9e-3 -0.2443-4.6057-0.50251-9.7399-1.2071-14.632 0 0-0.0972-0.83417-1.1332-0.93371-1.036-0.0996-1.9381-0.25177-2.5099-0.41186v-0.21307c0.14636-0.0262 0.28682-0.0438 0.368-0.18528 0 0 8.733 0.24589 8.733-0.36873s-8.7023-0.14106-8.7023-0.14106c-0.21894-1.0201-0.65058-3.0431-0.97793-3.0431zm0 9.0766c0.34605 0 0.71407-1.3e-4 0.71408 0.5394v2.36c0 0.54212-0.36803 0.54196-0.71408 0.54196-0.34606 0-0.7192 1.6e-4 -0.7192-0.54196v-2.36c-1e-5 -0.53953 0.37314-0.5394 0.7192-0.5394zm-12.73 16.475c0.34605 0 0.71407-1.3e-4 0.71407 0.5394v2.36c0 0.54211-0.36802 0.54196-0.71407 0.54196-0.34606 0-0.7192 1.5e-4 -0.7192-0.54196v-2.36c0-0.53953 0.37314-0.5394 0.7192-0.5394zm25.474 0c0.34606 0 0.71408-1.3e-4 0.71408 0.5394v2.36c0 0.54211-0.36802 0.54196-0.71408 0.54196-0.34605 0-0.71919 1.5e-4 -0.71919-0.54196v-2.36c-1e-5 -0.53953 0.37314-0.5394 0.71919-0.5394z" fill="#3296ff"/><circle cx="587.5" cy="375" r="74.595" fill="none" stroke="#3296ff" stroke-linecap="square" stroke-linejoin="round" stroke-width=".811" style="paint-order:normal"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
2
src/renderer/assets/aircraft/FGA_ACT_B_PROP.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="280mm" height="282.66mm" version="1.1" viewBox="0 0 280 282.66" xmlns="http://www.w3.org/2000/svg"><g transform="translate(35 -7.171)"><g transform="translate(-7.6294e-6 7.3444)"><g transform="matrix(4.5516 0 0 4.5516 -372.53 -527.39)" fill="#3296ff"><path transform="matrix(.26458 0 0 .26458 -7.9725e-5 4.7925e-5)" d="m396.53 449.99c-6.703 0-12.091 16.285-12.119 29.002l-0.17578 54.354-2.8828 7.209-14.512-0.18945c0.6477-4.764 1.2976-11.043-1.4473-15.457l-0.0469-1.3477 14.395 0.83985 0.16797-1.9668-14.578 0.97461c0-1.4239-1.0254-4.1602-2.3457-4.1602-1.4366 0-2.2472 2.4804-2.4375 4.1211l-14.088-1.1582-4e-3 2.4609 14.047-0.9668-0.1914 1.3164c-2.3109 4.8272-1.8613 10.199-0.92774 15.412-46.681 3.307-70.422 5.1355-71.252 5.2051-0.82972 0.0695-1.8463 0.90433-1.9707 2.293-0.0556 0.59954-0.16605 0.90065-0.33008 0.90039-0.16479-1e-3 -0.35633 0.0276-0.57422 0.082-0.21808 0.0533-0.43767 0.32575-0.6582 0.81641-0.67616 2.9741-0.27076 5.9302-0.0977 8.7734 0.0552 0.10885 12.16 0.73137 36.314 1.8672 24.156 1.1349 36.316 1.7029 36.48 1.7031 0.16403 3.7e-4 6.0384 0.17301 24.84 0.20703l2.123 5.0859c-0.0302 21.998 0.0965 58.62 7.0059 86.129-15.285 2.3628-23.055 3.6526-23.314 3.8594-2.0877 2.7596-2.3172 6.879-1.8203 9.998 0.0556 1e-3 4.4001 0.33632 13.033 1.0059l13.115 0.92578c0.10923-0.0544 1.4785-2.0469 1.4785-2.0469 0.21947 1.7517 0.2277 5.2639 2.7734 5.2676h2e-3c2.5457-4e-3 2.552-3.5159 2.7715-5.2676 0 0 1.3693 1.9924 1.4785 2.0469l13.115-0.92578c8.6331-0.66954 12.978-1.0047 13.033-1.0059 0.49693-3.119 0.26734-7.2384-1.8203-9.998-0.25928-0.20674-8.0293-1.4966-23.314-3.8594 6.9093-27.509 7.0361-64.131 7.0059-86.129l2.123-5.0859c18.801-0.034 24.678-0.20666 24.842-0.20703 0.16404-2.3e-4 12.323-0.56825 36.479-1.7031 24.155-1.1358 36.259-1.7583 36.314-1.8672 0.17311-2.8432 0.5785-5.7993-0.0976-8.7734-0.22035-0.49066-0.44013-0.76312-0.65821-0.81641-0.21807-0.0544-0.40943-0.0832-0.57421-0.082-0.16404 2.6e-4 -0.27257-0.30085-0.32813-0.90039-0.12435-1.3886-1.141-2.2234-1.9707-2.293-0.82972-0.0695-24.573-1.8981-71.254-5.2051 0.93358-5.2134 1.3832-10.585-0.92773-15.412l-0.19141-1.3164 14.047 0.9668-4e-3 -2.4609-14.088 1.1582c-0.19049-1.6407-1.0009-4.1211-2.4375-4.1211-1.3203 0-2.3457 2.7363-2.3457 4.1602l-14.576-0.97461 0.16602 1.9668 14.395-0.83985-0.0469 1.3477c-2.7449 4.4137-2.095 10.693-1.4473 15.457l-14.512 0.18945-2.8809-7.209-0.17578-54.354c0-12.782-5.4181-29.002-12.121-29.002zm-2.207 19.031h1.6133v4.8184h-1.6133zm2.8008 0h1.6133v4.8184h-1.6133zm-20.578 81.467h2.7774v7.1152h-2.7774zm3.8789 0h2.7773v7.1152h-2.7773zm29.434 0h2.7774v7.1152h-2.7774zm3.8789 0h2.7773v7.1152h-2.7773z" fill="#3296ff"/></g><circle cx="105" cy="139.83" r="139.18" fill="none" stroke="#3296ff" stroke-linecap="square" stroke-linejoin="round" stroke-width="1.6438" style="paint-order:normal"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
2
src/renderer/assets/aircraft/FGA_ACT_B_SHORTEN.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="280mm" height="311.54mm" version="1.1" viewBox="0 0 280 311.54" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-6.4969e-6 14.543)"><circle cx="140" cy="141.28" r="139.36" fill="none" stroke="#3296ff" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="4.3333" stroke-width="1.2759" style="paint-order:normal"/><path d="m152.63 24.911c-0.0267-25.744-10.66-39.454-12.634-39.454h1e-5c-1.9741 0-12.608 13.71-12.634 39.454l0.0182 79.957-1.6403 1.3481s-84.993 49.186-89.398 51.752-4.5756 5.1873-4.5756 5.1873-7.5179 14.841-7.7484 15.302c-0.23052 0.4615-0.27144 1.1507-0.27144 1.1507l0.1078 2.3443s6.6825-7.4591 6.8393-7.6432c0.1568-0.18415 0.32861-0.34095 0.7442-0.33769 0.41558 3e-3 1.0215 0.0362 1.4196-0.32729 0.93562-1.1932 2.1371-2.6676 3.9093-3.1924 1.7722-0.52482 39.634-11.689 59.608-17.581l31.015-1.8624v47.86l-0.95849 1.5429h-1.3832c-0.24979-1.7755-0.85068-1.9326-0.85068-1.9326l-11.633 0.12468s-1.2585 0.79803-1.2585 6.6315c0 10.609 1.3118 13.973 1.3118 13.973s0.30131 0.16754 1.2416 0.16754l2.5625 10.064s0.46106 0.0701 0.9494 0.0701l1.7637 5.2665 0.71822-0.0351 1.3923-5.3548c0.55067 0 0.99225-0.16884 0.99225-0.16884l0.0714-0.44288 9.2212 6.0198 5.3548 27.175s-33.731 22.555-34.623 23.158c-0.89108 0.60283-1.4159 2.6639-1.565 4.3768l-0.65199 7.4952 38.872-12.307 1.0494 5.3873 1.1104-5.3873 38.871 12.307-0.65198-7.4952c-0.14909-1.7129-0.67393-3.774-1.565-4.3768-0.8911-0.60285-34.623-23.158-34.623-23.158l5.3561-27.175 9.2199-6.0198 0.0714 0.44288s0.4429 0.16884 0.99356 0.16884l1.391 5.3548 0.71822 0.0351 1.765-5.2665c0.48833 0 0.9481-0.0701 0.9481-0.0701l2.5625-10.064c0.9403 0 1.2416-0.16754 1.2416-0.16754s1.3118-3.3645 1.3118-13.973c0-5.8335-1.2585-6.6315-1.2585-6.6315l-11.633-0.12468s-0.6009 0.15707-0.8507 1.9326h-1.3832l-0.95719-1.5429v-47.86l31.013 1.8624c19.974 5.8921 57.836 17.057 59.608 17.581 1.7722 0.5248 2.9749 1.9992 3.9106 3.1924 0.39808 0.36352 1.0027 0.33031 1.4182 0.32729 0.4156-3e-3 0.58741 0.15355 0.74421 0.33769 0.1568 0.18415 6.8393 7.6432 6.8393 7.6432l0.10781-2.3443s-0.0397-0.68921-0.27015-1.1507c-0.23051-0.4615-7.7497-15.302-7.7497-15.302s-0.16886-2.6209-4.5743-5.1873c-4.4054-2.5664-89.399-51.752-89.399-51.752l-1.639-1.3481 0.0169-79.957m-34.454 111.65c0.78911 0 1.6055 0.23981 1.6053 1.2949v6.738c2.3e-4 0.93982-0.81617 1.2949-1.6053 1.2949-0.78909 0-1.6053-0.35505-1.6053-1.2949v-6.738c0-1.0551 0.81618-1.2949 1.6053-1.2949zm5.0002 0c0.78909 0 1.6055 0.23981 1.6053 1.2949v6.738c2.4e-4 0.93982-0.81619 1.2949-1.6053 1.2949s-1.6053-0.35505-1.6053-1.2949v-6.738c0-1.0551 0.81618-1.2949 1.6053-1.2949zm33.577 0c0.78909 0 1.6053 0.23981 1.6053 1.2949v6.738c0 0.93982-0.81618 1.2949-1.6053 1.2949-0.7891 0-1.6055-0.35505-1.6053-1.2949v-6.738c-2.4e-4 -1.055 0.81618-1.2949 1.6053-1.2949zm5.0002 0c0.78909 1e-5 1.6053 0.2398 1.6053 1.2949v6.738c0 0.93982-0.81618 1.2949-1.6053 1.2949s-1.6055-0.35505-1.6053-1.2949v-6.738c-2.4e-4 -1.0551 0.81619-1.2949 1.6053-1.2949z" fill="#3296ff"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
3
src/renderer/assets/aircraft/FGA_ACT_C.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="360mm" height="369.09mm" version="1.1" viewBox="0 0 360 369.09" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><metadata><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><g transform="translate(75 36.046)"><g transform="translate(-65.5 -28.331)"><path d="m170.5-0.026086c-7.0846 9.35e-6 -19.026 24.031-19.062 58.205l0.0362 54.388-1.9176 10.818s-0.10598 1.4555-0.99653 1.9124-25.868 13.39-25.868 13.39c0.89235-6.9871 2.094-27.847-0.25947-27.847h-15.911c-3.162 1e-5 -2.337 31.287-0.34733 31.287h1.0188l1.163 3.968-94.45 48.717c-4.8538 2.6647-11.085 6.7435-12.179 12.611l-1.7264 14.181v2.7208l1.8819-8.6075c0.26207-1.101 1.0968-1.7912 2.1833-2.0856l48.418-14.553 1.5222 5.4184 1.2943-6.2934 32.906-10.202 1.2591 4.6033 1.4023-5.4184-0.02378-0.0238 17.489-5.4184h13.63v0.0238l1.1754 4.6751 1.1268-4.6989 27.248-0.014 0.0594 84.392c0.23612 14.268 3.6729 28.282 6.066 42.28 0 0-0.48489 3.4026-4.915 6.2216 0 0-36.324 23.321-38.756 24.91-2.4318 1.5884-3.5142 3.8978-3.5142 8.6897l0.0961 5.1067 52.194-11.616c1.3933 6.3589 5.2092 17.812 5.3703 18.305 0.16114 0.49226 0.88696 1.043 0.88696 1.043s0.44043 0.31323 0.75567 0.31323h1.486c0.31524 0 0.75567-0.31323 0.75567-0.31323s0.72582-0.55079 0.88695-1.043c0.16114-0.49225 3.977-11.946 5.3703-18.305l52.194 11.616 0.0956-5.1067c0-4.7918-1.0819-7.1013-3.5137-8.6897s-38.756-24.91-38.756-24.91c-4.4301-2.8189-4.915-6.2216-4.915-6.2216 2.3931-13.998 5.8299-28.012 6.066-42.28l0.06-84.392 27.248 0.014 1.1273 4.6989 1.1748-4.6751v-0.0238h13.63l17.49 5.4184-0.0238 0.0238 1.4023 5.4184 1.2586-4.6033 32.906 10.202 1.2948 6.2934 1.5222-5.4184 48.418 14.553c1.0865 0.29433 1.9212 0.98458 2.1833 2.0856l1.8824 8.6075v-2.7208l-1.7263-14.181c-1.0936-5.8671-7.3253-9.946-12.179-12.611l-94.45-48.717 1.163-3.968h1.0188c1.9896 0 2.8147-31.287-0.34734-31.287h-15.911c-2.3535 0-1.1518 20.86-0.25947 27.847 0 0-24.977-12.933-25.867-13.39-0.89055-0.45697-0.99705-1.9124-0.99705-1.9124l-1.9176-10.818 0.0362-54.388c-0.03593-34.174-11.977-58.205-19.062-58.205zm-2.373 45.661c0.8389 4.8e-5 1.0544 0.39604 1.0544 1.0673v3.692c0 0.68329-0.21552 1.0792-1.0544 1.0792-0.8389-6e-6 -1.0441-0.39594-1.0441-1.0792v-3.692c0-0.6713 0.20519-1.0673 1.0441-1.0673zm4.7454 0c0.8389 4.8e-5 1.0446 0.39604 1.0446 1.0673v3.692c0 0.68329-0.2057 1.0792-1.0446 1.0792-0.8389-6e-6 -1.0539-0.39594-1.0539-1.0792v-3.692c0-0.6713 0.215-1.0673 1.0539-1.0673zm-46.369 122.62c0.87915-2e-3 1.44 0.52759 1.44 1.4746v5.0349c0 0.82604-0.55805 1.4757-1.44 1.4757-0.88197 0-1.4379-0.64964-1.4379-1.4757v-5.0349c-2e-5 -0.93514 0.55878-1.4724 1.4379-1.4746zm87.992 0c0.87916 2e-3 1.4385 0.5395 1.4385 1.4746v5.0349c0 0.82604-0.55649 1.4757-1.4385 1.4757s-1.44-0.64964-1.44-1.4757v-5.0349c5e-5 -0.94705 0.56085-1.4766 1.44-1.4746zm-81.29 0.0476c0.87915-2e-3 1.4394 0.52759 1.4395 1.4746v5.0349c0 0.82603-0.55752 1.4757-1.4395 1.4757s-1.4385-0.64964-1.4385-1.4757v-5.0349c-2e-5 -0.93514 0.5593-1.4724 1.4385-1.4746zm74.589 0c0.87915 2e-3 1.4385 0.5395 1.4384 1.4746v5.0349c0 0.82603-0.55649 1.4757-1.4384 1.4757-0.88197 0-1.44-0.64964-1.44-1.4757v-5.0349c5e-5 -0.94705 0.56085-1.4766 1.44-1.4746z" fill="#3296ff" fill-rule="evenodd"/><circle cx="170.5" cy="172.29" r="179.31" fill="none" stroke="#3296ff" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="3" stroke-width="1.371" style="paint-order:normal"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
2
src/renderer/assets/aircraft/FGA_ACT_D.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="5203mm" height="5463.5mm" version="1.1" viewBox="0 0 5203 5463.5" xmlns="http://www.w3.org/2000/svg"><g transform="translate(2496.5 2583.2)"><path d="m103.62-2580.1c-130.08 0-255.75 434.93-255.75 588.23l-0.125 1240.4s-55.621 87.016-114.96 127.88c-59.342 40.86-294.12 203.78-294.12 203.78l12.788-24.751s2e-4 -204.6 0-255.75c-1e-4 -51.151-12.788-63.938-25.575-63.938-12.787 1e-4 -204.6 0-204.6 0-25.575 0-38.363 12.788-38.363 63.938 0 0-0.399 257.75 0 281.33 0.399 23.577 12.788 51.151 12.788 51.151h25.575l-0.62501 98.405s-1405.1 961.43-1444.4 988.54c-39.261 27.115-51.15 42.459-51.15 63.938v217.39l575.44-242.96 869.56-306.9 179.03-51.151 498.74-62.464s-0.736 1167.2-0.02 1290.1c0.706 122.92 63.489 432.48 63.489 432.48l-702.87 539.38-38.363 51.15v166.24l869.78-212.97 12.563 46.73 25.575 89.513 12.788 102.3 12.788 38.363 12.788-38.363 12.788-102.3 25.575-89.513 12.563-46.73 869.78 212.97v-166.24l-38.363-51.15-702.87-539.38s62.783-309.56 63.488-432.48c0.711-122.92-0.05-1290.1-0.05-1290.1l498.77 62.464 179.03 51.151 869.56 306.9 575.44 242.96v-217.39c0-21.479-11.889-36.823-51.151-63.938-39.261-27.115-1444.4-988.54-1444.4-988.54l-0.60001-98.405h25.575s12.389-27.573 12.788-51.151c0.399-23.577 0-281.33 0-281.33 0-51.15-12.788-63.938-38.363-63.938 0 0-191.81 1e-4 -204.6 0-12.788-1e-4 -25.575 12.788-25.575 63.938-2e-4 51.151 0 255.75 0 255.75l12.788 24.751s-234.77-162.92-294.12-203.78c-59.342-40.86-114.99-127.88-114.99-127.88l-0.104-1240.4c-1e-4 -153.3-125.68-588.23-255.75-588.23zm-38.363 409.2c6.347 2e-4 12.787 5.5342 12.787 11.064v67.809c0 5.4289-6.4405 10.865-12.787 10.864-6.3906 2e-4 -12.788-5.4355-12.788-10.864v-67.809c1e-4 -5.5302 6.3971-11.013 12.788-11.064zm76.726 0c6.3906 0.05 12.788 5.5342 12.788 11.064v67.809c-1e-4 5.4289-6.397 10.865-12.788 10.864-6.347 2e-4 -12.788-5.4355-12.788-10.864v-67.809c0-5.5302 6.4406-11.064 12.788-11.064zm-575.44 2186.7h25.575c6.347 2.01e-4 12.788 6.393 12.788 12.788v76.726c0 6.3929-6.4406 12.788-12.788 12.788h-25.575c-6.3906 1e-4 -12.787-6.3947-12.788-12.788v-76.726c1e-4 -6.3947 6.397-12.736 12.788-12.788zm115.09 0h25.575c6.347 2.01e-4 12.788 6.393 12.788 12.788v76.726c0 6.3929-6.4406 12.788-12.788 12.788h-25.575c-6.3906 1e-4 -12.787-6.3947-12.788-12.788v-76.726c2e-4 -6.3947 6.3971-12.736 12.788-12.788zm818.41 0h25.575c6.3907 0.05 12.788 6.393 12.788 12.788v76.726c-2e-4 6.3929-6.397 12.788-12.788 12.788h-25.575c-6.347 1e-4 -12.788-6.3947-12.788-12.788v-76.726c0-6.3947 6.4406-12.787 12.788-12.788zm115.09 0h25.575c6.3906 0.05 12.788 6.393 12.788 12.788v76.726c-1e-4 6.3929-6.3971 12.788-12.788 12.788h-25.575c-6.347 1e-4 -12.788-6.3947-12.788-12.788v-76.726c0-6.3947 6.4406-12.787 12.788-12.788zm-1048.6 140.66h25.575c6.347 1e-4 12.788 6.3929 12.788 12.787v76.726c0 6.3929-6.4406 12.788-12.788 12.788h-25.575c-6.3906 1e-4 -12.787-6.3947-12.788-12.788v-76.726c1e-4 -6.3946 6.397-12.736 12.788-12.787zm115.09 0h25.575c6.347 1e-4 12.788 6.3929 12.788 12.787v76.726c0 6.3929-6.4406 12.788-12.788 12.788h-25.575c-6.3906 1e-4 -12.787-6.3947-12.788-12.788v-76.726c2e-4 -6.3946 6.3971-12.736 12.788-12.787zm818.41 0h25.575c6.3907 0.05 12.788 6.3929 12.788 12.787v76.726c-2e-4 6.3929-6.397 12.788-12.788 12.788h-25.575c-6.347 1e-4 -12.788-6.3947-12.788-12.788v-76.726c0-6.3946 6.4406-12.787 12.788-12.787zm115.09 0h25.575c6.3906 0.05 12.788 6.3929 12.788 12.787v76.726c-1e-4 6.3929-6.3971 12.788-12.788 12.788h-25.575c-6.347 1e-4 -12.788-6.3947-12.788-12.788v-76.726c0-6.3946 6.4406-12.787 12.788-12.787z" fill="#3296ff" fill-rule="evenodd"/><circle cx="105" cy="135.8" r="2582.6" fill="none" stroke="#3296ff" stroke-linecap="square" stroke-linejoin="round" stroke-width="37.746" style="paint-order:normal"/></g></svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
2
src/renderer/assets/aircraft/FGA_ACT_E.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="660mm" height="735.62mm" version="1.1" viewBox="0 0 660 735.62" xmlns="http://www.w3.org/2000/svg"><g transform="translate(227.07 219.31)"><g transform="translate(-220.16 -219.35)"><path d="m323.98 0.041596c-12.621 1.1404-32.35 58.556-32.35 95.304v172.91l-46.402 31.844c1.7124-7.7226 3.623-25.137-0.66208-43.984h-33.315c-3.6679 12.285-5.2993 33.094 0.0391 51.47l3.3026 0.0898 3.0428 11.261c-67.538 46.949-135.82 92.856-204.08 138.75-2.0153 1.3847-2.119 1.8573-2.119 1.8573l-11.437 22.93v8.1344l26.342-17.935 71.254-28.565 34-11.466 0.69527 3.201 1.5605-3.992 51.247-17.319 1.0976 3.6346 1.041-4.3845 29.414-9.9624 21.011-3.2655 0.82027 6e-3 1.3632 4.7322 1.7772-4.7341 50.009-0.0273s-0.0109 126.27 0 148.94c0.0156 32.451 7.5281 73.581 8.5445 79.039s3.3484 11.282-3.1483 16.589c-6.4967 5.3071-71.763 58.406-77.1 62.77-5.3362 4.364-4.9704 10.253-4.7556 11.913s1.9276 15.884 1.9276 15.884l98.173-36.949 7.8414 28.559 1.7675 4e-3 7.8414-28.559 98.171 36.949s1.7128-14.223 1.9276-15.884 0.58251-7.5514-4.7536-11.915c-5.3362-4.3639-70.605-57.461-77.102-62.768-6.4967-5.3071-4.1647-11.131-3.1483-16.589s8.5308-46.587 8.5464-79.039c0.0109-22.668 0-148.94 0-148.94l50.007 0.0273 1.7773 4.7341 1.3632-4.7322 0.82222-8e-3 21.011 3.2674 29.413 9.9624 1.041 4.3826 1.0976-3.6326 51.249 17.319 1.5605 3.992 0.69331-3.201 34.002 11.464 71.252 28.567 26.344 17.935-2e-3 -8.1344-11.435-22.93s-0.1057-0.47265-2.121-1.8573c-68.258-45.89-136.54-91.8-204.08-138.75l3.0409-11.259 3.3045-0.0918c5.3383-18.376 3.705-39.185 0.0371-51.47h-33.315c-4.2851 18.847-2.3726 36.264-0.66013 43.986l-46.402-31.846v-172.91c0-36.748-19.762-94.167-32.383-95.308zm-4.3806 54.566h2.0546c0.8995-7e-6 1.2851 0.38391 1.2851 1.2812v7.5582c-4e-5 0.89669-0.38558 1.2812-1.2851 1.2812h-2.0546c-0.89949-9e-6 -1.2246-0.38449-1.2206-1.2812v-7.5582c-4e-3 -0.89728 0.32117-1.2812 1.2206-1.2812zm6.6422 0h2.0546c0.8995-7e-6 1.2851 0.38391 1.2851 1.2812v7.5582c-4e-5 0.89669-0.38558 1.2812-1.2851 1.2812h-2.0546c-0.89948-9e-6 -1.2246-0.38449-1.2206-1.2812v-7.5582c-4e-3 -0.89728 0.32117-1.2812 1.2206-1.2812zm43.543 294.97h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89668-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89676 0.38559-1.2813 1.2851-1.2812zm13.968 0h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89668-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89958-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89676 0.38559-1.2813 1.2851-1.2812zm-122 0.0488h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-8e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm13.97 0h2.5057c0.89955-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38558-1.2813 1.2851-1.2812zm94.048 13.818h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89668-0.38552 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm13.97 0h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89668-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm-122 0.0488h2.5057c0.89955-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm13.97 0h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38558-1.2813 1.2851-1.2812zm97.866 6.2614h8.8667zm-108.03 0.0488h8.8667zm104.23 7.5406h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38552 1.2792-1.2851 1.2792h-2.5057c-0.89957-5e-5 -1.2852-0.38261-1.2851-1.2792v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm13.97 0h2.5057c0.89954-6e-5 1.2831 0.38451 1.2831 1.2812v8.8394c2e-5 0.89667-0.38357 1.2792-1.2831 1.2792h-2.5057c-0.89957-5e-5 -1.2852-0.38261-1.2851-1.2792v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm-122 0.0488h2.5057c0.89955-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c1e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm13.97 0h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38558-1.2813 1.2851-1.2812z" fill="#3296ff"/><circle cx="323.1" cy="368.73" r="328.11" fill="none" stroke="#3296ff" stroke-width="3.7896" style="paint-order:normal"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
17
src/renderer/assets/aircraft/FGA_ACT_F.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="211.67mm" height="211.67mm" version="1.1" viewBox="0 0 211.67 211.67" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(953.33 -995.17)">
|
||||
<path d="m-742.19 1101c0 27.929-11.095 54.714-30.844 74.463-19.749 19.749-46.534 30.844-74.463 30.844-27.929 0-54.714-11.095-74.463-30.844-19.749-19.749-30.844-46.534-30.844-74.463 0-27.929 11.095-54.714 30.844-74.463 19.749-19.749 46.534-30.844 74.463-30.844 27.929 0 54.714 11.095 74.463 30.844 19.749 19.749 30.844 46.534 30.844 74.463z" fill="none" stroke="#3296ff" stroke-linejoin="round" stroke-width="1.0531"/>
|
||||
<path d="m-847.5 1004.7c-7.4097 0-9.4794 27.242-9.4556 35.842v13.103l-1.2407 2.0809-2.6718 3.1116-5.7373 4.7856-15.217 12.445c0.26327-2.4217 0.81772-10.57-0.18346-11.848l-8.6782 0.072c-0.70678 0.8906-1.6381 10.501 0.13788 15.728h1.1029l0.38829 1.823-21.816 16.071c0.5494-2.3946 1.2496-11.314 0.25043-13.182l-8.8583 0.014c-1.0492 4.8589-1.1533 10.88-0.0459 15.696l1.2043 0.04 0.50012 2.5271s-28.608 21.118-31.045 22.91c-2.4373 1.7913-3.8489 5.5589-3.8729 8.2254-0.0241 2.6665-0.0401 5.2116-0.0401 5.2116l35.659-15.492 0.65645 4.4375 1.1948-5.2253 9.3938-3.722 0.4792 5.7045 1.5361-6.4857 9.1575-3.7024 0.83374 5.6914 1.1619-6.4791 8.8095-3.6302 0.53827 2.4748 1.0438-3.1115 9.1247-2.9869 0.64327 2.4748 0.93875-2.9147 12.853-3.4791 0.32163 5.0153 1.4704 10.352 0.033 19.858c0.17362 4.5575 0.64186 9.1069 1.287 13.621l1.477 6.7877c0.23946 1.6304-0.74861 3.3195-1.8528 4.424 0 0-27.318 20.921-28.298 21.678-0.98046 0.7565-1.2339 2.0863-1.2339 2.0863l-2.2479 10.338 25.84-9.5902 11.73-4.0193 2.1403 6.7961 0.58694 6.9848 0.58694-6.9848 2.1403-6.7961 11.73 4.0193 25.84 9.5902-2.2479-10.338s-0.25346-1.3298-1.2339-2.0863c-0.98047-0.7566-28.298-21.678-28.298-21.678-1.1042-1.1045-2.0923-2.7936-1.8528-4.4239l1.477-6.7877c0.64515-4.5145 1.1134-9.0639 1.287-13.621l0.033-19.858 1.4705-10.352 0.32163-5.0153 12.853 3.4791 0.93876 2.9147 0.64326-2.4748 9.1247 2.9869 1.0438 3.1115 0.53826-2.4748 8.8095 3.6302 1.1619 6.4791 0.83375-5.6914 9.1575 3.7024 1.5361 6.4857 0.4792-5.7045 9.3938 3.722 1.1948 5.2253 0.65644-4.4375 35.659 15.492s-0.016-2.5452-0.0401-5.2117-1.4357-6.4341-3.8729-8.2254c-2.4373-1.7912-31.045-22.91-31.045-22.91l0.50013-2.5271 1.2043-0.04c1.1074-4.816 1.0033-10.837-0.0459-15.696l-8.8583-0.014c-0.99921 1.8687-0.29898 10.788 0.25042 13.182l-21.816-16.071 0.3883-1.8229h1.1029c1.776-5.2277 0.84466-14.838 0.13787-15.728l-8.6782-0.072c-1.0012 1.2776-0.44672 9.4259-0.18345 11.848l-15.217-12.445-5.7373-4.7856-2.6718-3.1116-1.2407-2.0809v-13.103c0.0237-8.6006-2.046-35.842-9.4556-35.842zm-2.0804 12.256h1.3916v3.5317h-1.3916zm2.8227 0h1.4048v3.5317h-1.4048zm-19.766 73.142h1.3982v3.5317h-1.3982zm3.5777 0h1.3917v3.5317h-1.3917zm29.501 0h1.3916v3.5317h-1.3916zm3.5645 0h1.4048v3.5317h-1.4048zm-36.643 4.2932h1.3982v3.5251h-1.3982zm3.5777 0h1.3917v3.5251h-1.3917zm29.501 0h1.3916v3.5251h-1.3916zm3.5645 0h1.4048v3.5251h-1.4048zm-27.426 2.0481h1.3983v3.5186h-1.3983zm14.015 0h1.4048v3.5186h-1.4048zm-9.919 0.01h1.3983v3.5251h-1.3983zm14.015 0h1.4048v3.5251h-1.4048zm-18.112 4.4901h1.3983v3.5251h-1.3983zm4.0962 0h1.3983v3.5251h-1.3983zm9.919 0h1.4048v3.5251h-1.4048zm4.0963 0h1.4048v3.5251h-1.4048zm-18.112 4.5033h1.3983v3.5316h-1.3983zm4.0962 0h1.3983v3.5316h-1.3983zm9.919 0h1.4048v3.5316h-1.4048zm4.0963 0h1.4048v3.5316h-1.4048z" fill="#3296ff"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
8
src/renderer/assets/button.css
Normal file
@@ -0,0 +1,8 @@
|
||||
.leaflet-touch .leaflet-control-layers-toggle {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
color:black;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
|
||||
62
src/renderer/check/mapper.js
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
var L = require('leaflet');
|
||||
|
||||
export function checkMapper(o) {
|
||||
if (o instanceof L.ParkingSpot) {
|
||||
/*
|
||||
if( o.box === undefined ) {
|
||||
debugger;
|
||||
} */
|
||||
return {
|
||||
'index': Number(o['id']),
|
||||
'_leaflet_id': o._leaflet_id,
|
||||
'type': 'parking',
|
||||
'parkingType': o.options.attributes.type,
|
||||
'name': o.options.attributes.name,
|
||||
'radius': String(o.options.attributes.radius),
|
||||
'lat': o._latlng.lat,
|
||||
'lng': o._latlng.lng,
|
||||
'box': o.box !== undefined ? o.box.getLatLngs() : null
|
||||
};
|
||||
} else if (o instanceof L.RunwayNode) {
|
||||
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)
|
||||
return { 'index': Number(o['glueindex']), '_leaflet_id': o._leaflet_id, 'type': o.holdPointType };
|
||||
} else if (o instanceof L.RunwayPolygon) {
|
||||
return {
|
||||
'type': 'runway_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 }));
|
||||
if (o.options.attributes===undefined) {
|
||||
return null;
|
||||
}
|
||||
return { 'start': Number(o['begin']), 'end': Number(o['end']), '_leaflet_id': o._leaflet_id, 'type': 'poly', 'direction': o.options.attributes.direction, 'isPushBackRoute': o.options.attributes.isPushBackRoute, latLngs: latLngs };
|
||||
}
|
||||
else {
|
||||
console.log('Unknown Type ')
|
||||
console.log(typeof o)
|
||||
}
|
||||
}
|
||||
|
||||
export function groMapper(o) {
|
||||
if (o instanceof L.Polygon) {
|
||||
|
||||
}
|
||||
}
|
||||
31
src/renderer/components/AiLayer.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import {aiLayer} from '../phi/AILayer'
|
||||
|
||||
export default {
|
||||
/* eslint-disable */
|
||||
name: 'ai-layer',
|
||||
props: [],
|
||||
mounted () {
|
||||
this.aiLayer = aiLayer({url: this.$store.state.Settings.settings.phi_url})
|
||||
if(this.aiLayer) {
|
||||
this.aiLayer.addTo(this.$parent.mapObject)
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
computed: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
129
src/renderer/components/Airport.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<!--
|
||||
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>
|
||||
<el-row>
|
||||
<el-col :span="3" class="text">{{airport.icao}}</el-col>
|
||||
<el-col :span="6" class="text">{{date}}</el-col>
|
||||
<el-col :span="6" class="text">{{upload_date}}</el-col>
|
||||
<el-col :span="9">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Goto"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Center to airport"
|
||||
>
|
||||
<el-button @click="goto" class="button" slot="reference" :disabled="editing">
|
||||
<i class="fas fa-bullseye"></i>
|
||||
</el-button>
|
||||
</el-popover>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Remove"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Remove this Work in progress file"
|
||||
>
|
||||
<el-button @click="remove" tooltip="Remove wip file" class="button" slot="reference" :disabled="editing">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</el-button>
|
||||
</el-popover>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Upload"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Upload work in progress"
|
||||
>
|
||||
<el-button @click="upload" tooltip="Upload to groundweb" class="button" slot="reference" :disabled="editing">
|
||||
<i class="fas fa-upload"></i>
|
||||
</el-button>
|
||||
</el-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
const $ = require('jquery');
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import {removeWip} from '../loaders/groundnet_functions'
|
||||
import Vue from 'vue'
|
||||
import { EventBus } from './event-bus.js';
|
||||
|
||||
export default {
|
||||
name: 'airport',
|
||||
components: { },
|
||||
props: {airport: Object, editing: Boolean},
|
||||
mounted () {
|
||||
this.$forceUpdate();
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
ok: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goto() {
|
||||
let airports = this.$store.state.Airports.airports
|
||||
.filter(a => a.properties.icao.match(this.airport.icao))
|
||||
if (airports.length > 0) {
|
||||
this.$store.commit('CENTER', [airports[0].geometry.coordinates[1], airports[0].geometry.coordinates[0]])
|
||||
}
|
||||
},
|
||||
remove() {
|
||||
removeWip(this.$store.state.Settings.settings.airportsDirectory, this.airport.icao)
|
||||
this.$store.dispatch('removeWip', this.airport.icao);
|
||||
},
|
||||
upload() {
|
||||
let airports = this.$store.state.Airports.airports
|
||||
.filter(a => a.properties.icao.match(this.airport.icao))
|
||||
if (airports.length > 0) {
|
||||
this.$store.commit('CENTER', [airports[0].geometry.coordinates[1], airports[0].geometry.coordinates[0]])
|
||||
}
|
||||
Vue.set(this.$parent.$parent.$parent, 'uploadVisible', true)
|
||||
this.$parent.$parent.$parent.$refs.upload.status()
|
||||
this.$parent.$parent.$parent.$refs.upload.check()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
date: function () {
|
||||
var d = new Date(this.airport.time)
|
||||
return d.toLocaleDateString() + ' ' + d.toLocaleTimeString()
|
||||
},
|
||||
upload_date: function () {
|
||||
if( this.airport.upload !== undefined ) {
|
||||
var d = new Date(this.airport.upload)
|
||||
return d.toLocaleDateString() + ' ' + d.toLocaleTimeString()
|
||||
} else {
|
||||
return "-"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.text {
|
||||
padding: 10px;
|
||||
}
|
||||
.button {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.el-popover--plain {
|
||||
padding: 5px 5px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,57 +1,287 @@
|
||||
<!--
|
||||
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="airport">
|
||||
<div>
|
||||
<div v-if="airport">
|
||||
<Upload :visible.sync="uploadVisible" ref="upload"></Upload>
|
||||
<el-dialog
|
||||
title="Add Airline"
|
||||
:visible.sync="dialogVisible"
|
||||
width="20%"
|
||||
: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>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">Cancel</el-button>
|
||||
<el-button type="primary" @click="addAirline">Confirm</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
title="Import File"
|
||||
:visible.sync="showImportFile"
|
||||
width="20%"
|
||||
:before-close="handleClose">
|
||||
<span>Beware wip will be overwritten</span>
|
||||
<el-row>
|
||||
<el-col :span="7">ICAO :</el-col>
|
||||
<el-col :span="15">{{ icao }}</el-col>
|
||||
<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">Name :</el-col>
|
||||
<el-col :span="15">{{ name }}</el-col>
|
||||
<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>
|
||||
<el-row>
|
||||
<el-col :span="7">Flights :</el-col>
|
||||
<el-col :span="15">{{ flights }}</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">Airlines :</el-col>
|
||||
<el-col :span="15">{{ airlines }}</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">Groundnet :</el-col>
|
||||
<el-col :span="15">{{groundnet}}</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">Parking Positions :</el-col>
|
||||
<el-col :span="15">{{ parking }}</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</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>
|
||||
</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-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="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-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-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="4">Uploaded :</el-col>
|
||||
<el-col :span="8" class="text">{{upload_date}}</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
export default {
|
||||
import EditButton from './EditButton'
|
||||
import FileSelect from './FileSelect'
|
||||
import Frequency from './Frequency'
|
||||
import ParkingList from './ParkingList'
|
||||
import Upload from './Upload'
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {showImportFile: false, activeTab: 'first', editing: false, uploadVisible: false, dialogVisible: false, airlineCode: '', fileImport: null}
|
||||
},
|
||||
components: {
|
||||
EditButton, FileSelect, Frequency, ParkingList, Upload
|
||||
},
|
||||
methods: {
|
||||
fileImportFileName (f) {
|
||||
this.fileImport = f
|
||||
},
|
||||
edit () {
|
||||
this.isEditing = true
|
||||
this.$emit('edit', true)
|
||||
},
|
||||
upload () {
|
||||
this.uploadVisible = true
|
||||
this.$refs.upload.status()
|
||||
this.$refs.upload.check()
|
||||
},
|
||||
test () {
|
||||
this.$parent.$parent.$parent.$refs.editLayer.test()
|
||||
},
|
||||
importFile () {
|
||||
this.showImportFile = false
|
||||
var fDir = this.$store.state.Settings.settings.airportsDirectory
|
||||
var fNew = path.join(fDir, this.icao[0], this.icao[1], this.icao[2], this.icao + '.groundnet.new.xml')
|
||||
|
||||
var editLayer = this.$parent.$parent.$parent.$refs.editLayer
|
||||
fs.copyFile(this.fileImport.path, fNew, () => {
|
||||
editLayer.reload(false)
|
||||
})
|
||||
},
|
||||
setEditing (editing) {
|
||||
this.editing = editing
|
||||
},
|
||||
addAirline () {
|
||||
this.dialogVisible = false
|
||||
this.$store.dispatch('addAirline', this.airlineCode)
|
||||
},
|
||||
addFrequency () {
|
||||
this.$store.dispatch('addFrequency', {type: 'AWOS', value: 0})
|
||||
},
|
||||
initLayer () {
|
||||
var parent = this.$parent
|
||||
while (parent !== undefined && parent.$refs.editLayer === undefined) {
|
||||
parent = parent.$parent
|
||||
}
|
||||
if (parent === undefined) {
|
||||
return
|
||||
}
|
||||
this.editLayer = parent.$refs.editLayer
|
||||
},
|
||||
handleClose () {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
fileImportName: function () {
|
||||
if (this.fileImport !== null) {
|
||||
console.log(this.fileImport)
|
||||
return this.fileImport.path
|
||||
}
|
||||
return 'Please select'
|
||||
},
|
||||
icao: function () {
|
||||
return this.$store.state.Editable.data.airport.icao
|
||||
return this.$store.state.Airports.currentAirport.icao
|
||||
},
|
||||
name: function () {
|
||||
return this.$store.state.Editable.data.airport.name
|
||||
return this.$store.state.Airports.currentAirport.name
|
||||
},
|
||||
flights: function () {
|
||||
return this.$store.state.Editable.data.airport.flights
|
||||
return this.$store.state.Airports.currentAirport.flights
|
||||
},
|
||||
airlines: function () {
|
||||
return this.$store.state.Editable.data.airport.airlines
|
||||
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
|
||||
},
|
||||
groundnet: function () {
|
||||
return this.$store.state.Editable.data.airport.groundnet
|
||||
return this.$store.state.Airports.currentAirport.groundnet
|
||||
},
|
||||
parking: function () {
|
||||
return this.$store.state.Editable.data.airport.parking
|
||||
return this.$store.state.Airports.currentAirport.parking
|
||||
},
|
||||
airport: function () {
|
||||
return this.$store.state.Editable.type === 'airport'
|
||||
wipgroundnet: function () {
|
||||
return this.$store.state.Airports.currentAirport.wipgroundnet
|
||||
},
|
||||
wipparking: function () {
|
||||
return this.$store.state.Airports.currentAirport.wipparking
|
||||
},
|
||||
wip: function () {
|
||||
// .icao
|
||||
var wip = this.$store.state.Settings.wip.filter(w => w.icao === this.$store.state.Airports.currentAirport.icao)
|
||||
if (wip.length > 0) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
date: function () {
|
||||
var wip = this.$store.state.Settings.wip.filter(w => w.icao === this.$store.state.Airports.currentAirport.icao)
|
||||
var d = new Date(wip[0].time)
|
||||
return d.toLocaleDateString() + ' ' + d.toLocaleTimeString()
|
||||
},
|
||||
upload_date: function () {
|
||||
var wip = this.$store.state.Settings.wip.filter(w => w.icao === this.$store.state.Airports.currentAirport.icao)
|
||||
if (wip[0].upload !== undefined) {
|
||||
var d = new Date(wip[0].upload)
|
||||
return d.toLocaleDateString() + ' ' + d.toLocaleTimeString()
|
||||
} else {
|
||||
return '-'
|
||||
}
|
||||
},
|
||||
airport: {
|
||||
get: function () {
|
||||
return this.$store.state.Airports.currentAirport !== undefined
|
||||
}
|
||||
},
|
||||
frequencyList: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Frequencies.items
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,6 +289,13 @@
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-row {
|
||||
padding: 0em
|
||||
padding: 0em;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.label {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +1,10 @@
|
||||
<template>
|
||||
<section class="edit-layer">
|
||||
<h1>edit-layer Component</h1>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import L from 'leaflet'
|
||||
export default {
|
||||
name: 'edit-layer',
|
||||
name: 'airport-layer',
|
||||
props: [],
|
||||
mounted () {
|
||||
this.add()
|
||||
|
||||
@@ -27,6 +27,21 @@
|
||||
<el-switch v-model="isPushback"></el-switch>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="demo-input-label">Direction :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-select v-model="direction" placeholder="Select">
|
||||
<el-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
:label="type.label"
|
||||
:value="type.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -36,6 +51,14 @@
|
||||
arc: function () {
|
||||
return this.$store.state.Editable.type === 'arc'
|
||||
},
|
||||
// ga (general aviation), cargo (cargo), gate (commercial passenger traffic),
|
||||
// mil-fighter (military fighter), mil-cargo (military transport)
|
||||
options: function () {
|
||||
return [{value: 'bi-directional', label: 'bi-directional'},
|
||||
{value: 'forward', label: 'forward'},
|
||||
{value: 'backward', label: 'backward'}
|
||||
]
|
||||
},
|
||||
name: {
|
||||
// getter
|
||||
get: function () {
|
||||
@@ -49,12 +72,23 @@
|
||||
isPushback: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Editable.data.arc.isPushBackRoute === '1'
|
||||
return this.$store.state.Editable.data.arc.isPushBackRoute === '1' ||
|
||||
this.$store.state.Editable.data.arc.isPushBackRoute === 1
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_PUSHBACK', newValue ? '1' : '0')
|
||||
}
|
||||
},
|
||||
direction: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Editable.data.arc.direction
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_DIRECTION', newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
106
src/renderer/components/ArcEditMulti.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<!--
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template>
|
||||
<div width="100%" v-if="multiarc">
|
||||
<!--
|
||||
airlineCodes: 0
|
||||
heading: 341.34
|
||||
index: 13
|
||||
lat: "N59 52.610885"
|
||||
lon: "W1 17.855144"
|
||||
name: "Western_Apron_Hanger"
|
||||
pushBackRoute: 27
|
||||
radius: 18
|
||||
type: "gate"
|
||||
-->
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="demo-input-label">Name :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-input placeholder="Please input" v-model="name"></el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="demo-input-label">Pushback :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-switch v-model="isPushback"></el-switch>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="demo-input-label">Direction :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-select v-model="direction" placeholder="Select">
|
||||
<el-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
:label="type.label"
|
||||
:value="type.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
export default {
|
||||
computed: {
|
||||
multiarc: function () {
|
||||
return this.$store.state.Editable.type === 'multiarc'
|
||||
},
|
||||
// ga (general aviation), cargo (cargo), gate (commercial passenger traffic),
|
||||
// mil-fighter (military fighter), mil-cargo (military transport)
|
||||
options: function () {
|
||||
return [{value: 'bi-directional', label: 'bi-directional'},
|
||||
{value: 'forward', label: 'forward'},
|
||||
{value: 'backward', label: 'backward'}
|
||||
]
|
||||
},
|
||||
name: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Editable.data.multiarc.name
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_ARC_NAME', newValue)
|
||||
}
|
||||
},
|
||||
isPushback: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Editable.data.multiarc.isPushBackRoute === '1' ||
|
||||
Number(this.$store.state.Editable.data.multiarc.isPushBackRoute) === Number(1)
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_PUSHBACK', newValue ? '1' : '0')
|
||||
}
|
||||
},
|
||||
direction: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Editable.data.multiarc.direction
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_DIRECTION', newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -5,12 +5,24 @@
|
||||
<div class="leaflet-sidebar-close">
|
||||
<i class="fa fa-caret-left"></i>
|
||||
</div>
|
||||
</h1>
|
||||
<div id="panel" width="100%">
|
||||
</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="15">{{ result.message }}</el-col>
|
||||
<el-col :span="7"><el-button v-on:click="show(result.id)">Show</el-button></el-col>
|
||||
|
||||
<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="15">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Description"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
: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-row>
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,5 +58,19 @@
|
||||
}
|
||||
.el-col {
|
||||
border-radius: 1px;
|
||||
padding: 0pt;
|
||||
}
|
||||
.button {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
.label {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
font-weight: normal;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,19 +3,32 @@
|
||||
<div class="select-button">
|
||||
...
|
||||
</div>
|
||||
<input type="file" @change="handleFileChange" webkitdirectory directory/>
|
||||
<input name="hiddenDir" type="file" v-on:change="handleFileChange($event)" webkitdirectory directory tabindex="-1"/>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
/* eslint-disable */
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
export default {
|
||||
|
||||
props: {
|
||||
value: File
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleFileChange (e) {
|
||||
this.$emit('input', e.target.files[0])
|
||||
try {
|
||||
if (e.target.files && e.target.files.length>0) {
|
||||
var first = e.target.files[0].webkitRelativePath.split("/")[0];
|
||||
var webkitdirectoryPath = e.target.files[0].path.split(first)[0] + first;
|
||||
this.$emit('input', webkitdirectoryPath)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +45,8 @@ export default {
|
||||
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.directory-select > input[type="file"] {
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
<!--
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template>
|
||||
<div id="EditBar">
|
||||
<EditButton icon="fas fa-edit" v-on:click="edit" :show="!editing" tooltip="Edit"></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>
|
||||
<!--<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"
|
||||
@@ -19,11 +35,25 @@
|
||||
</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>
|
||||
|
||||
<EditButton
|
||||
icon="fas fa-draw-polygon"
|
||||
v-on:click="drawPolyline"
|
||||
:show="editing"
|
||||
tooltip="Draw Taxiline"
|
||||
tooltip="Draw Bi-Directional Taxiline"
|
||||
></EditButton>
|
||||
<EditButton
|
||||
icon="fas fa-long-arrow-alt-right"
|
||||
v-on:click="drawForwardPolyline"
|
||||
:show="editing"
|
||||
tooltip="Draw Forward Taxiline"
|
||||
></EditButton>
|
||||
<EditButton
|
||||
icon="fas fa-arrows-alt-h"
|
||||
v-on:click="drawPushbackPolyline"
|
||||
:show="editing"
|
||||
tooltip="Draw Pushback"
|
||||
></EditButton>
|
||||
<EditButton
|
||||
icon="fas fa-parking"
|
||||
@@ -32,7 +62,6 @@
|
||||
tooltip="Draw Parking"
|
||||
></EditButton>
|
||||
<EditButton icon="fas fa-trash-alt" v-on:click="deleteFeature" :show="editing" tooltip="Remove"></EditButton>
|
||||
<EditButton icon="far fa-check-square" v-on:click="showCheck" :show="editing" tooltip="Check"></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>
|
||||
@@ -43,46 +72,109 @@
|
||||
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
const path = require('path')
|
||||
const fs = require('fs');
|
||||
const mapper = require('../check/mapper');
|
||||
|
||||
import EditButton from './EditButton'
|
||||
import ZoomButton from './ZoomButton';
|
||||
import Vue from 'vue'
|
||||
|
||||
import fileUrl from 'file-url'
|
||||
const path = require('path')
|
||||
|
||||
export default {
|
||||
components: { EditButton },
|
||||
components: { EditButton, ZoomButton },
|
||||
data () {
|
||||
return {isEditing: false, centerDialogVisible: false, saveDialogVisible: false, checkDialogVisible: false, checking: false, progress: 0, max: 0}
|
||||
return {isEditing: false, uploadVisible: false, centerDialogVisible: false, saveDialogVisible: false, checkDialogVisible: false, checking: false, progress: 0, max: 0, pavementLayerVisible: true}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods: {
|
||||
zoomout() {
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
this.$parent.$parent.zoomUpdated(9)
|
||||
},
|
||||
zoomin() {
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
this.$parent.$parent.zoomUpdated(14)
|
||||
},
|
||||
hideAPT() {
|
||||
this.pavementLayerVisible = !this.pavementLayerVisible
|
||||
this.$parent.$parent.$refs.pavementLayer.setVisible(this.pavementLayerVisible)
|
||||
},
|
||||
edit () {
|
||||
this.editing = true
|
||||
this.$parent.$parent.$refs.editLayer.enableEdit()
|
||||
this.isEditing = true
|
||||
this.$emit('edit', true)
|
||||
},
|
||||
setEditing (editing) {
|
||||
this.isEditing = editing
|
||||
},
|
||||
undoFirst () {
|
||||
this.editing = false
|
||||
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)
|
||||
},
|
||||
undoLast () {
|
||||
this.editing = false
|
||||
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 () {
|
||||
this.editing = false
|
||||
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.editing = false
|
||||
Vue.nextTick( () => {
|
||||
this.$parent.$parent.$refs.editLayer.save()
|
||||
this.$parent.$parent.$refs.editLayer.disableEdit()
|
||||
Vue.set(this, 'saveDialogVisible', false)
|
||||
this.$emit('edit', false)
|
||||
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)
|
||||
},
|
||||
scanGroundnets () {
|
||||
try {
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/worker.js`
|
||||
: `file://${process.resourcesPath}/workers/worker.js`
|
||||
console.log('make a worker: ', path.resolve(__dirname, 'worker.js'))
|
||||
|
||||
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
|
||||
var store = this.$store
|
||||
worker.onmessage = function (e) {
|
||||
if (e.data === 'scanStarted') {
|
||||
this.progress = 0
|
||||
this.max = 0
|
||||
} else if (e.data === 'DONE') {
|
||||
console.log('DONE')
|
||||
store.dispatch('getAirports')
|
||||
worker.terminate()
|
||||
} else if (e.data.length > 0) {
|
||||
if (e.data[0] === 'max') {
|
||||
}
|
||||
if (e.data[0] === 'progress') {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
pollData () {
|
||||
var workery = this.worker
|
||||
var view = this
|
||||
@@ -93,18 +185,34 @@
|
||||
view.scanning = Boolean(workery.checking)
|
||||
workery.view = view
|
||||
}
|
||||
}, 1000)
|
||||
}, 500)
|
||||
},
|
||||
|
||||
check () {
|
||||
try {
|
||||
this.scanning = true
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/check.js`
|
||||
: `file://${__dirname}/check.js`
|
||||
: `file://${process.resourcesPath}/workers/check.js`
|
||||
console.log('make a check worker: ', path.resolve(__dirname, 'check.js'))
|
||||
if(!this.$parent.$parent.$refs.pavementLayer.pavement) {
|
||||
this.max = 0
|
||||
this.checkDialogVisible = false
|
||||
this.$message({
|
||||
type: 'Error',
|
||||
showClose: true,
|
||||
message: `Check can't run without pavementlayer since runways aren't known. Is the APT file set correctly?`
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const worker = new Worker(winURL)
|
||||
worker.onerror = function(e) {
|
||||
worker.terminate()
|
||||
worker.view.max = 0
|
||||
worker.view.checkDialogVisible = false
|
||||
e.preventDefault(); // <-- "Hey browser, I handled it!"
|
||||
}
|
||||
|
||||
console.log(fileUrl('src/renderer/utils/check.js'))
|
||||
|
||||
worker.checking = this.checking
|
||||
@@ -114,15 +222,20 @@
|
||||
worker.progress = 0
|
||||
// var worker = new Worker(fileUrl('src/renderer/utils/worker.js'))
|
||||
this.worker = worker
|
||||
var xml = []
|
||||
var groundnet = []
|
||||
this.$parent.$parent.$refs.editLayer.groundnetLayerGroup.eachLayer(l => {
|
||||
console.log(l)
|
||||
xml.push(l)
|
||||
groundnet.push(l)
|
||||
})
|
||||
var features = groundnet.map(mapper.checkMapper).filter(n => n)
|
||||
var pavement = []
|
||||
this.$parent.$parent.$refs.pavementLayer.pavement.eachLayer(l => {
|
||||
console.log(l)
|
||||
pavement.push(l)
|
||||
})
|
||||
var features2 = pavement.map(mapper.checkMapper).filter(n => n)
|
||||
|
||||
var features = xml.map(this.featuresMapper).filter(n => n)
|
||||
|
||||
worker.postMessage(['check', features ] )
|
||||
worker.postMessage(['check', features.concat(features2) ] )
|
||||
this.pollData()
|
||||
// the reply
|
||||
var store = this.$store
|
||||
@@ -153,31 +266,29 @@
|
||||
}
|
||||
},
|
||||
drawPolyline () {
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
this.$parent.$parent.$refs.editLayer.drawPolyline()
|
||||
},
|
||||
drawForwardPolyline () {
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
this.$parent.$parent.$refs.editLayer.drawForwardPolyline()
|
||||
},
|
||||
drawPushbackPolyline () {
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
this.$parent.$parent.$refs.editLayer.drawPushbackPolyline()
|
||||
},
|
||||
drawParking () {
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
this.$parent.$parent.$refs.editLayer.drawParking()
|
||||
},
|
||||
deleteFeature () {
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
this.$parent.$parent.$refs.editLayer.deleteFeature()
|
||||
},
|
||||
showCheck() {
|
||||
this.$parent.$parent.$refs.editLayer.stopDrawing()
|
||||
Vue.set(this, 'checkDialogVisible', true)
|
||||
this.check()
|
||||
},
|
||||
featuresMapper(o) {
|
||||
if (o instanceof L.ParkingSpot) {
|
||||
return { 'index': Number(o['id']), '_leaflet_id': o._leaflet_id, 'type': 'parking', 'name': o.options.attributes.name, 'radius': String(o.options.attributes.radius) };
|
||||
} else if (o instanceof L.RunwayNode) {
|
||||
console.log(o)
|
||||
return { 'index': Number(o['glueindex']), '_leaflet_id': o._leaflet_id, 'type': 'runway' };
|
||||
} else if (o instanceof L.Polyline) {
|
||||
console.log(o)
|
||||
return { 'start': Number(o['begin']), 'end': Number(o['end']), '_leaflet_id': o._leaflet_id, 'type': 'poly' };
|
||||
} else {
|
||||
console.log('Unknown Type ')
|
||||
console.log(typeof o)
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
<template>
|
||||
</template>
|
||||
<!--
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template></template>
|
||||
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
@@ -11,6 +21,17 @@
|
||||
import {writeGroundnetXML} from '../loaders/groundnet_writer'
|
||||
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')
|
||||
|
||||
|
||||
const Coordinates = require('coordinate-parser');
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
|
||||
var selectedItem
|
||||
|
||||
// import {LSymbol} from 'leaflet-polylinedecorator'
|
||||
|
||||
@@ -20,11 +41,7 @@
|
||||
props: [],
|
||||
created () {
|
||||
|
||||
console.log(LMap)
|
||||
console.log(LMarker)
|
||||
console.log(L)
|
||||
console.log(LEdit)
|
||||
console.log(L2)
|
||||
[LMap, LMarker, L, LEdit, L2]
|
||||
console.log('Created Editlayer')
|
||||
// console.log(LSymbol)
|
||||
},
|
||||
@@ -51,6 +68,16 @@
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
}
|
||||
);
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.multiarc;
|
||||
},
|
||||
() => { this.editedMultiArc() }
|
||||
,
|
||||
{
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
}
|
||||
);
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.parking;
|
||||
@@ -61,50 +88,69 @@
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
}
|
||||
);
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Parkings.items;
|
||||
},
|
||||
() => { this.editedParkings() }
|
||||
,
|
||||
{
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
}
|
||||
);
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.remove()
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
maxId: 1, icao: String, checking: false
|
||||
maxId: 1, icao: String, checking: false, editing: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getParkings(ring) {
|
||||
var poly = turf.polygon(ring);
|
||||
var parkings = []
|
||||
this.groundnetLayerGroup.eachLayer(l => {
|
||||
//console.log(l)
|
||||
if (l instanceof L.ParkingSpot) {
|
||||
var tp = turf.point([l.getLatLng().lat, l.getLatLng().lng]);
|
||||
if (turf.booleanPointInPolygon(tp, poly)) {
|
||||
parkings.push(l);
|
||||
}
|
||||
}
|
||||
})
|
||||
this.selection = parkings;
|
||||
return parkings;
|
||||
},
|
||||
load (icao, force) {
|
||||
if (this.groundnetLayerGroup !== undefined) {
|
||||
this.groundnetLayerGroup.removeFrom(this.$parent.mapObject)
|
||||
}
|
||||
|
||||
this.$parent.$parent.setIcao(icao)
|
||||
this.icao = icao
|
||||
this.groundnetLayerGroup = readGroundnetXML(this.$store.state.Settings.settings.airportsDirectory, icao, force)
|
||||
if (this.groundnetLayerGroup === undefined) {
|
||||
console.console.error('ICAO not loaded ' + icao)
|
||||
console.warn('Groundnet for ICAO not loaded ' + icao)
|
||||
return
|
||||
}
|
||||
if (this.groundnetLayerGroup.getLayers().length === 0) {
|
||||
console.warn('Groundnet for ICAO not loaded ' + icao)
|
||||
}
|
||||
this.groundnetLayerGroup.eachLayer(l => {
|
||||
if (l instanceof L.TaxiwaySegment) {
|
||||
l.addListeners()
|
||||
l.addListeners()
|
||||
}
|
||||
if (l.updateArrows !== undefined) {
|
||||
l.updateArrows(this.$store.state.Settings.zoom)
|
||||
}
|
||||
})
|
||||
/*
|
||||
this.groundnetLayerGroup.eachLayer(l => {
|
||||
if (l instanceof L.TaxiwaySegment) {
|
||||
var decorator = L.polylineDecorator(l, {
|
||||
pattern: [
|
||||
// defines a pattern of 10px-wide dashes, repeated every 20px on the line
|
||||
{offset: 5, repeat: 50, symbol: L.Symbol.arrowHead({pixelSize: 15, pathOptions: {fillOpacity: 1, weight: 0}})}
|
||||
]
|
||||
})
|
||||
decorator.addTo(this.$parent.mapObject)
|
||||
}
|
||||
})
|
||||
*/
|
||||
|
||||
console.log(this.groundnetLayerGroup.maxId)
|
||||
|
||||
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
|
||||
@@ -132,8 +178,31 @@
|
||||
showCheck() {
|
||||
Vue.set(this, 'checking', true)
|
||||
},
|
||||
getEditing () {
|
||||
return this.editing;
|
||||
},
|
||||
onEdit (event) {
|
||||
switch (event.type) {
|
||||
case 'parking-group-angle':
|
||||
this.selection.forEach(element => {
|
||||
element.updateHeading(event.angle)
|
||||
});
|
||||
break;
|
||||
case 'parking-group-wingspan':
|
||||
this.selection.forEach(element => {
|
||||
element.updateRadius(event.wingspan/2)
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
enableEdit () {
|
||||
this.editable = true
|
||||
this.editing = true
|
||||
this.$store.commit('SET_EDIT', true)
|
||||
|
||||
this.featureLookup = [];
|
||||
this.groundnetLayerGroup.eachLayer(l => {
|
||||
l.enableEdit()
|
||||
@@ -145,10 +214,12 @@
|
||||
if (typeof l.bringToFront === 'function') {
|
||||
l.bringToFront()
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
this.$store.dispatch('addWip', {icao: this.icao}); },
|
||||
disableEdit () {
|
||||
this.editable = false
|
||||
this.editing = false
|
||||
this.$store.commit('SET_EDIT', false)
|
||||
this.groundnetLayerGroup.eachLayer(l => {
|
||||
l.disableEdit()
|
||||
})
|
||||
@@ -167,10 +238,44 @@
|
||||
case 'arc':
|
||||
this.removeArc(this.$store.state.Editable.data.arc)
|
||||
break;
|
||||
default:
|
||||
console.log('Remove : ' + this.$store.state.Editable.type)
|
||||
}
|
||||
},
|
||||
removeArc (arc) {
|
||||
console.log(arc);
|
||||
findRouteToPushback (index) {
|
||||
if (this.featureLookup===undefined || this.featureLookup[index]===undefined) {
|
||||
return
|
||||
}
|
||||
var parking = this.featureLookup[index].filter(n => n instanceof L.ParkingSpot)
|
||||
var walkedNodes = [index]
|
||||
var pushBackNodes = []
|
||||
this.walkPushbackRoute(index, walkedNodes, pushBackNodes)
|
||||
return pushBackNodes
|
||||
},
|
||||
walkPushbackRoute (index, walkedNodes, pushBackNodes) {
|
||||
var polyLines = this.featureLookup[index].filter(n => n instanceof L.Polyline)
|
||||
var holdNodes = this.featureLookup[index].filter(n => n instanceof L.HoldNode)
|
||||
holdNodes.forEach(n => {
|
||||
pushBackNodes.push(Number(n.glueindex));
|
||||
});
|
||||
|
||||
polyLines.forEach(l => {
|
||||
if( l.options.attributes.isPushBackRoute === 1 ) {
|
||||
if (Number(l.begin) === index && walkedNodes.indexOf(Number(l.end)) < 0) {
|
||||
walkedNodes.push(Number(l.end))
|
||||
pushBackNodes.concat(this.walkPushbackRoute(Number(l.end), walkedNodes, pushBackNodes))
|
||||
}
|
||||
if (Number(l.end) === index && walkedNodes.indexOf(Number(l.begin)) < 0 ) {
|
||||
walkedNodes.push(Number(l.begin))
|
||||
pushBackNodes.concat(this.walkPushbackRoute(Number(l.begin), walkedNodes, pushBackNodes))
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
removeArc (arc) {
|
||||
console.debug('Remove Arc : ' + arc);
|
||||
var arcLayer = this.groundnetLayerGroup.getLayer(this.$store.state.Editable.index);
|
||||
arcLayer.removeFrom(this.groundnetLayerGroup);
|
||||
},
|
||||
removeParking (index) {
|
||||
if(this.featureLookup[index]===undefined) {
|
||||
@@ -184,68 +289,254 @@
|
||||
});
|
||||
},
|
||||
show (index) {
|
||||
if(this.featureLookup[index]===undefined) {
|
||||
console.error("Lookup " + index + " failed ");
|
||||
if(Number.isNaN(index)) {
|
||||
return;
|
||||
}
|
||||
if(this.featureLookup===undefined || this.featureLookup[index]===undefined) {
|
||||
console.error("Lookup " + index + " failed ");
|
||||
this.buildLookup()
|
||||
}
|
||||
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 => {
|
||||
element.deselect();
|
||||
});
|
||||
}
|
||||
|
||||
this.featureLookup[index].forEach((element, i) => {
|
||||
if (element instanceof L.Polyline) {
|
||||
element._latlngs.forEach((e1, index1) => {
|
||||
console.log(e1);
|
||||
if (e1.attributes.index===index) {
|
||||
if (e1.attributes.index===Number(index)) {
|
||||
var latlng = {};
|
||||
latlng.lat = e1.lat;
|
||||
latlng.lng = e1.lng;
|
||||
this.$store.dispatch('setCenter', latlng);
|
||||
if(e1.__vertex._icon.style!=null) {
|
||||
if(e1.__vertex !== undefined && e1.__vertex !== null && e1.__vertex._icon.style!=null) {
|
||||
e1.__vertex._icon.style['background-color'] = 'red';
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
} else if (element instanceof L.RunwayNode) {
|
||||
var latlng = {};
|
||||
latlng.lat = element._latlng.lat;
|
||||
latlng.lng = element._latlng.lng;
|
||||
element.highlight();
|
||||
if (this.selectedItem != null && this.selectedItem.deselect !== undefined) {
|
||||
this.selectedItem.deselect();
|
||||
}
|
||||
this.selectedItem = element;
|
||||
element.select();
|
||||
this.$store.dispatch('setCenter', latlng);
|
||||
} else if (element instanceof L.ParkingSpot) {
|
||||
console.log(element);
|
||||
var latlng = {};
|
||||
latlng.lat = element._latlng.lat;
|
||||
latlng.lng = element._latlng.lng;
|
||||
element.highlight();
|
||||
if (this.selectedItem != null && this.selectedItem.deselect !== undefined) {
|
||||
this.selectedItem.deselect();
|
||||
}
|
||||
this.selectedItem = element;
|
||||
element.select();
|
||||
this.$store.dispatch('setCenter', latlng);
|
||||
}
|
||||
});
|
||||
},
|
||||
buildLookup () {
|
||||
this.featureLookup = {};
|
||||
this.groundnetLayerGroup.eachLayer((layer) => {
|
||||
if (layer instanceof L.Polyline) {
|
||||
// console.log(layer._latlngs)
|
||||
layer._latlngs.forEach(latlng => {
|
||||
if (latlng.attributes.index) {
|
||||
if( this.featureLookup[latlng.attributes.index] == undefined) {
|
||||
this.featureLookup[latlng.attributes.index] = [];
|
||||
}
|
||||
this.featureLookup[latlng.attributes.index].push(layer);
|
||||
}
|
||||
})
|
||||
} else if (layer instanceof L.RunwayNode || layer instanceof L.ParkingSpot || layer instanceof L.HoldNode) {
|
||||
if( this.featureLookup[layer.glueindex] == undefined) {
|
||||
this.featureLookup[layer.glueindex] = [];
|
||||
}
|
||||
this.featureLookup[layer.glueindex].push(layer);
|
||||
} else {
|
||||
console.warn(layer)
|
||||
}
|
||||
})
|
||||
},
|
||||
getPointCoords (index) {
|
||||
if(this.featureLookup[index]===undefined) {
|
||||
console.error("Lookup " + index + " failed ");
|
||||
return;
|
||||
}
|
||||
return this.featureLookup[index].map((element, i) => {
|
||||
if (element instanceof L.Polyline) {
|
||||
var latLng = element._latlngs.map((e1, index1) => {
|
||||
console.log(e1);
|
||||
if (e1.attributes.index===index) {
|
||||
var latlng = {};
|
||||
latlng.lat = e1.lat;
|
||||
latlng.lng = e1.lng;
|
||||
return latlng;
|
||||
}
|
||||
}).filter(n => n);
|
||||
return latLng[0];
|
||||
} else if (element instanceof L.RunwayNode) {
|
||||
var latlng = {};
|
||||
latlng.lat = element._latlng.lat;
|
||||
latlng.lng = element._latlng.lng;
|
||||
return latlng;
|
||||
} else if (element instanceof L.ParkingSpot) {
|
||||
console.log(element);
|
||||
var latlng = {};
|
||||
latlng.lat = element._latlng.lat;
|
||||
latlng.lng = element._latlng.lng;
|
||||
return latlng;
|
||||
}
|
||||
}).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 ");
|
||||
return;
|
||||
}
|
||||
return this.featureLookup[index].map((element, i) => {
|
||||
if (element instanceof L.RunwayNode) {
|
||||
element.setLatLng(latlng);
|
||||
}
|
||||
else if (element instanceof L.HoldNode) {
|
||||
element.setLatLng(latlng);
|
||||
}
|
||||
else if (element instanceof L.ParkingSpot) {
|
||||
// element.disableEdit();
|
||||
element.setLatLng(latlng);
|
||||
// element.enableEdit();
|
||||
// element.extensions();
|
||||
element.updateMiddleMarker();
|
||||
element.updateVertexFromDirection();
|
||||
element.updateWheelPos();
|
||||
element.updateBox();
|
||||
}
|
||||
else if (element instanceof L.Polyline) {
|
||||
element._latlngs.forEach((e1, index1) => {
|
||||
if (e1.attributes.index===index && (
|
||||
latlng.lat !== element.getLatLngs()[index1].lat ||
|
||||
latlng.lng !== element.getLatLngs()[index1].lng
|
||||
)
|
||||
) {
|
||||
element.getLatLngs()[index1].update(latlng);
|
||||
element.setLatLngs(element.getLatLngs());
|
||||
element.updateBeginVertex(latlng);
|
||||
element.editor.refresh();
|
||||
element.editor.reset();
|
||||
element.updateMiddle();
|
||||
}
|
||||
})
|
||||
} else if (element instanceof L.Editable.VertexMarker) {
|
||||
/*
|
||||
console.log(element);
|
||||
element.setLatLng(latlng);
|
||||
element.latlngs.forEach((latlng1, index) => {
|
||||
console.log(latlng1);
|
||||
if (latlng1.__vertex === element) {
|
||||
latlng1.update(latlng);
|
||||
}
|
||||
});
|
||||
element.editor.feature.setLatLngs(element.latlngs);
|
||||
element.editor.feature.updateMiddle();
|
||||
*/
|
||||
}
|
||||
});
|
||||
},
|
||||
refreshLookup(index) {
|
||||
//element.__vertex
|
||||
this.featureLookup[index] = this.featureLookup[index].filter(item => {
|
||||
return !(item instanceof L.Editable.VertexMarker && item.editor.__vertex === undefined)
|
||||
}
|
||||
);
|
||||
this.featureLookup[index].forEach((element, i) => {
|
||||
if (element instanceof L.Polyline) {
|
||||
element.editor.refresh();
|
||||
element.editor.reset();
|
||||
}
|
||||
});
|
||||
},
|
||||
removeNode (index) {
|
||||
if(this.featureLookup[index]===undefined) {
|
||||
console.error("Lookup " + index + " failed ");
|
||||
return;
|
||||
}
|
||||
this.featureLookup[index].forEach((element, i) => {
|
||||
if (element instanceof L.Polyline) {
|
||||
// element.latlngs.forEach();
|
||||
element._latlngs.forEach((e1, index1) => {
|
||||
console.log(e1);
|
||||
e1.__vertex.removeFrom(element.editor.editLayer);
|
||||
element._latlngs.splice(index1,1);
|
||||
if (element._latlngs.length==1) {
|
||||
this.featureLookup[index].splice(i,1);
|
||||
this.featureLookup[element._latlngs[0].__vertex.glueindex].forEach((otherEnd, j) => {
|
||||
console.log(j + ' ' + otherEnd);
|
||||
if(element === otherEnd){
|
||||
this.featureLookup[element._latlngs[0].__vertex.glueindex].splice(j,1);
|
||||
try {
|
||||
this.featureLookup[index].forEach((element, i) => {
|
||||
if (element instanceof L.Polyline) {
|
||||
console.debug('Poly : ' + i + ' ' + element.attributes);
|
||||
// Complete poly with be removed
|
||||
if ( element._latlngs.length <= 3 ) {
|
||||
console.debug('Remove short ' + element);
|
||||
if(Number(element.begin) !== index) {
|
||||
this.featureLookup[Number(element.begin)] = this.featureLookup[Number(element.begin)].filter(item => item !== element);
|
||||
this.refreshLookup(Number(element.begin))
|
||||
}
|
||||
if(Number(element.end) !== index) {
|
||||
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.$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);
|
||||
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.setEditlayer(this);
|
||||
polyline.enableEdit();
|
||||
polyline.editor.refresh();
|
||||
polyline.editor.reset();
|
||||
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);
|
||||
}
|
||||
if(element.getLatLngs().length === 1) {
|
||||
this.featureLookup[index] = this.featureLookup[index].filter(item => item !== element);
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
}
|
||||
// element.editor.splitShape(element._latlngs, index1);
|
||||
console.log('Removed');
|
||||
}
|
||||
});
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
}
|
||||
});
|
||||
} else if (element instanceof L.RunwayNode) {
|
||||
this.featureLookup[index] = this.featureLookup[index].filter(item => item !== element);
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
}
|
||||
});
|
||||
} else if (element instanceof L.RunwayNode) {
|
||||
console.log('Runway : ' + i + ' ' + element.attributes);
|
||||
this.featureLookup[index] = this.featureLookup[index].filter(item => item !== element);
|
||||
element.removeFrom(this.groundnetLayerGroup);
|
||||
} else {
|
||||
console.warn('WTF' + element);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
stopDrawing () {
|
||||
this.$parent.mapObject.editTools.stopDrawing()
|
||||
},
|
||||
drawPolyline () {
|
||||
var polyLine = this.$parent.mapObject.editTools.startPolyline()
|
||||
@@ -263,34 +554,160 @@
|
||||
event.target.addTo(this.groundnetLayerGroup)
|
||||
})
|
||||
},
|
||||
drawForwardPolyline () {
|
||||
var polyLine = this.$parent.mapObject.editTools.startPolyline()
|
||||
polyLine.addTo(this.groundnetLayerGroup)
|
||||
polyLine.groundnetLayerGroup = this.groundnetLayerGroup;
|
||||
polyLine.attributes = [];
|
||||
polyLine.options.attributes = {direction: 'forward' };
|
||||
polyLine.featureLookup = this.featureLookup;
|
||||
extendTaxiSegment(polyLine);
|
||||
polyLine.setEditlayer(this);
|
||||
//polyLine.extensions(this);
|
||||
polyLine.addListeners()
|
||||
|
||||
polyLine.on('editable:drawing:end', event => {
|
||||
console.debug(event)
|
||||
event.target.addTo(this.groundnetLayerGroup)
|
||||
})
|
||||
},
|
||||
drawPushbackPolyline () {
|
||||
var polyLine = this.$parent.mapObject.editTools.startPolyline()
|
||||
polyLine.addTo(this.groundnetLayerGroup)
|
||||
polyLine.groundnetLayerGroup = this.groundnetLayerGroup;
|
||||
polyLine.attributes = [];
|
||||
polyLine.options.attributes = {isPushBackRoute: 1, direction: 'bi-directional' };
|
||||
polyLine.featureLookup = this.featureLookup;
|
||||
extendTaxiSegment(polyLine);
|
||||
polyLine.setEditlayer(this);
|
||||
polyLine.updateStyle();
|
||||
//polyLine.extensions(this);
|
||||
polyLine.addListeners()
|
||||
|
||||
polyLine.on('editable:drawing:end', event => {
|
||||
console.debug(event)
|
||||
event.target.addTo(this.groundnetLayerGroup)
|
||||
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>";
|
||||
const icon = new L.DivIcon({
|
||||
className: 'custom-div-icon',
|
||||
html: fa_icon,
|
||||
iconSize: [30, 42],
|
||||
iconAnchor: [15, 42]
|
||||
});
|
||||
const node = new L.HoldNode(pt, { icon: icon });
|
||||
node.glueindex = nIndex;
|
||||
node.addTo(this.groundnetLayerGroup);
|
||||
node.featureLookup = this.featureLookup;
|
||||
node['holdPointType'] = 'PushBack'
|
||||
this.featureLookup[nIndex].push(node);
|
||||
node.addListeners();
|
||||
node.extensions();
|
||||
})
|
||||
},
|
||||
editedParking() {
|
||||
console.log(this.$store.state.Editable.data.parking)
|
||||
if (this.$store.state.Editable.index === undefined ||
|
||||
this.$store.state.Editable.data.parking === undefined ||
|
||||
this.featureLookup===undefined) {
|
||||
return
|
||||
}
|
||||
console.log('Edited Parking : ' + this.$store.state.Editable.data.parking)
|
||||
//Notify list
|
||||
if (this.featureLookup[this.$store.state.Editable.index]===undefined) {
|
||||
return
|
||||
}
|
||||
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();
|
||||
}
|
||||
})
|
||||
if (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");
|
||||
this.buildLookup()
|
||||
}
|
||||
if (this.featureLookup===undefined) {
|
||||
return
|
||||
}
|
||||
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) {
|
||||
element.options.attributes.name = newElement.name
|
||||
element.options.attributes.number = newElement.number
|
||||
element.options.attributes.type = newElement.type
|
||||
//element.updateVertexFromDirection();
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
/*
|
||||
this.$store.dispatch('updatedParking', this.$store.state.Editable.data.parking);
|
||||
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();
|
||||
}
|
||||
})
|
||||
*/
|
||||
},
|
||||
editedArc() {
|
||||
console.log('Edited Arc : ' + this.$store.state.Editable.index);
|
||||
if (!this.groundnetLayerGroup ||
|
||||
this.$store.state.Editable.index === undefined ||
|
||||
this.$store.state.Editable.data.arc === undefined ||
|
||||
this.featureLookup===undefined ||
|
||||
!this.editing) {
|
||||
return;
|
||||
}
|
||||
console.debug("Edit Type : " + this.$store.state.type);
|
||||
var arc = this.groundnetLayerGroup.getLayer(this.$store.state.Editable.index);
|
||||
if (arc && arc instanceof L.Polyline) {
|
||||
console.log('Edited Arc : ' + this.$store.state.Editable.index);
|
||||
arc.options.attributes = Object.assign({}, this.$store.state.Editable.data.arc)
|
||||
arc.updateStyle();
|
||||
}
|
||||
},
|
||||
editedMultiArc() {
|
||||
if (!this.groundnetLayerGroup ||
|
||||
this.$store.state.Editable.data.multiarc === undefined ||
|
||||
this.$store.state.Editable.data.multiarc.ids === undefined ||
|
||||
this.featureLookup===undefined ||
|
||||
!this.editing) {
|
||||
return;
|
||||
}
|
||||
console.debug("Edit Type : " + this.$store.state.Editable.data.multiarc.ids);
|
||||
this.$store.state.Editable.data.multiarc.ids.forEach(id => {
|
||||
console.debug(id);
|
||||
var arc = this.groundnetLayerGroup.getLayer(id);
|
||||
if (arc && arc instanceof L.Polyline) {
|
||||
console.log('Edited Arc : ' + this.$store.state.Editable.index);
|
||||
arc.options.attributes.direction = this.$store.state.Editable.data.multiarc.direction
|
||||
arc.options.attributes.name = this.$store.state.Editable.data.multiarc.name
|
||||
arc.options.attributes.isPushBackRoute = this.$store.state.Editable.data.multiarc.isPushBackRoute
|
||||
arc.updateStyle();
|
||||
}
|
||||
});
|
||||
},
|
||||
//Update Node
|
||||
editedNode() {
|
||||
if (this.$store.state.Editable.index === undefined ||
|
||||
this.$store.state.Editable.data.node === undefined ||
|
||||
this.featureLookup===undefined) {
|
||||
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;
|
||||
@@ -325,6 +742,7 @@
|
||||
iconAnchor: [15, 42]
|
||||
});
|
||||
|
||||
element['holdPointType'] = this.$store.state.Editable.data.node.holdPointType;
|
||||
element.setIcon(icon);
|
||||
}
|
||||
hasHoldPointNode = true;
|
||||
@@ -342,9 +760,13 @@
|
||||
latlng = element._latlngs[1];
|
||||
}
|
||||
} else if (element instanceof L.Polyline) {
|
||||
element._latlngs.forEach(element => {
|
||||
if(Number(element.__vertex.glueindex) === Number(nIndex)){
|
||||
latlng = element.__vertex.latlng;
|
||||
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)
|
||||
var position = new Coordinates(this.$store.state.Editable.data.node.coords);
|
||||
latlng = {lat: position.latitude, lng: position.longitude };
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -384,10 +806,12 @@
|
||||
node.addTo(this.groundnetLayerGroup);
|
||||
node.featureLookup = this.featureLookup;
|
||||
this.featureLookup[nIndex].push(node);
|
||||
node['holdPointType'] = this.$store.state.Editable.data.node.holdPointType;
|
||||
node.addListeners();
|
||||
node.extensions();
|
||||
}
|
||||
},
|
||||
// Finde nearest node
|
||||
closestLayerSnap (eventLatlng, snap) {
|
||||
var layers = []
|
||||
this.groundnetLayerGroup.eachLayer((layer) => {
|
||||
@@ -395,10 +819,15 @@
|
||||
// console.log(layer._latlngs)
|
||||
layer._latlngs.forEach(latlng => {
|
||||
if (latlng.__vertex) {
|
||||
let distance = latlng.distanceTo(eventLatlng)
|
||||
if (distance > 0 && distance < snap) {
|
||||
layers.push({d: distance, l: layer, latlng: latlng.__vertex.latlng, glueindex: latlng.__vertex.glueindex})
|
||||
if (Number.isNaN(latlng.glueindex)) {
|
||||
console.warn('No glueindex : ' + latlng.__vertex);
|
||||
}
|
||||
let distance = latlng.distanceTo(eventLatlng)
|
||||
if (distance >= 0 && distance < snap && latlng.glueindex >=0) {
|
||||
layers.push({d: distance, l: layer, latlng: latlng.__vertex.latlng, glueindex: latlng.glueindex})
|
||||
}
|
||||
} else {
|
||||
console.log(latlng);
|
||||
}
|
||||
})
|
||||
} else if (layer instanceof L.RunwayNode) {
|
||||
@@ -426,42 +855,168 @@
|
||||
}
|
||||
},
|
||||
drawParking () {
|
||||
this.$parent.mapObject._container.style.cursor = 'crosshair'
|
||||
this.$parent.mapObject.on('click', this.addParking)
|
||||
},
|
||||
removeLayerClick (event) {
|
||||
console.log(event)
|
||||
console.debug(event)
|
||||
this.groundnetLayerGroup.removeLayer(event.target)
|
||||
},
|
||||
addParking (event) {
|
||||
console.log(event.latlng)
|
||||
console.debug(event.latlng)
|
||||
if (event.latlng === undefined) {
|
||||
return
|
||||
}
|
||||
const circle = new L.ParkingSpot(event.latlng, {attributes: {radius: 20, heading: 0}})
|
||||
circle.id = (++this.groundnetLayerGroup.maxId)
|
||||
const newIndex = (++this.groundnetLayerGroup.maxId)
|
||||
const circle = new L.ParkingSpot(event.latlng, {attributes: {index: newIndex, radius: 26, heading: 0, type: 'gate'}})
|
||||
circle.id = newIndex
|
||||
circle.glueindex = circle.id
|
||||
circle.addTo(this.groundnetLayerGroup)
|
||||
circle.featureLookup = this.featureLookup
|
||||
circle.addListeners()
|
||||
circle.enableEdit()
|
||||
circle.extensions()
|
||||
circle.addListeners()
|
||||
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 => {
|
||||
if(element.deselect !== undefined) {
|
||||
element.deselect();
|
||||
}
|
||||
});
|
||||
}
|
||||
this.$store.dispatch('setParking', circle.options.attributes);
|
||||
this.$store.dispatch('setParkingCoords', circle.getLatLng().lat.toFixed(6) + ' ' + circle.getLatLng().lng.toFixed(6));
|
||||
circle.select()
|
||||
addFeature(circle)
|
||||
// console.log(this.groundnetLayerGroup)
|
||||
this.$parent.mapObject.off('click', this.addParking)
|
||||
this.$parent.mapObject._container.style.cursor = ''
|
||||
},
|
||||
reload (force) {
|
||||
this.load(this.icao, force)
|
||||
},
|
||||
link (index) {
|
||||
var layers = []
|
||||
var centerLatLng = null
|
||||
this.featureLookup[index].forEach(layer => {
|
||||
if (layer instanceof L.Polyline) {
|
||||
// console.log(layer._latlngs)
|
||||
layer._latlngs.forEach(latlng => {
|
||||
if (latlng.__vertex) {
|
||||
if (Number.isNaN(latlng.glueindex)) {
|
||||
console.warn('No glueindex : ' + latlng.__vertex);
|
||||
}
|
||||
|
||||
if (Number(latlng.glueindex) === index) {
|
||||
centerLatLng = latlng;
|
||||
}
|
||||
}
|
||||
})}
|
||||
})
|
||||
var newIndex = index
|
||||
var nearest = [];
|
||||
this.featureLookup.forEach(layers => {
|
||||
layers.forEach(layer => {
|
||||
if (layer instanceof L.ParkingSpot) {
|
||||
let distance = layer.getLatLng().distanceTo(centerLatLng);
|
||||
if (Number(layer.glueindex) !== newIndex && distance < 10) {
|
||||
nearest.push({d: distance, l: layer, glueindex: layer.glueindex })
|
||||
}
|
||||
}
|
||||
else if (layer instanceof L.Polyline) {
|
||||
// console.log(layer._latlngs)
|
||||
layer._latlngs.forEach(latlng => {
|
||||
if (latlng.__vertex) {
|
||||
if (Number.isNaN(latlng.glueindex)) {
|
||||
console.warn('No glueindex : ' + latlng.__vertex);
|
||||
}
|
||||
let distance = latlng.distanceTo(centerLatLng)
|
||||
if (Number(latlng.glueindex) !== Number(newIndex) && distance < 10) {
|
||||
nearest.push({d: distance, l: layer, latlng: latlng.__vertex.latlng, glueindex: latlng.glueindex })
|
||||
}
|
||||
} else {
|
||||
console.error("No __Vertex");
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
})
|
||||
var featureLookup = this.featureLookup;
|
||||
nearest = nearest.map(e => e.glueindex).filter((v, i, a) => a.indexOf(v) === i).filter(i => Number(i)!==newIndex)
|
||||
nearest.forEach(glueindex => {
|
||||
featureLookup[glueindex].forEach(layer => {
|
||||
featureLookup[newIndex].push(layer);
|
||||
if (layer instanceof L.RunwayNode) {
|
||||
layer.setLatLng(centerLatLng);
|
||||
}
|
||||
else if (layer instanceof L.HoldNode) {
|
||||
layer.setLatLng(centerLatLng);
|
||||
}
|
||||
else if (layer instanceof L.ParkingSpot) {
|
||||
layer.setLatLng(centerLatLng);
|
||||
layer.glueindex = String(newIndex);
|
||||
layer.id = String(newIndex);
|
||||
layer.options.attributes.index = newIndex;
|
||||
}
|
||||
else if (layer instanceof L.Polyline) {
|
||||
layer._latlngs.forEach((e1, index1) => {
|
||||
if (e1.attributes.index===Number(glueindex)) {
|
||||
if( Number(layer.begin)===Number(glueindex)) {
|
||||
layer.begin = String(newIndex);
|
||||
}
|
||||
if( Number(layer.end)===Number(glueindex)) {
|
||||
layer.end = String(newIndex);
|
||||
}
|
||||
e1.attributes.index = newIndex;
|
||||
e1.glueindex = newIndex;
|
||||
|
||||
layer.getLatLngs()[index1].update(centerLatLng);
|
||||
layer.editor.refresh();
|
||||
layer.editor.reset();
|
||||
layer.updateMiddle();
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
featureLookup[glueindex] = [];
|
||||
});
|
||||
},
|
||||
save () {
|
||||
var xml = []
|
||||
this.groundnetLayerGroup.eachLayer(l => {
|
||||
console.log(l)
|
||||
//console.debug(l)
|
||||
xml.push(l)
|
||||
})
|
||||
writeGroundnetXML(this.$store.state.Settings.settings.airportsDirectory, this.icao, xml)
|
||||
this.load(this.icao, false)
|
||||
},
|
||||
//Copy to test directory
|
||||
test() {
|
||||
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 fNew = path.join(this.$store.state.Settings.settings.testDirectory, 'Airports', this.icao[0], this.icao[1], this.icao[2], this.icao + '.groundnet.xml');
|
||||
try { fs.mkdirSync(path.join(this.$store.state.Settings.settings.testDirectory, 'Airports'), { recursive: true })} catch (err) { }
|
||||
try { fs.mkdirSync(path.join(this.$store.state.Settings.settings.testDirectory, 'Airports', this.icao[0]),{ recursive: true })} catch (err) { }
|
||||
try { fs.mkdirSync(path.join(this.$store.state.Settings.settings.testDirectory, 'Airports', this.icao[0], this.icao[1]), { recursive: true })} catch (err) { }
|
||||
try { fs.mkdirSync(path.join(this.$store.state.Settings.settings.testDirectory, 'Airports', this.icao[0], this.icao[1], this.icao[2]), { recursive: true })} catch (err) { }
|
||||
|
||||
try {
|
||||
fs.copyFileSync(f, fNew)
|
||||
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 {
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
<template>
|
||||
<label class="file-select">
|
||||
<div class="select-button">
|
||||
<span v-if="value">Selected File: {{value.name}}</span>
|
||||
<span v-else>Select File</span>
|
||||
...
|
||||
</div>
|
||||
<input type="file" @change="handleFileChange"/>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
|
||||
@@ -1,47 +1,75 @@
|
||||
<!--
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template>
|
||||
<l-map
|
||||
:zoom="zoom"
|
||||
:center="center"
|
||||
:options="options"
|
||||
@ready="ready"
|
||||
@update:zoom="zoomUpdated"
|
||||
@update:center="centerUpdated"
|
||||
@update:bounds="boundsUpdated"
|
||||
ref="map"
|
||||
>
|
||||
<!--The backgroundmap-->
|
||||
<l-tile-layer :url="url" :attribution="attribution">
|
||||
</l-tile-layer>
|
||||
<l-tile-layer :url="url" :attribution="attribution" :options="{maxZoom: 22, maxNativeZoom: 17}"></l-tile-layer>
|
||||
<!--
|
||||
<l-control position="topright" >
|
||||
<el-button @click="editAirport()">{{ icao }}</el-button>
|
||||
</l-control>
|
||||
-->
|
||||
<!--<l-marker :lat-lng="marker"></l-marker>-->
|
||||
<LeafletSidebar></LeafletSidebar>
|
||||
<EditBar></EditBar>
|
||||
<PavementLayer ref="pavementLayer"></PavementLayer>
|
||||
<LeafletSidebar ref="sidebar" @editParking="onEditSidebar" @edit="onEdit($event)"></LeafletSidebar>
|
||||
<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"
|
||||
:key="index"
|
||||
:lat-lng="[item.geometry.coordinates[1], item.geometry.coordinates[0]]"
|
||||
:radius="((item.properties.flights+5)*20)"
|
||||
:color='item.color'
|
||||
:color="item.color"
|
||||
@add="addEvent($event, item)"
|
||||
@click="onClick(item)"
|
||||
@click="onClick($event, item)"
|
||||
></l-circle>
|
||||
</l-layer-group>
|
||||
<EditLayer ref="editLayer"></EditLayer>
|
||||
<PavementLayer ref="pavementLayer"></PavementLayer>
|
||||
<ThresholdLayer ref="thresholdLayer"></ThresholdLayer>
|
||||
<TowerLayer ref="towerLayer"></TowerLayer>
|
||||
<ToolLayer ref="toolLayer" @select-poly="onSelectedPolygon"></ToolLayer>
|
||||
<EditBar ref="editBar" @edit="onEdit($event)"></EditBar>
|
||||
<ToolBar ref="toolBar"></ToolBar>
|
||||
</l-map>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import 'leaflet/dist/leaflet.css'
|
||||
import { LMap, LTileLayer, LMarker, LCircle, LLayerGroup } from 'vue2-leaflet'
|
||||
import '@/assets/button.css'
|
||||
import { LMap, LTileLayer, LMarker, LCircle, LLayerGroup, LControl } from 'vue2-leaflet'
|
||||
import LeafletSidebar from './LeafletSidebar'
|
||||
import AiLayer from './AiLayer'
|
||||
import EditBar from './EditBar'
|
||||
import ToolBar from './ToolBar'
|
||||
import EditLayer from './EditLayer'
|
||||
import ToolLayer from './ToolLayer'
|
||||
import TowerLayer from './TowerLayer'
|
||||
import PavementLayer from './PavementLayer'
|
||||
import ThresholdLayer from './ThresholdLayer'
|
||||
|
||||
import { Loading } from 'element-ui'
|
||||
import L from 'leaflet'
|
||||
|
||||
// https://github.com/KoRiGaN/Vue2Leaflet/issues/103
|
||||
delete L.Icon.Default.prototype._getIconUrl
|
||||
|
||||
L.Icon.Default.mergeOptions({
|
||||
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
|
||||
iconUrl: require('leaflet/dist/images/marker-icon.png'),
|
||||
@@ -49,46 +77,214 @@
|
||||
})
|
||||
export default {
|
||||
name: 'flightgear-map',
|
||||
components: { LMap, LTileLayer, LMarker, LCircle, LeafletSidebar, EditBar, EditLayer, PavementLayer, LLayerGroup },
|
||||
components: { LMap, LTileLayer, LMarker, LCircle, LeafletSidebar, AiLayer, EditBar, ToolBar, EditLayer, TowerLayer, PavementLayer, LLayerGroup, LControl, ThresholdLayer, ToolLayer },
|
||||
props: [],
|
||||
created () {
|
||||
this.loadingInstance = null
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Loading.icao
|
||||
},
|
||||
(newValue, oldValue) => {
|
||||
// debugger
|
||||
console.log('setIcaoLoading ' + oldValue + ' => ' + newValue + ' groundnetLoaded ' + this.groundnetLoaded + ' pavementLoaded ' + this.pavementLoaded + ' ' + this.loadingInstance)
|
||||
if (newValue !== oldValue && newValue !== '') {
|
||||
this.groundnetLoaded = newValue
|
||||
if ((this.loadingInstance === null || this.loadingInstance === undefined)) {
|
||||
this.loadingInstance = Loading.service({ fullscreen: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
,
|
||||
{
|
||||
deep: false,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Loading.groundnetLoaded
|
||||
},
|
||||
(newValue, oldValue) => {
|
||||
// debugger
|
||||
console.log('groundnetLoaded ' + oldValue + ' => ' + newValue + ' groundnetLoaded ' + this.groundnetLoaded + ' pavementLoaded ' + this.pavementLoaded + ' ' + this.loadingInstance)
|
||||
if (newValue !== oldValue) {
|
||||
this.groundnetLoaded = newValue
|
||||
if (this.groundnetLoaded &&
|
||||
this.pavementLoaded &&
|
||||
this.loadingInstance !== null) {
|
||||
this.loadingInstance.close()
|
||||
this.loadingInstance = null
|
||||
}
|
||||
}
|
||||
}
|
||||
,
|
||||
{
|
||||
deep: false,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Loading.pavementLoaded
|
||||
},
|
||||
(newValue, oldValue) => {
|
||||
console.log('pavementLoaded ' + oldValue + ' => ' + newValue + ' ' + this.groundnetLoaded + ' ' + this.pavementLoaded + ' ' + this.loadingInstance)
|
||||
if (newValue !== oldValue) {
|
||||
this.pavementLoaded = newValue
|
||||
if (this.groundnetLoaded &&
|
||||
this.pavementLoaded &&
|
||||
this.loadingInstance !== null) {
|
||||
this.loadingInstance.close()
|
||||
this.loadingInstance = null
|
||||
}
|
||||
}
|
||||
}
|
||||
,
|
||||
{
|
||||
deep: false,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
},
|
||||
mounted () {
|
||||
this.$store.dispatch('getAirports')
|
||||
this.$store.subscribe((mutation, state) => {
|
||||
if (mutation.type === 'BOUNDS' || mutation.type === 'SET_AIRPORTS') {
|
||||
if (mutation.type === 'CENTER' || mutation.type === 'SET_AIRPORTS' || mutation.type === 'ZOOM') {
|
||||
// console.log(this.$parent)
|
||||
// console.log(this.$store.state.Settings.bounds)
|
||||
let airportsToLoad = this.$store.state.Airports.airports
|
||||
.filter(feature => this.visible(feature))
|
||||
.map(feature => feature.properties.icao)
|
||||
if (airportsToLoad.length > 0 && airportsToLoad[0] !== this.editingAirport && this.zoom > 12) {
|
||||
this.$refs.editLayer.load(airportsToLoad[0])
|
||||
this.$refs.pavementLayer.load(airportsToLoad[0])
|
||||
this.editingAirport = airportsToLoad[0]
|
||||
this.$store.dispatch('setIcaoLoading', airportsToLoad[0])
|
||||
this.$nextTick(() => { // Loading should be closed asynchronously
|
||||
this.$refs.pavementLayer.load(airportsToLoad[0])
|
||||
this.$refs.editLayer.load(airportsToLoad[0])
|
||||
this.$refs.thresholdLayer.load(airportsToLoad[0])
|
||||
if (this.$refs.towerLayer) {
|
||||
this.$refs.towerLayer.load(airportsToLoad[0])
|
||||
}
|
||||
this.editingAirport = airportsToLoad[0]
|
||||
})
|
||||
}
|
||||
if (this.$refs.editLayer) {
|
||||
this.$refs.editLayer.setVisible(this.zoom >= 12)
|
||||
}
|
||||
if (this.$refs.airportLayer) {
|
||||
this.$refs.airportLayer.setVisible(this.zoom < 12)
|
||||
}
|
||||
this.$refs.editLayer.setVisible(this.zoom >= 12)
|
||||
this.$refs.airportLayer.setVisible(this.zoom < 12)
|
||||
|
||||
// console.log(this.groundnet)
|
||||
}
|
||||
})
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 'http://{s}.tile.osm.org/{z}/{x}/{y}.png'
|
||||
loadingInstance: Object,
|
||||
groundnetLoaded: false,
|
||||
pavementLoaded: false,
|
||||
url: 'https://a.tile.openstreetmap.de/{z}/{x}/{y}.png',
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
|
||||
marker: L.latLng(47.413220, -1.219482),
|
||||
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> ' +
|
||||
' © <a href="http://osm.org/copyright" target="_blank">OpenStreetMap</a> contributors',
|
||||
airports: this.$store.state.Airports.airports,
|
||||
options: {editable: true}
|
||||
options: {editable: true},
|
||||
layersControl: null,
|
||||
icao: 'TEST'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
visible (feature) {
|
||||
let bounds = this.$store.state.Settings.bounds
|
||||
if (!bounds.hasOwnProperty('getNorthEast')) {
|
||||
bounds = this.$refs.map.mapObject.getBounds()
|
||||
ready (e) {
|
||||
e.on('layeradd', this.onLayerAdd)
|
||||
},
|
||||
onLayerAdd (e) {
|
||||
if (this.layersControl === null) {
|
||||
this.layersControl = L.control.layers({}, {}, {position: 'topleft'})
|
||||
this.layersControl.addTo(this.$refs.map.mapObject)
|
||||
var icon = this.layersControl._container.ownerDocument.createElement('I')
|
||||
icon.className = 'fas fa-layer-group'
|
||||
icon.style = 'padding-top: 9px; height: 30px; width: 30px; text-align: center; vertical-align: sub;'
|
||||
this.layersControl._container.children[0].appendChild(icon)
|
||||
// this.layersControl.addOverlay(this.$refs.thresholdLayer, 'Threshold Layer')
|
||||
}
|
||||
let width = bounds.getNorthWest().distanceTo(bounds.getSouthEast())
|
||||
if (this.$refs.pavementLayer.getLayer() === e.layer) {
|
||||
// debugger
|
||||
var l = this.layersControl._layers.filter(l => l.name === 'APT Layer')
|
||||
if (l.length > 0 && l[0].layer !== this.$refs.pavementLayer.getLayer()) {
|
||||
this.layersControl.removeLayer(l[0].layer)
|
||||
this.layersControl.addOverlay(this.$refs.pavementLayer.getLayer(), 'APT Layer')
|
||||
}
|
||||
if (l.length === 0) {
|
||||
this.layersControl.addOverlay(this.$refs.pavementLayer.getLayer(), 'APT Layer')
|
||||
}
|
||||
}
|
||||
if (this.$refs.thresholdLayer !== undefined && this.$refs.thresholdLayer.getLayer() === e.layer) {
|
||||
l = this.layersControl._layers.filter(l => l.name === 'Threshold Layer')
|
||||
if (l.length > 0 && l[0].layer !== this.$refs.thresholdLayer.getLayer()) {
|
||||
this.layersControl.removeLayer(l[0].layer)
|
||||
this.layersControl.addOverlay(this.$refs.thresholdLayer.getLayer(), 'Threshold Layer')
|
||||
}
|
||||
if (l.length === 0) {
|
||||
this.layersControl.addOverlay(this.$refs.thresholdLayer.getLayer(), 'Threshold Layer')
|
||||
}
|
||||
this.$refs.thresholdLayer.zoomUpdated()
|
||||
}
|
||||
if (this.$refs.towerLayer !== undefined && this.$refs.towerLayer.getLayer() === e.layer) {
|
||||
l = this.layersControl._layers.filter(l => l.name === 'Tower Layer')
|
||||
if (l.length > 0 && l[0].layer !== this.$refs.towerLayer.getLayer()) {
|
||||
this.layersControl.removeLayer(l[0].layer)
|
||||
this.layersControl.addOverlay(this.$refs.towerLayer.getLayer(), 'Tower Layer')
|
||||
}
|
||||
if (l.length === 0) {
|
||||
this.layersControl.addOverlay(this.$refs.towerLayer.getLayer(), 'Tower Layer')
|
||||
}
|
||||
this.$refs.towerLayer.zoomUpdated()
|
||||
}
|
||||
},
|
||||
onSelectedPolygon (ring) {
|
||||
var parkings = this.$refs.editLayer.getParkings(ring)
|
||||
console.debug(ring)
|
||||
console.debug(parkings)
|
||||
|
||||
this.$store.commit('SET_EDIT_TYPE', 'parking-group')
|
||||
this.$refs.sidebar.setData(parkings)
|
||||
},
|
||||
onEdit (event) {
|
||||
if (event) {
|
||||
this.$refs.map.mapObject.options.minZoom = 13
|
||||
} else {
|
||||
this.$refs.map.mapObject.options.minZoom = 1
|
||||
}
|
||||
this.$refs.editLayer.enableEdit()
|
||||
this.$refs.towerLayer.enableEdit()
|
||||
this.$refs.editBar.setEditing(event)
|
||||
this.$refs.toolBar.setEditing(event)
|
||||
this.$refs.sidebar.setEditing(event)
|
||||
},
|
||||
onEditSidebar (event) {
|
||||
this.$refs.editLayer.onEdit(event)
|
||||
},
|
||||
editAirport () {
|
||||
if (this.editingAirport) {
|
||||
let airportsToLoad = this.$store.state.Airports.airports
|
||||
.filter(feature => feature.properties.icao === this.icao)
|
||||
let properties = Object.assign({}, airportsToLoad[0].properties)
|
||||
this.$store.commit('SET_EDIT_AIRPORT', properties)
|
||||
}
|
||||
},
|
||||
setIcao (icao) {
|
||||
this.icao = icao
|
||||
this.$store.dispatch('setCurrentAirport', icao)
|
||||
},
|
||||
visible (feature) {
|
||||
let bounds
|
||||
if (this.$refs.map) {
|
||||
bounds = this.$refs.map.mapObject.getBounds()
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
let width = L.latLng(bounds._northEast).distanceTo(L.latLng(bounds._southWest))
|
||||
// Load all airports in a minimum 5 km box
|
||||
if (width < 5000) {
|
||||
let rest = 5000 - width
|
||||
@@ -97,49 +293,106 @@
|
||||
}
|
||||
|
||||
let coordinates = feature.geometry.coordinates
|
||||
let ret = bounds.getNorthEast().lat > Number(coordinates[1]) &&
|
||||
bounds.getNorthEast().lng > Number(coordinates[0])
|
||||
let ret2 = bounds.getSouthWest().lat < Number(coordinates[1]) &&
|
||||
bounds.getSouthWest().lng < Number(coordinates[0])
|
||||
let ret = bounds._northEast.lat > Number(coordinates[1]) &&
|
||||
bounds._northEast.lng > Number(coordinates[0])
|
||||
let ret2 = bounds._southWest.lat < Number(coordinates[1]) &&
|
||||
bounds._southWest.lng < Number(coordinates[0])
|
||||
return ret && ret2
|
||||
},
|
||||
normalStyle (target) {
|
||||
if (target.airport.properties.groundnet === 0) {
|
||||
target.setStyle({color: 'red', fillColor: 'red', weight: '2'})
|
||||
} else if ((target.airport.properties.flights / target.airport.properties.parking) > 40) {
|
||||
target.setStyle({color: 'yellow', fillColor: 'yellow', weight: '2'})
|
||||
} else {
|
||||
target.setStyle({color: '#3388ff', fillColor: '#3388ff', weight: '2'})
|
||||
}
|
||||
},
|
||||
highlightStyle (target) {
|
||||
if (target.airport.properties.groundnet === 0) {
|
||||
target.setStyle({color: 'red', fillColor: 'red', weight: '5'})
|
||||
} else if ((target.airport.properties.flights / target.airport.properties.parking) > 40) {
|
||||
target.setStyle({color: 'yellow', fillColor: 'yellow', weight: '5'})
|
||||
} else {
|
||||
target.setStyle({color: '#3388ff', fillColor: '#3388ff', weight: '5'})
|
||||
}
|
||||
},
|
||||
// Triggered by adding airports to the map
|
||||
addEvent (event, item) {
|
||||
this.selected = null
|
||||
event.target.airport = item
|
||||
// console.log(event, item)
|
||||
if (item.properties.groundnet === 0) {
|
||||
event.target.setStyle({color: 'red', fillColor: 'red'})
|
||||
} else if ((item.properties.flights / item.properties.parking) > 40) {
|
||||
event.target.setStyle({color: 'yellow', fillColor: 'yellow'})
|
||||
}
|
||||
this.normalStyle(event.target)
|
||||
},
|
||||
onClick (item) {
|
||||
onClick (event, item) {
|
||||
console.log(item)
|
||||
if (this.selected !== null) {
|
||||
this.normalStyle(this.selected)
|
||||
}
|
||||
this.selected = event.target
|
||||
this.highlightStyle(this.selected)
|
||||
event.target.bringToBack()
|
||||
this.setIcao(item.properties.icao)
|
||||
this.$store.commit('SET_EDIT_AIRPORT', item.properties)
|
||||
let newCenter = L.latLng(item.geometry.coordinates[1], item.geometry.coordinates[0])
|
||||
this.$refs.map.setCenter(newCenter)
|
||||
},
|
||||
zoomUpdated (zoom) {
|
||||
if (zoom !== this.$store.state.Settings.zoom) {
|
||||
this.$store.dispatch('setZoom', zoom)
|
||||
this.$refs.airportLayer.setVisible(zoom < 12)
|
||||
if (this.$refs.towerLayer) {
|
||||
this.$refs.towerLayer.setVisible(this.zoom >= 12)
|
||||
}
|
||||
if (this.$refs.thresholdLayer) {
|
||||
this.$refs.thresholdLayer.setVisible(this.zoom >= 12)
|
||||
}
|
||||
this.$refs.pavementLayer.setVisible(zoom >= 12)
|
||||
}
|
||||
if (this.$refs.editLayer.groundnetLayerGroup) {
|
||||
this.$refs.editLayer.groundnetLayerGroup.eachLayer(function (layer) {
|
||||
if (layer.updateArrows !== undefined) {
|
||||
layer.updateArrows(zoom)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (this.$refs.thresholdLayer) {
|
||||
this.$refs.thresholdLayer.zoomUpdated()
|
||||
}
|
||||
if (this.$refs.towerLayer) {
|
||||
this.$refs.towerLayer.zoomUpdated()
|
||||
}
|
||||
},
|
||||
async centerUpdated (center) {
|
||||
if (center !== this.$store.state.Settings.center) {
|
||||
this.$store.dispatch('setCenter', center)
|
||||
this.$refs.airportLayer.setVisible(this.zoom < 12)
|
||||
if (this.$refs.thresholdLayer) {
|
||||
this.$refs.thresholdLayer.setVisible(this.zoom >= 12)
|
||||
}
|
||||
if (this.$refs.towerLayer) {
|
||||
this.$refs.towerLayer.setVisible(this.zoom >= 12)
|
||||
}
|
||||
this.$refs.pavementLayer.setVisible(this.zoom >= 12)
|
||||
}
|
||||
},
|
||||
async boundsUpdated (bounds) {
|
||||
/*
|
||||
if (bounds !== this.$store.state.Settings.bounds) {
|
||||
this.$store.dispatch('setBounds', bounds)
|
||||
this.$refs.airportLayer.setVisible(this.zoom < 12)
|
||||
this.$refs.pavementLayer.setVisible(this.zoom < 12)
|
||||
}
|
||||
*/
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
zoom: function () {
|
||||
return this.$store.state.Settings.zoom
|
||||
},
|
||||
isEditing: function () {
|
||||
return this.$refs.editLayer !== undefined && this.$refs.editLayer.editing
|
||||
},
|
||||
center: function () {
|
||||
return this.$store.state.Settings.center
|
||||
}
|
||||
@@ -157,4 +410,17 @@
|
||||
.flightgear-map {
|
||||
color: aqua;
|
||||
}
|
||||
.item {
|
||||
padding: 18px 0;
|
||||
}
|
||||
.l-control.el-card {
|
||||
padding-left: 2px;
|
||||
padding-top: 0px;
|
||||
padding-right: 2px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers-toggle {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
124
src/renderer/components/Frequency.vue
Normal file
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<div>
|
||||
<span>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<el-select v-model="type" placeholder="Select" :disabled="!editing">
|
||||
<el-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
:label="type.label"
|
||||
:value="type.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="13">
|
||||
<el-input
|
||||
placeholder="Please input frequency"
|
||||
v-model="value"
|
||||
:disabled="!editing"
|
||||
v-bind:class="{ invalid: !ok && editing}"
|
||||
></el-input>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<el-button @click="remove" v-if="editing" ><i class="fas fa-trash-alt"></i></el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="js">
|
||||
import EditButton from './EditButton'
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
name: 'frequency',
|
||||
components: { EditButton },
|
||||
props: {frequency: Object},
|
||||
mounted () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
ok: true, editLayer: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
remove () {
|
||||
this.$store.dispatch('removeFrequency', this.frequency)
|
||||
},
|
||||
isValid (frequency) {
|
||||
let ok = frequency >= 11800 && frequency <= 13700
|
||||
if (!ok) {
|
||||
return false
|
||||
}
|
||||
let fractions = (frequency - (Math.trunc(frequency/100)*100))
|
||||
let subFraction = Math.round(fractions % 25)
|
||||
switch (subFraction) {
|
||||
case 0:
|
||||
break
|
||||
case 5:
|
||||
break
|
||||
case 10:
|
||||
break
|
||||
case 15:
|
||||
break
|
||||
case 25:
|
||||
break
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
initLayer() {
|
||||
var parent = this.$parent
|
||||
while (parent.$refs.editLayer===undefined) {
|
||||
parent = parent.$parent
|
||||
}
|
||||
this.editLayer = parent.$refs.editLayer
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
editing: function () {
|
||||
if(this.editLayer=== null)
|
||||
this.initLayer()
|
||||
return this.editLayer.editing
|
||||
},
|
||||
options: function () {
|
||||
return [
|
||||
{value: 'AWOS', label: 'AWOS'},
|
||||
{value: 'GROUND', label: 'GROUND'},
|
||||
{value: 'TOWER', label: 'TOWER'},
|
||||
{value: 'APPROACH', label: 'APPROACH'},
|
||||
{value: 'DEPARTURE', label: 'DEPARTURE'}
|
||||
]
|
||||
},
|
||||
type: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.frequency.type;
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.frequency.type = newValue;
|
||||
}
|
||||
},
|
||||
value: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.frequency.value;
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.frequency.value = newValue;
|
||||
this.ok = this.isValid(newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.invalid {
|
||||
padding: 1px;
|
||||
background-color: red;
|
||||
}
|
||||
</style>
|
||||
71
src/renderer/components/Help.vue
Normal file
@@ -0,0 +1,71 @@
|
||||
<!--
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template>
|
||||
<div class="leaflet-sidebar-pane" id="home">
|
||||
<h1 class="leaflet-sidebar-header">
|
||||
{{version}}
|
||||
<div class="leaflet-sidebar-close"><i class="fa fa-caret-left"></i></div>
|
||||
</h1>
|
||||
<h2>Setup</h2>
|
||||
<ol>
|
||||
<li>Set directories in settings (bottom left)</li>
|
||||
<li>Start scans one after the other in sidebar with magnifying glass.</li>
|
||||
</ol>
|
||||
<h2>Search</h2>
|
||||
You can search for airports with ICAO or parts of the name. Only airports with flights are shown.
|
||||
If you want to view another one it will be added when you type the full ICAO.
|
||||
<h2>World view</h2>
|
||||
<p>
|
||||
When zoomed out you will see circles. Their size corresponds with the number of flights.
|
||||
Blue means Ok. Yellow to little parking in comparison to the number of flights. Red no groundnet.
|
||||
</p>
|
||||
<h2>Edit view</h2>
|
||||
<p>
|
||||
</p>
|
||||
<ul>
|
||||
<li>Undo undos all changes or all changes during session</li>
|
||||
<li>Save, saves the groundnet</li>
|
||||
<li>Check triggers the groundnet check.</li>
|
||||
<li>Draw bi directional taxiline</li>
|
||||
<li>Draw uni directional taxiline</li>
|
||||
<li>Draw pushback.</li>
|
||||
<li>Add parking</li>
|
||||
<li>Remove element, removes the currently selected element</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
export default {
|
||||
name: 'help',
|
||||
props: [],
|
||||
mounted () {
|
||||
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
computed: {
|
||||
version: function () {
|
||||
return ' Flightgear Airports ' + require('electron').remote.app.getVersion()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
@@ -1,128 +0,0 @@
|
||||
<template>
|
||||
<div id="wrapper">
|
||||
<img id="logo" src="~@/assets/logo.png" alt="electron-vue">
|
||||
<main>
|
||||
<div class="left-side">
|
||||
<span class="title">
|
||||
Welcome to your new project!
|
||||
</span>
|
||||
<system-information></system-information>
|
||||
</div>
|
||||
|
||||
<div class="right-side">
|
||||
<div class="doc">
|
||||
<div class="title">Getting Started</div>
|
||||
<p>
|
||||
electron-vue comes packed with detailed documentation that covers everything from
|
||||
internal configurations, using the project structure, building your application,
|
||||
and so much more.
|
||||
</p>
|
||||
<button @click="open('https://simulatedgreg.gitbooks.io/electron-vue/content/')">Read the Docs</button><br><br>
|
||||
</div>
|
||||
<div class="doc">
|
||||
<div class="title alt">Other Documentation</div>
|
||||
<button class="alt" @click="open('https://electron.atom.io/docs/')">Electron</button>
|
||||
<button class="alt" @click="open('https://vuejs.org/v2/guide/')">Vue.js</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SystemInformation from './LandingPage/SystemInformation'
|
||||
|
||||
export default {
|
||||
name: 'landing-page',
|
||||
components: { SystemInformation },
|
||||
methods: {
|
||||
open (link) {
|
||||
this.$electron.shell.openExternal(link)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro');
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body { font-family: 'Source Sans Pro', sans-serif; }
|
||||
|
||||
#wrapper {
|
||||
background:
|
||||
radial-gradient(
|
||||
ellipse at top left,
|
||||
rgba(255, 255, 255, 1) 40%,
|
||||
rgba(229, 229, 229, .9) 100%
|
||||
);
|
||||
height: 100vh;
|
||||
padding: 60px 80px;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
#logo {
|
||||
height: auto;
|
||||
margin-bottom: 20px;
|
||||
width: 420px;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
main > div { flex-basis: 50%; }
|
||||
|
||||
.left-side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.welcome {
|
||||
color: #555;
|
||||
font-size: 23px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #2c3e50;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.title.alt {
|
||||
font-size: 18px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.doc p {
|
||||
color: black;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.doc button {
|
||||
font-size: .8em;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
padding: 0.75em 2em;
|
||||
border-radius: 2em;
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
background-color: #4fc08d;
|
||||
transition: all 0.15s ease;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #4fc08d;
|
||||
}
|
||||
|
||||
.doc button.alt {
|
||||
color: #42b983;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
@@ -1,39 +1,54 @@
|
||||
<!--
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template>
|
||||
<div id="sidebar" class="leaflet-sidebar collapsed">
|
||||
<Upload :visible.sync="uploadVisible" ref="upload"></Upload>
|
||||
<!-- Nav tabs -->
|
||||
<div class="leaflet-sidebar-tabs">
|
||||
<ul role="tablist"> <!-- top aligned tabs -->
|
||||
<li><a href="#home" role="tab"><i class="fa fa-bars"></i></a></li>
|
||||
<li><a href="#edit" role="tab"><i class="fas fa-edit"></i></a></li>
|
||||
<!--<li><a href="#parking" role="tab"><i class="fas fa-parking"></i></a></li>-->
|
||||
<li :v-if="results"><a href="#check" role="tab"><i class="far fa-check-square"></i></a></li>
|
||||
<li><a href="#search" role="tab"><i class="fa fa-search"></i></a></li>
|
||||
<li><a href="#scan" role="tab"><i class="fa fa-sync"></i></a></li>
|
||||
<li><a href="#check" role="tab"><i class="far fa-check-square"></i></a></li>
|
||||
<li><a href="#wip" role="tab"><i class="fas fa-wrench"></i></a></li>
|
||||
</ul>
|
||||
|
||||
<ul role="tablist"> <!-- bottom aligned tabs -->
|
||||
<li><a href="#scan" role="tab"><i class="fa fa-sync"></i></a></li>
|
||||
<li><a href="#settings" role="tab"><i class="fas fa-cog"></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<div class="leaflet-sidebar-content">
|
||||
<div class="leaflet-sidebar-pane" id="home">
|
||||
<h1 class="leaflet-sidebar-header">
|
||||
Help
|
||||
<div class="leaflet-sidebar-close"><i class="fa fa-caret-left"></i></div>
|
||||
</h1>
|
||||
<p>A responsive sidebar for mapping libraries</p>
|
||||
</div>
|
||||
<Help/>
|
||||
<div class="leaflet-sidebar-pane" id="edit">
|
||||
<h1 class="leaflet-sidebar-header">
|
||||
Properties
|
||||
<div class="leaflet-sidebar-close"><i class="fa fa-caret-left"></i></div>
|
||||
</h1>
|
||||
<AirportEdit></AirportEdit>
|
||||
<ParkingEdit></ParkingEdit>
|
||||
<ArcEditMulti></ArcEditMulti>
|
||||
<ArcEdit></ArcEdit>
|
||||
<NodeEdit></NodeEdit>
|
||||
<NodeEdit></NodeEdit>
|
||||
<ParkingGroupEdit ref="parkingGroupEdit" @editParking="(msg) => $emit('editParking', msg)"></ParkingGroupEdit>
|
||||
<AirportEdit ref="airportEdit" @edit="$emit('edit', $event)"></AirportEdit>
|
||||
</div>
|
||||
<!--
|
||||
<div class="leaflet-sidebar-pane" id="parking">
|
||||
<ParkingList></ParkingList>
|
||||
</div>
|
||||
-->
|
||||
<div class="leaflet-sidebar-pane" id="search">
|
||||
<Search></Search>
|
||||
</div>
|
||||
@@ -46,6 +61,9 @@
|
||||
<div class="leaflet-sidebar-pane" id="check">
|
||||
<CheckPanel></CheckPanel>
|
||||
</div>
|
||||
<div class="leaflet-sidebar-pane" id="wip">
|
||||
<WorkInProgress></WorkInProgress>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -56,19 +74,31 @@
|
||||
import {} from 'leaflet-sidebar-v2'
|
||||
import L from 'leaflet'
|
||||
import AirportEdit from './AirportEdit'
|
||||
import CheckPanel from './CheckPanel'
|
||||
import ParkingEdit from './ParkingEdit'
|
||||
import ArcEdit from './ArcEdit'
|
||||
import ArcEditMulti from './ArcEditMulti'
|
||||
import CheckPanel from './CheckPanel'
|
||||
import FileSelect from './FileSelect'
|
||||
import Help from './Help'
|
||||
import NodeEdit from './NodeEdit'
|
||||
import ParkingEdit from './ParkingEdit'
|
||||
import ParkingGroupEdit from './ParkingGroupEdit'
|
||||
// import ParkingList from './ParkingList'
|
||||
import RunScan from './RunScan'
|
||||
import SettingsPanel from './SettingsPanel'
|
||||
import Search from './Search'
|
||||
import Upload from './Upload'
|
||||
import WorkInProgress from './WorkInProgress'
|
||||
|
||||
export default {
|
||||
name: 'leaflet-sidebar',
|
||||
components: { AirportEdit, ArcEdit, CheckPanel, NodeEdit, ParkingEdit, SettingsPanel, RunScan, FileSelect, Search },
|
||||
components: { Help, AirportEdit, ArcEdit, ArcEditMulti, CheckPanel, NodeEdit, ParkingEdit, ParkingGroupEdit, RunScan, FileSelect, SettingsPanel, Search, Upload, WorkInProgress },
|
||||
props: [],
|
||||
created () {
|
||||
window.addEventListener('keydown', this.doCommand)
|
||||
},
|
||||
destroyed () {
|
||||
window.removeEventListener('keydown', this.doCommand)
|
||||
},
|
||||
mounted () {
|
||||
this.add()
|
||||
},
|
||||
@@ -76,18 +106,41 @@
|
||||
this.remove()
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
return { uploadVisible: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
doCommand (e) {
|
||||
let cmd = String.fromCharCode(e.keyCode).toLowerCase()
|
||||
if (e.keyCode === 46 /** DEL */ && e.target.type !== 'text') {
|
||||
this.$parent.$parent.$refs.editLayer.deleteFeature()
|
||||
}
|
||||
console.log(cmd)
|
||||
},
|
||||
deferredMountedTo (parent) {
|
||||
this.sidebar = L.control.sidebar({
|
||||
autopan: false, // whether to maintain the centered map point when opening the sidebar
|
||||
closeButton: true, // whether t add a close button to the panes
|
||||
closeButton: true, // whether to add a close button to the panes
|
||||
container: 'sidebar', // the DOM container or #ID of a predefined sidebar container that should be used
|
||||
position: 'left' // left or right
|
||||
})
|
||||
parent.addControl(this.sidebar)
|
||||
this.$store.subscribe((mutation, state) => {
|
||||
switch (mutation.type) {
|
||||
case 'SET_EDIT_AIRPORT':
|
||||
case 'SET_EDIT_PARKING':
|
||||
case 'SET_EDIT_NODE':
|
||||
case 'SET_EDIT_RUNWAY':
|
||||
case 'SET_EDIT_ARC':
|
||||
this.sidebar.open('edit')
|
||||
break
|
||||
case 'CHECK_RESULTS':
|
||||
this.sidebar.open('check')
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
},
|
||||
remove () {
|
||||
if (this.sidebar) {
|
||||
@@ -99,14 +152,35 @@
|
||||
this.deferredMountedTo(this.$parent.mapObject)
|
||||
}
|
||||
},
|
||||
setEditing (editing) {
|
||||
this.$refs.parkingGroupEdit.setEditing(editing)
|
||||
this.$refs.airportEdit.setEditing(editing)
|
||||
},
|
||||
setData (data) {
|
||||
if (data.length > 0) {
|
||||
this.sidebar.open('edit')
|
||||
this.$refs.parkingGroupEdit.setData(data)
|
||||
}
|
||||
},
|
||||
scan () {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
results: function () {
|
||||
return this.$store.state.Check.results.length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
<style>
|
||||
/* global styles */
|
||||
.el-popover--plain {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
.el-popover__title {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -1,34 +1,60 @@
|
||||
<template>
|
||||
<div width="100%" v-if="node">
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="demo-input-label">Is on runway :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-switch v-model="isOnRunway"></el-switch>
|
||||
</el-col>
|
||||
<div width="100%" v-if="node">
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Coordinates :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-input placeholder="Please input" v-model="coordinates" :disabled="!editing"
|
||||
@focus="coordFocussed = true"
|
||||
@blur="coordFocussed = false"></el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Is on runway :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-switch v-model="isOnRunway" :disabled="!editing" @focus="runwayFocussed = true"
|
||||
@blur="runwayFocussed = false"></el-switch>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="9">
|
||||
<span class="label">Holdpoint Type :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-select v-model="holdPointType" placeholder="Select" :disabled="!editing" >
|
||||
<el-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
:label="type.label"
|
||||
:value="type.value"
|
||||
:disabled="type.disabled"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Goto"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Weld/Link nodes"
|
||||
>
|
||||
<el-button @click="link" slot="reference"><i class="fas fa-link"></i></el-button>
|
||||
</el-popover>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="demo-input-label">Holdpoint Type :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-select v-model="holdPointType" placeholder="Select">
|
||||
<el-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
:label="type.label"
|
||||
:value="type.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
const Coordinates = require('coordinate-parser');
|
||||
export default {
|
||||
/*
|
||||
methods: {
|
||||
@@ -37,14 +63,43 @@
|
||||
}
|
||||
},
|
||||
*/
|
||||
data () {
|
||||
return {
|
||||
coordFocussed: false, runwayFocussed: false, holdFocussed: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
link: function () {
|
||||
this.$parent.$parent.$parent.$refs.editLayer.link(this.$store.state.Editable.index)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
editing: {
|
||||
get: function () {
|
||||
return this.$parent.$parent.$parent.$refs.editLayer.editing
|
||||
}
|
||||
},
|
||||
options: function () {
|
||||
return [{value: 'none', label: 'none'}, {value: 'PushBack', label: 'PushBack'}, {value: 'normal', label: 'normal'}, {value: 'CAT II/III', label: 'CAT II/III'}]
|
||||
return [{value: 'none', label: 'none', disabled: false }, {value: 'PushBack', label: 'PushBack'}, {value: 'normal', label: 'normal'}, {value: 'CAT II/III', label: 'CAT II/III'}]
|
||||
},
|
||||
node: function () {
|
||||
return this.$store.state.Editable.type === 'node'
|
||||
return this.$store.state.Editable.type === 'node' || this.$store.state.Editable.type === 'runway'
|
||||
},
|
||||
// {index: 39, lat: "N58 27.343", lon: "W03 5.153", isOnRunway: 0, holdPointType: "none"}
|
||||
coordinates: {
|
||||
// getter
|
||||
get: function () {
|
||||
if(this.$store.state.Editable.index!==undefined) {
|
||||
return this.$store.state.Editable.data.node.coords;
|
||||
}
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
if (this.coordFocussed) {
|
||||
this.$store.commit('SET_EDIT_NODE_COORDS', newValue)
|
||||
}
|
||||
}
|
||||
},
|
||||
isOnRunway: {
|
||||
// getter
|
||||
get: function () {
|
||||
@@ -52,7 +107,9 @@
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_ISONRUNWAY', newValue ? 1 : 0)
|
||||
if(!this.runwayFocussed) {
|
||||
this.$store.commit('SET_EDIT_ISONRUNWAY', newValue ? 1 : 0)
|
||||
}
|
||||
}
|
||||
},
|
||||
holdPointType: {
|
||||
|
||||
@@ -12,72 +12,248 @@
|
||||
type: "gate"
|
||||
-->
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="demo-input-label">Name :</span>
|
||||
<el-col :span="4">
|
||||
<span class="label">Name :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-input placeholder="Please input" v-model="name"></el-input>
|
||||
<el-col :span="8">
|
||||
<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-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="demo-input-label">Size :</span>
|
||||
<span class="label">Size :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-radio-group v-model="wingspan">
|
||||
<el-col :span="17">
|
||||
<!--
|
||||
* Cat Models FG Radii N2M Radii
|
||||
* B Small Regionals ERJ CRJ ATR 14 6
|
||||
* C A319 A320 A321 B737 18 10
|
||||
* D B757, B767 26 15
|
||||
* E B777 B787 A330 A340 A360 33 24
|
||||
* F A380 40 24
|
||||
-->
|
||||
|
||||
<el-radio-group v-model="wingspan" :disabled="!editing">
|
||||
<el-tooltip content="PIPER PA-31/CESSNA 404 Titan" placement="top" effect="light">
|
||||
<el-radio :label="15">A</el-radio>
|
||||
<el-radio :label="15">A (7.5)</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="BOMBARDIER Regional Jet CRJ-200/DE HAVILLAND CANADA DHC-6" placement="top" effect="light">
|
||||
<el-radio :label="24">B</el-radio>
|
||||
<el-tooltip
|
||||
content="Beech 200 / Cessna 425"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-radio :label="20">- (10)</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="BOEING 737-700/AIRBUS A-320/EMBRAER ERJ 190-100" placement="top" effect="light">
|
||||
<el-radio :label="36">C</el-radio>
|
||||
<el-tooltip
|
||||
content="BOMBARDIER Regional Jet CRJ-200/DE HAVILLAND CANADA DHC-6"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-radio :label="28">B (14)</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
content="BOEING 737-700/AIRBUS A-320/EMBRAER ERJ 190-100"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-radio :label="36">C (18)</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="B767 Series/AIRBUS A-310" placement="top" effect="light">
|
||||
<el-radio :label="52">D</el-radio>
|
||||
<el-radio :label="52">D (26)</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="B777 Series/B787 Series/A330 Family" placement="top" effect="light">
|
||||
<el-radio :label="65">E</el-radio>
|
||||
<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-radio :label="80">F</el-radio>
|
||||
<el-radio :label="80">F (40)</el-radio>
|
||||
</el-tooltip>
|
||||
</el-radio-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="demo-input-label">Aircraft :</span>
|
||||
<span class="label">Aircraft :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
{{type}}
|
||||
<el-col :span="17">{{type}}</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="editing">
|
||||
<el-col :span="7">
|
||||
<span class="label">Calculate :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-radio-group v-model="calculate" size="small">
|
||||
<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>
|
||||
<el-col :span="7">
|
||||
<span class="demo-input-label">Parking Type :</span>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-select v-model="parking_type" placeholder="Select">
|
||||
<el-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
:label="type.label"
|
||||
:value="type.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Coordinates :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-popover
|
||||
placement="top-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-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Nosewheel Coordinates :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="E-Mail"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
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-popover>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Heading :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-input-number
|
||||
v-model="heading"
|
||||
:min="-361"
|
||||
:max="720"
|
||||
:step="0.1"
|
||||
:precision="1"
|
||||
:disabled="!editing || calculate ==='Heading'"
|
||||
></el-input-number>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Parking Type :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-select v-model="parking_type" placeholder="Select" :disabled="!editing">
|
||||
<el-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
:label="type.label"
|
||||
:value="type.value"
|
||||
:disabled="type.disabled"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Airline :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-select v-model="airlineCodes" multiple placeholder="Select" :disabled="!editing">
|
||||
<el-option
|
||||
v-for="item in airlines"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Pushback Route End :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">{{pushbackEnd}}</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
const convert = require('geo-coordinates-parser');
|
||||
|
||||
const turf = require('@turf/turf');
|
||||
|
||||
const turfOptions = { units: 'kilometers' };
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
show (idx) {
|
||||
this.$parent.$parent.$parent.$refs.editLayer.show(idx)
|
||||
},
|
||||
normalizeAngle( angle ) {
|
||||
if(angle >= 180) {
|
||||
return angle - 360;
|
||||
}
|
||||
if(angle <= -180) {
|
||||
return angle + 360;
|
||||
}
|
||||
return angle;
|
||||
},
|
||||
latToTurf (turfPoint) {
|
||||
return [turfPoint.decimalLongitude, turfPoint.decimalLatitude];
|
||||
},
|
||||
turfToLatLng: function (turfPoint) {
|
||||
return '' + turfPoint.geometry.coordinates[1].toFixed(6) + ',' + turfPoint.geometry.coordinates[0].toFixed(6);
|
||||
}
|
||||
},
|
||||
data () { return {calculate:'Nose Wheel', noseWheel: '', validRadii: [7.5, 10, 14, 18, 26, 33, 40], validN2M: [5, 5, 6, 10, 15, 24, 24] } },
|
||||
computed: {
|
||||
editing: {
|
||||
get: function () {
|
||||
return this.$parent.$parent.$parent.$refs.editLayer.editing
|
||||
}
|
||||
},
|
||||
parking: function () {
|
||||
return this.$store.state.Editable.type === 'parking'
|
||||
},
|
||||
airlines: function () {
|
||||
var airlineCodes = [];
|
||||
var storedairlineCodes = this.$store.state.Airports.currentAirport.airlines;
|
||||
// return [{value: 'bi-directional', label: 'bi-directional'},
|
||||
// {value: 'forward', label: 'forward'},
|
||||
// {value: 'backward', label: 'backward'}
|
||||
// ]
|
||||
if(storedairlineCodes) {
|
||||
storedairlineCodes.forEach(element => {
|
||||
airlineCodes.push({value: element, label: element});
|
||||
});
|
||||
}
|
||||
return airlineCodes
|
||||
},
|
||||
airlineCodes: {
|
||||
// getter
|
||||
get: function () {
|
||||
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(',')
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
return
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_PARKING_AIRLINES', newValue)
|
||||
}
|
||||
},
|
||||
name: {
|
||||
// getter
|
||||
get: function () {
|
||||
@@ -88,6 +264,100 @@
|
||||
this.$store.commit('SET_EDIT_PARKING_NAME', newValue)
|
||||
}
|
||||
},
|
||||
number: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Editable.data.parking.number
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_PARKING_NUMBER', newValue)
|
||||
}
|
||||
},
|
||||
coordinates: {
|
||||
// getter
|
||||
get: function () {
|
||||
if(this.$store.state.Editable.index!==undefined) {
|
||||
return this.$store.state.Editable.data.parking.coords;
|
||||
}
|
||||
},
|
||||
// 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)
|
||||
}
|
||||
},
|
||||
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;
|
||||
}
|
||||
}
|
||||
},
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
wingspan: {
|
||||
// getter
|
||||
get: function () {
|
||||
@@ -98,17 +368,31 @@
|
||||
this.$store.commit('SET_EDIT_PARKING_RADIUS', newValue / 2)
|
||||
}
|
||||
},
|
||||
pushbackEnd: function () {
|
||||
return this.$parent.$parent.$parent.$refs.editLayer.findRouteToPushback(this.$store.state.Editable.index)
|
||||
},
|
||||
type: function () {
|
||||
/**
|
||||
* Cat Models FG Radii N2M Radii
|
||||
* B Small Regionals ERJ CRJ ATR 14 6
|
||||
* C A319 A320 A321 B737 18 10
|
||||
* D B757, B767 26 15
|
||||
* E B777 B787 A330 A340 A360 33 24
|
||||
* F A380 40 24
|
||||
*/
|
||||
|
||||
switch (this.$store.state.Editable.data.parking.radius * 2) {
|
||||
case 15:
|
||||
return 'PIPER PA-31/CESSNA 404 Titan'
|
||||
case 24:
|
||||
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 65:
|
||||
case 66:
|
||||
return 'B777 Series/B787 Series/A330 Family'
|
||||
case 80:
|
||||
return 'BOEING 747-8/AIRBUS A-380-800'
|
||||
@@ -119,12 +403,12 @@
|
||||
// ga (general aviation), cargo (cargo), gate (commercial passenger traffic),
|
||||
// mil-fighter (military fighter), mil-cargo (military transport)
|
||||
options: function () {
|
||||
return [{value: 'none', label: 'none'},
|
||||
return [{value: 'none', label: 'none', disabled: true},
|
||||
{value: 'ga', label: 'general aviation'},
|
||||
{value: 'cargo', label: 'cargo'},
|
||||
{value: 'gate', label: 'commercial passenger traffic'},
|
||||
{value: 'mil-fighter', label: 'military fighter'},
|
||||
{value: 'mil-cargo', label: 'commercial passenger traffic'}
|
||||
{value: 'mil-cargo', label: 'military cargo'}
|
||||
]
|
||||
},
|
||||
parking_type: {
|
||||
@@ -143,3 +427,24 @@
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.el-row {
|
||||
margin: 1px;
|
||||
}
|
||||
.el-col {
|
||||
padding-left: 2pt;
|
||||
}
|
||||
.label {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.el-popover--plain {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
.el-popover__title {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
316
src/renderer/components/ParkingGroupEdit.vue
Normal file
@@ -0,0 +1,316 @@
|
||||
<template>
|
||||
<div v-if="parking">
|
||||
<!--
|
||||
airlineCodes: 0
|
||||
heading: 341.34
|
||||
index: 13
|
||||
lat: "N59 52.610885"
|
||||
lon: "W1 17.855144"
|
||||
name: "Western_Apron_Hanger"
|
||||
pushBackRoute: 27
|
||||
radius: 18
|
||||
type: "gate"
|
||||
-->
|
||||
<!--
|
||||
<el-row>
|
||||
<el-col :span="4">
|
||||
<span class="label">Name :</span>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-input placeholder="Name" v-model="name" :disabled="!editing"></el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
-->
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Size :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<!--
|
||||
* Cat Models FG Radii N2M Radii
|
||||
* B Small Regionals ERJ CRJ ATR 14 6
|
||||
* C A319 A320 A321 B737 18 10
|
||||
* D B757, B767 26 15
|
||||
* E B777 B787 A330 A340 A360 33 24
|
||||
* F A380 40 24
|
||||
-->
|
||||
<el-radio-group v-model="wingspan" :disabled="!editing" @change="wingspanChange">
|
||||
<el-tooltip content="PIPER PA-31/CESSNA 404 Titan" placement="top" effect="light">
|
||||
<el-radio :label="15">A</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
content="BOMBARDIER Regional Jet CRJ-200/DE HAVILLAND CANADA DHC-6"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-radio :label="28">B</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
content="BOEING 737-700/AIRBUS A-320/EMBRAER ERJ 190-100"
|
||||
placement="top"
|
||||
effect="light"
|
||||
>
|
||||
<el-radio :label="36">C</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="B767 Series/AIRBUS A-310" placement="top" effect="light">
|
||||
<el-radio :label="52">D</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="B777 Series/B787 Series/A330 Family" placement="top" effect="light">
|
||||
<el-radio :label="66">E</el-radio>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="BOEING 747-8/AIRBUS A-380-800" placement="top" effect="light">
|
||||
<el-radio :label="80">F</el-radio>
|
||||
</el-tooltip>
|
||||
</el-radio-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Aircraft :</span>
|
||||
</el-col>
|
||||
<el-col :span="17" class="value">{{type}}</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Heading :</span>
|
||||
</el-col>
|
||||
<el-col :span="13">
|
||||
<el-input-number
|
||||
v-model="avgHeading" @change="headingChange"
|
||||
:min="-361"
|
||||
:max="720"
|
||||
:step="0.1"
|
||||
:precision="1"
|
||||
:disabled="!editing"
|
||||
></el-input-number>
|
||||
</el-col>
|
||||
<el-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-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
:label="type.label"
|
||||
:value="type.value"
|
||||
:disabled="type.disabled"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">
|
||||
<span class="label">Airline :</span>
|
||||
</el-col>
|
||||
<el-col :span="17">
|
||||
<el-select v-model="airlineCodes" multiple placeholder="Select" :disabled="!editing">
|
||||
<el-option
|
||||
v-for="item in airlines"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
import Vue from 'vue'
|
||||
|
||||
const convert = require('geo-coordinates-parser');
|
||||
const Coordinates = require('coordinate-parser');
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
data: Object, avgHeading: 5, editing: Boolean, wingspan: 0
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
rotate() {
|
||||
this.avgHeading = this.avgHeading + 90;
|
||||
while (this.avgHeading>=360) {
|
||||
this.avgHeading -= 360
|
||||
}
|
||||
while (this.avgHeading<0) {
|
||||
this.avgHeading += 360
|
||||
}
|
||||
this.headingChange(this.avgHeading);
|
||||
},
|
||||
show (idx) {
|
||||
this.$parent.$parent.$parent.$refs.editLayer.show(idx)
|
||||
},
|
||||
setData (data) {
|
||||
this.data = data;
|
||||
this.setAvgHeading();
|
||||
},
|
||||
setEditing(editing) {
|
||||
this.editing = editing
|
||||
},
|
||||
setAvgHeading() {
|
||||
if( this.data === null || this.data === undefined) {
|
||||
return 0
|
||||
}
|
||||
this.avgHeading = Number( this.data.reduce(function (r, parking) {
|
||||
r.sum = r.sum + parking.options.attributes.heading;
|
||||
r.avg = r.sum / ++r.count;
|
||||
return r;
|
||||
}, { sum: 0, count: 0, avg: 0 }).avg);
|
||||
},
|
||||
wingspanChange( newValue ) {
|
||||
if ( newValue ) {
|
||||
this.$emit('editParking', {type: 'parking-group-wingspan', wingspan: newValue} )
|
||||
}
|
||||
},
|
||||
headingChange( newValue ) {
|
||||
while (newValue>=360) {
|
||||
newValue -= 360
|
||||
}
|
||||
while (newValue<0) {
|
||||
newValue += 360
|
||||
}
|
||||
if ( newValue ) {
|
||||
this.$emit('editParking', {type: 'parking-group-angle', angle: newValue} )
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
parking: function () {
|
||||
return this.data !== null && this.$store.state.Editable.type === 'parking-group'
|
||||
|
||||
},
|
||||
airlines: function () {
|
||||
var airlineCodes = [];
|
||||
var storedairlineCodes = this.$store.state.Airports.currentAirport.airlines;
|
||||
// return [{value: 'bi-directional', label: 'bi-directional'},
|
||||
// {value: 'forward', label: 'forward'},
|
||||
// {value: 'backward', label: 'backward'}
|
||||
// ]
|
||||
if(storedairlineCodes) {
|
||||
storedairlineCodes.forEach(element => {
|
||||
airlineCodes.push({value: element, label: element});
|
||||
});
|
||||
}
|
||||
return airlineCodes
|
||||
},
|
||||
airlineCodes: {
|
||||
// getter
|
||||
get: function () {
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
}
|
||||
},
|
||||
name: {
|
||||
// getter
|
||||
get: function () {
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
}
|
||||
},
|
||||
number: {
|
||||
// getter
|
||||
get: function () {
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
}
|
||||
},
|
||||
pushbackEnd: function () {
|
||||
return this.$parent.$parent.$parent.$refs.editLayer.findRouteToPushback(this.$store.state.Editable.index)
|
||||
},
|
||||
type: function () {
|
||||
/**
|
||||
* Cat Models FG Radii N2M Radii
|
||||
* B Small Regionals ERJ CRJ ATR 14 6
|
||||
* C A319 A320 A321 B737 18 10
|
||||
* D B757, B767 26 15
|
||||
* E B777 B787 A330 A340 A360 33 24
|
||||
* F A380 40 24
|
||||
*/
|
||||
|
||||
switch (this.wingspan) {
|
||||
case 15:
|
||||
return 'PIPER PA-31/CESSNA 404 Titan'
|
||||
case 28:
|
||||
return 'BOMBARDIER Regional Jet CRJ-200/DE HAVILLAND CANADA DHC-6'
|
||||
case 36:
|
||||
return 'BOEING 737-700/AIRBUS A-320/EMBRAER ERJ 190-100'
|
||||
case 52:
|
||||
return 'B767 Series/AIRBUS A-310'
|
||||
case 66:
|
||||
return 'B777 Series/B787 Series/A330 Family'
|
||||
case 80:
|
||||
return 'BOEING 747-8/AIRBUS A-380-800'
|
||||
default:
|
||||
return 'Unknown radius : ' + this.wingspan
|
||||
}
|
||||
},
|
||||
// ga (general aviation), cargo (cargo), gate (commercial passenger traffic),
|
||||
// mil-fighter (military fighter), mil-cargo (military transport)
|
||||
options: function () {
|
||||
return [{value: 'none', label: 'none', disabled: true},
|
||||
{value: 'ga', label: 'general aviation'},
|
||||
{value: 'cargo', label: 'cargo'},
|
||||
{value: 'gate', label: 'commercial passenger traffic'},
|
||||
{value: 'mil-fighter', label: 'military fighter'},
|
||||
{value: 'mil-cargo', label: 'military cargo'}
|
||||
]
|
||||
},
|
||||
parking_type: {
|
||||
// getter
|
||||
get: function () {
|
||||
if (this.$store.state.Editable.data.parking.type === undefined) {
|
||||
return 'none'
|
||||
}
|
||||
return this.$store.state.Editable.data.parking.type
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_PARKING_TYPE', newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.el-row {
|
||||
margin: 1px;
|
||||
}
|
||||
.el-col {
|
||||
padding-left: 2pt;
|
||||
}
|
||||
.label {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.value {
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
}
|
||||
.el-popover--plain {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
.el-popover__title {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
113
src/renderer/components/ParkingItem.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-link v-if="!editing" type="primary" @click="show(parking.index)">{{parking.name}} {{number}} {{parking.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">
|
||||
<el-option
|
||||
v-for="type in options"
|
||||
:key="type.value"
|
||||
:label="type.label"
|
||||
:value="type.value"
|
||||
:disabled="type.disabled"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
export default {
|
||||
name: 'parking-item',
|
||||
props: {parking: Object},
|
||||
mounted () {
|
||||
},
|
||||
data () {
|
||||
return { editLayer: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
show (idx) {
|
||||
if (this.editLayer === null) {
|
||||
this.initLayer()
|
||||
}
|
||||
if (this.editLayer) {
|
||||
return this.editLayer.show(idx)
|
||||
}
|
||||
},
|
||||
initLayer () {
|
||||
var parent = this.$parent
|
||||
while (parent && !parent.$refs.editLayer) {
|
||||
parent = parent.$parent
|
||||
}
|
||||
if (parent) {
|
||||
this.editLayer = parent.$refs.editLayer
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
options: function () {
|
||||
return [{value: 'none', label: 'none', disabled: true},
|
||||
{value: 'ga', label: 'general aviation'},
|
||||
{value: 'cargo', label: 'cargo'},
|
||||
{value: 'gate', label: 'commercial passenger traffic'},
|
||||
{value: 'mil-fighter', label: 'military fighter'},
|
||||
{value: 'mil-cargo', label: 'military cargo'}
|
||||
]
|
||||
},
|
||||
editing: function () {
|
||||
if (this.editLayer === null) {
|
||||
this.initLayer()
|
||||
}
|
||||
return this.editLayer.editing
|
||||
},
|
||||
name: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.parking.name
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_PARKING_ITEM_NAME', [this.parking.index, newValue])
|
||||
}
|
||||
},
|
||||
number: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.parking.number
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_PARKING_ITEM_NUMBER', [this.parking.index, newValue])
|
||||
}
|
||||
},
|
||||
parking_type: {
|
||||
// getter
|
||||
get: function () {
|
||||
if (this.parking.type === undefined) {
|
||||
return 'none'
|
||||
}
|
||||
return this.parking.type
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EDIT_PARKING_ITEM_TYPE', [this.parking.index, newValue])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
div.wide {
|
||||
width: 40%;
|
||||
}
|
||||
div.narrow {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
</style>
|
||||
53
src/renderer/components/ParkingList.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div>
|
||||
<!--
|
||||
<h1 class="leaflet-sidebar-header">
|
||||
Parking List
|
||||
<div class="leaflet-sidebar-close">
|
||||
<i class="fa fa-caret-left"></i>
|
||||
</div>
|
||||
</h1>
|
||||
-->
|
||||
<el-container direction="vertical">
|
||||
<div v-for="p in parkings" v-bind:key="p.index" class="row">
|
||||
<ParkingItem :parking="p"></ParkingItem>
|
||||
</div>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import ParkingItem from './ParkingItem'
|
||||
export default {
|
||||
name: 'parking-list',
|
||||
components: {ParkingItem},
|
||||
props: [],
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
parkings: {
|
||||
// getter
|
||||
get: function () {
|
||||
if (this.$store.state.Parkings.items !== undefined) {
|
||||
return this.$store.state.Parkings.items
|
||||
}
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
console.log(newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div.row.div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
<template>
|
||||
<section class="edit-layer">
|
||||
<h1>edit-layer Component</h1>
|
||||
</section>
|
||||
</template>
|
||||
<template></template>
|
||||
|
||||
<script lang="js">
|
||||
import { LMap, LMarker } from 'vue2-leaflet'
|
||||
@@ -25,20 +21,33 @@
|
||||
this.remove()
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
getLayer () {
|
||||
return this.pavement
|
||||
},
|
||||
load (icao) {
|
||||
// Callback for add
|
||||
readPavement(this.$store.state.Settings.settings.flightgearDirectory_apt, icao, this.read)
|
||||
},
|
||||
// Callback called when pavement read
|
||||
read (layer) {
|
||||
this.groundnet = layer
|
||||
if (this.groundnet) {
|
||||
this.groundnet.addTo(this.$parent.mapObject)
|
||||
this.pavement = layer
|
||||
if (this.pavement) {
|
||||
this.pavement.on('add', this.onAdd)
|
||||
this.pavement.addTo(this.$parent.mapObject)
|
||||
this.visible = true
|
||||
} else {
|
||||
this.$message({
|
||||
type: 'Error',
|
||||
showClose: true,
|
||||
message: `Couldn't load pavement from ${this.$store.state.Settings.settings.flightgearDirectory_apt}`
|
||||
})
|
||||
}
|
||||
this.groundnet.eachLayer(l => {
|
||||
},
|
||||
onAdd () {
|
||||
this.pavement.eachLayer(l => {
|
||||
if (l) {
|
||||
l.bringToBack()
|
||||
}
|
||||
@@ -57,7 +66,7 @@
|
||||
this.layerGroup = L.layerGroup()
|
||||
},
|
||||
remove () {
|
||||
if (this.layerGroup) {
|
||||
if (this.pavement) {
|
||||
this.$parent.removeLayer(this.layerGroup)
|
||||
}
|
||||
},
|
||||
@@ -67,11 +76,19 @@
|
||||
}
|
||||
},
|
||||
setVisible (visible) {
|
||||
if (this.layerGroup !== undefined) {
|
||||
if (visible) {
|
||||
this.layerGroup.addTo(this.$parent.mapObject)
|
||||
} else {
|
||||
this.layerGroup.removeFrom(this.$parent.mapObject)
|
||||
if (this.pavement !== undefined) {
|
||||
if (visible !== this.visible) {
|
||||
if (visible) {
|
||||
this.pavement.addTo(this.$parent.mapObject)
|
||||
this.pavement.eachLayer(l => {
|
||||
if (l) {
|
||||
l.bringToBack()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.pavement.removeFrom(this.$parent.mapObject)
|
||||
}
|
||||
this.visible = visible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
</div>
|
||||
</h1>
|
||||
<el-container direction="vertical">
|
||||
<span v-if="scanning" class="center">{{scanName}}</span>
|
||||
<el-progress :percentage="Number(((progress / max)*100).toPrecision(3))" v-if="max>0"></el-progress>
|
||||
<!--<el-progress :percentage="progress / max"></el-progress>-->
|
||||
<!--{{max}} {{progress}}-->
|
||||
@@ -45,7 +46,8 @@
|
||||
progress: 0,
|
||||
scanning: false,
|
||||
polling: null,
|
||||
worker: null
|
||||
worker: null,
|
||||
scanName: 'unknown'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -64,6 +66,7 @@
|
||||
scanAPT () {
|
||||
try {
|
||||
this.scanning = true
|
||||
this.scanName = 'Scanning APT'
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/worker.js`
|
||||
: `file://${process.resourcesPath}/workers/worker.js`
|
||||
@@ -71,13 +74,23 @@
|
||||
|
||||
const worker = new Worker(winURL)
|
||||
console.log(fileUrl('src/renderer/utils/worker.js'))
|
||||
worker.onerror = function (e) {
|
||||
console.error(e)
|
||||
worker.terminate()
|
||||
worker.scanning = false
|
||||
worker.view.progress = 0
|
||||
worker.view.max = 0
|
||||
worker.view.worker = null
|
||||
clearInterval(this.polling)
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
worker.scanning = this.scanning
|
||||
worker.max = this.max
|
||||
worker.progress = 0
|
||||
// var worker = new Worker(fileUrl('src/renderer/utils/worker.js'))
|
||||
this.worker = worker
|
||||
worker.postMessage(['scanapt', this.$store.state.Settings.settings.flightgearDirectory_apt])
|
||||
worker.postMessage(['scanapt', this.$store.state.Settings.settings.flightgearDirectory_apt, this.$store.state.Settings.settings.scanLogging])
|
||||
this.pollData()
|
||||
// the reply
|
||||
var store = this.$store
|
||||
@@ -110,6 +123,7 @@
|
||||
scanGroundnets () {
|
||||
try {
|
||||
this.scanning = true
|
||||
this.scanName = 'Scanning Groundnets'
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/worker.js`
|
||||
: `file://${process.resourcesPath}/workers/worker.js`
|
||||
@@ -117,13 +131,23 @@
|
||||
|
||||
const worker = new Worker(winURL)
|
||||
console.log(fileUrl('src/renderer/utils/worker.js'))
|
||||
worker.onerror = function (e) {
|
||||
console.error(e)
|
||||
worker.terminate()
|
||||
worker.scanning = false
|
||||
worker.view.progress = 0
|
||||
worker.view.max = 0
|
||||
worker.view.worker = null
|
||||
clearInterval(this.polling)
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
worker.scanning = this.scanning
|
||||
worker.max = this.max
|
||||
worker.progress = 0
|
||||
|
||||
this.worker = worker
|
||||
worker.postMessage(['scan', this.$store.state.Settings.settings.airportsDirectory])
|
||||
worker.postMessage(['scan', this.$store.state.Settings.settings.airportsDirectory, this.$store.state.Settings.settings.scanLogging])
|
||||
this.pollData()
|
||||
// the reply
|
||||
var store = this.$store
|
||||
@@ -144,7 +168,6 @@
|
||||
this.max = e.data[1]
|
||||
}
|
||||
if (e.data[0] === 'progress') {
|
||||
this.scanning = false
|
||||
this.progress += e.data[1]
|
||||
}
|
||||
}
|
||||
@@ -158,6 +181,7 @@
|
||||
// let flightgearDirectory = this.$store.state.settings.flightgearDirectory
|
||||
try {
|
||||
this.scanning = true
|
||||
this.scanName = 'Scanning Traffic'
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/worker.js`
|
||||
: `file://${process.resourcesPath}/workers/worker.js`
|
||||
@@ -165,12 +189,22 @@
|
||||
|
||||
const worker = new Worker(winURL)
|
||||
console.log(fileUrl('src/renderer/utils/worker.js'))
|
||||
worker.onerror = function (e) {
|
||||
console.error(e)
|
||||
worker.terminate()
|
||||
worker.scanning = false
|
||||
worker.view.progress = 0
|
||||
worker.view.max = 0
|
||||
worker.view.worker = null
|
||||
clearInterval(this.polling)
|
||||
e.preventDefault()
|
||||
}
|
||||
this.scanning = true
|
||||
worker.scanning = this.scanning
|
||||
worker.max = this.max
|
||||
worker.progress = this.progress
|
||||
this.worker = worker
|
||||
worker.postMessage(['scanai', this.$store.state.Settings.settings.flightgearDirectory_traffic])
|
||||
worker.postMessage(['scanai', this.$store.state.Settings.settings.flightgearDirectory_traffic, this.$store.state.Settings.settings.scanLogging])
|
||||
this.pollData()
|
||||
// the reply
|
||||
var store = this.$store
|
||||
@@ -182,9 +216,12 @@
|
||||
this.scanning = false
|
||||
console.log('DONE')
|
||||
store.dispatch('getAirports')
|
||||
worker.view.max = 0
|
||||
worker.view.scanning = false
|
||||
worker.terminate()
|
||||
if (worker.view.max !== undefined) {
|
||||
worker.view.max = 0
|
||||
}
|
||||
if (worker.view.scanning !== undefined) {
|
||||
worker.view.scanning = false
|
||||
}
|
||||
clearInterval(this.polling)
|
||||
} else if (e.data.length > 0) {
|
||||
if (e.data[0] === 'max') {
|
||||
@@ -209,4 +246,9 @@
|
||||
.el-button+.el-button {
|
||||
margin-left: 0px;
|
||||
}
|
||||
.center {
|
||||
font-weight: bold;
|
||||
font-size: 12pt;
|
||||
align-self: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
},
|
||||
data () {
|
||||
// this.$store.dispatch('getAirportsUnfiltered')
|
||||
return {searchterm: this.searchterm}
|
||||
return {searchterm: this.searchterm, lastSearchTerm: '', lastResult: {}}
|
||||
},
|
||||
methods: {
|
||||
goto (icao) {
|
||||
@@ -127,11 +127,26 @@
|
||||
computed: {
|
||||
searched: function () {
|
||||
console.log(this.searchterm)
|
||||
let searchRegex = new RegExp(this.searchterm, 'i')
|
||||
return this.$store.state.Airports.airports
|
||||
.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 }))
|
||||
if (this.searchterm !== this.lastSearchTerm) {
|
||||
let searchRegex = new RegExp(this.searchterm, 'i')
|
||||
let result = this.$store.state.Airports.airports
|
||||
.filter(point => point.geometry !== undefined)
|
||||
.filter(point => point.geometry.coordinates !== undefined)
|
||||
.filter(a => a.properties !== undefined)
|
||||
.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 }))
|
||||
if (result !== undefined &&
|
||||
result.length === 0 &&
|
||||
this.searchterm !== undefined &&
|
||||
this.searchterm.length >= 3) {
|
||||
this.$store.dispatch('getAirport', this.searchterm)
|
||||
}
|
||||
this.lastResult = result
|
||||
this.lastSearchTerm = this.searchterm
|
||||
return result
|
||||
}
|
||||
return this.lastResult
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,35 +8,130 @@
|
||||
</h1>
|
||||
<div id="panel" width="100%">
|
||||
<el-row>
|
||||
<el-col :span="7">Airports Directory</el-col>
|
||||
<el-col :span="15">{{ airports_directory }}</el-col>
|
||||
<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">
|
||||
<directory-select @input="airportsDirectorySelect"></directory-select>
|
||||
<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="7">Flightgear Directory</el-col>
|
||||
<el-col :span="15">{{ flightgear_directory }}</el-col>
|
||||
<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">
|
||||
<directory-select @input="flightgearDirectorySelect"></directory-select>
|
||||
<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="7">AI Directory</el-col>
|
||||
<el-col :span="15">{{ AI_directory }}</el-col>
|
||||
<el-col :span="22" class="label">Traffic Directory</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="22" v-bind:class="{ invalid: !Traffic_directory_ok, file_label: Traffic_directory_ok}">{{ Traffic_directory }}</el-col>
|
||||
<el-col :span="2">
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">Traffic Directory</el-col>
|
||||
<el-col :span="15">{{ Traffic_directory }}</el-col>
|
||||
<el-col :span="22" class="label">APT File</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="22" v-bind:class="{invalid: !apt_file_ok}" >{{ apt_file }}</el-col>
|
||||
<el-col :span="2">
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="7">APT File</el-col>
|
||||
<el-col :span="15">{{ apt_file }}</el-col>
|
||||
<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-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>
|
||||
@@ -46,6 +141,9 @@
|
||||
<script lang="js">
|
||||
import FileSelect from './FileSelect'
|
||||
import DirectorySelect from './DirectorySelect'
|
||||
|
||||
const { ipcRenderer } = require('electron')
|
||||
const fs = require('fs')
|
||||
export default {
|
||||
name: 'settings-panel',
|
||||
components: { DirectorySelect, FileSelect },
|
||||
@@ -54,34 +152,124 @@
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
return { ok: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
flightgearDirectorySelect: function (flightgearDirectory) {
|
||||
console.log(flightgearDirectory)
|
||||
this.$store.commit('FLIGHTGEAR_DIRECTORY', flightgearDirectory.path)
|
||||
this.$store.commit('FLIGHTGEAR_DIRECTORY', flightgearDirectory)
|
||||
},
|
||||
airportsDirectorySelect: function (flightgearDirectory) {
|
||||
console.log(flightgearDirectory)
|
||||
this.$store.commit('AIPORTS_DIRECTORY', flightgearDirectory.path)
|
||||
this.$store.commit('AIPORTS_DIRECTORY', flightgearDirectory)
|
||||
},
|
||||
testDirectorySelect: function (testDirectory) {
|
||||
console.log(testDirectory)
|
||||
this.$store.commit('TEST_DIRECTORY', testDirectory)
|
||||
},
|
||||
debug: function () {
|
||||
ipcRenderer.send('OpenDebugger', 'ping')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
email: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Settings.settings.email
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_EMAIL', newValue)
|
||||
}
|
||||
},
|
||||
name: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Settings.settings.name
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_NAME', newValue)
|
||||
}
|
||||
},
|
||||
phi_url: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Settings.settings.phi_url
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_PHI_URL', newValue)
|
||||
}
|
||||
},
|
||||
flightgear_directory: function () {
|
||||
return this.$store.state.Settings.settings.flightgearDirectory
|
||||
},
|
||||
flightgear_directory_ok: function () {
|
||||
try {
|
||||
fs.accessSync(this.$store.state.Settings.settings.flightgearDirectory)
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
AI_directory: function () {
|
||||
return this.$store.state.Settings.settings.flightgearDirectory_ai
|
||||
},
|
||||
Traffic_directory: function () {
|
||||
return this.$store.state.Settings.settings.flightgearDirectory_traffic
|
||||
},
|
||||
Traffic_directory_ok: function () {
|
||||
try {
|
||||
fs.accessSync(this.$store.state.Settings.settings.flightgearDirectory_traffic)
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
apt_file: function () {
|
||||
return this.$store.state.Settings.settings.flightgearDirectory_apt
|
||||
},
|
||||
apt_file_ok: function () {
|
||||
try {
|
||||
fs.accessSync(this.$store.state.Settings.settings.flightgearDirectory_apt)
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
airports_directory: function () {
|
||||
return this.$store.state.Settings.settings.airportsDirectory
|
||||
},
|
||||
airports_directory_ok: function () {
|
||||
try {
|
||||
fs.accessSync(this.$store.state.Settings.settings.airportsDirectory)
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
test_directory: function () {
|
||||
return this.$store.state.Settings.settings.testDirectory
|
||||
},
|
||||
test_directory_ok: function () {
|
||||
try {
|
||||
fs.accessSync(this.$store.state.Settings.settings.testDirectory)
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
scanLogging: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$store.state.Settings.settings.scanLogging === 1
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.$store.commit('SET_SCAN_LOGGING', newValue ? 1 : 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,9 +277,21 @@
|
||||
|
||||
<style>
|
||||
.el-row {
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.el-col {
|
||||
border-radius: 4px;
|
||||
}
|
||||
.label {
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.file_label {
|
||||
padding: 5px;
|
||||
}
|
||||
.invalid {
|
||||
padding: 5px;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
91
src/renderer/components/ThresholdLayer.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<template></template>
|
||||
|
||||
<script lang="js">
|
||||
import { LMap, LMarker } from 'vue2-leaflet'
|
||||
import L from 'leaflet'
|
||||
import LEdit from 'leaflet-editable/src/Leaflet.Editable.js'
|
||||
import {readThresholdXML} from '../loaders/threshold_loader'
|
||||
|
||||
export default {
|
||||
name: 'edit-layer',
|
||||
props: [],
|
||||
created () {
|
||||
},
|
||||
mounted () {
|
||||
console.log(LMap)
|
||||
console.log(LMarker)
|
||||
console.log(L)
|
||||
console.log(LEdit)
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.remove()
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getLayer () {
|
||||
return this.layerGroup
|
||||
},
|
||||
load (icao) {
|
||||
this.$parent.mapObject.createPane('threshold-pane')
|
||||
this.$parent.mapObject.getPane('threshold-pane').style.zIndex = 550
|
||||
// Callback for add
|
||||
this.layerGroup = readThresholdXML(this.$store.state.Settings.settings.airportsDirectory, icao, this.read)
|
||||
if (!this.layerGroup) {
|
||||
console.warn('Threshold for ICAO not loaded ' + icao)
|
||||
return
|
||||
}
|
||||
this.layerGroup.addTo(this.$parent.mapObject)
|
||||
this.visible = true
|
||||
this.icao = icao
|
||||
},
|
||||
deferredMountedTo (parent) {
|
||||
},
|
||||
remove () {
|
||||
if (this.layerGroup) {
|
||||
this.$parent.removeLayer(this.layerGroup)
|
||||
}
|
||||
},
|
||||
add () {
|
||||
if (this.$parent._isMounted) {
|
||||
this.deferredMountedTo(this.$parent.mapObject)
|
||||
}
|
||||
},
|
||||
setVisible (visible) {
|
||||
if (this.layerGroup !== undefined) {
|
||||
if (visible !== this.visible) {
|
||||
if (visible) {
|
||||
this.layerGroup.addTo(this.$parent.mapObject)
|
||||
} else {
|
||||
this.layerGroup.removeFrom(this.$parent.mapObject)
|
||||
}
|
||||
this.visible = visible
|
||||
}
|
||||
}
|
||||
},
|
||||
zoomUpdated () {
|
||||
if (this.layerGroup) {
|
||||
this.layerGroup.eachLayer(l => {
|
||||
if (l instanceof L.Threshold) {
|
||||
l.updateIcon(this.$parent.mapObject)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
computed: {
|
||||
edit: function () {
|
||||
console.log('Zoom : ' + this.$store.state.Settings.zoom)
|
||||
if (this.$store.state.Settings.zoom > 12) {
|
||||
console.log('Zoom above 12')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
67
src/renderer/components/ToolBar.vue
Normal file
@@ -0,0 +1,67 @@
|
||||
<!--
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template>
|
||||
<div id="ToolBar">
|
||||
<ToolButton
|
||||
icon="fas fa-draw-polygon"
|
||||
v-on:click="drawPolyline"
|
||||
:show="editing"
|
||||
tooltip="Draw Guideline"
|
||||
></ToolButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
import ToolButton from './ToolButton'
|
||||
import Vue from 'vue'
|
||||
|
||||
import fileUrl from 'file-url'
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
|
||||
|
||||
export default {
|
||||
components: { ToolButton },
|
||||
data () {
|
||||
return {isEditing: false}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods: {
|
||||
drawPolyline () {
|
||||
this.$parent.$parent.$refs.toolLayer.stopDrawing()
|
||||
this.$parent.$parent.$refs.toolLayer.drawPolyline()
|
||||
},
|
||||
setEditing (edit) {
|
||||
this.isEditing = edit;
|
||||
if(!this.isEditing) {
|
||||
this.$parent.$parent.$refs.toolLayer.stopDrawing()
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
editing: {
|
||||
// getter
|
||||
get: function () {
|
||||
console.log(`Getting Visible : ${this.isEditing}`)
|
||||
return this.isEditing
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
this.isEditing = newValue
|
||||
console.log(`Setting Visible : ${this.isEditing}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
64
src/renderer/components/ToolButton.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template></template>
|
||||
|
||||
<script lang="js">
|
||||
import L from 'leaflet'
|
||||
import '@fortawesome/fontawesome-free/css/all.css'
|
||||
import ToolControl from '../leaflet/ToolControl.js'
|
||||
export default {
|
||||
name: 'edit-bar',
|
||||
props: {
|
||||
icon: String,
|
||||
show: Boolean,
|
||||
tooltip: String
|
||||
},
|
||||
watch: {
|
||||
show: function (newVal, oldVal) { // watch it
|
||||
console.log('Prop changed: ', newVal, ' | was: ', oldVal)
|
||||
if (newVal) {
|
||||
this.add()
|
||||
} else {
|
||||
this.remove()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
console.debug(L)
|
||||
console.debug(ToolControl)
|
||||
this.add()
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.remove()
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deferredMountedTo (parent) {
|
||||
this.editbutton = new L.ToolControl({html: `<i class="${this.icon}"></i>`, callback: this.click, tooltip: this.tooltip})
|
||||
if (this.show) {
|
||||
parent.addControl(this.editbutton)
|
||||
}
|
||||
},
|
||||
click () {
|
||||
// console.log(parent)
|
||||
this.$emit('click')
|
||||
},
|
||||
remove () {
|
||||
if (this.editbutton) {
|
||||
this.$parent.$parent.mapObject.removeControl(this.editbutton)
|
||||
}
|
||||
},
|
||||
add () {
|
||||
if (this.$parent.$parent._isMounted) {
|
||||
this.deferredMountedTo(this.$parent.$parent.mapObject)
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
127
src/renderer/components/ToolLayer.vue
Normal file
@@ -0,0 +1,127 @@
|
||||
<!--
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template></template>
|
||||
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
import {LMap, LMarker} from 'vue2-leaflet'
|
||||
import L from 'leaflet'
|
||||
import LEdit from 'leaflet-editable/src/Leaflet.Editable.js'
|
||||
const turf = require('@turf/turf')
|
||||
|
||||
|
||||
export default {
|
||||
name: 'tool-layer',
|
||||
props: [],
|
||||
mounted () {
|
||||
this.add()
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.remove()
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deferredMountedTo (parent) {
|
||||
this.toolLayerGroup = L.layerGroup();
|
||||
this.toolLayerGroup.addTo(this.$parent.mapObject)
|
||||
},
|
||||
remove () {
|
||||
if (this.sidebar) {
|
||||
this.$parent.removeLayer(this.sidebar)
|
||||
}
|
||||
},
|
||||
add () {
|
||||
if (this.$parent._isMounted) {
|
||||
this.deferredMountedTo(this.$parent.mapObject)
|
||||
}
|
||||
},
|
||||
stopDrawing () {
|
||||
this.$parent.mapObject.editTools.stopDrawing()
|
||||
this.toolLayerGroup.eachLayer((layer) => {
|
||||
layer.removeFrom(this.toolLayerGroup);
|
||||
});
|
||||
},
|
||||
drawPolyline () {
|
||||
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('editable:drawing:end', event => {
|
||||
console.debug(event)
|
||||
var latLngs = event.target.getLatLngs()[0].map( latLng => ([latLng.lat, latLng.lng]));
|
||||
|
||||
|
||||
// turf rings must start/end with the same point
|
||||
latLngs.push(latLngs[0]);
|
||||
var longest = 0;
|
||||
var angleLongest = 0;
|
||||
latLngs.forEach((item, index, arr) => {
|
||||
if (index > 0) {
|
||||
var angle = turf.bearing(turf.point([arr[index-1][1], arr[index-1][0]]), turf.point([arr[index][1], arr[index][0]])) + 180;
|
||||
|
||||
var dist = turf.distance( turf.point(arr[index-1]), turf.point(arr[index]));
|
||||
if (dist>longest) {
|
||||
longest = dist;
|
||||
angleLongest = angle;
|
||||
}
|
||||
}
|
||||
});
|
||||
event.target.bindTooltip(angleLongest.toFixed(2) + '°', {permanent: true})
|
||||
|
||||
var ring = [latLngs];
|
||||
|
||||
this.$emit('select-poly', ring);
|
||||
})
|
||||
polyLine.on('editable:vertex:dragend', event => {
|
||||
console.debug(event)
|
||||
var latLngs = event.target.getLatLngs()[0].map( latLng => ([latLng.lat, latLng.lng]));
|
||||
|
||||
|
||||
// turf rings must start/end with the same point
|
||||
latLngs.push(latLngs[0]);
|
||||
var longest = 0;
|
||||
var angleLongest = 0;
|
||||
latLngs.forEach((item, index, arr) => {
|
||||
if (index > 0) {
|
||||
var angle = turf.bearing(turf.point([arr[index-1][1], arr[index-1][0]]), turf.point([arr[index][1], arr[index][0]])) + 180;
|
||||
|
||||
var dist = turf.distance( turf.point(arr[index-1]), turf.point(arr[index]));
|
||||
if (dist>longest) {
|
||||
longest = dist;
|
||||
angleLongest = angle;
|
||||
}
|
||||
}
|
||||
});
|
||||
event.target.setTooltipContent(angleLongest.toFixed(2) + '°')
|
||||
|
||||
var ring = [latLngs];
|
||||
|
||||
this.$emit('select-poly', ring);
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
computed: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
111
src/renderer/components/TowerLayer.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<!--
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template></template>
|
||||
|
||||
<script lang="js">
|
||||
import { LMap, LMarker } from 'vue2-leaflet'
|
||||
import L from 'leaflet'
|
||||
import LEdit from 'leaflet-editable/src/Leaflet.Editable.js'
|
||||
import {readTowerXML} from '../loaders/tower_loader'
|
||||
|
||||
export default {
|
||||
name: 'tower-layer',
|
||||
props: [],
|
||||
created () {
|
||||
console.debug([LMap, LMarker, L, LEdit])
|
||||
},
|
||||
mounted () {
|
||||
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.remove()
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getLayer () {
|
||||
return this.layerGroup
|
||||
},
|
||||
load (icao) {
|
||||
this.$parent.mapObject.createPane('tower-pane')
|
||||
this.$parent.mapObject.getPane('tower-pane').style.zIndex = 550
|
||||
// Callback for add
|
||||
this.layerGroup = readTowerXML(this.$store.state.Settings.settings.airportsDirectory, icao, this.read)
|
||||
if (!this.layerGroup) {
|
||||
console.warn('Tower for ICAO not loaded ' + icao)
|
||||
return
|
||||
}
|
||||
this.layerGroup.addTo(this.$parent.mapObject)
|
||||
this.visible = true
|
||||
this.icao = icao
|
||||
},
|
||||
deferredMountedTo (parent) {
|
||||
},
|
||||
remove () {
|
||||
if (this.layerGroup) {
|
||||
this.$parent.removeLayer(this.layerGroup)
|
||||
}
|
||||
},
|
||||
add () {
|
||||
if (this.$parent._isMounted) {
|
||||
this.deferredMountedTo(this.$parent.mapObject)
|
||||
}
|
||||
},
|
||||
enableEdit () {
|
||||
if (this.layerGroup) {
|
||||
this.layerGroup.eachLayer(l => {
|
||||
if (l instanceof L.TowerMarker) {
|
||||
l.enableEdit(this.$parent.mapObject)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
save () {
|
||||
},
|
||||
|
||||
setVisible (visible) {
|
||||
if (this.layerGroup !== undefined) {
|
||||
if (visible !== this.visible) {
|
||||
if (visible) {
|
||||
this.layerGroup.addTo(this.$parent.mapObject)
|
||||
} else {
|
||||
this.layerGroup.removeFrom(this.$parent.mapObject)
|
||||
}
|
||||
this.visible = visible
|
||||
}
|
||||
}
|
||||
},
|
||||
zoomUpdated () {
|
||||
if (this.layerGroup) {
|
||||
this.layerGroup.eachLayer(l => {
|
||||
if (l instanceof L.TowerMarker) {
|
||||
l.updateIcon(this.$parent.mapObject)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
edit: function () {
|
||||
console.log('Zoom : ' + this.$store.state.Settings.zoom)
|
||||
if (this.$store.state.Settings.zoom > 12) {
|
||||
console.log()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
319
src/renderer/components/Upload.vue
Normal file
@@ -0,0 +1,319 @@
|
||||
<template>
|
||||
<el-dialog :title.sync="title" :visible.sync="visible" width="30%" center>
|
||||
<span v-if="max>0">
|
||||
<el-progress :percentage="Number(((progress / max)*100).toPrecision(3))" v-if="max>0"></el-progress>
|
||||
</span>
|
||||
<span v-if="results.length>0" style="color: red">{{results.length}} Errors please correct first</span><br/>
|
||||
<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/>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleOkClicked" :disabled="!comittable">{{buttonText}}</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
/* eslint-disable */
|
||||
import Vue from 'vue'
|
||||
import fileUrl from 'file-url'
|
||||
import axios from 'axios'
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const mapper = require('../check/mapper');
|
||||
|
||||
export default {
|
||||
name: 'upload',
|
||||
props: [],
|
||||
mounted () {
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Loading.groundnetLoaded;
|
||||
},
|
||||
() => { if(this.$store.state.Loading.groundnetLoaded &&
|
||||
this.$store.state.Loading.pavementLoaded &&
|
||||
this.visible) this.check() }
|
||||
,
|
||||
{
|
||||
deep: false
|
||||
}
|
||||
);
|
||||
this.$store.watch(
|
||||
function (state) {
|
||||
return state.Loading.pavementLoaded;
|
||||
},
|
||||
() => { if(this.$store.state.Loading.groundnetLoaded &&
|
||||
this.$store.state.Loading.pavementLoaded &&
|
||||
this.visible) this.check() }
|
||||
,
|
||||
{
|
||||
deep: false
|
||||
}
|
||||
);
|
||||
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
gplv2: false, message: null, error: false, progress: 0, max: 0, azure: false, success: false, uploading: false, buttonText: 'Upload'
|
||||
}
|
||||
},
|
||||
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';
|
||||
}
|
||||
|
||||
},
|
||||
status () {
|
||||
this.azure = false;
|
||||
var xhr = new XMLHttpRequest();
|
||||
var parent = this.$parent;
|
||||
|
||||
this.message = 'Checking for Groundweb health'
|
||||
xhr.open('GET', 'http://groundweb.azurewebsites.net/groundnets/status', true);
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.status !== 200){
|
||||
parent.$refs.upload.message = 'Azure down';
|
||||
parent.$refs.upload.error = true;
|
||||
console.error(xhr);
|
||||
}
|
||||
}
|
||||
xhr.addEventListener("load", this.reqListener);
|
||||
try {
|
||||
xhr.send();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
this.error = true;
|
||||
}
|
||||
},
|
||||
handleOkClicked () {
|
||||
if( this.success ) {
|
||||
// Upload success close
|
||||
Vue.set(this.$parent, 'uploadVisible', false)
|
||||
return;
|
||||
}
|
||||
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');
|
||||
|
||||
if (f == null || !fs.existsSync(f)) {
|
||||
this.message = 'File doesn\'t exist';
|
||||
return;
|
||||
}
|
||||
|
||||
var data = fs.readFileSync(f, 'utf8').toString();
|
||||
var blob = new Blob([data]);
|
||||
var url = URL.createObjectURL(blob);
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'http://groundweb.azurewebsites.net/groundnets/upload', true);
|
||||
|
||||
// define new form
|
||||
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');
|
||||
|
||||
var parent = this.$parent;
|
||||
var messageField = this.message;
|
||||
// action after uploading happens
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.status !== 200){
|
||||
parent.$refs.upload.message = 'Upload Error'
|
||||
parent.$refs.upload.error = true;
|
||||
console.error(xhr);
|
||||
}
|
||||
}
|
||||
xhr.onload = function(e) {
|
||||
console.log("File uploading completed! ");
|
||||
console.log(e);
|
||||
parent.$refs.upload.uploading = false
|
||||
if (e.srcElement.status===500) {
|
||||
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.$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) {
|
||||
response.validationErrors.forEach(element => {
|
||||
parent.$refs.upload.message += element.message + '\r\n';
|
||||
});
|
||||
}
|
||||
} else if(JSON.parse(e.srcElement.response) !== undefined) {
|
||||
var response = JSON.parse(e.srcElement.response);
|
||||
parent.$refs.upload.message = response.err;
|
||||
} else {
|
||||
parent.$refs.upload.message = response.message;
|
||||
}
|
||||
};
|
||||
this.message = "File uploading started!"
|
||||
|
||||
// do the uploading
|
||||
console.log("File uploading started!");
|
||||
xhr.send(formData);
|
||||
},
|
||||
pollData () {
|
||||
var workery = this.worker
|
||||
var view = this
|
||||
workery.polling = setInterval(() => {
|
||||
if (workery != null) {
|
||||
view.max = Number(workery.max)
|
||||
view.progress = Number(workery.progress)
|
||||
view.scanning = Boolean(workery.checking)
|
||||
workery.view = view
|
||||
}
|
||||
}, 500)
|
||||
},
|
||||
check () {
|
||||
try {
|
||||
if(!(this.$store.state.Loading.groundnetLoaded &&
|
||||
this.$store.state.Loading.pavementLoaded)) {
|
||||
return
|
||||
}
|
||||
this.scanning = true
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/check.js`
|
||||
: `file://${process.resourcesPath}/workers/check.js`
|
||||
console.debug('make a check worker: ', path.resolve(__dirname, 'check.js'))
|
||||
|
||||
const worker = new Worker(winURL)
|
||||
console.debug(fileUrl('src/renderer/utils/check.js'))
|
||||
|
||||
worker.checking = this.checking
|
||||
worker.max = this.max
|
||||
worker.view = this
|
||||
worker.editLayer = this.$parent.$parent.$refs.editLayer
|
||||
worker.progress = 0
|
||||
// var worker = new Worker(fileUrl('src/renderer/utils/worker.js'))
|
||||
this.worker = worker
|
||||
var groundnet = []
|
||||
|
||||
if (!this.editLayer().groundnetLayerGroup) {
|
||||
this.message = 'Groundnet not visible'
|
||||
}
|
||||
if (!this.pavementLayer().pavement) {
|
||||
this.message = 'Pavement not visible'
|
||||
}
|
||||
this.editLayer().groundnetLayerGroup.eachLayer(l => {
|
||||
console.log(l)
|
||||
if (l instanceof L.Polyline) {
|
||||
l._latlngs[0].glueindex = this.begin;
|
||||
l._latlngs.slice(-1)[0].glueindex = this.end;
|
||||
l.extensions(this)
|
||||
}
|
||||
groundnet.push(l)
|
||||
})
|
||||
var features = groundnet.map(mapper.checkMapper).filter(n => n)
|
||||
var pavement = []
|
||||
this.pavementLayer().pavement.eachLayer(l => {
|
||||
console.log(l)
|
||||
pavement.push(l)
|
||||
})
|
||||
var features2 = pavement.map(mapper.checkMapper).filter(n => n)
|
||||
|
||||
worker.postMessage(['check', features.concat(features2) ] )
|
||||
this.pollData()
|
||||
// the reply
|
||||
var store = this.$store
|
||||
worker.onmessage = function (e) {
|
||||
if (e.data === 'checkStarted') {
|
||||
this.progress = 0
|
||||
this.max = 4
|
||||
} else if (e.data[0] === 'DONE') {
|
||||
console.log('DONE')
|
||||
worker.terminate()
|
||||
worker.view.max = 0
|
||||
worker.view.checkDialogVisible = false
|
||||
clearInterval(this.polling)
|
||||
this.checking = false
|
||||
} else if (e.data.length > 0) {
|
||||
if (e.data[0] === 'max') {
|
||||
this.max = e.data[1]
|
||||
}
|
||||
if (e.data[0] === 'progress') {
|
||||
this.progress += e.data[1]
|
||||
}
|
||||
}
|
||||
// console.log(e.data)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
editLayer () {
|
||||
var parent = this.$parent;
|
||||
while (!parent.icao||parent.$refs.editLayer==undefined) {
|
||||
parent = parent.$parent;
|
||||
if (parent.icao&&parent.$refs.editLayer!==undefined) {
|
||||
return parent.$refs.editLayer;
|
||||
}
|
||||
}
|
||||
},
|
||||
pavementLayer () {
|
||||
var parent = this.$parent;
|
||||
while (!parent.icao||parent.$refs.pavementLayer==undefined) {
|
||||
parent = parent.$parent;
|
||||
if (parent.icao&&parent.$refs.pavementLayer!==undefined) {
|
||||
return parent.$refs.pavementLayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
visible: {
|
||||
// getter
|
||||
get: function () {
|
||||
return this.$attrs.visible
|
||||
},
|
||||
// setter
|
||||
set: function (newValue) {
|
||||
Vue.set(this.$parent, 'uploadVisible', newValue)
|
||||
}
|
||||
},
|
||||
textClass: function () {
|
||||
return !this.error?'center':'error'
|
||||
},
|
||||
title: function () {
|
||||
return `Upload ${this.icao} to groundweb.`
|
||||
},
|
||||
icao: {
|
||||
get: function () {
|
||||
var parent = this.$parent;
|
||||
while (!parent.icao) {
|
||||
parent = parent.$parent;
|
||||
if (parent.icao) {
|
||||
return parent.icao;
|
||||
}
|
||||
}
|
||||
return this.$store.state.Airports.currentAirport.icao
|
||||
},
|
||||
set: function (newValue) {
|
||||
console.error('ICAO being set ' + newValue);
|
||||
}
|
||||
},
|
||||
comittable: function () {
|
||||
return this.$store.state.Check.results.filter(a => a.id>=0).length === 0 && this.gplv2 && this.max === 0 && this.azure && !this.uploading
|
||||
},
|
||||
results: function () {
|
||||
return this.$store.state.Check.results.filter(a => a.id>=0)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.center { text-align: center; vertical-align: middle; padding: 5px; font-size: 12pt; font-weight: normal;}
|
||||
.error { text-align: center; color: red; padding: 5px; font-size: 12pt; font-weight: normal;}
|
||||
.el-dialog--center .el-dialog__body { padding: 5px;}
|
||||
</style>
|
||||
66
src/renderer/components/WorkInProgress.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
|
||||
<section class="work-in-progress">
|
||||
<h1 class="leaflet-sidebar-header">
|
||||
Work in progress
|
||||
<div class="leaflet-sidebar-close"><i class="fa fa-caret-left"></i></div>
|
||||
</h1>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="3" class="text">
|
||||
ICAO
|
||||
</el-col>
|
||||
<el-col :span="7" class="text">
|
||||
Edited
|
||||
</el-col>
|
||||
<el-col :span="8" class="text">
|
||||
Uploaded
|
||||
</el-col>
|
||||
<el-col :span="6" class="text">
|
||||
Actions
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row v-for="w in wip" :key="w.icao">
|
||||
<Airport :airport="w" :editing="editing"></Airport>
|
||||
</el-row>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import Airport from './Airport'
|
||||
export default {
|
||||
name: 'work-in-progress',
|
||||
props: [],
|
||||
components: {Airport},
|
||||
mounted () {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
computed: {
|
||||
editing: {
|
||||
get: function () {
|
||||
return this.$store.state.Editable.editing
|
||||
}
|
||||
},
|
||||
wip: function () {
|
||||
return this.$store.state.Settings.wip
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.text {
|
||||
padding: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.el-row {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
||||
64
src/renderer/components/ZoomButton.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template></template>
|
||||
|
||||
<script lang="js">
|
||||
import L from 'leaflet'
|
||||
import '@fortawesome/fontawesome-free/css/all.css'
|
||||
import EditBar from '../leaflet/ZoomControl.js'
|
||||
export default {
|
||||
name: 'edit-bar',
|
||||
props: {
|
||||
icon: String,
|
||||
show: Boolean,
|
||||
tooltip: String
|
||||
},
|
||||
watch: {
|
||||
show: function (newVal, oldVal) { // watch it
|
||||
console.log('Prop changed: ', newVal, ' | was: ', oldVal)
|
||||
if (newVal) {
|
||||
this.add()
|
||||
} else {
|
||||
this.remove()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
console.debug(L)
|
||||
console.debug(EditBar)
|
||||
this.add()
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.remove()
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deferredMountedTo (parent) {
|
||||
this.editbutton = new L.ZoomControl({html: `<i class="${this.icon}"></i>`, callback: this.click, tooltip: this.tooltip})
|
||||
if (this.show) {
|
||||
parent.addControl(this.editbutton)
|
||||
}
|
||||
},
|
||||
click () {
|
||||
// console.log(parent)
|
||||
this.$emit('click')
|
||||
},
|
||||
remove () {
|
||||
if (this.editbutton) {
|
||||
this.$parent.$parent.mapObject.removeControl(this.editbutton)
|
||||
}
|
||||
},
|
||||
add () {
|
||||
if (this.$parent.$parent._isMounted) {
|
||||
this.deferredMountedTo(this.$parent.$parent.mapObject)
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
14
src/renderer/components/event-bus.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
import Vue from 'vue'
|
||||
export const EventBus = new Vue()
|
||||
@@ -2,7 +2,7 @@
|
||||
L.EditControl = L.Control.extend({
|
||||
|
||||
options: {
|
||||
position: 'topleft',
|
||||
position: 'topright',
|
||||
callback: null,
|
||||
kind: '',
|
||||
html: '<i class="fas fa-draw-polygon"></i>',
|
||||
@@ -16,11 +16,23 @@ L.EditControl = L.Control.extend({
|
||||
link.href = '#';
|
||||
link.title = this.options.tooltip;
|
||||
link.innerHTML = this.options.html;
|
||||
L.DomEvent.on(link, 'click', L.DomEvent.stop)
|
||||
.on(link, 'click', function () {
|
||||
window.LAYER = this.options.callback.call(map.editTools);
|
||||
}, this);
|
||||
|
||||
link.callback = this.options.callback;
|
||||
link.addEventListener('click',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}, false);
|
||||
link.addEventListener('mousedown',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
window.LAYER = this.callback.call(map.editTools);
|
||||
}, false);
|
||||
link.addEventListener('mouseup',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}, false);
|
||||
return container;
|
||||
}
|
||||
});
|
||||
@@ -32,6 +44,33 @@ L.NewMarkerControl = L.EditControl.extend({
|
||||
callback: null,
|
||||
kind: 'marker',
|
||||
html: '🖈'
|
||||
}
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = L.DomUtil.create('div', 'leaflet-control leaflet-bar'),
|
||||
link = L.DomUtil.create('a', '', container);
|
||||
|
||||
link.href = '#';
|
||||
link.title = this.options.tooltip;
|
||||
link.innerHTML = this.options.html;
|
||||
link.callback = this.options.callback;
|
||||
link.addEventListener('click',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}, false);
|
||||
link.addEventListener('mousedown',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
window.LAYER = this.callback.call(map.editTools);
|
||||
}, false);
|
||||
link.addEventListener('mouseup',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}, false);
|
||||
return container;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
25
src/renderer/leaflet/Runway.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
L.RunwayPolygon = L.Polygon.extend({
|
||||
});
|
||||
|
||||
var runwayPoly = function (runwayPoints) {
|
||||
var runwayPoly = new L.RunwayPolygon(runwayPoints);
|
||||
runwayPoly.setStyle({ color: 'grey', fillColor: 'grey', opacity: 0.5, fillOpacity: 0.5, interactive: false });
|
||||
|
||||
return runwayPoly;
|
||||
}
|
||||
|
||||
module.exports = runwayPoly;
|
||||
25
src/renderer/leaflet/Taxiway.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
L.TaxiwayPolygon = L.Polygon.extend({
|
||||
});
|
||||
|
||||
var taxiwayPoly = function (runwayPoints) {
|
||||
var taxiwayPoly = new L.TaxiwayPolygon(runwayPoints);
|
||||
taxiwayPoly.setStyle({ color: 'grey', fillColor: 'grey', opacity: 0.3, fillOpacity: 0.3, interactive: false });
|
||||
|
||||
return taxiwayPoly;
|
||||
}
|
||||
|
||||
module.exports = taxiwayPoly;
|
||||
36
src/renderer/leaflet/ToolControl.js
Normal file
@@ -0,0 +1,36 @@
|
||||
/* eslint-disable */
|
||||
L.ToolControl = L.Control.extend({
|
||||
options: {
|
||||
position: 'bottomright',
|
||||
callback: null,
|
||||
kind: 'marker',
|
||||
html: '🖈'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = L.DomUtil.create('div', 'leaflet-control leaflet-bar'),
|
||||
link = L.DomUtil.create('a', '', container);
|
||||
|
||||
link.href = '#';
|
||||
link.title = this.options.tooltip;
|
||||
link.innerHTML = this.options.html;
|
||||
link.callback = this.options.callback;
|
||||
link.addEventListener('click',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}, false);
|
||||
link.addEventListener('mousedown',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
window.LAYER = this.callback.call(map.editTools);
|
||||
}, false);
|
||||
link.addEventListener('mouseup',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}, false);
|
||||
return container;
|
||||
}
|
||||
});
|
||||
76
src/renderer/leaflet/ZoomControl.js
Normal file
@@ -0,0 +1,76 @@
|
||||
/* eslint-disable */
|
||||
L.ZoomControl = L.Control.extend({
|
||||
|
||||
options: {
|
||||
position: 'topleft',
|
||||
callback: null,
|
||||
kind: '',
|
||||
html: '<i class="fas fa-draw-polygon"></i>',
|
||||
tooltip: 'tooltip'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = L.DomUtil.create('div', 'leaflet-control leaflet-bar'),
|
||||
link = L.DomUtil.create('a', '', container);
|
||||
|
||||
link.href = '#';
|
||||
link.title = this.options.tooltip;
|
||||
link.innerHTML = this.options.html;
|
||||
link.callback = this.options.callback;
|
||||
link.addEventListener('click',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}, false);
|
||||
link.addEventListener('mousedown',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
window.LAYER = this.callback.call(map.editTools);
|
||||
}, false);
|
||||
link.addEventListener('mouseup',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}, false);
|
||||
return container;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
L.NewMarkerControl = L.EditControl.extend({
|
||||
options: {
|
||||
position: 'topright',
|
||||
callback: null,
|
||||
kind: 'marker',
|
||||
html: '🖈'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = L.DomUtil.create('div', 'leaflet-control leaflet-bar'),
|
||||
link = L.DomUtil.create('a', '', container);
|
||||
|
||||
link.href = '#';
|
||||
link.title = this.options.tooltip;
|
||||
link.innerHTML = this.options.html;
|
||||
link.callback = this.options.callback;
|
||||
link.addEventListener('click',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}, false);
|
||||
link.addEventListener('mousedown',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
window.LAYER = this.callback.call(map.editTools);
|
||||
}, false);
|
||||
link.addEventListener('mouseup',function (event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}, false);
|
||||
return container;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,6 +7,16 @@ const store = require('../store');
|
||||
|
||||
var $ = require('jquery');
|
||||
L.HoldNode = L.Marker.extend({
|
||||
select() {
|
||||
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';
|
||||
}
|
||||
},
|
||||
addListeners: function () {
|
||||
this.on('editable:drawing:move', function (event) {
|
||||
console.log("Move : ", event);
|
||||
|
||||
93
src/renderer/loaders/ParkingAircraftMarker.js
Normal file
@@ -0,0 +1,93 @@
|
||||
/* eslint-disable */
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
|
||||
|
||||
var metersPerPixel = function (latitude, zoomLevel) {
|
||||
var earthCircumference = 40075017;
|
||||
var latitudeRadians = latitude * (Math.PI / 180);
|
||||
return earthCircumference * Math.cos(latitudeRadians) / Math.pow(2, zoomLevel + 8);
|
||||
};
|
||||
|
||||
var pixelValue = function (latitude, meters, zoomLevel) {
|
||||
return meters / metersPerPixel(latitude, zoomLevel);
|
||||
};
|
||||
|
||||
|
||||
function stripSVG(fName) {
|
||||
var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm;
|
||||
var svg = fs.readFileSync(path.join(__static, '/', fName), 'utf8');
|
||||
var svg2 = rx.exec(svg);
|
||||
return svg2[0];
|
||||
}
|
||||
|
||||
const airLinerSVGs = {
|
||||
A: stripSVG('FGA_ACT_A_GA.svg'),
|
||||
B: stripSVG('FGA_ACT_B_PROP.svg'),
|
||||
C: stripSVG('FGA_ACT_C.svg'),
|
||||
D: stripSVG('FGA_ACT_D.svg'),
|
||||
E: stripSVG('FGA_ACT_E.svg'),
|
||||
F: stripSVG('FGA_ACT_F.svg')
|
||||
};
|
||||
|
||||
L.ParkingAircraftMarker = L.Marker.extend({
|
||||
options: {
|
||||
zIndexOffset: 10000,
|
||||
},
|
||||
|
||||
initialize: function (latlng, options) {
|
||||
L.Marker.prototype.initialize(latlng, options);
|
||||
L.Util.setOptions(this, options);
|
||||
this.heading = options.heading;
|
||||
this.updateIcon();
|
||||
|
||||
this.isDragging = false;
|
||||
|
||||
},
|
||||
updateProperties: function(properties) {
|
||||
this.heading = properties.heading;
|
||||
this.updateIcon();
|
||||
},
|
||||
updateIcon : function() {
|
||||
if(this._map !== undefined && this._map !== null) {
|
||||
var metersPP = metersPerPixel(this._map.getCenter().lat, this._map.getZoom());
|
||||
console.log(metersPP);
|
||||
var scale = 0.07 / metersPP;
|
||||
this.setIcon(L.divIcon({
|
||||
iconSize: null,
|
||||
className: 'aircraft-marker-icon',
|
||||
html: `<div style=\'transform: translateX(-10px) translateY(-10px); height: 20px; width: 20px; border: 1px red\'>${airLinerSVG}</div>`,
|
||||
}));
|
||||
this.getElement().children.item(0).children.item(0).style = `transform: translateX(-200px) translateY(-200px) scale(${scale},${scale}) rotate(${(this.heading)-45}deg)`;
|
||||
}
|
||||
else {
|
||||
this.setIcon(L.divIcon({
|
||||
iconSize: null,
|
||||
className: 'aircraft-marker-icon',
|
||||
html: `<div style=\'transform: rotate(${this.heading}deg) scale(0.001,0.001) \'>${airLinerSVG}</div>`,
|
||||
}));
|
||||
}
|
||||
},
|
||||
onAdd : function(map) {
|
||||
var metersPP = metersPerPixel(map.getCenter().lat, map.getZoom());
|
||||
console.log(metersPP);
|
||||
console.log(this);
|
||||
this.updateIcon();
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
//Builds a marker for a ai or multiplayer aircraft
|
||||
module.exports.default = function (latlng, options) {
|
||||
return new L.ParkingAircraftMarker(latlng, options);
|
||||
}
|
||||
|
||||
/*
|
||||
var l1 = feature.properties.callsign,
|
||||
l2 = feature.properties.heading + 'T ' + feature.properties.speed + 'KTAS ' +
|
||||
formatFL(feature.geometry.coordinates[2]),
|
||||
l3 = feature.properties.departureAirportId + ' -> ' + feature.properties.arrivalAirportId;
|
||||
|
||||
*/
|
||||
@@ -5,41 +5,66 @@ const turf = require('@turf/turf');
|
||||
const util = require('util');
|
||||
const store = require('../store');
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
// ratchet to known radii
|
||||
const validRadii = [7.5, 10, 14, 18, 26, 33, 40];
|
||||
|
||||
const validN2M = [5, 5, 6, 10, 15, 24, 24];
|
||||
|
||||
var $ = require('jquery');
|
||||
L.ParkingSpot = L.Circle.extend({
|
||||
createDirection: function () {
|
||||
if (this.direction === undefined ) {
|
||||
var start = this._latlng;
|
||||
var center = this._latlng;
|
||||
var options = { units: 'kilometers' };
|
||||
|
||||
var end = turf.destination([start.lng, start.lat], this.options.attributes.radius / 1000, this.options.attributes.heading - 180, options);
|
||||
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
|
||||
var rad2 = start.distanceTo(this.turfToLatLng(end), options);
|
||||
console.debug('Dist ', start, [start.lng, start.lat], end.geometry.coordinates, this.options.attributes.radius, rad2);
|
||||
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);
|
||||
// console.log(util.inspect(this.editor));
|
||||
if(this.editor._resizeLatLng.__vertex !== undefined){
|
||||
this.editor._resizeLatLng.__vertex.setLatLng(this.turfToLatLng(end));
|
||||
}
|
||||
this.direction = L.polyline([start, this.turfToLatLng(end)]);
|
||||
this.direction = L.polyline([this.turfToLatLng(start), this.turfToLatLng(end)]);
|
||||
this.direction.addTo(this.editor.editLayer);
|
||||
this.frontWheel = L.circleMarker(center, {radius:4, weight: 2 });
|
||||
this.frontWheel.addTo(this.editor.editLayer);
|
||||
this.updateWheelPos();
|
||||
this.updateBox();
|
||||
const parkingSize = validRadii.indexOf(this.options.attributes.radius);
|
||||
if(parkingSize>=0) {
|
||||
this.setStyle({ opacity: 0, fill: false });
|
||||
}
|
||||
}
|
||||
},
|
||||
updateMiddleMarker: function() {
|
||||
if (this.editEnabled()) {
|
||||
try {
|
||||
console.log("Update Middle ", this.editor.editLayer._layers[0]);
|
||||
console.debug("Update Middle ", this.editor.editLayer._layers[0]);
|
||||
var o = this.editor.editLayer._layers;
|
||||
|
||||
console.log(o);
|
||||
console.debug(o);
|
||||
for (var key in o) {
|
||||
if (o.hasOwnProperty(key)) {
|
||||
console.log(key, o[key]);
|
||||
console.log(this.editor._resizeLatLng.__vertex==o[key]);
|
||||
// console.log(this.editor._resizeLatLng.__vertex._icon);
|
||||
console.log(o[key] == this.direction);
|
||||
console.debug(key, o[key]);
|
||||
console.debug(this.editor._resizeLatLng.__vertex==o[key]);
|
||||
// console.debug(this.editor._resizeLatLng.__vertex._icon);
|
||||
console.debug(o[key] == this.direction);
|
||||
if (this.editor._resizeLatLng.__vertex!=o[key] &&
|
||||
o[key] != this.direction) {
|
||||
o[key] != this.direction &&
|
||||
o[key] != this.frontWheel &&
|
||||
o[key] != this.box) {
|
||||
o[key].setLatLng(this.getLatLng());
|
||||
}
|
||||
}
|
||||
@@ -47,112 +72,247 @@ L.ParkingSpot = L.Circle.extend({
|
||||
//Object.values(o);
|
||||
/*
|
||||
.forEach(vertex => {
|
||||
console.log(this.editor._resizeLatLng.__vertex==vertex);
|
||||
console.debug(this.editor._resizeLatLng.__vertex==vertex);
|
||||
});
|
||||
*/
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
},
|
||||
removeDirection: function () {
|
||||
removeDirection() {
|
||||
this.direction = undefined;
|
||||
},
|
||||
//
|
||||
updateVertexFromDirection: function () {
|
||||
updateHeading(heading) {
|
||||
this.options.attributes.heading = heading;
|
||||
this.updateVertexFromDirection();
|
||||
this.updateWheelPos();
|
||||
this.updateBox();
|
||||
},
|
||||
updateRadius(radius) {
|
||||
this._mRadius = radius;
|
||||
this.updateDirectionFromVertex();
|
||||
this.updateVertexFromDirection();
|
||||
this.updateWheelPos();
|
||||
this.updateBox();
|
||||
},
|
||||
// Update the direction vertex from the direction
|
||||
updateVertexFromDirection() {
|
||||
if (this.editEnabled()) {
|
||||
var start = this._latlng;
|
||||
var center = this._latlng;
|
||||
var options = { units: 'kilometers' };
|
||||
var end = turf.destination([start.lng, start.lat], this.options.attributes.radius / 1000, this.options.attributes.heading - 180, options);
|
||||
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
|
||||
var rad2 = start.distanceTo(this.turfToLatLng(end), options);
|
||||
var rad2 = center.distanceTo(this.turfToLatLng(end), options);
|
||||
this.setRadius(rad2);
|
||||
if(this.editor._resizeLatLng.__vertex!== undefined){
|
||||
this.editor._resizeLatLng.__vertex.setLatLng(this.turfToLatLng(end));
|
||||
}
|
||||
this.direction.setLatLngs([start, this.turfToLatLng(end)]);
|
||||
this.direction.setLatLngs([this.turfToLatLng(start), this.turfToLatLng(end)]);
|
||||
}
|
||||
},
|
||||
updateDirectionFromVertex: function () {
|
||||
// Update the direction from the moved direction vertex
|
||||
updateDirectionFromVertex() {
|
||||
if (this.editEnabled()) {
|
||||
var start = this._latlng;
|
||||
var end = this.editor._resizeLatLng.__vertex.getLatLng();
|
||||
var heading = turf.bearing([start.lng, start.lat], [end.lng, end.lat]);
|
||||
this.options.attributes.heading = heading + 180;
|
||||
const counts = [7.5, 12, 18, 26, 32.5, 40];
|
||||
this.options.attributes.heading = heading;
|
||||
const output = validRadii.reduce((prev, curr) => Math.abs(curr - this._mRadius) < Math.abs(prev - this._mRadius) ? curr : prev);
|
||||
|
||||
const output = counts.reduce((prev, curr) => Math.abs(curr - this._mRadius) < Math.abs(prev - this._mRadius) ? curr : prev);
|
||||
console.debug('Found radius ' + output);
|
||||
|
||||
console.log(output);
|
||||
this._mRadius = output;
|
||||
this.options.attributes.radius = this._mRadius;
|
||||
this.direction.setLatLngs([start, end]);
|
||||
}
|
||||
},
|
||||
highlight() {
|
||||
updateWheelPos() {
|
||||
var start = this._latlng;
|
||||
var options = { units: 'kilometers' };
|
||||
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));
|
||||
}
|
||||
}
|
||||
},
|
||||
updateBox() {
|
||||
var start = [this._latlng.lng, this._latlng.lat];
|
||||
var options = { units: 'kilometers' };
|
||||
const parkingSize = validRadii.indexOf(this.options.attributes.radius);
|
||||
|
||||
var backwards = this.normalizeAngle(this.options.attributes.heading + 180);
|
||||
var left = this.normalizeAngle(this.options.attributes.heading - 90);
|
||||
var right = this.normalizeAngle(this.options.attributes.heading + 90);
|
||||
|
||||
var radiusKM = this.options.attributes.radius / 1000;
|
||||
var halfRadiusKM = radiusKM/2;
|
||||
var thirdRadiusKM = radiusKM/3;
|
||||
|
||||
if (parkingSize>=0) {
|
||||
this.setStyle({ opacity: 0, fill: false });
|
||||
var frontWheelEnd = turf.destination(start, validN2M[parkingSize] / 1000, this.options.attributes.heading, options);
|
||||
var front = turf.destination(start, radiusKM, this.options.attributes.heading, options);
|
||||
|
||||
var back = turf.destination(start, radiusKM, backwards, options);
|
||||
|
||||
var leftBack = turf.destination(back, radiusKM, left, options);
|
||||
var rightBack = turf.destination(back, radiusKM, right, options);
|
||||
|
||||
var leftMiddle = turf.destination(start, radiusKM, left, options);
|
||||
var rightMiddle = turf.destination(start, radiusKM, right, options);
|
||||
|
||||
var leftFront = turf.destination(front, thirdRadiusKM, left, options);
|
||||
var rightFront = turf.destination(front, thirdRadiusKM, right, options);
|
||||
|
||||
var leftIntermediate = turf.destination(leftFront, halfRadiusKM, backwards, options);
|
||||
var rightIntermediate = turf.destination(rightFront, halfRadiusKM, backwards, options);
|
||||
|
||||
if(this.box === undefined) {
|
||||
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.on('click', function (event) {
|
||||
console.debug("Click Parking Box : " + event.target);
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
event.target._parkingSpot.featureLookup !== undefined &&
|
||||
event.target._parkingSpot.featureLookup[store.default.state.Editable.index]!==undefined) {
|
||||
event.target._parkingSpot.featureLookup[store.default.state.Editable.index].forEach(element => {
|
||||
if(element.deselect !== undefined) {
|
||||
element.deselect();
|
||||
}
|
||||
});
|
||||
}
|
||||
event.target._parkingSpot.select();
|
||||
});
|
||||
if(this.editor && this.editor.editLayer) {
|
||||
this.box.addTo(this.editor.editLayer);
|
||||
}
|
||||
}
|
||||
if(this.box!==undefined) {
|
||||
var latlngs = [leftBack, rightBack, rightMiddle, rightIntermediate, rightFront, leftFront, leftIntermediate, leftMiddle].map(l => this.turfToLatLng(l));
|
||||
console.debug(latlngs);
|
||||
this.box.setLatLngs(latlngs);
|
||||
}
|
||||
}
|
||||
},
|
||||
normalizeAngle( angle ) {
|
||||
if(angle >= 180) {
|
||||
return angle - 360;
|
||||
}
|
||||
if(angle <= -180) {
|
||||
return angle + 360;
|
||||
}
|
||||
return angle;
|
||||
},
|
||||
select() {
|
||||
store.default.dispatch('setParking', this.options.attributes);
|
||||
store.default.dispatch('setParkingCoords', this.getLatLng().lat.toFixed(6) + ' ' + this.getLatLng().lng.toFixed(6));
|
||||
var style = {};
|
||||
style['color'] = 'red';
|
||||
this.setStyle(style);
|
||||
if(this.direction) {
|
||||
this.direction.setStyle(style);
|
||||
this.frontWheel.setStyle(style);
|
||||
}
|
||||
this.updateWheelPos();
|
||||
this.updateBox();
|
||||
if(this.box) {
|
||||
this.box.setStyle(style);
|
||||
}
|
||||
},
|
||||
deselect() {
|
||||
var style = {};
|
||||
style['color'] = '#3388ff';
|
||||
this.setStyle(style);
|
||||
if(this.direction) {
|
||||
this.direction.setStyle(style);
|
||||
this.frontWheel.setStyle(style);
|
||||
}
|
||||
this.updateWheelPos();
|
||||
this.updateBox();
|
||||
if(this.box) {
|
||||
this.box.setStyle(style);
|
||||
}
|
||||
},
|
||||
addListeners: function () {
|
||||
this.on('editable:drawing:move', function (event) {
|
||||
console.log("Move : ", event);
|
||||
console.log("Move : ", event.latlng);
|
||||
console.debug("Move Parking Spot: ", event);
|
||||
console.debug("Move Parking Spot : ", event.latlng);
|
||||
// Is it the edit vertex (Middle) moving?
|
||||
if(event.target.editor._resizeLatLng.__vertex._icon !== event.sourceTarget._element){
|
||||
event.target.setLatLng(event.latlng);
|
||||
event.target.updateVertexFromDirection();
|
||||
event.target.updateWheelPos();
|
||||
event.target.updateBox();
|
||||
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.updateWheelPos();
|
||||
event.target.updateBox();
|
||||
}
|
||||
});
|
||||
/*
|
||||
this.on('editable:vertex:drag', function (event) {
|
||||
console.log("Drag : ", event);
|
||||
this.on('add', function (event) {
|
||||
console.log(event);
|
||||
event.target.updateBox();
|
||||
if(event.target.box !== undefined) {
|
||||
event.target.box.addTo(event.target._map);
|
||||
}
|
||||
});
|
||||
*/
|
||||
this.on('click', function (event) {
|
||||
console.log("Click : " + event.target);
|
||||
this.on('remove', function (event) {
|
||||
console.log(event);
|
||||
if(event.target.box !== undefined) {
|
||||
event.target.box.removeFrom(event.target._map);
|
||||
}
|
||||
});
|
||||
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);
|
||||
this.highlight();
|
||||
this.unwatch = store.default.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.parking;
|
||||
},
|
||||
() => {
|
||||
if (event.target instanceof L.ParkingSpot) {
|
||||
event.target.setStyle({color : '#3388ff'});
|
||||
this.unwatch();
|
||||
}
|
||||
}
|
||||
,
|
||||
{
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
}
|
||||
);
|
||||
store.default.dispatch('setParkingCoords', event.target.getLatLng().lat.toFixed(6) + ' ' + event.target.getLatLng().lng.toFixed(6));
|
||||
event.target.updateWheelPos();
|
||||
event.target.updateBox();
|
||||
/*
|
||||
store.default.dispatch('setParkingHeading', this.options.attributes.heading)
|
||||
store.default.dispatch('setParkingRadius', this.options.attributes.radius)
|
||||
*/
|
||||
});
|
||||
this.on('click', function (event) {
|
||||
console.debug("Click Parking : " + event.target);
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
this.featureLookup[store.default.state.Editable.index]!==undefined) {
|
||||
this.featureLookup[store.default.state.Editable.index].forEach(element => {
|
||||
if(element.deselect !== undefined) {
|
||||
element.deselect();
|
||||
}
|
||||
});
|
||||
}
|
||||
event.target.select();
|
||||
});
|
||||
this.on('editable:vertex:clicked', function (event) {
|
||||
console.log(this.featureLookup[event.vertex.glueindex]);
|
||||
console.debug(this.featureLookup[event.vertex.glueindex]);
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
this.featureLookup[store.default.state.Editable.index]!==undefined) {
|
||||
this.featureLookup[store.default.state.Editable.index].forEach(element => {
|
||||
if(element.deselect !== undefined) {
|
||||
element.deselect();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(event.target.editor._resizeLatLng.__vertex._icon !== event.sourceTarget._element){
|
||||
event.vertex._icon.style['background-color'] = 'red';
|
||||
store.default.dispatch('setParking', event.target.options.attributes);
|
||||
this.unwatch = store.default.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.parking;
|
||||
},
|
||||
() => {
|
||||
event.target.setStyle({color : '#3388ff'});
|
||||
this.unwatch();
|
||||
}
|
||||
,
|
||||
{
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
}
|
||||
);
|
||||
|
||||
this.select();
|
||||
}
|
||||
|
||||
});
|
||||
@@ -163,6 +323,21 @@ L.ParkingSpot = L.Circle.extend({
|
||||
},
|
||||
updateStyle: function () {
|
||||
|
||||
},
|
||||
selectParking() {
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
this.featureLookup[store.default.state.Editable.index]!==undefined) {
|
||||
this.featureLookup[store.default.state.Editable.index].forEach(element => {
|
||||
if(element.deselect !== undefined) {
|
||||
element.deselect();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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]};
|
||||
@@ -194,6 +369,8 @@ L.ParkingSpot = L.Circle.extend({
|
||||
// element.extensions();
|
||||
element.updateMiddleMarker();
|
||||
element.updateVertexFromDirection();
|
||||
element.updateWheelPos();
|
||||
element.updateBox();
|
||||
}
|
||||
else if (element instanceof L.TaxiwaySegment) {
|
||||
if (element.begin === dragIndex) {
|
||||
@@ -209,10 +386,10 @@ L.ParkingSpot = L.Circle.extend({
|
||||
element.updateMiddle();
|
||||
}
|
||||
} else if (element instanceof L.Editable.VertexMarker) {
|
||||
console.log(element);
|
||||
console.debug(element);
|
||||
element.setLatLng(event.latlng);
|
||||
element.latlngs.forEach((latlng, index) => {
|
||||
console.log(latlng);
|
||||
console.debug(latlng);
|
||||
if (latlng.__vertex === element) {
|
||||
latlng.update(event.latlng);
|
||||
}
|
||||
@@ -260,7 +437,7 @@ 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.log( '$', circle.id, key , value);
|
||||
console.debug( '$', circle.id, key , value);
|
||||
|
||||
if(isNaN(value))
|
||||
circle.options.attributes[ key ] = value;
|
||||
|
||||
@@ -15,37 +15,31 @@ L.RunwayNode = L.Marker.extend({
|
||||
});
|
||||
this.on('click', function (event) {
|
||||
console.log("Click Runway : ", event);
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
this.featureLookup[store.default.state.Editable.index]!==undefined) {
|
||||
this.featureLookup[store.default.state.Editable.index].forEach(element => {
|
||||
element.deselect();
|
||||
});
|
||||
}
|
||||
event.target.options.attributes.selected = true;
|
||||
if (store.default.state.Editable.index !== event.target.options.attributes.index) {
|
||||
store.default.dispatch('setRunway', event.target.options.attributes);
|
||||
}
|
||||
this.unwatch = store.default.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.runway;
|
||||
},
|
||||
() => {
|
||||
// Reset colour
|
||||
if(event.target instanceof L.RunwayNode &&
|
||||
event.target.options.attributes &&
|
||||
event.target.options.attributes.selected) {
|
||||
event.target.options.attributes.selected = false;
|
||||
event.target.updateStyle();
|
||||
this.unwatch();
|
||||
}
|
||||
}
|
||||
,
|
||||
{
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
},
|
||||
highlight() {
|
||||
var style = {};
|
||||
style['color'] = 'red';
|
||||
this.setStyle(style);
|
||||
select() {
|
||||
try {
|
||||
this._icon.style['color'] = 'red';
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
deselect() {
|
||||
try {
|
||||
this._icon.style['color'] = 'black';
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
extensions: function (editLayer) {
|
||||
this.options.attributes = {};
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
/* eslint-disable */
|
||||
var L = require('leaflet');
|
||||
const store = require('../store');
|
||||
|
||||
|
||||
L.TaxiwaySegment = L.Polyline.extend({
|
||||
begin: String,
|
||||
end: String,
|
||||
bidirectional: Boolean,
|
||||
|
||||
updateBeginVertex: function (latlng) {
|
||||
if (this._latlngs[0].__vertex) {
|
||||
this._latlngs[0].__vertex.setLatLng(latlng);
|
||||
}
|
||||
},
|
||||
updateEndVertex: function (latlng) {
|
||||
if (this._latlngs[1].__vertex) {
|
||||
this._latlngs[1].__vertex.setLatLng(latlng);
|
||||
}
|
||||
},
|
||||
|
||||
updateMiddle: function () {
|
||||
this._latlngs.forEach(element => {
|
||||
if (element.__vertex.middleMarker) {
|
||||
element.__vertex.middleMarker.updateLatLng();
|
||||
}
|
||||
});
|
||||
},
|
||||
extensions: function (editLayer) {
|
||||
this._latlngs[0].__vertex.glueindex = this.begin;
|
||||
this._latlngs.slice(-1)[0].__vertex.glueindex = this.end;
|
||||
if (typeof this.featureLookup[this.begin] === 'undefined') {
|
||||
this.featureLookup[this.begin] = new Array();
|
||||
}
|
||||
if (typeof this.featureLookup[this.end] === 'undefined') {
|
||||
this.featureLookup[this.end] = new Array();
|
||||
}
|
||||
this.featureLookup[this.begin].push(this);
|
||||
this.featureLookup[this.end].push(this);
|
||||
},
|
||||
addListeners: function () {
|
||||
this.on('click', function (event) {
|
||||
console.log("Click : " + event.target);
|
||||
store.default.dispatch('setArc', event.target.options.attributes);
|
||||
store.default.watch( function (state) {
|
||||
return state.Editable.data.arc;
|
||||
},
|
||||
() => {
|
||||
console.log(this)
|
||||
}
|
||||
,
|
||||
{
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
});
|
||||
});
|
||||
this.on('editable:drawing:move', function (event) {
|
||||
console.log(event.target);
|
||||
if (dragIndex >= 0) {
|
||||
this.follow(dragIndex, event);
|
||||
}
|
||||
});
|
||||
this.on('editable:vertex:clicked', function (event) {
|
||||
console.log(this.featureLookup[event.vertex.glueindex]);
|
||||
|
||||
store.default.dispatch('setNode', event.vertex.latlng.attributes)
|
||||
event.vertex._icon.style['background-color'] = 'red';
|
||||
});
|
||||
var dragIndex = -1;
|
||||
this.on('editable:vertex:dragstart', function (event) {
|
||||
console.log("Event Target : ", event.target);
|
||||
console.log("Middle Marker : ", event.vertex == event.vertex.middleMarker);
|
||||
console.log("Middle Marker : ", event.vertex.glueindex == undefined);
|
||||
if (event.vertex.glueindex == undefined)
|
||||
return;
|
||||
dragIndex = event.vertex.glueindex;
|
||||
});
|
||||
this.on('editable:vertex:dragend', function (event) {
|
||||
console.log("Dragend : ", event.vertex);
|
||||
if (dragIndex > 0) {
|
||||
this.featureLookup[dragIndex].forEach(element => {
|
||||
if (element instanceof L.ParkingSpot) {
|
||||
//element.setLatLng(event);
|
||||
console.log(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
dragIndex = -1;
|
||||
});
|
||||
},
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
follow(dragIndex, event) {
|
||||
this.featureLookup[dragIndex].forEach(element => {
|
||||
if (element !== event.target) {
|
||||
if (element instanceof L.RunwayNode) {
|
||||
element.setLatLng(event.latlng);
|
||||
}
|
||||
else if (element instanceof L.HoldNode) {
|
||||
element.setLatLng(event.latlng);
|
||||
}
|
||||
else if (element instanceof L.ParkingSpot) {
|
||||
// element.disableEdit();
|
||||
element.setLatLng(event.latlng);
|
||||
// element.enableEdit();
|
||||
// element.extensions();
|
||||
element.updateMiddleMarker();
|
||||
element.updateVertexFromDirection();
|
||||
}
|
||||
else if (element instanceof L.TaxiwaySegment) {
|
||||
if (element.begin === dragIndex) {
|
||||
element.getLatLngs()[0].update(event.latlng);
|
||||
element.setLatLngs(element.getLatLngs());
|
||||
element.updateBeginVertex(event.latlng);
|
||||
element.updateMiddle();
|
||||
}
|
||||
if (element.end === dragIndex) {
|
||||
element.getLatLngs()[element.getLatLngs().length - 1].update(event.latlng);
|
||||
element.setLatLngs(element.getLatLngs());
|
||||
element.updateEndVertex(event.latlng);
|
||||
element.updateMiddle();
|
||||
}
|
||||
} else if (element instanceof L.Editable.VertexMarker) {
|
||||
console.log(element);
|
||||
element.setLatLng(event.latlng);
|
||||
element.latlngs.forEach((latlng, index) => {
|
||||
console.log(latlng);
|
||||
if (latlng.__vertex === element) {
|
||||
latlng.update(event.latlng);
|
||||
}
|
||||
});
|
||||
element.editor.feature.setLatLngs(element.latlngs);
|
||||
element.editor.feature.updateMiddle();
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
updateStyle() {
|
||||
var style = {};
|
||||
if (this.options.attributes.isPushBackRoute) {
|
||||
style.color = 'magenta';
|
||||
}
|
||||
console.log("isPushBackRoute ", this.options.attributes.isPushBackRoute);
|
||||
this.setStyle(style);
|
||||
if (!this.bidirectional) {
|
||||
this.setText(' ► ', { repeat: true, attributes: { fill: 'red', size: 20 } })
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,25 +1,31 @@
|
||||
/* eslint-disable */
|
||||
const Vue = require('vue');
|
||||
|
||||
var L = require('leaflet');
|
||||
const store = require('../store');
|
||||
const util = require('util');
|
||||
const assign = require('core-js/fn/object/assign');
|
||||
|
||||
exports.extendTaxiSegment = function (taxiwaySegment) {
|
||||
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._latlngs[0].__vertex.setLatLng(latlng);
|
||||
this.selectVertex(Number(this._latlngs[0].glueindex));
|
||||
}
|
||||
};
|
||||
taxiwaySegment.__proto__.updateEndVertex = function (latlng) {
|
||||
if(this._latlngs[1].__vertex){
|
||||
this._latlngs[1].__vertex.setLatLng(latlng);
|
||||
if (this._latlngs[1].__vertex) {
|
||||
this._latlngs[1].__vertex.setLatLng(latlng);
|
||||
this.selectVertex(Number(this._latlngs[1].glueindex));
|
||||
}
|
||||
};
|
||||
|
||||
taxiwaySegment.__proto__.updateMiddle = function () {
|
||||
this._latlngs.forEach(element => {
|
||||
if(element.__vertex.middleMarker){
|
||||
if (element.__vertex && element.__vertex.middleMarker) {
|
||||
element.__vertex.middleMarker.updateLatLng();
|
||||
}
|
||||
});
|
||||
@@ -29,149 +35,410 @@ exports.extendTaxiSegment = function (taxiwaySegment) {
|
||||
};
|
||||
taxiwaySegment.__proto__.extensions = function (editLayer) {
|
||||
this.editLayer = editLayer;
|
||||
this._latlngs[0].__vertex.glueindex = this.begin;
|
||||
this._latlngs.slice(-1)[0].__vertex.glueindex = this.end;
|
||||
if (typeof this.featureLookup[this.begin] === 'undefined') {
|
||||
this.featureLookup[this.begin] = new Array();
|
||||
this._latlngs[0].glueindex = this.begin;
|
||||
this._latlngs.slice(-1)[0].glueindex = this.end;
|
||||
if (this.featureLookup) {
|
||||
if (typeof this.featureLookup[this.begin] === 'undefined') {
|
||||
this.featureLookup[this.begin] = new Array();
|
||||
}
|
||||
if (typeof this.featureLookup[this.end] === 'undefined') {
|
||||
this.featureLookup[this.end] = new Array();
|
||||
}
|
||||
this.featureLookup[this.begin].push(this);
|
||||
this.featureLookup[this.end].push(this);
|
||||
this.bidirectional = true;
|
||||
}
|
||||
if (typeof this.featureLookup[this.end] === 'undefined') {
|
||||
this.featureLookup[this.end] = new Array();
|
||||
}
|
||||
this.featureLookup[this.begin].push(this);
|
||||
this.featureLookup[this.end].push(this);
|
||||
this.bidirectional = true;
|
||||
};
|
||||
taxiwaySegment.__proto__.select = function () {
|
||||
this.options.attributes.selected = true;
|
||||
this.updateStyle();
|
||||
};
|
||||
taxiwaySegment.__proto__.selectVertex = function (index) {
|
||||
this.getLatLngs().forEach(element => {
|
||||
if (Number(element.glueindex) === index) {
|
||||
if (element.__vertex._icon != null) {
|
||||
element.__vertex.__proto__.deselect = function () {
|
||||
if (this._icon != null) {
|
||||
this._icon.style.setProperty('background-color', 'white');
|
||||
this._icon.style.setProperty('color', 'white');
|
||||
} else if (this.icon != null) {
|
||||
if (this.icon.style != null) {
|
||||
this.icon.style['background-color'] = 'white';
|
||||
} else {
|
||||
this.setStyle({ color: 'white' })
|
||||
}
|
||||
} else if (this.options.icon != null) {
|
||||
if (this.options.icon.style != null) {
|
||||
this.options.icon.style['background-color'] = 'white';
|
||||
} else {
|
||||
this.options.icon._setIconStyles({ color: 'white' })
|
||||
}
|
||||
}
|
||||
}
|
||||
element.__vertex._icon.style.setProperty('background-color', 'red');
|
||||
element.__vertex._icon.style.setProperty('color', 'red');
|
||||
} else if (element.__vertex !== undefined && element.__vertex.icon != null) {
|
||||
if (element.__vertex.icon.style != null) {
|
||||
element.__vertex.icon.style['background-color'] = 'red';
|
||||
} else {
|
||||
element.__vertex.setStyle({ color: 'red' })
|
||||
}
|
||||
} else if (element.__vertex.options.icon != null) {
|
||||
if (element.__vertex.options.icon.style != null) {
|
||||
element.__vertex.options.icon.style['background-color'] = 'red';
|
||||
} else {
|
||||
element.__vertex.options.icon._setIconStyles({ color: 'red' })
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
taxiwaySegment.__proto__.deselect = function () {
|
||||
this.options.attributes.selected = false;
|
||||
this.updateStyle();
|
||||
this.getLatLngs().forEach(element => {
|
||||
if (element.__vertex !== undefined) {
|
||||
if (element.__vertex._icon != null) {
|
||||
element.__vertex._icon.style['background-color'] = 'white';
|
||||
} else if (element.__vertex.icon != null) {
|
||||
if (element.__vertex.icon.style != null) {
|
||||
element.__vertex.icon.style['background-color'] = 'white';
|
||||
} else {
|
||||
element.__vertex.setStyle({ color: 'white' })
|
||||
}
|
||||
} else if (element.__vertex.options.icon != null) {
|
||||
if (element.__vertex.options.icon.style != null) {
|
||||
element.__vertex.options.icon.style['background-color'] = 'white';
|
||||
} else {
|
||||
element.__vertex.options.icon._setIconStyles({ color: 'white' })
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
taxiwaySegment.__proto__.addListeners = function () {
|
||||
this.on('click', function (event) {
|
||||
event.target.setStyle({color : 'red'});
|
||||
console.log("Click : " + event.target);
|
||||
if (store.default.state.Editable.data.arc === undefined ||
|
||||
store.default.state.Editable.data.arc !== event.target.options.attributes) {
|
||||
if(event.target.options.attributes === undefined) {
|
||||
event.target.options.attributes = {};
|
||||
}
|
||||
event.target.options.attributes.index = event.target._leaflet_id;
|
||||
event.target.options.attributes.selected = true;
|
||||
store.default.dispatch('setArc', event.target.options.attributes);
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
this.featureLookup[store.default.state.Editable.index] !== undefined) {
|
||||
this.featureLookup[store.default.state.Editable.index].forEach(element => {
|
||||
element.deselect();
|
||||
});
|
||||
}
|
||||
this.unwatch = store.default.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.arc;
|
||||
},
|
||||
() => {
|
||||
// Reset colour
|
||||
if(event.target instanceof L.Polyline &&
|
||||
event.target.options.attributes &&
|
||||
event.target.options.attributes.selected) {
|
||||
event.target.options.attributes.selected = false;
|
||||
event.target.updateStyle();
|
||||
this.unwatch();
|
||||
}
|
||||
}
|
||||
,
|
||||
{
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
event.target.select();
|
||||
console.debug("Click : " + util.inspect(event.originalEvent));
|
||||
if (!event.originalEvent.ctrlKey) {
|
||||
if (store.default.state.Editable.data.arc === undefined ||
|
||||
store.default.state.Editable.data.arc !== event.target.options.attributes) {
|
||||
if (event.target.options.attributes === undefined) {
|
||||
event.target.options.attributes = {};
|
||||
}
|
||||
event.target.options.attributes.index = event.target._leaflet_id;
|
||||
|
||||
this.editLayer.featureLookup[event.target._leaflet_id] = [];
|
||||
this.featureLookup[event.target._leaflet_id].push(this);
|
||||
event.target.options.attributes.selected = true;
|
||||
store.default.dispatch('setArc', event.target.options.attributes);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
var arcs = event.target.expandArc(event.target.options.attributes);
|
||||
var multiarc = {name: '', index: 900719925474099, ids: [] ,isPushBackRoute: null, direction: null};
|
||||
if (store.default.state.Editable.data.multiarc === undefined ||
|
||||
store.default.state.Editable.data.multiarc !== event.target.options.attributes) {
|
||||
if (event.target.options.attributes === undefined) {
|
||||
event.target.options.attributes = {};
|
||||
}
|
||||
event.target.options.attributes.index = event.target._leaflet_id;
|
||||
|
||||
this.editLayer.featureLookup[event.target._leaflet_id] = [];
|
||||
this.featureLookup[event.target._leaflet_id].push(this);
|
||||
event.target.options.attributes.selected = true;
|
||||
|
||||
//multiarc.name = JSON.parse(JSON.stringify(event.target.options.attributes.name));
|
||||
//multiarc.isPushBackRoute = JSON.parse(JSON.stringify(event.target.options.attributes.isPushBackRoute));
|
||||
//multiarc.direction = JSON.parse(JSON.stringify(event.target.options.attributes.direction));
|
||||
if(event.target.options.attributes.name!==undefined) {
|
||||
multiarc.name = assign(event.target.options.attributes.name);
|
||||
}
|
||||
multiarc.isPushBackRoute = assign(event.target.options.attributes.isPushBackRoute);
|
||||
multiarc.direction = assign(event.target.options.attributes.direction);
|
||||
|
||||
this.editLayer.featureLookup[900719925474099] = [];
|
||||
|
||||
multiarc.ids = [];
|
||||
|
||||
//TODO
|
||||
store.default.dispatch('setMultiArc', multiarc);
|
||||
}
|
||||
var editLayer = this.editLayer;
|
||||
arcs.forEach(id => {
|
||||
console.debug(id);
|
||||
var arc = editLayer.groundnetLayerGroup.getLayer(id);
|
||||
if (arc && arc instanceof L.Polyline) {
|
||||
editLayer.featureLookup[900719925474099].push(arc);
|
||||
arc.select();
|
||||
}
|
||||
});
|
||||
store.default.dispatch('setMultiArcIds', arcs);
|
||||
}
|
||||
});
|
||||
this.on('editable:drawing:move', function (event) {
|
||||
console.log(event.target);
|
||||
if (dragIndex >= 0) {
|
||||
this.selectVertex(dragIndex);
|
||||
console.log('GlueDrag : ' + dragIndex + '\t' + event.target.dragIndex);
|
||||
this.follow(dragIndex, event);
|
||||
}
|
||||
});
|
||||
this.on('editable:vertex:new', event => {
|
||||
console.log(event)
|
||||
let closest = this.editLayer.closestLayerSnap(event.latlng, 10)
|
||||
if (closest) {
|
||||
event.latlng.__vertex['glueindex'] = Number(closest.glueindex);
|
||||
event.latlng.__vertex.setLatLng(closest.latlng);
|
||||
this.editLayer.featureLookup[event.latlng.__vertex.glueindex].push(event.latlng.__vertex);
|
||||
console.log(closest)
|
||||
} else {
|
||||
event.latlng.__vertex['glueindex'] = ++this.editLayer.groundnetLayerGroup.maxId;
|
||||
this.editLayer.featureLookup[event.latlng.__vertex.glueindex] = [];
|
||||
this.editLayer.featureLookup[event.latlng.__vertex.glueindex].push(event.latlng.__vertex);
|
||||
}
|
||||
event.latlng.attributes = {index: event.latlng.__vertex.glueindex, isOnRunway: 0};
|
||||
})
|
||||
this.on('editable:middlemarker:mousedown', event => {
|
||||
console.debug('editable:middlemarker:mousedown');
|
||||
}),
|
||||
this.on('editable:vertex:new', event => {
|
||||
console.debug('editable:vertex:new ' + event.vertex.getIndex() + '\t' + event.vertex.getLastIndex() + '\t');
|
||||
// Find nearest node
|
||||
let closest = this.editLayer.closestLayerSnap(event.latlng, 5)
|
||||
let taxiwaySegment = event.latlng.__vertex.editor.feature;
|
||||
if (taxiwaySegment.options.attributes === undefined) {
|
||||
taxiwaySegment.options.attributes = { direction: 'bi-directional' };
|
||||
}
|
||||
taxiwaySegment.updateStyle();
|
||||
if (event.vertex.getIndex() !== 0 && event.vertex.getIndex() !== event.vertex.getLastIndex()) {
|
||||
var nextIndex = ++taxiwaySegment.editLayer.groundnetLayerGroup.maxId;
|
||||
var splitOffNodes = taxiwaySegment.getLatLngs().splice(-1);
|
||||
var remainingNodes = taxiwaySegment.getLatLngs();
|
||||
splitOffNodes.unshift(L.latLng(remainingNodes[1].lat, remainingNodes[1].lng, remainingNodes[1].alt));
|
||||
remainingNodes[1]['glueindex'] = nextIndex;
|
||||
remainingNodes[1].attributes = { index: nextIndex, isOnRunway: 0 };
|
||||
taxiwaySegment.options.attributes.end = nextIndex;
|
||||
splitOffNodes[0]['glueindex'] = nextIndex;
|
||||
splitOffNodes[0].attributes = { index: nextIndex, isOnRunway: 0 };
|
||||
taxiwaySegment.setLatLngs(remainingNodes);
|
||||
//taxiwaySegment.editor.refresh();
|
||||
//taxiwaySegment.editor.reset();
|
||||
if (splitOffNodes.length > 1) {
|
||||
var polyline = new L.Polyline(splitOffNodes, { attributes: {} });
|
||||
polyline.addTo(taxiwaySegment.editLayer.$parent.$parent.$refs.map.mapObject);
|
||||
polyline.addTo(taxiwaySegment.editLayer.groundnetLayerGroup);
|
||||
extendTaxiSegment(polyline);
|
||||
polyline.addListeners();
|
||||
polyline.setEditlayer(taxiwaySegment.editLayer);
|
||||
polyline.enableEdit(taxiwaySegment.editLayer.$parent.$parent.$refs.map.mapObject);
|
||||
polyline.editor.refresh();
|
||||
//polyline.editor.reset();
|
||||
polyline.featureLookup = this.featureLookup;
|
||||
polyline.options.attributes.name = taxiwaySegment.options.attributes.name;
|
||||
polyline.options.attributes.direction = taxiwaySegment.options.attributes.direction;
|
||||
polyline.options.attributes.isPushBackRoute = taxiwaySegment.options.attributes.isPushBackRoute;
|
||||
polyline.options.attributes.begin = nextIndex;
|
||||
polyline.options.attributes.end = taxiwaySegment.end;
|
||||
polyline.updateStyle();
|
||||
polyline.begin = nextIndex;
|
||||
polyline.end = taxiwaySegment.end;
|
||||
taxiwaySegment.end = nextIndex;
|
||||
this.editLayer.featureLookup[nextIndex] = [];
|
||||
this.featureLookup[nextIndex].push(taxiwaySegment);
|
||||
this.featureLookup[nextIndex].push(polyline);
|
||||
}
|
||||
} else {
|
||||
// Glue to another node
|
||||
if (closest) {
|
||||
event.latlng['glueindex'] = Number(closest.glueindex);
|
||||
event.latlng.__vertex.setLatLng(closest.latlng);
|
||||
event.latlng.attributes = { index: event.latlng.glueindex, isOnRunway: 0 };
|
||||
// Push Vertex to lookup
|
||||
this.editLayer.featureLookup[event.latlng.glueindex].push(event.latlng.__vertex);
|
||||
if (taxiwaySegment.options.attributes.begin === undefined) {
|
||||
taxiwaySegment.options.attributes.begin = event.latlng['glueindex']
|
||||
} else {
|
||||
taxiwaySegment.options.attributes.end = event.latlng['glueindex']
|
||||
}
|
||||
if (taxiwaySegment.getLatLngs().length === 1) {
|
||||
taxiwaySegment.begin = closest.glueindex;
|
||||
}
|
||||
taxiwaySegment.end = closest.glueindex;
|
||||
console.log(`Closest : ${closest}`)
|
||||
} else {
|
||||
event.vertex.latlng['glueindex'] = ++this.editLayer.groundnetLayerGroup.maxId;
|
||||
event.vertex.latlng.attributes = { index: event.vertex.latlng.glueindex, isOnRunway: 0 };
|
||||
this.editLayer.featureLookup[event.vertex.latlng.glueindex] = [];
|
||||
this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(event.vertex);
|
||||
this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(taxiwaySegment);
|
||||
// taxiwaySegment.editor.refresh();
|
||||
//taxiwaySegment.editor.reset();
|
||||
if (taxiwaySegment.options.attributes.begin === undefined) {
|
||||
taxiwaySegment.options.attributes.begin = event.vertex.latlng['glueindex']
|
||||
taxiwaySegment.begin = event.vertex.latlng.glueindex;
|
||||
} else if (taxiwaySegment.options.attributes.end === undefined ||
|
||||
(taxiwaySegment.getLatLngs()[taxiwaySegment.getLatLngs().length - 1].glueindex &&
|
||||
Number(taxiwaySegment.getLatLngs()[taxiwaySegment.getLatLngs().length - 1].glueindex) !== taxiwaySegment.options.attributes.end)) {
|
||||
taxiwaySegment.options.attributes.end = event.vertex.latlng['glueindex']
|
||||
taxiwaySegment.end = Number(event.vertex.latlng.glueindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
//this.splitShape(taxiwaySegment.getLatLngs(), )
|
||||
});
|
||||
this.on('editable:vertex:deleted', event => {
|
||||
console.debug('editable:vertex:deleted')
|
||||
});
|
||||
this.on('editable:vertex:mousedown', event => {
|
||||
console.debug('editable:vertex:mousedown')
|
||||
event.layer.editor.map.fire('mousedown', event);
|
||||
});
|
||||
this.on('editable:vertex:click', event => {
|
||||
console.debug('editable:vertex:click')
|
||||
});
|
||||
this.on('editable:vertex:rawclick', event => {
|
||||
event.cancel()
|
||||
console.debug('editable:vertex:rawclick')
|
||||
});
|
||||
this.on('editable:vertex:clicked', function (event) {
|
||||
console.log(this.featureLookup[event.vertex.glueindex]);
|
||||
|
||||
store.default.dispatch('setNode', event.vertex.latlng.attributes)
|
||||
if(event.vertex._icon!=null) {
|
||||
event.vertex._icon.style['background-color'] = 'red';
|
||||
} else if(event.vertex.icon!=null ) {
|
||||
if(event.vertex.icon.style!=null) {
|
||||
event.vertex.icon.style['background-color'] = 'red';
|
||||
} else {
|
||||
event.vertex.setStyle({color : 'red'})
|
||||
}
|
||||
} else if(event.vertex.options.icon!=null ) {
|
||||
if(event.vertex.options.icon.style!=null) {
|
||||
event.vertex.options.icon.style['background-color'] = 'red';
|
||||
} else {
|
||||
event.vertex.options.icon._setIconStyles({color : 'red'})
|
||||
}
|
||||
}
|
||||
this.unwatch = store.default.watch(
|
||||
function (state) {
|
||||
return state.Editable.data.node;
|
||||
},
|
||||
() => {
|
||||
if(event.vertex._icon!=null) {
|
||||
event.vertex._icon.style['background-color'] = 'white';
|
||||
} else if(event.vertex.icon!=null ) {
|
||||
if(event.vertex.icon.style!=null) {
|
||||
event.vertex.icon.style['background-color'] = 'white';
|
||||
} else {
|
||||
event.vertex.setStyle({color : 'white'})
|
||||
}
|
||||
} else if(event.vertex.options.icon!=null ) {
|
||||
if(event.vertex.options.icon.style!=null) {
|
||||
event.vertex.options.icon.style['background-color'] = 'white';
|
||||
} else {
|
||||
event.vertex.options.icon._setIconStyles({color : 'white'})
|
||||
}
|
||||
}
|
||||
this.unwatch();
|
||||
}
|
||||
,
|
||||
{
|
||||
deep: true //add this if u need to watch object properties change etc.
|
||||
}
|
||||
);
|
||||
});
|
||||
var dragIndex = -1;
|
||||
this.on('editable:vertex:dragstart', function (event) {
|
||||
console.log("Event Target : ", event.target);
|
||||
console.log("Middle Marker : ", event.vertex == event.vertex.middleMarker);
|
||||
console.log("Middle Marker : ", event.vertex.glueindex == undefined);
|
||||
if(event.vertex.glueindex == undefined)
|
||||
return;
|
||||
dragIndex = event.vertex.glueindex;
|
||||
});
|
||||
this.on('editable:vertex:dragend', function (event) {
|
||||
console.log("Dragend : ", event.vertex);
|
||||
if (dragIndex > 0) {
|
||||
this.featureLookup[dragIndex].forEach(element => {
|
||||
if (element instanceof L.ParkingSpot) {
|
||||
//element.setLatLng(event);
|
||||
console.log(element);
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
this.featureLookup[store.default.state.Editable.index] !== undefined) {
|
||||
this.featureLookup[store.default.state.Editable.index].forEach(element => {
|
||||
if (element.deselect !== undefined) {
|
||||
element.deselect();
|
||||
}
|
||||
});
|
||||
}
|
||||
dragIndex = -1;
|
||||
if (!this.editor.map.editTools.drawing()) {
|
||||
var hold = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.HoldNode);
|
||||
if (hold.length > 0) {
|
||||
hold[0].select();
|
||||
}
|
||||
var parking = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.ParkingSpot);
|
||||
if (parking.length > 0) {
|
||||
parking[0].selectParking();
|
||||
} else {
|
||||
this.editLayer.featureLookup[event.vertex.latlng.glueindex].forEach
|
||||
store.default.dispatch('setNode', event.vertex.latlng)
|
||||
this.selectVertex(store.default.state.Editable.index)
|
||||
}
|
||||
}
|
||||
});
|
||||
var dragIndex = -1;
|
||||
this.on('editable:vertex:dragstart', function (event) {
|
||||
console.log("Drag Start : ", event.target);
|
||||
console.log("Middle Marker : ", event.vertex == event.vertex.middleMarker, event.vertex.latlng.glueindex == undefined);
|
||||
if (event.vertex.latlng.glueindex == undefined)
|
||||
return;
|
||||
console.log("Drag Start : ", event.vertex.latlng.glueindex);
|
||||
dragIndex = event.vertex.latlng.glueindex;
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
this.featureLookup[store.default.state.Editable.index] !== undefined) {
|
||||
this.featureLookup[store.default.state.Editable.index].forEach(element => {
|
||||
if (element.deselect !== undefined) {
|
||||
element.deselect();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!this.editor.map.editTools.drawing()) {
|
||||
var hold = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.HoldNode);
|
||||
if (hold.length > 0) {
|
||||
hold[0].select();
|
||||
}
|
||||
var parking = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.ParkingSpot);
|
||||
if (parking.length > 0) {
|
||||
parking[0].selectParking();
|
||||
} else {
|
||||
this.selectVertex(Number(dragIndex))
|
||||
}
|
||||
}
|
||||
});
|
||||
this.on('editable:vertex:dragend', function (event) {
|
||||
console.log("Dragend : ", event.vertex);
|
||||
try {
|
||||
if (dragIndex > 0) {
|
||||
event.target.featureLookup[dragIndex].forEach(element => {
|
||||
if (element instanceof L.ParkingSpot) {
|
||||
//element.setLatLng(event);
|
||||
console.log(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
dragIndex = -1;
|
||||
var parking = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.ParkingSpot);
|
||||
if (parking.length > 0) {
|
||||
parking[0].selectParking();
|
||||
} else {
|
||||
if (Number(event.vertex.latlng.glueindex) !== store.default.state.Editable.index) {
|
||||
if (Number(store.default.state.Editable.index) >= 0 &&
|
||||
this.featureLookup[store.default.state.Editable.index] !== undefined) {
|
||||
this.featureLookup[store.default.state.Editable.index].forEach(element => {
|
||||
if (element.deselect !== undefined) {
|
||||
element.deselect();
|
||||
}
|
||||
});
|
||||
}
|
||||
store.default.dispatch('setNode', event.vertex.latlng)
|
||||
}
|
||||
var lines = this.featureLookup[event.vertex.latlng.glueindex].filter(n => n instanceof L.Polyline);
|
||||
Vue.default.nextTick(function () {
|
||||
lines.forEach(line => {
|
||||
line.selectVertex(store.default.state.Editable.index)
|
||||
});
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
taxiwaySegment.__proto__.follow = function (dragIndex, event) {
|
||||
taxiwaySegment.__proto__.expandArc = function (attributes) {
|
||||
var isPushBackRoute = attributes.isPushBackRoute;
|
||||
var ids = [];
|
||||
var walkedNodes = [];
|
||||
var segmentIds = [];
|
||||
console.debug('start Walk');
|
||||
ids = ids.concat(this.walkPushbackRoute(attributes.begin, walkedNodes, isPushBackRoute));
|
||||
ids = ids.concat(this.walkPushbackRoute(attributes.end, walkedNodes, isPushBackRoute));
|
||||
return ids;
|
||||
}
|
||||
|
||||
taxiwaySegment.__proto__.walkPushbackRoute = function (index, walkedNodes, isPushBackRoute) {
|
||||
console.debug('Walk Level');
|
||||
walkedNodes.push(index)
|
||||
var segmentIds = [];
|
||||
var polyLines = this.featureLookup[index].filter(n => n instanceof L.Polyline);
|
||||
if (polyLines===undefined || polyLines.length>2) {
|
||||
console.debug('Walk ' + index + '\t' + polyLines.length);
|
||||
return;
|
||||
}
|
||||
|
||||
polyLines.forEach(l => {
|
||||
segmentIds.push(l._leaflet_id);
|
||||
console.debug('Walk Next ' + index + '\t' +
|
||||
(walkedNodes.indexOf(index)<0) + '\t'+
|
||||
l.begin + '\t'+
|
||||
(walkedNodes.indexOf(Number(l.begin))<0) + '\t'+
|
||||
l.end + '\t'+
|
||||
(walkedNodes.indexOf(Number(l.end))<0) + '\t'+
|
||||
l.options.attributes.direction + '\t' +
|
||||
l.options.attributes.begin + '\t' +
|
||||
l.options.attributes.end);
|
||||
console.debug('Walk isPushBackRoute ' + l.options.attributes.isPushBackRoute + '\t' + isPushBackRoute + '\t' + (l.options.attributes.isPushBackRoute === isPushBackRoute));
|
||||
if(l.options.attributes.isPushBackRoute === isPushBackRoute ) {
|
||||
console.debug(Number(l.begin) === index && walkedNodes.indexOf(Number(l.end)) < 0);
|
||||
if (Number(l.begin) === index && walkedNodes.indexOf(Number(l.end)) < 0) {
|
||||
console.debug( 'Walk forward ' + l.options.attributes.direction );
|
||||
segmentIds = segmentIds.concat(this.walkPushbackRoute(Number(l.end), walkedNodes, isPushBackRoute))
|
||||
}
|
||||
console.debug(Number(l.end) === index && walkedNodes.indexOf(Number(l.begin)) < 0);
|
||||
if (Number(l.end) === index && walkedNodes.indexOf(Number(l.begin)) < 0 ) {
|
||||
console.debug( 'Walk backward ' + l.options.attributes.direction );
|
||||
segmentIds = segmentIds.concat(this.walkPushbackRoute(Number(l.begin), walkedNodes, isPushBackRoute))
|
||||
}
|
||||
}
|
||||
});
|
||||
return segmentIds;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
taxiwaySegment.__proto__.follow = function (dragIndex, event) {
|
||||
this.featureLookup[dragIndex].forEach(element => {
|
||||
if(element !== event.target){
|
||||
if (element !== event.target) {
|
||||
if (element instanceof L.RunwayNode) {
|
||||
element.setLatLng(event.latlng);
|
||||
}
|
||||
@@ -185,6 +452,8 @@ exports.extendTaxiSegment = function (taxiwaySegment) {
|
||||
// element.extensions();
|
||||
element.updateMiddleMarker();
|
||||
element.updateVertexFromDirection();
|
||||
element.updateWheelPos();
|
||||
element.updateBox();
|
||||
}
|
||||
else if (element instanceof L.Polyline) {
|
||||
if (Number(element.begin) === Number(dragIndex)) {
|
||||
@@ -199,7 +468,8 @@ exports.extendTaxiSegment = function (taxiwaySegment) {
|
||||
element.updateEndVertex(event.latlng);
|
||||
element.updateMiddle();
|
||||
}
|
||||
} else if (element instanceof L.Editable.VertexMarker) {
|
||||
} else if (element instanceof L.Editable.VertexMarker &&
|
||||
element !== event.vertex) {
|
||||
console.log(element);
|
||||
element.setLatLng(event.latlng);
|
||||
element.latlngs.forEach((latlng, index) => {
|
||||
@@ -210,26 +480,65 @@ exports.extendTaxiSegment = function (taxiwaySegment) {
|
||||
});
|
||||
element.editor.feature.setLatLngs(element.latlngs);
|
||||
element.editor.feature.updateMiddle();
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
taxiwaySegment.__proto__.updateStyle = function() {
|
||||
taxiwaySegment.__proto__.updateArrows = function (zoom) {
|
||||
if( this._map === null) {
|
||||
return;
|
||||
}
|
||||
if (this.options.attributes.direction === 'forward') {
|
||||
this.setText(null);
|
||||
if (zoom <= 16) {
|
||||
this.setText(' >', { repeat: true, offset: 6, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 15px serif;' } })
|
||||
} else if (zoom <= 19 ) {
|
||||
this.setText(' > ', { repeat: true, offset: 7, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 20px serif;' } })
|
||||
} else {
|
||||
this.setText(' > ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } })
|
||||
}
|
||||
} else if (this.options.attributes.direction === 'backward') {
|
||||
this.setText(null);
|
||||
if (zoom <= 16) {
|
||||
this.setText(' <', { repeat: true, offset: 6, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 15px serif;' } })
|
||||
} else if (zoom <= 19 ) {
|
||||
this.setText(' < ', { repeat: true, offset: 7, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 20px serif;' } })
|
||||
} else {
|
||||
this.setText(' < ', { repeat: true, offset: 10, attributes: { fill: 'red', style: 'vertical-align: bottom; vertical-align: bottom; font-weight: bold; font: bold 30px serif;' } })
|
||||
}
|
||||
} else {
|
||||
this.setText(null);
|
||||
}
|
||||
}
|
||||
|
||||
taxiwaySegment.__proto__.updateStyle = function () {
|
||||
var style = {};
|
||||
if(this.options.attributes.selected){
|
||||
style.color = 'red';
|
||||
} else if (this.options.attributes.isPushBackRoute) {
|
||||
style.color = 'magenta';
|
||||
if(!this.options.attributes) {
|
||||
return;
|
||||
}
|
||||
if (this.options.attributes.selected) {
|
||||
style.color = 'red';
|
||||
} else if (this.options.attributes.isPushBackRoute) {
|
||||
style.color = 'magenta';
|
||||
}
|
||||
else {
|
||||
style.color = '#3388ff';
|
||||
style.color = '#3388ff';
|
||||
}
|
||||
this.setStyle(style);
|
||||
if (!this.bidirectional) {
|
||||
this.setText(' ► ', {repeat: true, attributes: {fill: 'red', size: 20}})
|
||||
} else {
|
||||
this.setText('')
|
||||
}
|
||||
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;' } })
|
||||
} 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;' } })
|
||||
} else {
|
||||
this.setText(null);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.extendTaxiSegment = extendTaxiSegment;
|
||||
81
src/renderer/loaders/Threshold.js
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
/* eslint-disable */
|
||||
|
||||
const convert = require('geo-coordinates-parser');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
|
||||
|
||||
|
||||
L.Threshold = L.Marker.extend({
|
||||
options: {
|
||||
zIndexOffset: 20000,
|
||||
},
|
||||
stripSVG: function(fName) {
|
||||
var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm;
|
||||
var svg = fs.readFileSync(path.join(__static, '/', fName), 'utf8');
|
||||
var svg2 = rx.exec(svg);
|
||||
return svg2[0];
|
||||
},
|
||||
updateIcon : function(map) {
|
||||
console.debug(`Lat Lng Threshold ${this.getLatLng()}`);
|
||||
if(map !== null) {
|
||||
var metersPP = this.metersPerPixel(map.getCenter().lat, map.getZoom());
|
||||
console.debug('Old Meters per pixel ' + this.metersPP);
|
||||
console.debug('New Meters per pixel ' + metersPP);
|
||||
if(this._metersPP != metersPP) {
|
||||
var pixelSize = (this.iconSize/2) / metersPP;
|
||||
var scale = pixelSize/this.iconSize;
|
||||
var offset = 0;//-(this.iconSize/2);
|
||||
this.setIcon(L.divIcon({
|
||||
iconSize: 64,
|
||||
className: 'threshold-marker-icon',
|
||||
html: `<div style=\'transform: translateX(${offset}px) translateY(${offset}px) scale(${scale}) rotate(${this.options.heading}deg); border: 1px red\'>${this.svg}</div>`,
|
||||
}));
|
||||
|
||||
this.update(this.getLatLng());
|
||||
console.debug();
|
||||
this.setLatLng(this.getLatLng());
|
||||
this._metersPP = metersPP;
|
||||
}
|
||||
}
|
||||
},
|
||||
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);
|
||||
},
|
||||
|
||||
|
||||
});
|
||||
|
||||
L.Threshold.addInitHook(function(){
|
||||
this.svg = this.stripSVG('FGA_THR.svg');
|
||||
this.iconSize = 500;
|
||||
});
|
||||
|
||||
//Builds a marker for a ai or multiplayer aircraft
|
||||
var threshold = function (n, options) {
|
||||
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
|
||||
var heading = n.find('hdg-deg/text()').text();
|
||||
|
||||
var marker = new L.Threshold([latlon.decimalLatitude, latlon.decimalLongitude], {heading: heading, pane: 'threshold-pane'});
|
||||
return marker;
|
||||
}
|
||||
|
||||
module.exports = threshold;
|
||||
78
src/renderer/loaders/Tower.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
/* eslint-disable */
|
||||
|
||||
const convert = require('geo-coordinates-parser');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
|
||||
|
||||
|
||||
L.TowerMarker = L.Marker.extend({
|
||||
options: {
|
||||
zIndexOffset: 10000,
|
||||
},
|
||||
stripSVG: function(fName) {
|
||||
var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm;
|
||||
var svg = fs.readFileSync(path.join(__static, '/', fName), 'utf8');
|
||||
var svg2 = rx.exec(svg);
|
||||
return svg2[0];
|
||||
},
|
||||
updateIcon : function(map) {
|
||||
console.debug(`Lat Lng Threshold ${this.getLatLng()}`);
|
||||
if(map !== null) {
|
||||
var metersPP = this.metersPerPixel(map.getCenter().lat, map.getZoom());
|
||||
console.debug('Old Meters per pixel ' + this.metersPP);
|
||||
console.debug('New Meters per pixel ' + metersPP);
|
||||
if(this._metersPP != metersPP) {
|
||||
var pixelSize = (this.iconSize/2) / metersPP;
|
||||
var scale = pixelSize/this.iconSize;
|
||||
var offset = 0;//-(this.iconSize/2);
|
||||
this.setIcon(L.divIcon({
|
||||
iconSize: 64,
|
||||
className: 'threshold-marker-icon',
|
||||
html: `<div style=\'transform: translateX(${offset}px) translateY(${offset}px) scale(${scale}) rotate(${this.options.heading}deg); border: 1px red\'>${this.svg}</div>`,
|
||||
}));
|
||||
|
||||
this.update(this.getLatLng());
|
||||
console.debug();
|
||||
this.setLatLng(this.getLatLng());
|
||||
this._metersPP = metersPP;
|
||||
}
|
||||
}
|
||||
},
|
||||
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);
|
||||
},
|
||||
|
||||
|
||||
});
|
||||
|
||||
L.TowerMarker.addInitHook(function(){
|
||||
this.svg = this.stripSVG('tower.svg');
|
||||
this.iconSize = 64;
|
||||
});
|
||||
|
||||
//Builds a marker for a ai or multiplayer aircraft
|
||||
var tower = function (n, options) {
|
||||
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
|
||||
return new L.TowerMarker([latlon.decimalLatitude, latlon.decimalLongitude], {heading: 0, pane: 'tower-pane'});
|
||||
}
|
||||
|
||||
module.exports = tower;
|
||||
10
src/renderer/loaders/groundnet_functions.js
Normal file
@@ -0,0 +1,10 @@
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
exports.removeWip = function (fDir, icao) {
|
||||
var fNew = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.new.xml');
|
||||
if( fs.existsSync(fNew) ) {
|
||||
fs.unlinkSync(fNew);
|
||||
}
|
||||
}
|
||||
@@ -17,19 +17,31 @@ var $ = require('jquery');
|
||||
|
||||
var featureLookup = {};
|
||||
|
||||
var frequencies = [];
|
||||
|
||||
function addFrequencies (type, value) {
|
||||
value.split(' ').forEach(frequencyValue => {
|
||||
if( value.length > 0) {
|
||||
var frequency = {type: type, value: frequencyValue};
|
||||
frequencies.push(frequency);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
exports.addFeature = function (feature) {
|
||||
featureLookup[feature.id] = new Array();
|
||||
}
|
||||
|
||||
exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
try {
|
||||
layerGroup = L.layerGroup();
|
||||
store.default.dispatch('setGroundnetLoaded', false);
|
||||
var layerGroup = L.layerGroup();
|
||||
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))
|
||||
return;
|
||||
if (f == null || (!fs.existsSync(f) && force)|| (!fs.existsSync(f) && !fs.existsSync(fNew) ))
|
||||
return layerGroup;
|
||||
if (fNew != null && fs.existsSync(fNew) && !force) {
|
||||
f = fNew;
|
||||
}
|
||||
@@ -47,12 +59,39 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
console.error("Error in " + airline);
|
||||
throw err;
|
||||
}
|
||||
// <frequencies>
|
||||
// <AWOS>13135</AWOS>
|
||||
// <GROUND>12175</GROUND>
|
||||
// <TOWER>11870</TOWER>
|
||||
// <APPROACH>12120</APPROACH>
|
||||
// </frequencies>
|
||||
|
||||
frequencies = [];
|
||||
var approach = xml.find('groundnet/frequencies/APPROACH/text()').text();
|
||||
addFrequencies('APPROACH', approach);
|
||||
var awos = xml.find('groundnet/frequencies/AWOS/text()').text();
|
||||
addFrequencies('AWOS', awos);
|
||||
var clearance = xml.find('groundnet/frequencies/CLEARANCE/text()').text();
|
||||
addFrequencies('CLEARANCE', clearance);
|
||||
var departure = xml.find('groundnet/frequencies/DEPARTURE/text()').text();
|
||||
addFrequencies('DEPARTURE', departure);
|
||||
var ground = xml.find('groundnet/frequencies/GROUND/text()').text();
|
||||
addFrequencies('GROUND', ground);
|
||||
var tower = xml.find('groundnet/frequencies/TOWER/text()').text();
|
||||
addFrequencies('TOWER', tower);
|
||||
var unicom = xml.find('groundnet/frequencies/UNICOM/text()').text();
|
||||
addFrequencies('UNICOM', unicom);
|
||||
|
||||
store.default.dispatch('setFrequencies', frequencies);
|
||||
|
||||
var parkingNodes = xml.find('groundnet/parkingList/Parking');
|
||||
console.log("Parking Nodes" + parkingNodes.length);
|
||||
console.debug("Parking Nodes length" + parkingNodes.length);
|
||||
|
||||
var merged = new Array();
|
||||
|
||||
var nodesLookup = {};
|
||||
featureLookup = [];
|
||||
|
||||
|
||||
parkingNodes.map(n => {
|
||||
var circle = parkingSpot(n, layerGroup);
|
||||
@@ -62,12 +101,27 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
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)}
|
||||
)).sort((p1, p2) => {
|
||||
if (p1.name === p2.name) {
|
||||
return p1.number?p1.number.localeCompare(p2.number):-1;
|
||||
} else {
|
||||
return p1.name.localeCompare(p2.name)
|
||||
}}));
|
||||
|
||||
// Get all nodes into the lookup
|
||||
var taxiNodes = xml.find('groundnet/TaxiNodes/node');
|
||||
taxiNodes.map(n => {
|
||||
//attrs.lat
|
||||
//console.log(n.attr('lat') + " " + n.attr('lon'));
|
||||
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
|
||||
try {
|
||||
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.maxId = Math.max(layerGroup.maxId, Number(n.attr('index')))
|
||||
@@ -102,6 +156,7 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
featureLookup[n.attr('begin')].forEach(element => {
|
||||
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;
|
||||
element.updateStyle();
|
||||
}
|
||||
@@ -111,7 +166,8 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
featureLookup[n.attr('end')].forEach(element => {
|
||||
if (element instanceof L.Polyline && element.end === n.attr('begin') && element.begin === n.attr('end')) {
|
||||
element.bidirectional = true;
|
||||
bidirectional = true;
|
||||
element.options.attributes.direction = 'bi-directional'
|
||||
bidirectional = true;
|
||||
element.updateStyle();
|
||||
}
|
||||
});
|
||||
@@ -119,12 +175,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);
|
||||
extendTaxiSegment(polyline);
|
||||
polyline.addListeners();
|
||||
polyline._latlngs[0].attributes = {};
|
||||
$.each(beginNode.attrs, function (key, value) {
|
||||
console.log(key + "\t" + value);
|
||||
console.debug(key + "\t" + value);
|
||||
|
||||
if (isNaN(value))
|
||||
polyline._latlngs[0].attributes[key] = value;
|
||||
@@ -133,7 +190,7 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
});
|
||||
polyline._latlngs[1].attributes = {};
|
||||
$.each(endNode.attrs, function (key, value) {
|
||||
console.log(key + "\t" + value);
|
||||
console.debug(key + "\t" + value);
|
||||
|
||||
if (isNaN(value))
|
||||
polyline._latlngs[1].attributes[key] = value;
|
||||
@@ -141,13 +198,14 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
polyline._latlngs[1].attributes[key] = Number(value);
|
||||
});
|
||||
$.each(n.attrs, function (key, value) {
|
||||
console.log(key + "\t" + value);
|
||||
console.debug(key + "\t" + value);
|
||||
|
||||
if (isNaN(value))
|
||||
polyline.options.attributes[key] = value;
|
||||
else
|
||||
polyline.options.attributes[key] = Number(value);
|
||||
});
|
||||
polyline.options.attributes.direction = 'forward'
|
||||
polyline.updateStyle();
|
||||
|
||||
polyline.begin = beginNode.attr('index');
|
||||
@@ -168,7 +226,7 @@ exports.readGroundnetXML = function (fDir, icao, force) {
|
||||
}
|
||||
}
|
||||
}).sort();
|
||||
|
||||
store.default.dispatch('setGroundnetLoaded', true);
|
||||
|
||||
return layerGroup;
|
||||
});
|
||||
|
||||
@@ -3,7 +3,6 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const markers = require('./MagneticVertex');
|
||||
const TaxiwaySegment = require('./TaxiwaySegment');
|
||||
|
||||
const parkingSpot = require('./ParkingSpot.js');
|
||||
|
||||
@@ -15,56 +14,130 @@ const mathjs = require('mathjs');
|
||||
|
||||
var builder = require('xmlbuilder');
|
||||
|
||||
var featureLookup = [];
|
||||
var parkings = [];
|
||||
var pushBackNodeLookup = [];
|
||||
|
||||
/**
|
||||
* Walk nodes until the pushback node is found.
|
||||
* @param {*} index
|
||||
*/
|
||||
|
||||
function findRouteToPushback (index) {
|
||||
if (featureLookup===undefined) {
|
||||
return
|
||||
}
|
||||
var walkedNodes = [index]
|
||||
var pushBackNodes = []
|
||||
walkPushbackRoute(index, walkedNodes, pushBackNodes)
|
||||
|
||||
return pushBackNodes
|
||||
}
|
||||
|
||||
function walkPushbackRoute (index, walkedNodes, pushBackNodes) {
|
||||
var polyLines = featureLookup[index];
|
||||
if (polyLines===undefined) {
|
||||
return;
|
||||
}
|
||||
if (pushBackNodeLookup[index]!==undefined) {
|
||||
pushBackNodes.push(pushBackNodeLookup[index]['@index']);
|
||||
}
|
||||
|
||||
polyLines.forEach(l => {
|
||||
if( l['@isPushBackRoute'] === '1' ) {
|
||||
if (Number(l['@begin']) === index && walkedNodes.indexOf(Number(l['@end'])) < 0) {
|
||||
walkedNodes.push(Number(l['@end']))
|
||||
pushBackNodes.concat(walkPushbackRoute(Number(l['@end']), walkedNodes, pushBackNodes))
|
||||
}
|
||||
if (Number(l['@end']) === index && walkedNodes.indexOf(Number(l['@begin'])) < 0 ) {
|
||||
walkedNodes.push(Number(l['@begin']))
|
||||
pushBackNodes.concat(walkPushbackRoute(Number(l['@begin']), walkedNodes, pushBackNodes))
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
exports.writeGroundnetXML = function (fDir, icao, featureList) {
|
||||
try {
|
||||
var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.new.xml');
|
||||
try { fs.mkdirSync(path.join(fDir), { recursive: true })} catch (err) { }
|
||||
try { fs.mkdirSync(path.join(fDir, icao[0]),{ recursive: true })} catch (err) { }
|
||||
try { fs.mkdirSync(path.join(fDir, icao[0], icao[1]), { recursive: true })} catch (err) { }
|
||||
try { fs.mkdirSync(path.join(fDir, icao[0], icao[1], icao[2]), { recursive: true })} catch (err) { }
|
||||
|
||||
var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.new.xml');
|
||||
var fBak = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.bak.xml');
|
||||
|
||||
if( fs.existsSync(f) ) {
|
||||
fs.copyFileSync(f, fBak);
|
||||
}
|
||||
if (f == null)
|
||||
return;
|
||||
pushBackNodeLookup = [];
|
||||
|
||||
console.log(featureList);
|
||||
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 featureLookup = [];
|
||||
var version = new Date().toUTCString() + ' by FlightgearAirports ' + require('electron').remote.app.getVersion();
|
||||
var name = store.default.state.Settings.settings.name;
|
||||
|
||||
featureLookup = [];
|
||||
// Loaded segments
|
||||
featureList.filter(o => o instanceof L.TaxiwaySegment).filter(n => n).forEach(element => {
|
||||
var begin = mapBeginNode(element);
|
||||
if(begin['@index']==="")
|
||||
console.warn("Begin missing");
|
||||
nodes[begin['@index']] = begin;
|
||||
var end = mapEndNode(element);
|
||||
if(end['@index']==="")
|
||||
console.warn("End missing");
|
||||
nodes[end['@index']] = end;
|
||||
});
|
||||
// New segments
|
||||
featureList.filter(o => o instanceof L.Polyline).filter(n => n).forEach(arcElement => {
|
||||
// element._latlngs.forEach(latlng => { nodes[latlng.__vertex.glueindex] = mapVertexNode(latlng) });
|
||||
// element._latlngs.forEach(latlng => { nodes[latlng.glueindex] = mapVertexNode(latlng) });
|
||||
var startIndex = -1;
|
||||
console.log(arcElement.options.attributes);
|
||||
console.debug(arcElement.options.attributes);
|
||||
var currentArc = arcElement.options.attributes;
|
||||
arcElement._latlngs.forEach( latlng => {
|
||||
if (latlng.__vertex !== undefined && latlng.__vertex.glueindex !== undefined) {
|
||||
nodes[latlng.__vertex.glueindex] = mapVertexNode(latlng);
|
||||
if (startIndex > 0) {
|
||||
if (latlng !== undefined && latlng.glueindex !== undefined) {
|
||||
nodes[latlng.glueindex] = mapVertexNode(latlng);
|
||||
if (startIndex >= 0) {
|
||||
if (featureLookup[startIndex] == undefined) {
|
||||
featureLookup[startIndex] = [];
|
||||
}
|
||||
if (featureLookup[latlng.__vertex.glueindex] == undefined) {
|
||||
featureLookup[latlng.__vertex.glueindex] = [];
|
||||
if (featureLookup[latlng.glueindex] == undefined) {
|
||||
featureLookup[latlng.glueindex] = [];
|
||||
}
|
||||
if( currentArc.direction === 'bi-directional' || currentArc.direction === 'forward' ){
|
||||
arc = { '@begin': startIndex, '@end': String(latlng.glueindex) };
|
||||
styleArc(currentArc, arc);
|
||||
arcList.push(arc);
|
||||
featureLookup[startIndex][latlng.glueindex] = arc;
|
||||
}
|
||||
if( currentArc.direction === 'bi-directional' || currentArc.direction === 'backward' ){
|
||||
arc = { '@begin': String(latlng.glueindex), '@end': startIndex };
|
||||
styleArc(currentArc, arc);
|
||||
arcList.push(arc);
|
||||
featureLookup[latlng.glueindex][startIndex] = arc;
|
||||
}
|
||||
if (currentArc.direction === '' || !currentArc.direction) {
|
||||
console.error( "Arc without direction " + util.inspect(currentArc) );
|
||||
}
|
||||
arc = { '@begin': startIndex, '@end': String(latlng.__vertex.glueindex) };
|
||||
styleArc(currentArc, arc);
|
||||
arcList.push(arc);
|
||||
featureLookup[startIndex][latlng.__vertex.glueindex] = arc;
|
||||
arc = { '@begin': String(latlng.__vertex.glueindex), '@end': startIndex };
|
||||
styleArc(currentArc, arc);
|
||||
arcList.push(arc);
|
||||
featureLookup[latlng.__vertex.glueindex][startIndex] = arc;
|
||||
}
|
||||
startIndex = latlng.__vertex.glueindex;
|
||||
startIndex = latlng.glueindex;
|
||||
} else {
|
||||
console.error( "LatLng without glueindex " + util.inspect(latlng) );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -75,51 +148,106 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
|
||||
});
|
||||
|
||||
|
||||
// delete the parkings
|
||||
// Find the index of the pushback node
|
||||
parkings.forEach(n => {
|
||||
nodes[n['@index']] = null;
|
||||
var pushBackNode = findRouteToPushback(Number(n['@index']))[0];
|
||||
if (pushBackNode!==undefined) {
|
||||
n['@pushBackRoute'] = pushBackNode;
|
||||
}
|
||||
});
|
||||
nodes = nodes.filter(n => n);
|
||||
|
||||
arcList = arcList.filter(a => a['@begin'] !== a['@end']);
|
||||
|
||||
nodes.sort((p, p2) => { return p['@index'] - p2['@index'] });
|
||||
//console.debug(util.inspect(nodes));
|
||||
var uniqueNodes = nodes.filter((v, i, a) => a.indexOf(v) === i);
|
||||
|
||||
var maxId = uniqueNodes.slice(-1)[0]['@index'];
|
||||
var approachList = store.default.state.Frequencies.items.filter(f => f.type === 'APPROACH').map(mapFrequency);
|
||||
|
||||
var xmlObj = { groundnet: { version: 1, parkingList: { Parking: parkings }, TaxiNodes: { node: uniqueNodes }, TaxiWaySegments: { arc: arcList } } };
|
||||
var awosList = store.default.state.Frequencies.items.filter(f => f.type === 'AWOS').map(mapFrequency);
|
||||
|
||||
var clearanceList = store.default.state.Frequencies.items.filter(f => f.type === 'CLEARANCE').map(mapFrequency);
|
||||
|
||||
var departureList = store.default.state.Frequencies.items.filter(f => f.type === 'DEPARTURE').map(mapFrequency);
|
||||
|
||||
var groundList = store.default.state.Frequencies.items.filter(f => f.type === 'GROUND').map(mapFrequency);
|
||||
|
||||
var towerList = store.default.state.Frequencies.items.filter(f => f.type === 'TOWER').map(mapFrequency);
|
||||
|
||||
var unicomList = store.default.state.Frequencies.items.filter(f => f.type === 'UNICOM').map(mapFrequency);
|
||||
|
||||
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 } } };
|
||||
|
||||
xmlString = builder.create(xmlObj).end({ pretty: true });
|
||||
fs.writeFileSync(f, xmlString);
|
||||
console.log(xmlString);
|
||||
console.debug(xmlString);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
return layerGroup;
|
||||
return;
|
||||
}
|
||||
|
||||
var mapFrequency = function (o) {
|
||||
return mathjs.round(o.value, 0);
|
||||
}
|
||||
|
||||
var mapParkings = function (o) {
|
||||
console.log(o);
|
||||
console.debug(o);
|
||||
if (o instanceof L.ParkingSpot) {
|
||||
var lat = convertLat(o.getLatLng());
|
||||
var lon = convertLon(o.getLatLng());
|
||||
// <Parking index="0" type="gate" name="GA_Parking" lat="S9 25.739923" lon="E160 2.927602" heading="67" radius="44" airlineCodes="" />
|
||||
return { '@index': String(o['id']), '@type': o.options.attributes.type, '@name': o.options.attributes.name, '@lat': lat, '@lon': lon, '@heading': Number(o.options.attributes.heading), '@radius': String(o.options.attributes.radius) };
|
||||
var parking = { '@index': String(o['id']), '@type': o.options.attributes.type, '@name': o.options.attributes.name, '@lat': lat, '@lon': lon, '@heading': Number(o.options.attributes.heading%360).toFixed(1), '@radius': String(o.options.attributes.radius) };
|
||||
if( o.options.attributes.airlineCodes) {
|
||||
console.debug(o.options.attributes.airlineCodes);
|
||||
parking['@airlineCodes'] = o.options.attributes.airlineCodes;
|
||||
}
|
||||
if(o.options.attributes.number !== undefined &&
|
||||
typeof o.options.attributes.number === 'number' || (
|
||||
typeof o.options.attributes.number === 'string' &&
|
||||
o.options.attributes.number.trim() !== ''
|
||||
)
|
||||
) {
|
||||
console.debug(o.options.attributes.number);
|
||||
parking['@number'] = o.options.attributes.number;
|
||||
}
|
||||
|
||||
return parking;
|
||||
}
|
||||
}
|
||||
|
||||
var mapRunwayNodes = function (o) {
|
||||
console.log(o);
|
||||
console.debug(o);
|
||||
if (o instanceof L.RunwayNode) {
|
||||
return { '@index': String(o['glueindex']), '@lat': convertLat(o._latlng), '@lon': convertLon(o._latlng), '@isOnRunway': '1', '@holdPointType': 'none' };
|
||||
var runwayNode = { '@index': String(o['glueindex']),
|
||||
'@lat': convertLat(o._latlng),
|
||||
'@lon': convertLon(o._latlng),
|
||||
'@isOnRunway': '1',
|
||||
'@holdPointType': 'none' };
|
||||
return runwayNode;
|
||||
}
|
||||
if (o instanceof L.HoldNode) {
|
||||
return { '@index': String(o['glueindex']), '@lat': convertLat(o._latlng), '@lon': convertLon(o._latlng), '@isOnRunway': '0', '@holdPointType': o['holdPointType'] };
|
||||
// return { '@index': String(o['glueindex']), '@lat': convertLat(o._latlng), '@lon': convertLon(o._latlng), '@isOnRunway': '0', '@holdPointType': o['holdPointType'] };
|
||||
}
|
||||
}
|
||||
|
||||
var mapHoldPoint = function (o) {
|
||||
if (o instanceof L.HoldNode) {
|
||||
if( o['holdPointType'] === undefined )
|
||||
{
|
||||
console.error('Oh dear ' + o);
|
||||
}
|
||||
return { '@index': String(o['glueindex']), '@holdPointType': o['holdPointType'] };
|
||||
}
|
||||
}
|
||||
|
||||
var mapBeginNode = function (o) {
|
||||
if (o instanceof L.TaxiwaySegment) {
|
||||
console.log(o);
|
||||
console.debug(o);
|
||||
// <Parking index="0" type="gate" name="GA_Parking" lat="S9 25.739923" lon="E160 2.927602" heading="67" radius="44" airlineCodes="" />
|
||||
return { '@index': String(o['begin']), '@lat': convertLat(o._latlngs[0]), '@lon': convertLon(o._latlngs[0]), '@isOnRunway': '0', '@type': 'begin' };
|
||||
}
|
||||
@@ -127,7 +255,7 @@ var mapBeginNode = function (o) {
|
||||
|
||||
var mapEndNode = function (o) {
|
||||
if (o instanceof L.TaxiwaySegment) {
|
||||
console.log(o);
|
||||
console.debug(o);
|
||||
// <Parking index="0" type="gate" name="GA_Parking" lat="S9 25.739923" lon="E160 2.927602" heading="67" radius="44" airlineCodes="" />
|
||||
return { '@index': String(o['end']), '@lat': convertLat(o._latlngs[1]), '@lon': convertLon(o._latlngs[1]), '@isOnRunway': '0', '@type': 'end' };
|
||||
}
|
||||
@@ -135,32 +263,32 @@ var mapEndNode = function (o) {
|
||||
|
||||
var mapVertexNode = function (l) {
|
||||
if (l instanceof L.LatLng) {
|
||||
console.log(l);
|
||||
console.debug(l);
|
||||
// <Parking index="0" type="gate" name="GA_Parking" lat="S9 25.739923" lon="E160 2.927602" heading="67" radius="44" airlineCodes="" />
|
||||
return { '@index': String(l.__vertex.glueindex), '@lat': convertLat(l), '@lon': convertLon(l), '@isOnRunway': '0', '@holdPointType': l.attributes['holdPointType'] };
|
||||
return { '@index': String(l.glueindex), '@lat': convertLat(l), '@lon': convertLon(l), '@isOnRunway': '0', '@holdPointType': l.attributes['holdPointType'] };
|
||||
}
|
||||
}
|
||||
|
||||
var convertLat = function (latlng) {
|
||||
console.log(latlng.lat);
|
||||
//console.debug(latlng.lat);
|
||||
var NS = latlng.lat > 0 ? 'N' : 'S';
|
||||
var deg = mathjs.floor(mathjs.abs(latlng.lat));
|
||||
var min = (mathjs.abs(latlng.lat) - deg) * 60;
|
||||
// console.log(NS + deg + " " + min);
|
||||
// console.debug(NS + deg + " " + min);
|
||||
return NS + String(deg).padStart(2, '0') + " " + mathjs.round(min, 3);
|
||||
}
|
||||
|
||||
var convertLon = function (latlng) {
|
||||
console.log(latlng.lng);
|
||||
//console.debug(latlng.lng);
|
||||
var NS = latlng.lng > 0 ? 'E' : 'W';
|
||||
var deg = mathjs.floor(mathjs.abs(latlng.lng));
|
||||
var min = (mathjs.abs(latlng.lng) - deg) * 60;
|
||||
// console.log(NS + deg + " " + min);
|
||||
// console.debug(NS + deg + " " + min);
|
||||
return NS + String(deg).padStart(2, '0') + " " + mathjs.round(min, 3);
|
||||
}
|
||||
|
||||
var styleArc = function (attributes, arc) {
|
||||
console.log(attributes);
|
||||
//console.debug(attributes);
|
||||
if(attributes !== undefined){
|
||||
if (attributes.isPushBackRoute !== undefined && Number(attributes.isPushBackRoute) === 1 ) {
|
||||
arc['@isPushBackRoute'] = "1";
|
||||
|
||||
@@ -1,155 +1,511 @@
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
/* eslint-disable */
|
||||
const lineReader = require('readline');
|
||||
const zlib = require('zlib');
|
||||
// const geodesy = require('geodesy');
|
||||
const LatLonEllipsoidal = require( 'geodesy/latlon-ellipsoidal-vincenty.js').default;
|
||||
const LatLonEllipsoidal = require('geodesy/latlon-ellipsoidal-vincenty.js').default;
|
||||
const fs = require('fs');
|
||||
|
||||
module.exports.readPavement = function (f, icao, cb) {
|
||||
console.log(f);
|
||||
layerGroup = L.layerGroup();
|
||||
var currentFeature;
|
||||
const store = require('../store');
|
||||
|
||||
lineReader.createInterface({
|
||||
input: fs.createReadStream(f).pipe(zlib.createGunzip())
|
||||
}).on('line', function (line) {
|
||||
var fields = line.split(/[ ]+/);
|
||||
// var fields = line.match('([0-9]+)');
|
||||
if (fields == null)
|
||||
return;
|
||||
var scanMethod = scanMethods[fields[0]];
|
||||
if (scanMethod != null) {
|
||||
currentFeature = scanMethod(fields, icao, layerGroup, currentFeature);
|
||||
const buildRunwayPoly = require('../leaflet/Runway.js');
|
||||
const buildTaxiwayPoly = require('../leaflet/Taxiway.js');
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} line
|
||||
* @param {*} icao
|
||||
* @param {*} layerGroup
|
||||
* @param {*} currentFeature
|
||||
*/
|
||||
|
||||
function bezier(line, icao, layerGroup, currentFeature) {
|
||||
var previous = currentFeature.slice(-1)[0].slice(-1)[0];
|
||||
if (previous !== undefined &&
|
||||
Number(previous[0]) !== Number(line[1]) &&
|
||||
Number(previous[1]) !== Number(line[2])) {
|
||||
|
||||
var midpoint = calcMidpoint([Number(previous[0]), Number(previous[1])],
|
||||
[Number(line[1]), Number(line[2])]);
|
||||
|
||||
var startPoint = [Number(previous[0]), Number(previous[1])];
|
||||
var endPoint = [Number(line[1]), Number(line[2])];
|
||||
|
||||
if (module.exports.debug) {
|
||||
L.polyline([startPoint, endPoint], { color: 'fuchsia' }).addTo(layerGroup);
|
||||
var marker = new L.marker(endPoint, { title: 'endpoint', color: 'fuchsia' });
|
||||
marker.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), { className: "my-label", offset: [0, 0] });
|
||||
marker.addTo(layerGroup);
|
||||
}
|
||||
else {
|
||||
if (fields[0] == '99') {
|
||||
lineReader.close();
|
||||
|
||||
var control = [Number(line[3]), Number(line[4])];
|
||||
if (!isNaN(control[0]) && control[0] !== undefined && !isNaN(control[1]) && control[1] !== undefined) {
|
||||
|
||||
var controlReflected = pointReflection([Number(line[3]), Number(line[4])],
|
||||
[Number(line[1]), Number(line[2])]);
|
||||
// L.marker(control, { title: 'control' }).addTo(layerGroup);
|
||||
|
||||
// L.marker(controlPointReflected, { title: 'controlReflected' }).addTo(layerGroup);
|
||||
// L.polyline([controlPointReflected, control], { color: 'green' }).addTo(layerGroup);
|
||||
|
||||
// L.polyline([controlReflected, control], { color: 'red' }).addTo(layerGroup);
|
||||
// L.polyline([controlReflected, midpoint], { color: 'aqua' }).addTo(layerGroup);
|
||||
|
||||
var modifiedControlPoint = calcMidpoint(controlReflected, midpoint);
|
||||
// var modifiedControlPoint = controlReflected;
|
||||
|
||||
var points = null;
|
||||
if (exports.bezierPoint === null) {
|
||||
|
||||
if (module.exports.debug) {
|
||||
L.polyline([startPoint, controlReflected, endPoint], { color: 'purple' }).addTo(layerGroup);
|
||||
|
||||
var marker = new L.marker(controlReflected, { title: 'control First' });
|
||||
marker.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), { className: "my-label", offset: [0, 0] });
|
||||
marker.addTo(layerGroup);
|
||||
}
|
||||
points = deCasteljau([
|
||||
[Number(previous[0]), Number(previous[1])],
|
||||
controlReflected, [Number(line[1]), Number(line[2])]]);
|
||||
exports.bezierPoint = control;
|
||||
} else {
|
||||
if (module.exports.debug) {
|
||||
L.polyline([startPoint, exports.bezierPoint, controlReflected, endPoint], { color: 'purple' }).addTo(layerGroup);
|
||||
var marker = new L.marker(exports.bezierPoint, { title: 'exports.bezierPoint' }).addTo(layerGroup);
|
||||
marker.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), { className: "my-label", offset: [0, 10] });
|
||||
marker.addTo(layerGroup);
|
||||
|
||||
var marker1 = new L.marker(controlReflected, { title: 'controlReflected' }).addTo(layerGroup);
|
||||
marker1.bindTooltip(String(currentFeature.slice(-1)[0].length + ' ' + line), { className: "my-label", offset: [0, -10] });
|
||||
marker1.addTo(layerGroup);
|
||||
|
||||
}
|
||||
points = deCasteljau([
|
||||
[Number(previous[0]), Number(previous[1])],
|
||||
exports.bezierPoint,
|
||||
controlReflected,
|
||||
[Number(line[1]), Number(line[2])]]);
|
||||
exports.bezierPoint = control;
|
||||
}
|
||||
|
||||
// L.polyline([previous, control, [Number(line[1]), Number(line[2])]]).addTo(layerGroup);
|
||||
for (let index = 0; index < points.length; index++) {
|
||||
const element = points[index];
|
||||
if (element[0] === "NaN") {
|
||||
console.debug(control);
|
||||
}
|
||||
currentFeature.slice(-1)[0].push(element);
|
||||
}
|
||||
} else {
|
||||
var points = null;
|
||||
if (module.exports.debug) {
|
||||
L.polyline([startPoint, exports.bezierPoint, endPoint], { color: 'purple' }).addTo(layerGroup);
|
||||
L.marker(exports.bezierPoint, { title: 'exports.bezierPoint' }).addTo(layerGroup);
|
||||
}
|
||||
|
||||
points = deCasteljau([
|
||||
[Number(previous[0]), Number(previous[1])],
|
||||
exports.bezierPoint,
|
||||
[Number(line[1]), Number(line[2])]]);
|
||||
|
||||
for (let index = 0; index < points.length; index++) {
|
||||
const element = points[index];
|
||||
if (element[0] === "NaN") {
|
||||
console.debug(control);
|
||||
}
|
||||
currentFeature.slice(-1)[0].push(element);
|
||||
}
|
||||
// console.log('Ignored:', line);
|
||||
}
|
||||
}).on('error', function (err) {
|
||||
console.log(err);
|
||||
lr.close();
|
||||
}).on('close', function () {
|
||||
console.log("End");
|
||||
cb(layerGroup);
|
||||
});
|
||||
}
|
||||
//L.marker([Number(line[3]), Number(line[4])]).addTo(layerGroup);
|
||||
|
||||
currentFeature.slice(-1)[0].push([line[1], line[2]]);
|
||||
return currentFeature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reflect point p on midpoint
|
||||
*/
|
||||
var pointReflectionMidpoint = function (p, p0, p1) {
|
||||
var dx, dy, a, b, x, y;
|
||||
|
||||
dx = (p0[0] + p1[0]) / 2 - p[0];
|
||||
dy = (p0[1] + p1[1]) / 2 - p[1];
|
||||
|
||||
return [(p0[0] + p1[0]) / 2 + dx, (p0[1] + p1[1]) / 2 + dy];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reflect point p on midpoint
|
||||
*/
|
||||
var pointReflection = function (p, p0) {
|
||||
var dx, dy;
|
||||
|
||||
dx = p0[0] - p[0];
|
||||
dy = p0[1] - p[1];
|
||||
|
||||
return [p0[0] + dx, p0[1] + dy];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reflect point p along line through points p0 and p1
|
||||
*
|
||||
* @author Balint Morvai <balint@morvai.de>
|
||||
* @license http://en.wikipedia.org/wiki/MIT_License MIT License
|
||||
* @param p point to reflect
|
||||
* @param p0 first point for reflection line
|
||||
* @param p1 second point for reflection line
|
||||
* @return object
|
||||
*/
|
||||
var reflect = function (p, p0, p1) {
|
||||
var dx, dy, a, b, x, y;
|
||||
|
||||
dx = p1[0] - p0[0];
|
||||
dy = p1[1] - p0[1];
|
||||
a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
|
||||
b = 2 * dx * dy / (dx * dx + dy * dy);
|
||||
x = a * (p[0] - p0[0]) + b * (p[1] - p0[1]) + p0[0];
|
||||
y = b * (p[0] - p0[0]) - a * (p[1] - p0[1]) + p0[1];
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
function calcMidpoint(p1, p2) {
|
||||
return [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2];
|
||||
}
|
||||
|
||||
function lerp(p1, p2, t) {
|
||||
const s = 1 - t;
|
||||
return [p1[0] * s + p2[0] * t, p1[1] * s + p2[1] * t];
|
||||
}
|
||||
|
||||
function deCasteljau(p1, p2, control) {
|
||||
const numSegments = 10;
|
||||
var intermediates = [];
|
||||
|
||||
for (let index = 0; index <= numSegments; index++) {
|
||||
p3 = lerp(p1, control, index / numSegments);
|
||||
p4 = lerp(control, p2, index / numSegments);
|
||||
var intermediate = lerp(p3, p4, index / numSegments);
|
||||
intermediates.push([String(intermediate[0]), String(intermediate[1])]);
|
||||
}
|
||||
intermediates.push(p2);
|
||||
return intermediates;
|
||||
}
|
||||
|
||||
function deCasteljauSegment(pointArray, len) {
|
||||
var subPoints = [];
|
||||
if (pointArray.length == 1) {
|
||||
return pointArray[0];
|
||||
}
|
||||
for (let index = 1; index < pointArray.length; index++) {
|
||||
subPoints.push(lerp(pointArray[index - 1], pointArray[index], len));
|
||||
}
|
||||
return deCasteljauSegment(subPoints, len);
|
||||
}
|
||||
|
||||
|
||||
function deCasteljau(pointArray) {
|
||||
const numSegments = 10;
|
||||
var intermediates = [];
|
||||
|
||||
for (let index = 0; index < numSegments; index++) {
|
||||
intermediates.push(deCasteljauSegment(pointArray, index / numSegments));
|
||||
}
|
||||
return intermediates;
|
||||
}
|
||||
|
||||
function createPoly(currentFeature, layerGroup) {
|
||||
switch (module.exports.type) {
|
||||
case 110:
|
||||
var taxiwayPoly = new L.Polygon(currentFeature);
|
||||
taxiwayPoly.setStyle({ color: module.exports.colour, interactive: false });
|
||||
taxiwayPoly.addTo(layerGroup);
|
||||
break;
|
||||
case 120:
|
||||
var taxiwayPoly = new L.Polygon(currentFeature);
|
||||
taxiwayPoly.setStyle({ color: module.exports.colour, interactive: false });
|
||||
taxiwayPoly.addTo(layerGroup);
|
||||
break;
|
||||
case 130:
|
||||
var taxiwayPoly = new L.Polygon(currentFeature);
|
||||
taxiwayPoly.setStyle({ color: module.exports.colour, fillOpacity: .0, interactive: false });
|
||||
taxiwayPoly.addTo(layerGroup);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function createLineString(currentFeature, layerGroup) {
|
||||
switch (module.exports.type) {
|
||||
case 110:
|
||||
var taxiwayPoly = new L.Polyline(currentFeature);
|
||||
taxiwayPoly.setStyle({ color: module.exports.colour, interactive: false });
|
||||
taxiwayPoly.addTo(layerGroup);
|
||||
break;
|
||||
case 120:
|
||||
var taxiwayPoly = new L.Polyline(currentFeature);
|
||||
taxiwayPoly.setStyle({ color: module.exports.colour, interactive: false });
|
||||
taxiwayPoly.addTo(layerGroup);
|
||||
break;
|
||||
case 130:
|
||||
var taxiwayPoly = new L.Polyline(currentFeature);
|
||||
taxiwayPoly.setStyle({ color: module.exports.colour, interactive: false });
|
||||
taxiwayPoly.addTo(layerGroup);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.readPavement = function (f, icao, callback) {
|
||||
console.log(f);
|
||||
var pavementLayerGroup = L.layerGroup();
|
||||
var currentFeature;
|
||||
|
||||
store.default.dispatch('setPavementLoaded', false);
|
||||
|
||||
if (!fs.existsSync(f)) {
|
||||
store.default.dispatch('setPavementLoaded', true);
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
fs.accessSync(f, fs.constants.R_OK);
|
||||
lineReader.createInterface({
|
||||
input: fs.createReadStream(f).pipe(zlib.createGunzip())
|
||||
}).on('line', function (line) {
|
||||
try {
|
||||
var fields = line.split(/[ ]+/);
|
||||
// var fields = line.match('([0-9]+)');
|
||||
if (fields == null)
|
||||
return;
|
||||
var scanMethod = scanMethods[fields[0]];
|
||||
if (scanMethod != null) {
|
||||
currentFeature = scanMethod(fields, icao, pavementLayerGroup, currentFeature);
|
||||
}
|
||||
else {
|
||||
if (fields[0] == '99') {
|
||||
lineReader.close();
|
||||
}
|
||||
// console.log('Ignored:', line);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error reading : ' + line + error);
|
||||
}
|
||||
}).on('error', function (err) {
|
||||
store.default.dispatch('setPavementLoaded', true);
|
||||
console.error(err);
|
||||
lr.close();
|
||||
callback();
|
||||
}).on('close', function () {
|
||||
store.default.dispatch('setPavementLoaded', true);
|
||||
console.log("End");
|
||||
callback(pavementLayerGroup);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('no access!');
|
||||
store.default.dispatch('setPavementLoaded', true);
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.debug = false;
|
||||
module.exports.isScanning = false;
|
||||
module.exports.colour = 'grey';
|
||||
module.exports.type = 0;
|
||||
module.exports.bezierPoint = null;
|
||||
|
||||
|
||||
var scanMethods = {
|
||||
1: (line, icao) => {
|
||||
// console.log('Airport:', line);
|
||||
if (line[4]===icao){
|
||||
console.log('Airport:', line);
|
||||
if (line[4] === icao) {
|
||||
console.debug('Airport:', line);
|
||||
module.exports.isScanning = true;
|
||||
} else {
|
||||
module.exports.isScanning = false;
|
||||
}
|
||||
},
|
||||
// APTDAT 715 Segment
|
||||
10: (line, icao, layerGroup) => {
|
||||
if (module.exports.isScanning) {
|
||||
var pointMiddle = new LatLonEllipsoidal(Number(line[1]), Number(line[2]));
|
||||
var point1 = pointMiddle.destinationPoint(line[5] / 6.562, line[4]);
|
||||
var point2 = pointMiddle.destinationPoint(line[5] / 6.562, line[4] - 180);
|
||||
|
||||
var runwayPoints = [];
|
||||
|
||||
var bearing = point1.initialBearingTo(point2);
|
||||
// Width in ft
|
||||
var runwayWidth = Number(line[8]) / 3.281;
|
||||
|
||||
runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing + 90)));
|
||||
runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (bearing + 90)));
|
||||
runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (bearing - 90)));
|
||||
runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing - 90)));
|
||||
|
||||
var runwayPoly = buildTaxiwayPoly(runwayPoints);
|
||||
runwayPoly.addTo(layerGroup);
|
||||
}
|
||||
},
|
||||
// Runway
|
||||
100: (line, icao, layerGroup) => {
|
||||
if (module.exports.isScanning) {
|
||||
console.log('Runway ', line );
|
||||
var point1 = new LatLonEllipsoidal(Number(line[9]), Number(line[10]));
|
||||
var point2 = new LatLonEllipsoidal(Number(line[18]), Number(line[19]));
|
||||
console.debug('Runway ', line);
|
||||
var point1 = new LatLonEllipsoidal(Number(line[9]), Number(line[10]));
|
||||
var point2 = new LatLonEllipsoidal(Number(line[18]), Number(line[19]));
|
||||
|
||||
var runwayPoints = [];
|
||||
var runwayPoints = [];
|
||||
|
||||
var bearing = point1.initialBearingTo(point2);
|
||||
var runwayWidth = Number(line[1]);
|
||||
var destination = point1.destinationPoint( 1000, bearing);
|
||||
var bearing = point1.initialBearingTo(point2);
|
||||
var runwayWidth = Number(line[1]);
|
||||
var destination = point1.destinationPoint(1000, bearing);
|
||||
|
||||
runwayPoints.push(point1.destinationPoint( runwayWidth/2, (bearing+90)));
|
||||
runwayPoints.push(point2.destinationPoint( runwayWidth/2, (bearing+90)));
|
||||
runwayPoints.push(point2.destinationPoint( runwayWidth/2, (bearing-90)));
|
||||
runwayPoints.push(point1.destinationPoint( runwayWidth/2, (bearing-90)));
|
||||
|
||||
runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing + 90)));
|
||||
runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (bearing + 90)));
|
||||
runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (bearing - 90)));
|
||||
runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (bearing - 90)));
|
||||
|
||||
var runwayPoly = new L.Polygon(runwayPoints);
|
||||
runwayPoly.setStyle({color: 'grey', interactive: false});
|
||||
runwayPoly.addTo(layerGroup);
|
||||
var runwayPoly = buildRunwayPoly(runwayPoints);
|
||||
runwayPoly.addTo(layerGroup);
|
||||
|
||||
var runwayLine = new L.Polyline([point1,point2]);
|
||||
runwayLine.setStyle({color: 'red'});
|
||||
// runwayLine.addTo(layerGroup);
|
||||
|
||||
var runwayLine1 = new L.Polyline([point1 ,destination]);
|
||||
runwayLine1.setStyle({color: 'red'});
|
||||
// runwayLine1.addTo(layerGroup);
|
||||
var displacedEnd1 = point1.destinationPoint(Number(line[20]), bearing)
|
||||
var displacedEnd2 = point2.destinationPoint(Number(line[20]), bearing - 180)
|
||||
|
||||
var runwayLine = new L.Polyline([displacedEnd1, displacedEnd2]);
|
||||
runwayLine.setStyle({ color: 'yellow', stroke: true, dashArray: [50, 50] });
|
||||
runwayLine.addTo(layerGroup);
|
||||
|
||||
var t1 = new L.Polyline([displacedEnd1.destinationPoint(runwayWidth / 2, (bearing - 90)),
|
||||
displacedEnd1.destinationPoint(runwayWidth / 2, (bearing + 90))]);
|
||||
t1.setStyle({ color: 'yellow' });
|
||||
t1.addTo(layerGroup);
|
||||
|
||||
var t2 = new L.Polyline([displacedEnd2.destinationPoint(runwayWidth / 2, (bearing - 90)),
|
||||
displacedEnd2.destinationPoint(runwayWidth / 2, (bearing + 90))]);
|
||||
t2.setStyle({ color: 'yellow' });
|
||||
t2.addTo(layerGroup);
|
||||
|
||||
var runwayLine1 = new L.Polyline([point1, destination]);
|
||||
runwayLine1.setStyle({ color: 'red' });
|
||||
// runwayLine1.addTo(layerGroup);
|
||||
}
|
||||
},
|
||||
// Pavement
|
||||
110: (line, icao, layerGroup, currentFeature) => {
|
||||
if (!module.exports.isScanning)
|
||||
return undefined;
|
||||
if(typeof currentFeature !== 'undefined')
|
||||
{
|
||||
var taxiwayPoly = new L.Polygon(currentFeature);
|
||||
taxiwayPoly.setStyle({color: 'grey', interactive: false});
|
||||
taxiwayPoly.addTo(layerGroup);
|
||||
return undefined;
|
||||
if (typeof currentFeature !== 'undefined') {
|
||||
createPoly(currentFeature, layerGroup);
|
||||
}
|
||||
module.exports.colour = 'grey';
|
||||
module.exports.type = 110;
|
||||
return [[]];
|
||||
},
|
||||
120: (line, icao, layerGroup, currentFeature) => {
|
||||
if (!module.exports.isScanning)
|
||||
return undefined;
|
||||
return undefined;
|
||||
if (typeof currentFeature !== 'undefined') {
|
||||
createPoly(currentFeature, layerGroup);
|
||||
}
|
||||
module.exports.colour = 'yellow';
|
||||
module.exports.type = 120;
|
||||
return [[]];
|
||||
},
|
||||
130: (line, icao, layerGroup, currentFeature) => {
|
||||
if (!module.exports.isScanning)
|
||||
return undefined;
|
||||
return undefined;
|
||||
if (typeof currentFeature !== 'undefined') {
|
||||
createPoly(currentFeature, layerGroup);
|
||||
}
|
||||
module.exports.colour = 'black';
|
||||
module.exports.type = 130;
|
||||
return [[]];
|
||||
},
|
||||
111: (line, icao, layerGroup, currentFeature) => {
|
||||
if (!module.exports.isScanning)
|
||||
return;
|
||||
console.log(line);
|
||||
currentFeature.slice(-1)[0].push([line[1], line[2]]);
|
||||
return;
|
||||
console.debug(line);
|
||||
var previous = currentFeature.slice(-1)[0].slice(-1)[0];
|
||||
if (previous !== undefined &&
|
||||
previous !== null &&
|
||||
previous[0] === line[1] &&
|
||||
previous[1] === line[2]) {
|
||||
module.exports.bezierPoint = null;
|
||||
} else {
|
||||
currentFeature.slice(-1)[0].push([line[1], line[2]]);
|
||||
module.exports.bezierPoint = null;
|
||||
}
|
||||
return currentFeature;
|
||||
},
|
||||
// Bezier
|
||||
112: (line, icao, layerGroup, currentFeature) => {
|
||||
if (!module.exports.isScanning)
|
||||
return;
|
||||
console.log(line);
|
||||
currentFeature.slice(-1)[0].push([line[1], line[2]]);
|
||||
return currentFeature;
|
||||
if (!module.exports.isScanning) {
|
||||
return;
|
||||
}
|
||||
console.debug(line);
|
||||
return bezier(line, icao, layerGroup, currentFeature);
|
||||
},
|
||||
113: (line, icao, layerGroup, currentFeature) => {
|
||||
if (!module.exports.isScanning)
|
||||
return;
|
||||
if (!module.exports.isScanning) {
|
||||
return;
|
||||
}
|
||||
console.debug(line);
|
||||
currentFeature.slice(-1)[0].push([line[1], line[2]]);
|
||||
currentFeature.push([]);
|
||||
exports.bezierPoint = null;
|
||||
return currentFeature;
|
||||
},
|
||||
// Bezier
|
||||
114: (line, icao, layerGroup, currentFeature) => {
|
||||
if (!module.exports.isScanning)
|
||||
return;
|
||||
currentFeature.slice(-1)[0].push([line[1], line[2]]);
|
||||
if (!module.exports.isScanning) {
|
||||
return;
|
||||
}
|
||||
console.debug(line);
|
||||
bezier(line, icao, layerGroup, currentFeature);
|
||||
currentFeature.push([]);
|
||||
exports.bezierPoint = null;
|
||||
// currentFeature.slice(-1)[0].push([line[1], line[2]]);
|
||||
return currentFeature;
|
||||
},
|
||||
115: (line, icao, layerGroup, currentFeature) => {
|
||||
if (!module.exports.isScanning)
|
||||
return;
|
||||
currentFeature.slice(-1)[0].push([line[1], line[2]]);
|
||||
var taxiwayLine = new L.Polyline(currentFeature);
|
||||
taxiwayLine.setStyle({color: 'red'});
|
||||
// taxiwayLine.addTo(layerGroup);
|
||||
return;
|
||||
console.debug(line);
|
||||
if (exports.bezierPoint !== null) {
|
||||
bezier(line, icao, layerGroup, currentFeature);
|
||||
}
|
||||
else {
|
||||
currentFeature.slice(-1)[0].push([line[1], line[2]]);
|
||||
}
|
||||
createLineString(currentFeature, layerGroup);
|
||||
exports.bezierPoint = null;
|
||||
},
|
||||
// End with Bezier
|
||||
116: (line, icao, layerGroup, currentFeature) => {
|
||||
if (!module.exports.isScanning)
|
||||
return;
|
||||
currentFeature.slice(-1)[0].push([line[1], line[2]]);
|
||||
var taxiwayLine = new L.Polyline(currentFeature);
|
||||
taxiwayLine.setStyle({color: 'red'});
|
||||
return;
|
||||
console.debug(line);
|
||||
currentFeature = bezier(line, icao, layerGroup, currentFeature);
|
||||
createLineString(currentFeature, layerGroup);
|
||||
exports.bezierPoint = null;
|
||||
// taxiwayLine.addTo(layerGroup);
|
||||
},
|
||||
99: (l) => {
|
||||
console.log('Finished');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
73
src/renderer/loaders/threshold_loader.js
Normal file
@@ -0,0 +1,73 @@
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
var xamel = require('xamel');
|
||||
const convert = require('geo-coordinates-parser');
|
||||
|
||||
const store = require('../store');
|
||||
|
||||
const util = require('util');
|
||||
|
||||
const threshold = require('./Threshold.js');
|
||||
|
||||
|
||||
var $ = require('jquery');
|
||||
|
||||
exports.readThresholdXML = function (fDir, icao, force) {
|
||||
try {
|
||||
var layerGroup = L.layerGroup();
|
||||
layerGroup.maxId = 0;
|
||||
var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.threshold.xml');
|
||||
var fNew = path.join(fDir, icao[0], icao[1], icao[2], icao + '.threshold.new.xml');
|
||||
|
||||
if (f == null || !fs.existsSync(f))
|
||||
return;
|
||||
if (fNew != null && fs.existsSync(fNew) && !force) {
|
||||
f = fNew;
|
||||
}
|
||||
|
||||
var features = new Array();
|
||||
|
||||
// map.on("editable:vertex:new", function (event) {
|
||||
// log.console("Add vertex " + event);
|
||||
// });
|
||||
|
||||
var xmlGroundnet = fs.readFileSync(f, 'utf8').toString();
|
||||
xamel.parse(xmlGroundnet, function (err, xml) {
|
||||
console.debug("parsed " + path.basename(f));
|
||||
if (err !== null) {
|
||||
console.error("Error in " + airline);
|
||||
throw err;
|
||||
}
|
||||
|
||||
var thresholdNodes = xml.find('PropertyList/runway/threshold');
|
||||
console.log("Threshold Nodes" + thresholdNodes.length);
|
||||
|
||||
var merged = new Array();
|
||||
|
||||
var nodesLookup = {};
|
||||
featureLookup = [];
|
||||
|
||||
|
||||
thresholdNodes.map(n => {
|
||||
var icon = threshold(n);
|
||||
icon.addTo(layerGroup);
|
||||
|
||||
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
|
||||
/*
|
||||
var marker = new L.Circle([latlon.decimalLatitude, latlon.decimalLongitude], 5);
|
||||
marker.addTo(layerGroup);
|
||||
*/
|
||||
|
||||
// features.push(circle);
|
||||
}).sort();
|
||||
|
||||
return layerGroup;
|
||||
});
|
||||
// var jsonAirports = JSON.parse(geoJSON);
|
||||
// return jsonAirports;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
return layerGroup;
|
||||
};
|
||||
83
src/renderer/loaders/tower_loader.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
var xamel = require('xamel');
|
||||
const convert = require('geo-coordinates-parser');
|
||||
|
||||
const store = require('../store');
|
||||
|
||||
const util = require('util');
|
||||
|
||||
const tower = require('./Tower.js');
|
||||
|
||||
|
||||
var $ = require('jquery');
|
||||
|
||||
exports.readTowerXML = function (fDir, icao, force) {
|
||||
try {
|
||||
var layerGroup = L.layerGroup();
|
||||
layerGroup.maxId = 0;
|
||||
var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.twr.xml');
|
||||
var fNew = path.join(fDir, icao[0], icao[1], icao[2], icao + '.twr.new.xml');
|
||||
|
||||
if (f == null || !fs.existsSync(f))
|
||||
return;
|
||||
if (fNew != null && fs.existsSync(fNew) && !force) {
|
||||
f = fNew;
|
||||
}
|
||||
|
||||
var features = new Array();
|
||||
|
||||
// map.on("editable:vertex:new", function (event) {
|
||||
// log.console("Add vertex " + event);
|
||||
// });
|
||||
|
||||
var xmlGroundnet = fs.readFileSync(f, 'utf8').toString();
|
||||
xamel.parse(xmlGroundnet, function (err, xml) {
|
||||
console.debug("parsed " + path.basename(f));
|
||||
if (err !== null) {
|
||||
console.error("Error in " + airline);
|
||||
throw err;
|
||||
}
|
||||
|
||||
var towerNodes = xml.find('PropertyList/tower/twr');
|
||||
console.log("Tower " + towerNodes.length);
|
||||
|
||||
var merged = new Array();
|
||||
|
||||
var nodesLookup = {};
|
||||
featureLookup = [];
|
||||
|
||||
|
||||
towerNodes.map(n => {
|
||||
var towerIcon = tower(n, layerGroup);
|
||||
towerIcon.addTo(layerGroup);
|
||||
/*
|
||||
//DEBUG Code
|
||||
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
|
||||
var marker = new L.Circle([latlon.decimalLatitude, latlon.decimalLongitude], 5);
|
||||
marker.addTo(layerGroup);
|
||||
*/
|
||||
features.push(towerIcon);
|
||||
}).sort();
|
||||
|
||||
return layerGroup;
|
||||
});
|
||||
// var jsonAirports = JSON.parse(geoJSON);
|
||||
// return jsonAirports;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
return layerGroup;
|
||||
};
|
||||
268
src/renderer/phi/AILayer.js
Normal file
@@ -0,0 +1,268 @@
|
||||
/* eslint-disable */
|
||||
const $ = require('jquery');
|
||||
|
||||
const aiAircraftMarker = require('./AircraftMarker').default;
|
||||
|
||||
var aiLayerLookup = {};
|
||||
|
||||
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
|
||||
|
||||
var metersPerPixel = function (latitude, zoomLevel) {
|
||||
var earthCircumference = 40075017;
|
||||
var latitudeRadians = latitude * (Math.PI / 180);
|
||||
return earthCircumference * Math.cos(latitudeRadians) / Math.pow(2, zoomLevel + 8);
|
||||
};
|
||||
|
||||
var pixelValue = function (latitude, meters, zoomLevel) {
|
||||
return meters / metersPerPixel(latitude, zoomLevel);
|
||||
};
|
||||
|
||||
function mapSGPropertyNode(node) {
|
||||
var o = {};
|
||||
node.children.forEach(child => {
|
||||
if (child.nChildren > 0) {
|
||||
o[child['name']] = mapSGPropertyNode(child);
|
||||
} else {
|
||||
switch (child.type) {
|
||||
case "string":
|
||||
o[child['name']] = child.value;
|
||||
break;
|
||||
case "bool":
|
||||
o[child['name']] = Boolean(child.value);
|
||||
break;
|
||||
case "double":
|
||||
case "int":
|
||||
o[child['name']] = child.value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
o.name = node.name;
|
||||
o.index = node.index;
|
||||
o.path = node.path;
|
||||
return o;
|
||||
}
|
||||
|
||||
(function (factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([
|
||||
'knockout', 'leaflet', 'props'
|
||||
], factory);
|
||||
} else {
|
||||
// Browser globals
|
||||
factory();
|
||||
}
|
||||
}(function (ko, leaflet, SGPropertyNode) {
|
||||
|
||||
var AITypeToCssClassMap = {
|
||||
aircraft: "ai-aircraft-marker-icon",
|
||||
multiplayer: "mp-aircraft-marker-icon"
|
||||
}
|
||||
|
||||
function formatFL(num) {
|
||||
return "F" + ("000" + (num / 100).toFixed(0)).substr(-3, 3);
|
||||
}
|
||||
|
||||
function ViewModel(h, l) {
|
||||
var self = this;
|
||||
|
||||
self.heading = h;
|
||||
self.labelLines = l;
|
||||
}
|
||||
|
||||
L.AILayer = L.GeoJSON.extend({
|
||||
options: {
|
||||
pointToLayer: function (feature, latlng) {
|
||||
var options = {
|
||||
title: feature.properties.callsign,
|
||||
alt: feature.properties.callsign,
|
||||
riseOnHover: true,
|
||||
draggable: true,
|
||||
};
|
||||
|
||||
var aiMarker = null;
|
||||
|
||||
if (feature.properties.type == "aircraft") {
|
||||
if (aiLayerLookup[feature.id] === undefined) {
|
||||
aiMarker = aiAircraftMarker(latlng, feature.properties);
|
||||
aiMarker.on('add', function (e) {
|
||||
});
|
||||
aiMarker.options.draggable = true;
|
||||
//We can't drag multiplayer
|
||||
if (feature.properties.type == "aircraft") {
|
||||
aiMarker.on('dragstart', function (evt) {
|
||||
evt.target.isDragging = true;
|
||||
});
|
||||
|
||||
aiMarker.on('dragend', function (evt) {
|
||||
if (evt.target !== this)
|
||||
return;
|
||||
var pos = evt.target.getLatLng();
|
||||
|
||||
var props = {
|
||||
name: "position",
|
||||
children: [
|
||||
{
|
||||
name: "latitude-deg",
|
||||
value: pos.lat,
|
||||
}, {
|
||||
name: "longitude-deg",
|
||||
value: pos.lng,
|
||||
},
|
||||
],
|
||||
};
|
||||
$.post("json" + feature.properties.path, JSON.stringify(props));
|
||||
evt.target.isDragging = false;
|
||||
});
|
||||
}
|
||||
aiLayerLookup[feature.id] = aiMarker;
|
||||
return aiMarker;
|
||||
} else {
|
||||
var aiMarker = aiLayerLookup[feature.id];
|
||||
aiMarker.setLatLng({lat: feature.geometry.coordinates[1],
|
||||
lng: feature.geometry.coordinates[0]});
|
||||
aiMarker.updateProperties(feature.properties);
|
||||
return aiMarker;
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
// onEachFeature : function(feature, layer) {
|
||||
// },
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
L.GeoJSON.prototype.onAdd.call(this, map);
|
||||
this.update(++this.updateId);
|
||||
},
|
||||
|
||||
onRemove: function (map) {
|
||||
this.updateId++;
|
||||
L.GeoJSON.prototype.onRemove.call(this, map);
|
||||
},
|
||||
|
||||
stop: function () {
|
||||
this.updateId++;
|
||||
},
|
||||
|
||||
// Refresh method called every 10s to reload other aircraft
|
||||
updateId: 0,
|
||||
update: function (id) {
|
||||
var self = this;
|
||||
|
||||
if (self.updateId != id)
|
||||
return;
|
||||
|
||||
var url = this.options.url + "/json/ai/models?d=99";
|
||||
var jqxhr = $.get(url).done(function (data) {
|
||||
try {
|
||||
self.clearLayers();
|
||||
self.addData(self.aiPropsToGeoJson(data, [
|
||||
"aircraft", "multiplayer", "carrier"
|
||||
], self._map.getBounds()));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
||||
}
|
||||
}).fail(function (a, b) {
|
||||
self.updateId++;
|
||||
// alert('failed to load AI data');
|
||||
}).always(function () {
|
||||
});
|
||||
|
||||
if (self.updateId == id) {
|
||||
setTimeout(function () {
|
||||
self.update(id)
|
||||
}, 10000);
|
||||
}
|
||||
},
|
||||
|
||||
// Builds the GeoJSON representation of AI, Multiplayer and Carriers
|
||||
aiPropsToGeoJson: function (props, types, bounds) {
|
||||
var geoJSON = {
|
||||
type: "FeatureCollection",
|
||||
features: [],
|
||||
};
|
||||
|
||||
|
||||
types.forEach(function (type) {
|
||||
props.children.filter(childObject => childObject.path.includes(type))
|
||||
.map(mapSGPropertyNode)
|
||||
.forEach(function (child) {
|
||||
|
||||
if (!child["valid"])
|
||||
return;
|
||||
|
||||
var path = child.path;
|
||||
var position = child.position;
|
||||
var orientation = child.orientation;
|
||||
var velocities = child.velocities;
|
||||
var lon = position["longitude-deg"];
|
||||
var lat = position["latitude-deg"];
|
||||
if (false == bounds.contains(L.latLng(lat, lon))) {
|
||||
return;
|
||||
}
|
||||
var alt = position["altitude-ft"];
|
||||
var heading = orientation["true-heading-deg"];
|
||||
var id = child.id;
|
||||
var callsign = "";
|
||||
var name = "";
|
||||
var speed = 0;
|
||||
var departureAirportId = "";
|
||||
var arrivalAirportId = "";
|
||||
if (type == "multiplayer") {
|
||||
name = child["sim"]["model"]["path"];
|
||||
}
|
||||
if (type == "carrier") {
|
||||
callsign = child["sign"];
|
||||
name = child["name"];
|
||||
speed = velocities["speed-kts"];
|
||||
} else {
|
||||
callsign = child["callsign"];
|
||||
speed = velocities["true-airspeed-kt"];
|
||||
departureAirportId = child["departure-airport-id"];
|
||||
arrivalAirportId = child["arrival-airport-id"];
|
||||
}
|
||||
|
||||
geoJSON.features.push({
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
lon, lat, alt.toFixed(0)
|
||||
],
|
||||
},
|
||||
"id": id,
|
||||
"properties": {
|
||||
"path": path,
|
||||
"type": type,
|
||||
"heading": heading.toFixed(0),
|
||||
"speed": speed.toFixed(0),
|
||||
"callsign": callsign,
|
||||
"name": name,
|
||||
"departureAirportId": departureAirportId,
|
||||
"arrivalAirportId": arrivalAirportId,
|
||||
},
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
return geoJSON;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
L.aiLayer = function (options) {
|
||||
return new L.AILayer(null, options);
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
export function aiLayer(options) {
|
||||
return undefined //new L.AILayer(null, options);
|
||||
}
|
||||
87
src/renderer/phi/AircraftMarker.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/* eslint-disable */
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
|
||||
|
||||
var metersPerPixel = function (latitude, zoomLevel) {
|
||||
var earthCircumference = 40075017;
|
||||
var latitudeRadians = latitude * (Math.PI / 180);
|
||||
return earthCircumference * Math.cos(latitudeRadians) / Math.pow(2, zoomLevel + 8);
|
||||
};
|
||||
|
||||
var pixelValue = function (latitude, meters, zoomLevel) {
|
||||
return meters / metersPerPixel(latitude, zoomLevel);
|
||||
};
|
||||
|
||||
|
||||
function stripSVG(fName) {
|
||||
var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm;
|
||||
var svg = fs.readFileSync(path.join(__static, '/', fName), 'utf8');
|
||||
var svg2 = rx.exec(svg);
|
||||
return svg2[0];
|
||||
}
|
||||
|
||||
const airLinerSVG = stripSVG('Airplane_silhouette.svg');
|
||||
const gaSVG = stripSVG('Black_aircraft_icon.svg');
|
||||
|
||||
L.ParkingAircraftMarker = L.Marker.extend({
|
||||
options: {
|
||||
zIndexOffset: 10000,
|
||||
},
|
||||
|
||||
initialize: function (latlng, options) {
|
||||
L.Marker.prototype.initialize(latlng, options);
|
||||
L.Util.setOptions(this, options);
|
||||
this.heading = options.heading;
|
||||
this.updateIcon();
|
||||
|
||||
this.isDragging = false;
|
||||
|
||||
},
|
||||
updateProperties: function(properties) {
|
||||
this.heading = properties.heading;
|
||||
this.updateIcon();
|
||||
},
|
||||
updateIcon : function() {
|
||||
if(this._map !== undefined && this._map !== null) {
|
||||
var metersPP = metersPerPixel(this._map.getCenter().lat, this._map.getZoom());
|
||||
console.log(metersPP);
|
||||
var scale = 0.07 / metersPP;
|
||||
this.setIcon(L.divIcon({
|
||||
iconSize: null,
|
||||
className: 'aircraft-marker-icon',
|
||||
html: `<div style=\'transform: translateX(-10px) translateY(-10px); height: 20px; width: 20px; border: 1px red\'>${airLinerSVG}</div>`,
|
||||
}));
|
||||
this.getElement().children.item(0).children.item(0).style = `transform: translateX(-200px) translateY(-200px) scale(${scale},${scale}) rotate(${(this.heading)-45}deg)`;
|
||||
}
|
||||
else {
|
||||
this.setIcon(L.divIcon({
|
||||
iconSize: null,
|
||||
className: 'aircraft-marker-icon',
|
||||
html: `<div style=\'transform: rotate(${this.heading}deg) scale(0.001,0.001) \'>${airLinerSVG}</div>`,
|
||||
}));
|
||||
}
|
||||
},
|
||||
onAdd : function(map) {
|
||||
var metersPP = metersPerPixel(map.getCenter().lat, map.getZoom());
|
||||
console.log(metersPP);
|
||||
console.log(this);
|
||||
this.updateIcon();
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
//Builds a marker for a ai or multiplayer aircraft
|
||||
module.exports.default = function (latlng, options) {
|
||||
return new L.ParkingAircraftMarker(latlng, options);
|
||||
}
|
||||
|
||||
/*
|
||||
var l1 = feature.properties.callsign,
|
||||
l2 = feature.properties.heading + 'T ' + feature.properties.speed + 'KTAS ' +
|
||||
formatFL(feature.geometry.coordinates[2]),
|
||||
l3 = feature.properties.departureAirportId + ' -> ' + feature.properties.arrivalAirportId;
|
||||
|
||||
*/
|
||||
@@ -1,26 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
import L from 'leaflet'
|
||||
|
||||
import { createPersistedState, createSharedMutations } from 'vuex-electron'
|
||||
|
||||
import modules from './modules'
|
||||
|
||||
Vue.use(Vuex)
|
||||
//https://a.tile.openstreetmap.de
|
||||
//'http://{s}.tile.osm.org/{z}/{x}/{y}.png'
|
||||
|
||||
export default new Vuex.Store({
|
||||
modules,
|
||||
plugins: [
|
||||
createPersistedState(),
|
||||
createSharedMutations()
|
||||
],
|
||||
strict: process.env.NODE_ENV !== 'production',
|
||||
state: { zoom: 13,
|
||||
center: L.latLng(47.413220, -1.219482),
|
||||
url: 'http://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png',
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
|
||||
marker: L.latLng(47.413220, -1.219482)}
|
||||
})
|
||||
@@ -6,19 +6,32 @@ const ADD_AIRPORT = 'ADD_AIRPORT';
|
||||
const SET_AIRPORTS = 'SET_AIRPORTS';
|
||||
const SET_UNFILTERED_AIRPORTS = 'SET_UNFILTERED_AIRPORTS';
|
||||
const RESET_AIRPORTS = 'RESET_AIRPORTS';
|
||||
const SET_CURRENT_AIRPORT = 'SET_CURRENT_AIRPORT';
|
||||
const UPDATE_CURRENT_AIRPORT = 'UPDATE_CURRENT_AIRPORT';
|
||||
|
||||
const state = {
|
||||
airports: [], unfilteredairports:[]
|
||||
airports: [], unfilteredairports:[], currentAirport: {}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
'DELETE_INDEXED_DB' () { },
|
||||
ADD_AIRPORT (state, airports) {
|
||||
state.airports.push(airports);
|
||||
airports.forEach(airport => {
|
||||
airport.properties.manual = true;
|
||||
idb.saveAirport(airport);
|
||||
});
|
||||
Vue.set(state, 'airports', state.airports.concat(airports));
|
||||
},
|
||||
'UPDATE_CURRENT_AIRPORT' (state, airport) {
|
||||
Vue.set(state, 'currentAirport', airport.properties);
|
||||
idb.saveAirport(airport);
|
||||
},
|
||||
SET_AIRPORTS (state, airports) {
|
||||
Vue.set(state, 'airports', airports);
|
||||
},
|
||||
SET_CURRENT_AIRPORT (state, airport) {
|
||||
Vue.set(state, 'currentAirport', airport);
|
||||
},
|
||||
SET_UNFILTERED_AIRPORTS (state, airports) {
|
||||
state.unfilteredairports = airports;
|
||||
},
|
||||
@@ -38,7 +51,48 @@ const actions = {
|
||||
let airports = await idb.getAirports();
|
||||
context.commit(SET_AIRPORTS, airports
|
||||
.filter(point => typeof point.geometry.coordinates !== "undefined" )
|
||||
.filter(point => point.properties.flights > 0 ));
|
||||
.filter(point => (point.properties.flights > 0 || point.properties.manual)));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
async addAirline(context, airlineCode) {
|
||||
try {
|
||||
airlineCode = airlineCode.toUpperCase()
|
||||
let airports = await idb.getAirports();
|
||||
let searchRegex = new RegExp(this.state.Airports.currentAirport.icao, 'i');
|
||||
let airport = airports
|
||||
.filter(point => typeof point.geometry.coordinates !== "undefined" )
|
||||
.filter(a => searchRegex.test(a.properties.icao));
|
||||
if (airport[0] !== undefined && !airport[0].properties.airlines.includes(airlineCode)) {
|
||||
airport[0].properties.airlines.push(airlineCode);
|
||||
airport[0].properties.airlines.sort();
|
||||
}
|
||||
context.commit(UPDATE_CURRENT_AIRPORT, airport[0]);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
async setCurrentAirport(context, icao) {
|
||||
try {
|
||||
let airports = await idb.getAirports();
|
||||
let searchRegex = new RegExp(icao, 'i');
|
||||
let airport = airports
|
||||
.filter(point => typeof point.geometry.coordinates !== "undefined" )
|
||||
.filter(a => searchRegex.test(a.properties.icao));
|
||||
context.commit(SET_CURRENT_AIRPORT, airport[0].properties);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
async getAirport(context, icao) {
|
||||
try {
|
||||
let airports = await idb.getAirports();
|
||||
let searchRegex = new RegExp(icao, 'i');
|
||||
let airport = airports
|
||||
.filter(point => typeof point.geometry.coordinates !== "undefined" )
|
||||
.filter(a => searchRegex.test(a.properties.icao));
|
||||
context.commit(ADD_AIRPORT, airport);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,37 @@
|
||||
/**
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
import Vue from 'vue'
|
||||
|
||||
const state = {
|
||||
type: 'none',
|
||||
index: 'none',
|
||||
data: {airports: {}, parking: {}, arc: {}, node: {}, runway: {}}
|
||||
editing: false,
|
||||
data: {airports: {}, parking: {}, arc: {}, multiarc: {}, node: {}, runway: {}}
|
||||
}
|
||||
|
||||
const SET_EDIT_AIRPORT = 'SET_EDIT_AIRPORT'
|
||||
const SET_EDIT_PARKING = 'SET_EDIT_PARKING'
|
||||
const SET_EDIT_ARC = 'SET_EDIT_ARC'
|
||||
const SET_EDIT_MULTI_ARC = 'SET_EDIT_MULTI_ARC'
|
||||
const SET_EDIT_RUNWAY = 'SET_EDIT_RUNWAY'
|
||||
|
||||
const mutations = {
|
||||
SET_EDIT_TYPE (state, type) {
|
||||
state.type = type
|
||||
},
|
||||
SET_EDIT (state, editing) {
|
||||
state.editing = editing
|
||||
},
|
||||
SET_EDIT_AIRPORT (state, airport) {
|
||||
Vue.set(state.data, 'airport', airport)
|
||||
state.index = airport.icao
|
||||
@@ -28,19 +48,26 @@ const mutations = {
|
||||
if (node === undefined) {
|
||||
return
|
||||
}
|
||||
Vue.set(state, 'data', {})
|
||||
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, 'runway', runway)
|
||||
Vue.set(state.data, 'node', runway)
|
||||
Vue.set(state, 'index', runway.index)
|
||||
Vue.set(state, 'type', 'runway')
|
||||
},
|
||||
SET_EDIT_ARC (state, arc) {
|
||||
Vue.set(state, 'data', {})
|
||||
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', '')
|
||||
@@ -48,24 +75,89 @@ const mutations = {
|
||||
Vue.set(state, 'index', arc.index)
|
||||
Vue.set(state, 'type', 'arc')
|
||||
},
|
||||
SET_EDIT_MULTI_ARC (state, arc) {
|
||||
if (arc === undefined) {
|
||||
return
|
||||
}
|
||||
if (!state.data || state.type !== 'multiarc') {
|
||||
Vue.set(state, 'data', {multiarc: {}})
|
||||
}
|
||||
Vue.set(state.data.multiarc, 'isPushBackRoute', arc.isPushBackRoute)
|
||||
Vue.set(state.data.multiarc, 'direction', arc.direction)
|
||||
if (state.data.multiarc.name === undefined) {
|
||||
Vue.set(state.data.multiarc, 'name', '')
|
||||
}
|
||||
Vue.set(state, 'index', arc.index)
|
||||
|
||||
Vue.set(state, 'type', 'multiarc')
|
||||
},
|
||||
'SET_EDIT_MULTI_ARC_IDS' (state, arcs) {
|
||||
if (arcs === undefined) {
|
||||
return
|
||||
}
|
||||
if (!state.data || state.type !== 'multiarc') {
|
||||
return
|
||||
}
|
||||
if (state.data.multiarc.ids === undefined) {
|
||||
state.data.multiarc.ids = []
|
||||
}
|
||||
state.data.multiarc.ids = state.data.multiarc.ids.concat(arcs.filter(n => n).filter((v, i, a) => a.indexOf(v) === i))
|
||||
},
|
||||
'SET_EDIT_PARKING_NAME' (state, parkingName) {
|
||||
Vue.set(state.data.parking, 'name', parkingName)
|
||||
},
|
||||
'SET_EDIT_PARKING_NUMBER' (state, parkingName) {
|
||||
Vue.set(state.data.parking, 'number', parkingName)
|
||||
},
|
||||
'SET_EDIT_PARKING_HEADING' (state, heading) {
|
||||
while (heading >= 360) {
|
||||
heading -= 360
|
||||
}
|
||||
while (heading < 0) {
|
||||
heading += 360
|
||||
}
|
||||
|
||||
Vue.set(state.data.parking, 'heading', heading)
|
||||
},
|
||||
'SET_EDIT_PARKING_AIRLINES' (state, airlineCodes) {
|
||||
Vue.set(state.data.parking, 'airlineCodes', airlineCodes)
|
||||
},
|
||||
'SET_EDIT_PARKING_TYPE' (state, type) {
|
||||
Vue.set(state.data.parking, 'type', type)
|
||||
},
|
||||
'SET_EDIT_PARKING_RADIUS' (state, radius) {
|
||||
Vue.set(state.data.parking, 'radius', radius)
|
||||
},
|
||||
'SET_EDIT_PARKING_COORDS' (state, coords) {
|
||||
Vue.set(state.data.parking, 'coords', coords)
|
||||
},
|
||||
'SET_EDIT_ARC_NAME' (state, arcName) {
|
||||
Vue.set(state.data.arc, 'name', arcName)
|
||||
if (state.type === 'arc') {
|
||||
Vue.set(state.data.arc, 'name', arcName)
|
||||
} else {
|
||||
Vue.set(state.data.multiarc, 'name', arcName)
|
||||
}
|
||||
},
|
||||
'SET_EDIT_PUSHBACK' (state, isPushBackRoute) {
|
||||
Vue.set(state.data.arc, 'isPushBackRoute', isPushBackRoute)
|
||||
if (state.type === 'arc') {
|
||||
Vue.set(state.data.arc, 'isPushBackRoute', Number(isPushBackRoute))
|
||||
} else {
|
||||
Vue.set(state.data.multiarc, 'isPushBackRoute', Number(isPushBackRoute))
|
||||
}
|
||||
},
|
||||
'SET_EDIT_DIRECTION' (state, direction) {
|
||||
if (state.type === 'arc') {
|
||||
Vue.set(state.data.arc, 'direction', direction)
|
||||
} else {
|
||||
Vue.set(state.data.multiarc, 'direction', direction)
|
||||
}
|
||||
},
|
||||
'SET_EDIT_HOLDPOINTTYPE' (state, holdPointType) {
|
||||
Vue.set(state.data.node, 'holdPointType', holdPointType)
|
||||
},
|
||||
'SET_EDIT_NODE_COORDS' (state, coords) {
|
||||
Vue.set(state.data.node, 'coords', coords)
|
||||
},
|
||||
'SET_EDIT_ISONRUNWAY' (state, isOnRunway) {
|
||||
Vue.set(state.data.node, 'isOnRunway', isOnRunway)
|
||||
}
|
||||
@@ -81,11 +173,27 @@ const actions = {
|
||||
async setParking (context, parking) {
|
||||
context.commit(SET_EDIT_PARKING, parking)
|
||||
},
|
||||
async setParkingRadius (context, radius) {
|
||||
context.commit('SET_EDIT_PARKING_RADIUS', radius)
|
||||
},
|
||||
async setParkingHeading (context, heading) {
|
||||
context.commit('SET_EDIT_PARKING_HEADING', heading)
|
||||
},
|
||||
async setParkingCoords (context, coords) {
|
||||
context.commit('SET_EDIT_PARKING_COORDS', coords)
|
||||
},
|
||||
async setArc (context, arc) {
|
||||
context.commit(SET_EDIT_ARC, arc)
|
||||
},
|
||||
async setMultiArc (context, arc) {
|
||||
context.commit(SET_EDIT_MULTI_ARC, arc)
|
||||
},
|
||||
async setMultiArcIds (context, arc) {
|
||||
context.commit('SET_EDIT_MULTI_ARC_IDS', arc)
|
||||
},
|
||||
async setNode (context, node) {
|
||||
context.commit('SET_EDIT_NODE', node)
|
||||
context.commit('SET_EDIT_NODE', node.attributes)
|
||||
context.commit('SET_EDIT_NODE_COORDS', node.lat.toFixed(6) + ' ' + node.lng.toFixed(6))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
43
src/renderer/store/modules/Frequencies.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
const state = { items: [] }
|
||||
|
||||
const mutations = {
|
||||
ADD_FREQUENCY: (state, item) => {
|
||||
state.items.push(item)
|
||||
},
|
||||
UPDATE_FREQUENCY: (state, item) => {
|
||||
const existingItem = state.items.find((i) => i.id === item.id)
|
||||
Object.assign(existingItem, item)
|
||||
},
|
||||
REMOVE_FREQUENCY: (state, item) => {
|
||||
const index = state.items.indexOf(item)
|
||||
if (index > -1) {
|
||||
state.items.splice(index, 1)
|
||||
}
|
||||
},
|
||||
SET_FREQUENCIES (state, frequencies) {
|
||||
Vue.set(state, 'items', frequencies)
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
async addFrequency (context, frequency) {
|
||||
context.commit('ADD_FREQUENCY', frequency)
|
||||
},
|
||||
async updateFrequency (context, frequency) {
|
||||
context.commit('SET_GROUND', frequency)
|
||||
},
|
||||
async removeFrequency (context, frequency) {
|
||||
context.commit('REMOVE_FREQUENCY', frequency)
|
||||
},
|
||||
async setFrequencies (context, frequencies) {
|
||||
context.commit('SET_FREQUENCIES', frequencies)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
51
src/renderer/store/modules/Loading.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
import Vue from 'vue'
|
||||
|
||||
const state = { icao: '', groundnetLoaded: false, pavementLoaded: false }
|
||||
|
||||
const mutations = {
|
||||
SET_ICAO_LOADING (state, icao) {
|
||||
Vue.set(state, 'icao', icao)
|
||||
},
|
||||
SET_GROUNDNET_LOADED (state, loaded) {
|
||||
Vue.set(state, 'groundnetLoaded', loaded)
|
||||
},
|
||||
SET_PAVEMENT_LOADED (state, loaded) {
|
||||
Vue.set(state, 'pavementLoaded', loaded)
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
async setIcaoLoading (context, p) {
|
||||
context.commit('SET_ICAO_LOADING', p)
|
||||
},
|
||||
async setGroundnetLoaded (context, p) {
|
||||
if (typeof p !== 'boolean') {
|
||||
console.error('Not Boolean')
|
||||
}
|
||||
context.commit('SET_GROUNDNET_LOADED', p)
|
||||
},
|
||||
async setPavementLoaded (context, p) {
|
||||
if (typeof p !== 'boolean') {
|
||||
console.error('Not Boolean')
|
||||
}
|
||||
context.commit('SET_PAVEMENT_LOADED', p)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
60
src/renderer/store/modules/Parkings.js
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
import Vue from 'vue'
|
||||
|
||||
const state = { items: [] }
|
||||
|
||||
const mutations = {
|
||||
ADD_PARKING: (state, item) => {
|
||||
state.items.push(item)
|
||||
},
|
||||
UPDATE_PARKING: (state, item) => {
|
||||
const existingItem = state.items.find((i) => i.index === item.index)
|
||||
if (existingItem !== undefined) {
|
||||
Object.assign(existingItem, item)
|
||||
}
|
||||
},
|
||||
SET_PARKINGS (state, parkings) {
|
||||
Vue.set(state, 'items', parkings)
|
||||
},
|
||||
'SET_EDIT_PARKING_ITEM_NAME' (state, value) {
|
||||
const existingItem = state.items.find((i) => i.index === value[0])
|
||||
Vue.set(existingItem, 'name', value[1])
|
||||
},
|
||||
'SET_EDIT_PARKING_ITEM_NUMBER' (state, value) {
|
||||
const existingItem = state.items.find((i) => i.index === value[0])
|
||||
Vue.set(existingItem, 'number', value[1])
|
||||
},
|
||||
'SET_EDIT_PARKING_ITEM_TYPE' (state, value) {
|
||||
const existingItem = state.items.find((i) => i.index === value[0])
|
||||
Vue.set(existingItem, 'type', value[1])
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
async addParking (context, p) {
|
||||
context.commit('ADD_FREADD_PARKINGQUENCY', p)
|
||||
},
|
||||
async updatedParking (context, p) {
|
||||
context.commit('UPDATE_PARKING', p)
|
||||
},
|
||||
async setParkings (context, parkings) {
|
||||
context.commit('SET_PARKINGS', parkings)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
@@ -1,43 +1,104 @@
|
||||
/* eslint-disable */
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const state = {
|
||||
settings: { flightgearDirectory: '.' },
|
||||
settings: { flightgearDirectory: '.', testDirectory: '.', email: 'flightgearairports@example.org', name: 'unknown', phi_url: 'http://localhost:8080' },
|
||||
zoom: 14,
|
||||
center: [47.413220, -1.219482],
|
||||
bounds: undefined
|
||||
bounds: undefined,
|
||||
wip: []
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
'DELETE_INDEXED_DB' () { },
|
||||
'FLIGHTGEAR_DIRECTORY' (state, flightgearDirectory) {
|
||||
state.settings.flightgearDirectory = flightgearDirectory
|
||||
state.settings.flightgearDirectory_ai = flightgearDirectory + '/data/AI'
|
||||
state.settings.flightgearDirectory_traffic = flightgearDirectory + '/data/AI/Traffic'
|
||||
state.settings.flightgearDirectory_apt = flightgearDirectory + '/data/Airports/apt.dat.gz'
|
||||
'DELETE_INDEXED_DB'() { },
|
||||
'FLIGHTGEAR_DIRECTORY'(state, flightgearDirectory) {
|
||||
try {
|
||||
fs.accessSync(flightgearDirectory)
|
||||
state.settings.flightgearDirectory = flightgearDirectory
|
||||
} catch (err) {
|
||||
try {
|
||||
fs.accessSync(flightgearDirectory.replace(/\.App/, ''))
|
||||
state.settings.flightgearDirectory = flightgearDirectory.replace(/\.App/, '')
|
||||
} catch (error) {
|
||||
console.warn(error)
|
||||
}
|
||||
}
|
||||
|
||||
state.settings.flightgearDirectory_ai = flightgearDirectory + path.sep + 'AI'
|
||||
state.settings.flightgearDirectory_traffic = path.join(flightgearDirectory, 'AI', 'Traffic');
|
||||
state.settings.flightgearDirectory_apt = path.join(flightgearDirectory, 'Airports', 'apt.dat.gz');
|
||||
},
|
||||
'AIPORTS_DIRECTORY' (state, airportsDirectory) {
|
||||
'AIPORTS_DIRECTORY'(state, airportsDirectory) {
|
||||
state.settings.airportsDirectory = airportsDirectory
|
||||
},
|
||||
'ZOOM' (state, zoom) {
|
||||
'TEST_DIRECTORY'(state, testDirectory) {
|
||||
state.settings.testDirectory = testDirectory
|
||||
},
|
||||
'ZOOM'(state, zoom) {
|
||||
state.zoom = zoom
|
||||
},
|
||||
'CENTER' (state, center) {
|
||||
'CENTER'(state, center) {
|
||||
state.center = center
|
||||
},
|
||||
'BOUNDS' (state, bounds) {
|
||||
'BOUNDS'(state, bounds) {
|
||||
state.bounds = bounds
|
||||
},
|
||||
'SET_EMAIL'(state, email) {
|
||||
state.settings.email = email
|
||||
},
|
||||
'SET_NAME'(state, name) {
|
||||
state.settings.name = name
|
||||
},
|
||||
'SET_PHI_URL'(state, phi_url) {
|
||||
state.settings.phi_url = phi_url
|
||||
},
|
||||
'SET_SCAN_LOGGING'(state, scanLogging) {
|
||||
state.settings.scanLogging = scanLogging
|
||||
},
|
||||
'ADD_WIP'(state, airport) {
|
||||
const item = state.wip.find((e) => e.icao === airport.icao)
|
||||
airport.time = Date.now()
|
||||
if (item === null || item === undefined) {
|
||||
state.wip.push(airport)
|
||||
} else {
|
||||
Object.assign(item, airport)
|
||||
}
|
||||
state.wip.sort((w1, w2) => w1.time - w2.time)
|
||||
},
|
||||
'UPLOAD_WIP'(state, icao) {
|
||||
const item = state.wip.find((e) => e.icao === icao)
|
||||
item.upload = Date.now()
|
||||
state.wip.sort((p, p2) => { return p.time - p2.time })
|
||||
},
|
||||
'REMOVE_WIP'(state, icao) {
|
||||
const item = state.wip.find((e) => e.icao === icao)
|
||||
const index = state.wip.indexOf(item)
|
||||
if (index > -1) {
|
||||
state.wip.splice(index, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const plugins = []
|
||||
|
||||
const actions = {
|
||||
async setZoom (context, zoom) {
|
||||
async setZoom(context, zoom) {
|
||||
context.commit('ZOOM', zoom)
|
||||
},
|
||||
async setCenter (context, center) {
|
||||
context.commit('CENTER', center)
|
||||
async setCenter(context, center) {
|
||||
if (center.lat !== context.state.center.lat || center.lng !== context.state.center.lng) {
|
||||
context.commit('CENTER', center)
|
||||
}
|
||||
},
|
||||
async setBounds (context, bounds) {
|
||||
async setBounds(context, bounds) {
|
||||
context.commit('BOUNDS', bounds)
|
||||
},
|
||||
async addWip(context, airport) {
|
||||
context.commit('ADD_WIP', airport)
|
||||
},
|
||||
async removeWip(context, icao) {
|
||||
context.commit('REMOVE_WIP', icao)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/* eslint-disable */
|
||||
const lineReader = require('readline');
|
||||
const fs = require('fs');
|
||||
const airports = require('./airports');
|
||||
|
||||
var scanMethods = {
|
||||
1: (l, apts) => {
|
||||
console.log('Airport:', l);
|
||||
|
||||
var airportFeature = airports.getAirport(apts, l[4]);
|
||||
console.log(JSON.stringify(airportFeature));
|
||||
airportFeature.properties.name = l.slice(5).join(' ').replace('\t', ' ');
|
||||
console.debug(airportFeature.properties.name);
|
||||
// apts.update(airportFeature);
|
||||
},
|
||||
99: (l) => {
|
||||
console.log('Finished');
|
||||
}
|
||||
};
|
||||
|
||||
function scan (f, apts) {
|
||||
console.log(f);
|
||||
lineReader.createInterface({
|
||||
input: fs.createReadStream(f)
|
||||
}).on('line', function (line) {
|
||||
var fields = line.split(/[ ]+/);
|
||||
// var fields = line.match('([0-9]+)');
|
||||
if (fields == null)
|
||||
return;
|
||||
var scanMethod = scanMethods[fields[0]];
|
||||
if (scanMethod != null) {
|
||||
scanMethod(fields, apts);
|
||||
}
|
||||
else {
|
||||
if (fields[0] == '99') {
|
||||
lineReader.close();
|
||||
}
|
||||
// console.log('Ignored:', line);
|
||||
}
|
||||
}).on('error', function (err) {
|
||||
console.log(err);
|
||||
lr.close();
|
||||
}).on('close', function () {
|
||||
console.log("End");
|
||||
airports.save();
|
||||
});
|
||||
}
|
||||
|
||||
// export default { scan, name }
|
||||
|
||||
@@ -1,46 +1,178 @@
|
||||
/* eslint-disable */
|
||||
const lineReader = require('readline');
|
||||
const zlib = require('zlib');
|
||||
|
||||
var icao;
|
||||
|
||||
async function asyncForEach(array, callback) {
|
||||
function aptForEach(array, apt, features, callback) {
|
||||
logger('info', "AsyncForEach Len " + array.length);
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
try {
|
||||
var res = await callback(array[index], index, array);
|
||||
logger('info', "Index " + index + " " + res);
|
||||
apt = callback(array[index], index, apt);
|
||||
logger('info', "Index : " + index + " Result : " + apt);
|
||||
} catch (error) {
|
||||
logger('error', error);
|
||||
}
|
||||
}
|
||||
saveAirport(features, apt).then(t => {
|
||||
postMessage(['progress', array.length]);
|
||||
logger('info', `Stored : ${apt.icao}` );
|
||||
if( apt.last ) {
|
||||
postMessage('DONE');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.boundingBox = null;
|
||||
|
||||
var scanMethods = {
|
||||
1: async (l, apts) => {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
1: (l, apts, apt) => {
|
||||
try {
|
||||
logger('info', 'Airport:', l);
|
||||
icao = l[4];
|
||||
saveName(apts, l[4], l.slice(5).join(' ').replace('\t', ' '))
|
||||
.then(result => {
|
||||
resolve(result)
|
||||
}).catch( err => {reject(err)});
|
||||
});
|
||||
return promise;
|
||||
apt.icao = l[4];
|
||||
apt.name = l.slice(5).join(' ').replace('\t', ' ');
|
||||
apt.type = 'airport'
|
||||
return apt;
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
14: async (l, apts) => {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
logger('info','Viewport:', l);
|
||||
saveCoordinates(apts, icao, l[1], l[2]).then(result => {
|
||||
resolve(result)
|
||||
}).catch( err => {reject(err)});;
|
||||
});
|
||||
return promise;
|
||||
14: (l, apts, apt) => {
|
||||
logger('info', 'Viewport:', l);
|
||||
try {
|
||||
updateBoundingBox(apt, l[1], l[2]);
|
||||
return apt;
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
99: async (l) => {
|
||||
logger('info','Finished');
|
||||
16: (l, apts, apt) => {
|
||||
logger('info', 'Seaplane:', l);
|
||||
apt.icao = l[4];
|
||||
apt.name = l.slice(5).join(' ').replace('\t', ' ');
|
||||
apt.type = 'seaplane'
|
||||
resolve(apt);
|
||||
},
|
||||
17: (l, apts, apt) => {
|
||||
logger('info', 'Heliport:', l);
|
||||
apt.icao = l[4];
|
||||
apt.name = l.slice(5).join(' ').replace('\t', ' ');
|
||||
apt.type = 'heliport'
|
||||
},
|
||||
18: (l, apts, apt) => {
|
||||
logger('info', 'Airport light beacon:', l);
|
||||
try {
|
||||
updateBoundingBox(apt, l[1], l[2]);
|
||||
return apt;
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
19: (l, apts, apt) => {
|
||||
logger('info', 'Windsock:', l);
|
||||
try {
|
||||
updateBoundingBox(apt, l[1], l[2]);
|
||||
return apt;
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
111: (l, apts, apt) => {
|
||||
logger('info', 'Node :', l);
|
||||
try {
|
||||
updateBoundingBox(apt, l[1], l[2]);
|
||||
return apt;
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
112: (l, apts, apt) => {
|
||||
logger('info', 'Node :', l);
|
||||
try {
|
||||
updateBoundingBox(apt, l[1], l[2]);
|
||||
return apt;
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
113: (l, apts, apt) => {
|
||||
logger('info', 'Node :', l);
|
||||
try {
|
||||
updateBoundingBox(apt, l[1], l[2]);
|
||||
return apt;
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
},
|
||||
99: (l) => {
|
||||
logger('info', 'Finished');
|
||||
}
|
||||
};
|
||||
|
||||
function updateBoundingBox(apt, lat, lon) {
|
||||
if (lat > 90 || lat < -90) {
|
||||
logger('debug', `${lat} out of bounds`);
|
||||
}
|
||||
if (!apt.boundingBoxCenter || isNaN(apt.boundingBoxCenter[0]) || isNaN(apt.boundingBoxCenter[1])) {
|
||||
apt.boundingBoxCenter = [lon, lat];
|
||||
} else {
|
||||
var avgLon = (Number(lon) + Number(apt.boundingBoxCenter[0])) / 2;
|
||||
var avgLat = (Number(lat) + Number(apt.boundingBoxCenter[1])) / 2;
|
||||
apt.boundingBoxCenter = [avgLon, avgLat];
|
||||
}
|
||||
}
|
||||
|
||||
async function saveAirport(features, apt) {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
var transaction = features.transaction("airports", "readwrite");
|
||||
var objectStore = transaction.objectStore("airports");
|
||||
var index = objectStore.index('icaoIndex');
|
||||
if (!apt || !apt.icao) {
|
||||
return;
|
||||
}
|
||||
var objectGetRequest = index.get(apt.icao);
|
||||
|
||||
objectGetRequest.onsuccess = function (event) {
|
||||
logger('info', 'objectGetRequest', event);
|
||||
var feature = event.target.result;
|
||||
if (!feature) {
|
||||
feature = {
|
||||
"type": "Feature",
|
||||
'properties': { 'icao': icao, 'name': '', 'twr': false, 'threshold': false, 'flights': 0, airlines: [] },
|
||||
'geometry': {
|
||||
"type": "Point"
|
||||
}
|
||||
};
|
||||
}
|
||||
feature.properties.name = apt.name;
|
||||
feature.properties.icao = apt.icao;
|
||||
feature.properties.type = apt.type;
|
||||
feature.geometry.coordinates = apt.boundingBoxCenter;
|
||||
logger('info', "Storing Airport : " + feature.properties.icao + " Name : " + feature.properties.name);
|
||||
// Create another request that inserts the item back into the database
|
||||
var updateAirportRequest = objectStore.put(feature);
|
||||
|
||||
// Log the transaction that originated this request
|
||||
logger('info', "The transaction that originated this request is " + updateAirportRequest);
|
||||
|
||||
// When this new request succeeds, run the displayData() function again to update the display
|
||||
updateAirportRequest.onsuccess = function (event) {
|
||||
logger('info', "Stored Name : " + event.target.result);
|
||||
resolve(event.target.result);
|
||||
};
|
||||
updateAirportRequest.onerror = function (event) {
|
||||
logger('info', "Error ", event);
|
||||
reject(event);
|
||||
};
|
||||
};
|
||||
objectGetRequest.onerror = function (event) {
|
||||
logger('info', "Error ", event);
|
||||
reject(event);
|
||||
};
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
async function saveName(features, icao, name) {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
var transaction = features.transaction("airports", "readwrite");
|
||||
@@ -62,32 +194,32 @@ async function saveName(features, icao, name) {
|
||||
}
|
||||
feature.properties.name = name;
|
||||
feature.properties.icao = icao;
|
||||
logger('info',"Storing ICAO : " + feature.properties.icao + " Name : " + name );
|
||||
logger('info', "Storing ICAO : " + feature.properties.icao + " Name : " + name);
|
||||
// Create another request that inserts the item back into the database
|
||||
var updateAirportRequest = objectStore.put(feature);
|
||||
|
||||
// Log the transaction that originated this request
|
||||
logger('info',"The transaction that originated this request is " + updateAirportRequest);
|
||||
logger('info', "The transaction that originated this request is " + updateAirportRequest);
|
||||
|
||||
// When this new request succeeds, run the displayData() function again to update the display
|
||||
updateAirportRequest.onsuccess = function (event) {
|
||||
logger('info',"Stored Name : " + event.target.result);
|
||||
logger('info', "Stored Name : " + event.target.result);
|
||||
resolve(event.target.result);
|
||||
};
|
||||
updateAirportRequest.onerror = function (event) {
|
||||
logger('info',"Error ", event);
|
||||
logger('info', "Error ", event);
|
||||
reject(event);
|
||||
};
|
||||
};
|
||||
objectGetRequest.onerror = function (event) {
|
||||
logger('info',"Error ", event);
|
||||
logger('info', "Error ", event);
|
||||
reject(event);
|
||||
};
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
async function saveCoordinates(features, icao, lat, lon) {
|
||||
async function saveCoordinates(features, icao, boundingBoxCenter) {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
|
||||
var transaction = features.transaction("airports", "readwrite");
|
||||
@@ -96,7 +228,7 @@ async function saveCoordinates(features, icao, lat, lon) {
|
||||
var objectStoreRequest = index.get(icao);
|
||||
|
||||
objectStoreRequest.onsuccess = function (event) {
|
||||
logger('info', 'objectStoreRequest',event);
|
||||
logger('info', 'objectStoreRequest', event);
|
||||
var feature = event.target.result;
|
||||
if (!feature) {
|
||||
feature = {
|
||||
@@ -107,26 +239,27 @@ async function saveCoordinates(features, icao, lat, lon) {
|
||||
}
|
||||
};
|
||||
}
|
||||
feature.geometry.coordinates = [lon, lat];
|
||||
logger('info',"ICAO : " + feature.properties.icao);
|
||||
|
||||
feature.geometry.coordinates = boundingBoxCenter;
|
||||
logger('info', "ICAO : " + feature.properties.icao);
|
||||
// Create another request that inserts the item back into the database
|
||||
var updateAirportRequest = objectStore.put(feature);
|
||||
|
||||
// Log the transaction that originated this request
|
||||
logger('info',"The transaction that originated this request is " + updateAirportRequest);
|
||||
logger('info', "The transaction that originated this request is " + updateAirportRequest);
|
||||
|
||||
// When this new request succeeds, run the displayData() function again to update the display
|
||||
updateAirportRequest.onsuccess = function (event) {
|
||||
logger('info',"Stored Position : " + event.target.result);
|
||||
logger('info', "Stored Position : " + event.target.result);
|
||||
resolve("Stored Position : " + event.target.result);
|
||||
};
|
||||
updateAirportRequest.onerror = function (event) {
|
||||
logger('info',"Error ", event);
|
||||
logger('info', "Error ", event);
|
||||
reject(event);
|
||||
};
|
||||
};
|
||||
objectStoreRequest.onerror = function (event) {
|
||||
logger('info',"Error ", event);
|
||||
logger('info', "Error ", event);
|
||||
reject(event);
|
||||
};
|
||||
});
|
||||
@@ -134,63 +267,76 @@ async function saveCoordinates(features, icao, lat, lon) {
|
||||
}
|
||||
|
||||
async function scanAPTIntoDB(f, features) {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
try {
|
||||
var i;
|
||||
var count = 0;
|
||||
var postMessage = this.postMessage;
|
||||
var lines = [];
|
||||
require('fs').createReadStream(f).pipe(zlib.createGunzip())
|
||||
.on('data', function(chunk) {
|
||||
for (i=0; i < chunk.length; ++i)
|
||||
.on('data', function (chunk) {
|
||||
for (i = 0; i < chunk.length; ++i)
|
||||
if (chunk[i] == 10) count++;
|
||||
})
|
||||
.on('end', function() {
|
||||
postMessage(['max', count]);
|
||||
console.log('Line Count',count);
|
||||
.on('end', function () {
|
||||
postMessage(['max', count*2]);
|
||||
console.log('Line Count', count);
|
||||
lineReader.createInterface({
|
||||
input: fs.createReadStream(f).pipe(zlib.createGunzip())
|
||||
}).on('line', function (line) {
|
||||
lines.push(line);
|
||||
var fields = line.split(/[ ]+/);
|
||||
if (fields[0] == '99') {
|
||||
logger('info',"End Reading");
|
||||
logger('info', "End Reading");
|
||||
}
|
||||
}).on('error', function (err) {
|
||||
logger('info',err);
|
||||
logger('info', err);
|
||||
lr.close();
|
||||
}).on('close', async function () {
|
||||
logger('info',"End File Read");
|
||||
asyncForEach(lines, async line => {
|
||||
//await waitFor(5000);
|
||||
try {
|
||||
postMessage(['progress', 1]);
|
||||
logger('info', "End File Read");
|
||||
var currentAirport = [];
|
||||
var currentIcao = null;
|
||||
try {
|
||||
lines.forEach((line, index) => {
|
||||
var fields = line.split(/[ ]+/);
|
||||
// var fields = line.match('([0-9]+)');
|
||||
if (fields != null) {
|
||||
var scanMethod = scanMethods[fields[0]];
|
||||
if (scanMethod != null) {
|
||||
var text = await scanMethod(fields, features);
|
||||
logger('info', 'Scanned', text);
|
||||
resolve(text);
|
||||
} else {
|
||||
resolve('Ignored ' + line);
|
||||
}
|
||||
if ([1, 16, 17, 99].indexOf(Number(fields[0])) >= 0) {
|
||||
var apt = { icao: currentIcao, last: Number(fields[0])===99 }
|
||||
var bla = aptForEach(currentAirport, apt, features, (line, index, apt) => {
|
||||
//await waitFor(5000);
|
||||
try {
|
||||
var fields = line.split(/[ ]+/);
|
||||
// var fields = line.match('([0-9]+)');
|
||||
if (fields != null) {
|
||||
var scanMethod = scanMethods[fields[0]];
|
||||
if (scanMethod != null) {
|
||||
var text = scanMethod(fields, features, apt);
|
||||
logger('info', `Scanned ${fields[0]}`, text);
|
||||
resolve(text);
|
||||
} else {
|
||||
resolve('Ignored ' + line);
|
||||
}
|
||||
}
|
||||
return apt;
|
||||
} catch (error) {
|
||||
logger('error', error);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
postMessage(['progress', currentAirport.length]);
|
||||
currentIcao = fields[4]
|
||||
currentAirport = [];
|
||||
}
|
||||
} catch (error) {
|
||||
logger('error', error);
|
||||
reject(error);
|
||||
}
|
||||
}).then(t => {
|
||||
currentAirport.push(line);
|
||||
});
|
||||
logger('info', "Finished");
|
||||
postMessage('DONE');
|
||||
}).catch(reason => {
|
||||
// postMessage('DONE');
|
||||
} catch (error) {
|
||||
logger('error', "Crashed");
|
||||
logger('error', reason);
|
||||
postMessage('DONE');
|
||||
});
|
||||
logger('error', error);
|
||||
postMessage('DONE');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
reject(error);
|
||||
|
||||
@@ -1,16 +1,30 @@
|
||||
/* eslint-disable */
|
||||
const winURL = process.env.NODE_ENV === 'development'
|
||||
? `http://localhost:9080/src/renderer/utils/`
|
||||
: `file://D:/GIT/flightgear-airports/src/renderer/utils/`
|
||||
: `file://${process.resourcesPath}/workers/`
|
||||
|
||||
var path = require('path');
|
||||
const fs = require('fs');
|
||||
//debugger;
|
||||
var turf;
|
||||
|
||||
importScripts('../../../node_modules/dijkstrajs/dijkstra.js');
|
||||
var check_msg;
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
importScripts('../../../node_modules/dijkstrajs/dijkstra.js');
|
||||
turf = require('./node_modules/@turf/turf');
|
||||
} else if (process.env.NODE_ENV === 'mocha') {
|
||||
importScripts('../../../node_modules/dijkstrajs/dijkstra.js');
|
||||
turf = require('../../../node_modules/@turf/turf')
|
||||
} else {
|
||||
importScripts('dijkstra.js');
|
||||
turf = require('@turf/turf')
|
||||
}
|
||||
|
||||
const homedir = require('os').homedir();
|
||||
|
||||
importScripts('logger.js');
|
||||
importScripts('haversine.js');
|
||||
|
||||
function errorReceiver(event) {
|
||||
throw event.data;
|
||||
@@ -18,7 +32,7 @@ function errorReceiver(event) {
|
||||
|
||||
onmessage = function (event) {
|
||||
postMessage('checkStarted');
|
||||
logger('info', 'Check Started');
|
||||
logger('info', 'Check Started');
|
||||
console.log(event.data);
|
||||
if (event.data[0] === 'check') {
|
||||
checkGroundnet(event.data[1]).then(result => {
|
||||
@@ -27,79 +41,388 @@ onmessage = function (event) {
|
||||
// event.origin.webContents.send('scanFinished');
|
||||
}
|
||||
).catch(result => {
|
||||
console.log('Crashed');
|
||||
console.log(result);
|
||||
postMessage('DONE');
|
||||
console.error('Crashed');
|
||||
console.error(result);
|
||||
postMessage(['DONE', [{id: -1, message: ['Crashed', result ]}]]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements the checks of the groundnet
|
||||
* @param {*} data
|
||||
*/
|
||||
|
||||
async function checkGroundnet(data) {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
try {
|
||||
// debugger;
|
||||
const fName = process.env.NODE_ENV === 'development'
|
||||
? './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);
|
||||
var runwayNodes = data.map(mapRunwayNodes).filter(n => n !== undefined);
|
||||
var runwayNodeIDs = data.map(mapRunwayNodeId).filter(n => n !== undefined);
|
||||
var runwayNodes = data.map(mapRunwayNode).filter(n => n !== undefined);
|
||||
var pushbackNodes = data.map(mapPushbackNodes).filter(n => n !== undefined);
|
||||
var edges = data.map(mapEdges).filter(n => n !== undefined);
|
||||
this.max = parkings.length * runwayNodes.length;
|
||||
|
||||
var normalNodes = data.map(mapEdges).filter(n => n !== undefined)
|
||||
.flatMap(m => m.latLngs).filter(n => runwayNodeIDs.indexOf(Number(n.index)) < 0);
|
||||
|
||||
var runways = data.map(mapRunways).filter(n => n !== undefined);
|
||||
|
||||
this.max = 30;
|
||||
this.postMessage(['max', this.max]);
|
||||
|
||||
var graph = {};
|
||||
var boxes = {};
|
||||
//debugger;
|
||||
data.forEach(element => {
|
||||
//debugger;
|
||||
if (element.box !== undefined && element.box !== null) {
|
||||
boxes[element.index] = element.box[0].map(latlng => [latlng.lat, latlng.lng]);
|
||||
boxes[element.index].push(boxes[element.index][0]);
|
||||
}
|
||||
});
|
||||
var directionalGraph = {};
|
||||
var bidirectionalGraph = {};
|
||||
|
||||
console.log(parkings);
|
||||
parkings.forEach(element => {
|
||||
graph[element] = {};
|
||||
directionalGraph[element] = {};
|
||||
bidirectionalGraph[element] = {};
|
||||
});
|
||||
runwayNodes.forEach(element => {
|
||||
graph[element] = {};
|
||||
runwayNodeIDs.forEach(element => {
|
||||
directionalGraph[element] = {};
|
||||
bidirectionalGraph[element] = {};
|
||||
});
|
||||
var notOkNodes = [];
|
||||
//debugger;
|
||||
|
||||
console.log(edges);
|
||||
if (edges === undefined) {
|
||||
resolve([{ id: -1, message: check_msg.NO_EDGES }]);
|
||||
}
|
||||
this.postMessage(['progress', 1]);
|
||||
if (runways.length === 0) {
|
||||
resolve([{ id: -1, message: check_msg.NO_RUNWAYS }]);
|
||||
}
|
||||
this.postMessage(['progress', 1]);
|
||||
edges.forEach(edge => {
|
||||
directionalGraph[edge.start] = {};
|
||||
bidirectionalGraph[edge.start] = {};
|
||||
directionalGraph[edge.end] = {};
|
||||
bidirectionalGraph[edge.end] = {};
|
||||
if (edge.latLngs !== undefined) {
|
||||
// Check if there are segments > 2km
|
||||
edge.latLngs.forEach((latLng, index, arr) => {
|
||||
if (index > 0) {
|
||||
var d = distance([arr[index - 1].lng, arr[index - 1].lat], [latLng.lng, latLng.lat]);
|
||||
if (d > 2000) {
|
||||
notOkNodes.push({ id: Number(arr[index - 1].index), message: check_msg.LONG_ROUTE_START });
|
||||
notOkNodes.push({ id: Number(arr[index].index), message: check_msg.LONG_ROUTE_END });
|
||||
}
|
||||
//console.log(d);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
this.postMessage(['progress', 1]);
|
||||
// Add edges to graphs
|
||||
edges.forEach(element => {
|
||||
graph[element.start] = {};
|
||||
graph[element.end] = {};
|
||||
});
|
||||
edges.forEach(element => {
|
||||
var node1 = graph[element.start];
|
||||
node1[Number(element.end)] = 1;
|
||||
var node2 = graph[element.end];
|
||||
node2[Number(element.start)] = 1;
|
||||
var node1 = directionalGraph[element.start];
|
||||
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;
|
||||
}
|
||||
if (element.direction === 'bi-directional' || element.direction === 'backward') {
|
||||
node2[Number(element.start)] = 1;
|
||||
}
|
||||
|
||||
var node3 = bidirectionalGraph[element.start];
|
||||
var node4 = bidirectionalGraph[element.end];
|
||||
node3[Number(element.end)] = 1;
|
||||
node4[Number(element.start)] = 1;
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
var isLegitEnd = function (v) {
|
||||
if (Object.keys(bidirectionalGraph[v]).length <= 1) {
|
||||
return true;
|
||||
}
|
||||
return Object.keys(bidirectionalGraph[v]).filter(v => runwayNodeIDs[v]).length === 0;
|
||||
}
|
||||
runwayNodeIDs = runwayNodeIDs.filter(
|
||||
(v, i) => isLegitEnd(v)
|
||||
);
|
||||
// Check if there is a route from every parking to every runway node
|
||||
var okNodes = [];
|
||||
logger('info', graph);
|
||||
logger('info', directionalGraph);
|
||||
parkings.forEach(parkingNode => {
|
||||
runwayNodes.forEach(runwayNode => {
|
||||
var ok = checkRoute(graph, parkingNode, runwayNode);
|
||||
if(ok) {
|
||||
okNodes.push(parkingNode);
|
||||
okNodes.push(runwayNode);
|
||||
}
|
||||
this.postMessage(['progress', 1]);
|
||||
runwayNodeIDs.forEach(runwayNode => {
|
||||
var ok = checkRoute(directionalGraph, parkingNode, runwayNode);
|
||||
if (ok) {
|
||||
okNodes.push(parkingNode);
|
||||
okNodes.push(runwayNode);
|
||||
} else {
|
||||
console.log(`No route from Parking ${parkingNode} to Runwaynode ${runwayNode}`);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
okNodes = okNodes.filter((v,i) => okNodes.indexOf(v) === i);
|
||||
var allLegitimateEndNodes = parkings.concat(runwayNodes);
|
||||
var notOkNodes = allLegitimateEndNodes.filter(
|
||||
(v,i) => okNodes.indexOf(v) < 0
|
||||
).map(
|
||||
id => {return {id:id, message:'Node not connected'}}
|
||||
);
|
||||
// Build pushback directionalGraph
|
||||
var noPushbackGraph = {};
|
||||
parkings.forEach(element => {
|
||||
noPushbackGraph[element] = {};
|
||||
});
|
||||
pushbackNodes.forEach(element => {
|
||||
noPushbackGraph[element] = {};
|
||||
});
|
||||
edges.filter(element => element.isPushBackRoute).forEach(element => {
|
||||
noPushbackGraph[element.start] = {};
|
||||
noPushbackGraph[element.end] = {};
|
||||
});
|
||||
// add all pushback edges
|
||||
edges.filter(element => element.isPushBackRoute).forEach(element => {
|
||||
var node1 = noPushbackGraph[Number(element.start)];
|
||||
node1[Number(element.end)] = 1;
|
||||
var node2 = noPushbackGraph[Number(element.end)];
|
||||
node2[Number(element.start)] = 1;
|
||||
});
|
||||
|
||||
|
||||
var okPushbacks = [];
|
||||
// Check pushback
|
||||
var multiplePushbackRoutes = {};
|
||||
parkings.forEach(parkingNode => {
|
||||
pushbackNodes.forEach(pushbackNode => {
|
||||
var numRoutes = checkRoute(noPushbackGraph, parkingNode, pushbackNode);
|
||||
if (numRoutes === 0) {
|
||||
if (multiplePushbackRoutes[parkingNode] === undefined &&
|
||||
Object.keys(noPushbackGraph[parkingNode]) > 0) {
|
||||
// Only when there is a edge leaving
|
||||
multiplePushbackRoutes[parkingNode] = [];
|
||||
}
|
||||
} else if (numRoutes === 1) {
|
||||
if (multiplePushbackRoutes[parkingNode] === undefined) {
|
||||
multiplePushbackRoutes[parkingNode] = [pushbackNode];
|
||||
} else {
|
||||
multiplePushbackRoutes[parkingNode].push(pushbackNode);
|
||||
}
|
||||
} else if (numRoutes > 1) {
|
||||
if (multiplePushbackRoutes[parkingNode] === undefined) {
|
||||
multiplePushbackRoutes[parkingNode] = [pushbackNode];
|
||||
} else {
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
this.postMessage(['progress', 1]);
|
||||
var rogueHoldPoints = pushbackNodes.map(
|
||||
id => {
|
||||
var routes = noPushbackGraph[id];
|
||||
if (Object.keys(routes).length < 1)
|
||||
return { id: id, message: check_msg.UNCONNECTED_PUSHBACK }
|
||||
/*
|
||||
else if(Object.keys(routes).length>1)
|
||||
return { id: id, message: 'Multiple connected pushback node' }
|
||||
*/
|
||||
}
|
||||
).filter(n => n !== undefined);
|
||||
this.postMessage(['progress', 1]);
|
||||
var wrongPushbackRoutes = parkings.filter(
|
||||
function (e) {
|
||||
return this[e] != undefined && this[e].length != 1;
|
||||
}
|
||||
, multiplePushbackRoutes).map(
|
||||
id => {
|
||||
var endPoints = multiplePushbackRoutes[id];
|
||||
if (endPoints.length < 1)
|
||||
return { id: id, message: check_msg.NO_WAY_TO_HOLDPOINT }
|
||||
else
|
||||
return { id: id, message: check_msg.MULTIPLE_PUSHBACK }
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
this.postMessage(['progress', 1]);
|
||||
okNodes = okNodes.filter((v, i) => okNodes.indexOf(v) === i);
|
||||
var notOkNodesParkings = parkings.filter(
|
||||
(v, i) => okNodes.indexOf(v) < 0
|
||||
).map(
|
||||
id => { return { id: id, message: check_msg.NO_RUNWAY_ROUTE } }
|
||||
);
|
||||
this.postMessage(['progress', 1]);
|
||||
|
||||
var notOkNodesRunways = runwayNodeIDs.filter(
|
||||
(v, i) => okNodes.indexOf(v) < 0
|
||||
).map(
|
||||
id => { return { id: id, message: check_msg.NO_RUNWAY_ROUTE } }
|
||||
);
|
||||
this.postMessage(['progress', 1]);
|
||||
|
||||
if (parkings.length === 0) {
|
||||
notOkNodes.push({id:0, message:'No parkings'});
|
||||
notOkNodes.push({ id: 0, message: check_msg.NO_PARKINGS });
|
||||
}
|
||||
if (runwayNodes.length === 0) {
|
||||
notOkNodes.push({id:0, message:'No Runwaynodes'});
|
||||
this.postMessage(['progress', 1]);
|
||||
if (runwayNodeIDs.length === 0) {
|
||||
notOkNodes.push({ id: 0, message: check_msg.NO_RUNWAY_NODES });
|
||||
}
|
||||
this.postMessage(['progress', 1]);
|
||||
var allEnds = Object.entries(bidirectionalGraph).filter(
|
||||
(v, i) => Object.keys(v[1]).length <= 1
|
||||
);
|
||||
// Ends that are not on Runway and not a Parking or Pushback
|
||||
var allLegitimateEndNodes = parkings.concat(runwayNodeIDs).concat(pushbackNodes);
|
||||
var danglingEnds = allEnds.filter(
|
||||
(v, i) => allLegitimateEndNodes.indexOf(Number(v[0])) < 0
|
||||
).map(
|
||||
v => { return { id: Number(v[0]), message: check_msg.NOT_LEGIT_END } }
|
||||
);
|
||||
this.postMessage(['progress', 1]);
|
||||
|
||||
var parkingNodes = data.map(mapParkingNode).filter(n => n !== undefined);
|
||||
|
||||
var overlappingParkings = [];
|
||||
parkingNodes.forEach(parkingNode => {
|
||||
if (boxes[parkingNode.index] === undefined) {
|
||||
overlappingParkings.push({ id: parkingNode.index, message: check_msg.UNKNOWN_RADIUS });
|
||||
}
|
||||
});
|
||||
// Check for intersecting radii
|
||||
parkingNodes.forEach(parkingNode => {
|
||||
parkingNodes.forEach(parkingNode1 => {
|
||||
console.log(parkingNode, parkingNode1);
|
||||
if (parkingNode.index !== parkingNode1.index) {
|
||||
var d = distance([parkingNode.lng, parkingNode.lat],
|
||||
[parkingNode1.lng, parkingNode1.lat]);
|
||||
if (d < parkingNode.radius + parkingNode1.radius + 10) {
|
||||
// If bigger circles intersect we should check the boxes
|
||||
if (boxes[parkingNode.index] !== null && boxes[parkingNode1.index] !== null &&
|
||||
boxes[parkingNode.index] !== undefined && boxes[parkingNode1.index] !== undefined) {
|
||||
var poly1 = turf.polygon([boxes[parkingNode.index]]);
|
||||
|
||||
var poly2 = turf.polygon([boxes[parkingNode1.index]]);
|
||||
|
||||
var intersection = turf.intersect(poly1, poly2);
|
||||
if (intersection !== null) {
|
||||
overlappingParkings.push({ id: parkingNode.index, message: check_msg.OVERLAPPING_PARKINGS });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
var invalidParkings = [];
|
||||
// Check for name
|
||||
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 });
|
||||
}
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
this.postMessage(['progress', 1]);
|
||||
|
||||
//Check for dual pushback/runway nodes
|
||||
runwayNodeIDs.forEach(runwayNode => {
|
||||
if (pushbackNodes.indexOf(runwayNode) >= 0) {
|
||||
notOkNodes.push({ id: runwayNode, message: check_msg.DUAL_PUSHBACK });
|
||||
}
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
//Check if runwaynodes are on runway
|
||||
runwayNodes.forEach(runwayNode => {
|
||||
if( runways.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 ) {
|
||||
notOkNodes.push({ id: normalNode.index, message: check_msg.NON_RUNWAYNODE_ON_RUNWAY });
|
||||
}
|
||||
});
|
||||
this.postMessage(['progress', 1]);
|
||||
|
||||
notOkNodes = notOkNodes.concat(invalidParkings);
|
||||
if (invalidParkings.length === 0) {
|
||||
notOkNodes.push({ id: -1, message: check_msg.PARKINGS_VALID });
|
||||
}
|
||||
notOkNodes = notOkNodes.concat(overlappingParkings);
|
||||
if (overlappingParkings.length === 0) {
|
||||
notOkNodes.push({ id: -1, message: check_msg.NO_OVERLAPPING_PARKINGS });
|
||||
}
|
||||
var danglingEnds = Object.entries(graph).filter(
|
||||
(v,i) => Object.keys(v[1]).length <= 1
|
||||
).filter(
|
||||
(v,i) => allLegitimateEndNodes.indexOf(Number(v[0])) < 0
|
||||
).map(
|
||||
v => {return {id:Number(v[0]), message:'Node not a legimate end'}}
|
||||
);
|
||||
notOkNodes = notOkNodes.concat(danglingEnds);
|
||||
|
||||
// check1(graph);
|
||||
// check2();
|
||||
// this.postMessage(['progress', 1]);
|
||||
if (danglingEnds.length === 0) {
|
||||
notOkNodes.push({ id: -1, message: check_msg.NO_INVALID_ENDS });
|
||||
}
|
||||
notOkNodes = notOkNodes.concat(notOkNodesParkings).concat(rogueHoldPoints);
|
||||
if (notOkNodesParkings.length === 0 && rogueHoldPoints === 0) {
|
||||
notOkNodes.push({ id: -1, message: check_msg.ROUTES_FROM_PARKINGS_OK });
|
||||
}
|
||||
|
||||
notOkNodes = notOkNodes.concat(notOkNodesRunways);
|
||||
if (notOkNodesRunways.length === 0) {
|
||||
notOkNodes.push({ id: -1, message: check_msg.ROUTES_FROM_RUNWAYS_OK });
|
||||
}
|
||||
notOkNodes = notOkNodes.concat(wrongPushbackRoutes);
|
||||
notOkNodes = notOkNodes.concat(notConnectedToPushback);
|
||||
notOkNodes = notOkNodes.concat(multipleTaxiRoutes);
|
||||
notOkNodes = notOkNodes.concat(pushbackExitNotBidirectional);
|
||||
if (wrongPushbackRoutes.length === 0 &&
|
||||
notConnectedToPushback.length === 0 &&
|
||||
multipleTaxiRoutes.length === 0 &&
|
||||
pushbackExitNotBidirectional.length === 0
|
||||
) {
|
||||
notOkNodes.push({ id: -1, message: check_msg.PUSHBACK_ROUTES_OK });
|
||||
}
|
||||
resolve(notOkNodes);
|
||||
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
@@ -107,53 +430,104 @@ async function checkGroundnet(data) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
function checkRoute(graph, from, to) {
|
||||
function checkRoute(directionalGraph, from, to) {
|
||||
try {
|
||||
var pathD = this.dijkstra.find_path(graph, from, to);
|
||||
if (pathD.length>0) {
|
||||
console.log(pathD);
|
||||
var pathD = this.dijkstra.find_path(directionalGraph, from, to);
|
||||
if (pathD.length > 0) {
|
||||
console.log(pathD);
|
||||
return pathD.length;
|
||||
}
|
||||
return true;
|
||||
return 0;
|
||||
} catch (error) {
|
||||
console.log('No route from ' + from + ' to ' + to);
|
||||
return false;
|
||||
// console.error(error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function check1(graph) {
|
||||
var graph1 = {
|
||||
a: {b: 1, d: 1},
|
||||
b: {a: 1, c: 1, e: 1},
|
||||
c: {b: 1, f: 1},
|
||||
d: {a: 1, e: 1, g: 1},
|
||||
e: {b: 1, d: 1, f: 1, h: 1},
|
||||
f: {c: 1, e: 1, i: 1},
|
||||
g: {d: 1, h: 1},
|
||||
h: {e: 1, g: 1, i: 1},
|
||||
i: {f: 1, h: 1}
|
||||
function check1(directionalGraph) {
|
||||
var directionalGraph1 = {
|
||||
a: { b: 1, d: 1 },
|
||||
b: { a: 1, c: 1, e: 1 },
|
||||
c: { b: 1, f: 1 },
|
||||
d: { a: 1, e: 1, g: 1 },
|
||||
e: { b: 1, d: 1, f: 1, h: 1 },
|
||||
f: { c: 1, e: 1, i: 1 },
|
||||
g: { d: 1, h: 1 },
|
||||
h: { e: 1, g: 1, i: 1 },
|
||||
i: { f: 1, h: 1 }
|
||||
};
|
||||
var path = this.dijkstra.find_path(graph, 'a', 'i');
|
||||
var path = this.dijkstra.find_path(directionalGraph, 'a', 'i');
|
||||
console.log(path);
|
||||
}
|
||||
|
||||
function check2(params) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
var mapPushbackNodes = function (o) {
|
||||
if (o.type === 'PushBack') {
|
||||
return o.index;
|
||||
}
|
||||
}
|
||||
|
||||
var mapParkings = function (o) {
|
||||
if(o.type === 'parking')
|
||||
return o.index;
|
||||
console.log(o);
|
||||
if (o.type === 'parking')
|
||||
return o.index;
|
||||
}
|
||||
|
||||
var mapRunwayNodes = function (o) {
|
||||
if(o.type === 'runway')
|
||||
return o.index;
|
||||
console.log(o);
|
||||
var mapParkingNode = function (o) {
|
||||
// debugger;
|
||||
if (o.type === 'parking')
|
||||
return { index: o.index, lat: o.lat, lng: o.lng, name: o.name, radius: Number(o.radius), type: o.type, parkingType: o.parkingType };
|
||||
console.debug(o);
|
||||
}
|
||||
|
||||
var mapBoxes = function (o) {
|
||||
// debugger;
|
||||
if (o.type === 'parking')
|
||||
return { index: o.index };
|
||||
}
|
||||
|
||||
var mapRunwayNodeId = function (o) {
|
||||
if (o.type === 'runway')
|
||||
return o.index;
|
||||
console.debug(o);
|
||||
}
|
||||
|
||||
var mapRunwayNode = function (o) {
|
||||
if (o.type === 'runway') {
|
||||
return {index:o.index, lat: o.lat, lng: o.lng};
|
||||
}
|
||||
}
|
||||
|
||||
var mapRunways = function (o) {
|
||||
if (o.type === 'runway_poly') {
|
||||
var pts = o.pavement[0].map(latLngToArray);
|
||||
pts.push(pts[0]);
|
||||
return turf.polygon([pts]);
|
||||
}
|
||||
}
|
||||
|
||||
var mapEdges = function (o) {
|
||||
if(o.type === 'poly')
|
||||
return {start: o.start, end: o.end};
|
||||
console.log(o);
|
||||
if (o.type === 'poly')
|
||||
// debugger;
|
||||
return {
|
||||
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) {
|
||||
return turf.point([turfPoint.lng, turfPoint.lat]);
|
||||
};
|
||||
|
||||
var latLngToArray = function (turfPoint) {
|
||||
//debugger;
|
||||
|
||||
return [turfPoint.lng, turfPoint.lat];
|
||||
};
|
||||
|
||||
var turfToLatLng = function (turfPoint) {
|
||||
return '' + turfPoint.geometry.coordinates[1].toFixed(6) + ',' + turfPoint.geometry.coordinates[0].toFixed(6);
|
||||
};
|
||||
|
||||
32
src/renderer/utils/check_msg.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"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", ""],
|
||||
"NO_PARKINGS": ["No parkings", ""],
|
||||
"NO_RUNWAYNODES": ["No Runwaynodes", ""],
|
||||
"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", ""],
|
||||
"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", ""],
|
||||
"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", ""],
|
||||
"PUSHBACK_NOT_CONNECTED": ["Pushback Holding Point not Connected to Pushback Route", ""],
|
||||
"TO_MANY_PUSHBACK_TAXI_ROUTES": ["Too many Taxi routes from Pushback Holding Point", ""],
|
||||
"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?"]
|
||||
}
|
||||
21
src/renderer/utils/haversine.js
Normal file
@@ -0,0 +1,21 @@
|
||||
var earthRadius = 6371008.8;
|
||||
|
||||
|
||||
function distance(point1, point2) {
|
||||
var dLat = degrees_to_radians((point2[1] - point1[1]));
|
||||
var dLon = degrees_to_radians((point2[0] - point1[0]));
|
||||
var lat1 = degrees_to_radians(point1[1]);
|
||||
var lat2 = degrees_to_radians(point2[1]);
|
||||
|
||||
var a = Math.pow(Math.sin(dLat / 2), 2) +
|
||||
Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
|
||||
|
||||
return earthRadius * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
}
|
||||
|
||||
function degrees_to_radians(degrees)
|
||||
{
|
||||
var pi = Math.PI;
|
||||
return degrees * (pi/180);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var util = require("util")
|
||||
var util = require("util");
|
||||
|
||||
const d = new Date();
|
||||
|
||||
@@ -10,12 +10,20 @@ const fName = 'scan_' + d.getFullYear()
|
||||
+ d.getSeconds()
|
||||
+ d.getMilliseconds() + '.log';
|
||||
|
||||
var logStream = require('fs').createWriteStream( fName, {autoClose: true});
|
||||
var logStream = null;
|
||||
|
||||
var loggerInit = function (logging) {
|
||||
if (logging) {
|
||||
logStream = require('fs').createWriteStream( fName, {autoClose: true});
|
||||
}
|
||||
}
|
||||
|
||||
var logger = function (level, msg, o) {
|
||||
var d = new Date();
|
||||
logStream.write(d.toUTCString() + '|' + level + ' | ' + msg + '\r\n');
|
||||
if (o != undefined) {
|
||||
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');
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// const fs = require('fs');
|
||||
// const path = require('path');
|
||||
// const math = require('mathjs');
|
||||
// const util = require('util');
|
||||
// const airports = require('./airports.js');
|
||||
// const homedir = require('os').homedir();
|
||||
// const apt = require('apt.js');
|
||||
/*
|
||||
Copyright 2020 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Iterates over an array with a async function and await
|
||||
* @param {*} array The array being iterated over
|
||||
* @param {*} callback
|
||||
*/
|
||||
|
||||
const { Debugger } = require("electron");
|
||||
|
||||
async function asyncForEach(array, callback) {
|
||||
logger('info', "AsyncForEach Len " + array.length);
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
@@ -43,7 +48,7 @@ async function scanGroundnetFiles(p, features) {
|
||||
try {
|
||||
logger('info', 'Start Groundnets ' + p);
|
||||
var files = traverseDir(p);
|
||||
this.postMessage(['max', files.length]);
|
||||
this.postMessage(['max', files.length*2]);
|
||||
logger('info', files);
|
||||
|
||||
asyncForEach(files, async f => {
|
||||
@@ -181,6 +186,9 @@ function scanTrafficIntoDB(p, features) {
|
||||
|
||||
function traverseDir(dir) {
|
||||
var result = [];
|
||||
if(!fs.existsSync(dir)) {
|
||||
return result;
|
||||
}
|
||||
fs.readdirSync(dir).forEach(file => {
|
||||
let fullPath = path.join(dir, file);
|
||||
if (fs.lstatSync(fullPath).isDirectory()) {
|
||||
@@ -236,26 +244,57 @@ function readAI(f, apts) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const aircraftLookup = {};
|
||||
|
||||
dat.trafficlist.aircraft.map(n => {
|
||||
try {
|
||||
if(aircraftLookup[n['required-aircraft']] === undefined) {
|
||||
aircraftLookup[n['required-aircraft']] = [];
|
||||
}
|
||||
aircraftLookup[n['required-aircraft']].push(n.airline);
|
||||
aircraftLookup[n['required-aircraft']] = aircraftLookup[n['required-aircraft']].filter((v, i, a) => a.indexOf(v) === i);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
//debugger;
|
||||
});
|
||||
|
||||
|
||||
logger('info', 'Traffic', dat.trafficlist.flight);
|
||||
|
||||
logger('info', "Departure flights " + dat.trafficlist.flight.length);
|
||||
|
||||
var merged = new Array();
|
||||
// Flat list. Each flight departing or landing counts as one.
|
||||
var merged = [];
|
||||
|
||||
var airports = {};
|
||||
|
||||
|
||||
dat.trafficlist.flight.map(n => {
|
||||
merged.push(n.departure.port);
|
||||
merged.push(n.departure.port);
|
||||
merged.push(n.arrival.port);
|
||||
|
||||
if(airports[n.departure.port] === undefined) {
|
||||
airports[n.departure.port] = [];
|
||||
}
|
||||
if(airports[n.arrival.port] === undefined) {
|
||||
airports[n.arrival.port] = [];
|
||||
}
|
||||
airports[n.departure.port] = airports[n.departure.port].concat(aircraftLookup[n['required-aircraft']]);
|
||||
airports[n.departure.port] = airports[n.departure.port].filter((v, i, a) => a.indexOf(v) === i)
|
||||
airports[n.arrival.port] = airports[n.arrival.port].concat(aircraftLookup[n['required-aircraft']]);
|
||||
airports[n.arrival.port] = airports[n.arrival.port].filter((v, i, a) => a.indexOf(v) === i)
|
||||
}).sort();
|
||||
|
||||
//debugger;
|
||||
var counts = {};
|
||||
for (var i = 0; i < merged.length; i++) {
|
||||
counts[merged[i]] = 1 + (counts[merged[i]] || 0);
|
||||
}
|
||||
|
||||
asyncForEach(Object.keys(counts), async key => {
|
||||
logger('info', key);
|
||||
await store(key, airline[1], counts[key]);
|
||||
asyncForEach(Object.keys(counts), async icao => {
|
||||
logger('info', icao);
|
||||
await store(icao, airports[icao], counts[icao]);
|
||||
}).then(t => {
|
||||
logger('info', "Finished");
|
||||
resolve();
|
||||
@@ -287,7 +326,7 @@ function readAI(f, apts) {
|
||||
* @param {*} value
|
||||
*/
|
||||
|
||||
function store(icao, airline, value) {
|
||||
function store(icao, airlines, value) {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
logger('info', "Airport " + icao + " has " + value + " new flights");
|
||||
// Make a request to get a record by key from the object store
|
||||
@@ -297,18 +336,18 @@ function store(icao, airline, value) {
|
||||
var objectStoreRequest = index.get(icao);
|
||||
|
||||
objectStoreRequest.onsuccess = function (event) {
|
||||
logger('info', 'Stored ', event);
|
||||
logger('info', 'Store Request', event);
|
||||
var feature = objectStoreRequest.result;
|
||||
if (!feature) {
|
||||
feature = createFeature(icao);
|
||||
}
|
||||
feature.properties.flights += value;
|
||||
logger('info', "Airline : ", airline);
|
||||
if (!feature.properties.airlines.includes(airline)) {
|
||||
feature.properties.airlines.push(airline);
|
||||
feature.properties.airlines.sort();
|
||||
}
|
||||
logger('info', "ICAO : " + feature.properties.icao + " Flights : " + feature.properties.flights);
|
||||
logger('info', "Airlines : ", JSON.stringify(airlines));
|
||||
//debugger;
|
||||
feature.properties.airlines = feature.properties.airlines.concat(airlines);
|
||||
feature.properties.airlines = feature.properties.airlines.filter((v, i, a) => a.indexOf(v) === i)
|
||||
feature.properties.airlines.sort()
|
||||
// Create another request that inserts the item back into the database
|
||||
var updateAirportRequest = objectStore.put(feature);
|
||||
|
||||
@@ -317,16 +356,16 @@ function store(icao, airline, value) {
|
||||
|
||||
// When this new request succeeds, run the displayData() function again to update the display
|
||||
updateAirportRequest.onsuccess = function (event) {
|
||||
logger('info', "Stored", event);
|
||||
logger('info', "Updated Success", event);
|
||||
resolve();
|
||||
};
|
||||
updateAirportRequest.onerror = function (event) {
|
||||
logger('info', "Error storing ", event);
|
||||
logger('info', "Error updating ", event);
|
||||
reject(event);
|
||||
};
|
||||
};
|
||||
objectStoreRequest.onerror = function (event) {
|
||||
logger('info', "Error " + event);
|
||||
logger('info', "Error reading" + event);
|
||||
reject(event);
|
||||
};
|
||||
});
|
||||
@@ -342,7 +381,8 @@ function store(icao, airline, value) {
|
||||
async function readGroundnet(f, features) {
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
try {
|
||||
var filename = path.basename(f).match('^([^.]+)\\.([^.]+)\\.([^.]+)');
|
||||
var thisPostMessage = this.postMessage;
|
||||
var filename = path.basename(f).match('^([^.]+)\\.([^.]+)(\\.new)?\\.([^.]+)');
|
||||
if (filename == null) {
|
||||
resolve("File didn't match");
|
||||
}
|
||||
@@ -430,12 +470,18 @@ async function readGroundnet(f, features) {
|
||||
logger('info', 'groundnet : ' + filename[1]);
|
||||
if (dat['?xml'].groundnet) {
|
||||
var nodes = dat['?xml'].groundnet.TaxiNodes;
|
||||
var parkingnodes = dat['?xml'].groundnet.parkingList;
|
||||
if (nodes && nodes.node) {
|
||||
logger('info', nodes);
|
||||
}
|
||||
feature['properties']['groundnet'] = nodes && nodes.node ? nodes.node.length : 0;
|
||||
var nodes = dat['?xml'].groundnet.parkingList;
|
||||
feature['properties']['parking'] = nodes && nodes.Parking ? nodes.Parking.length : 0;
|
||||
if(filename [3] === '.new') {
|
||||
feature['properties']['wipgroundnet'] = nodes && nodes.node ? nodes.node.length : 0;
|
||||
feature['properties']['wipparking'] = parkingnodes && parkingnodes.Parking ? parkingnodes.Parking.length : 0;
|
||||
|
||||
} else {
|
||||
feature['properties']['groundnet'] = nodes && nodes.node ? nodes.node.length : 0;
|
||||
feature['properties']['parking'] = parkingnodes && parkingnodes.Parking ? parkingnodes.Parking.length : 0;
|
||||
}
|
||||
}
|
||||
} else if (filename[2] == 'ils') {
|
||||
logger('info', 'ils : ' + filename[1]);
|
||||
@@ -448,6 +494,7 @@ async function readGroundnet(f, features) {
|
||||
// report on the success of the transaction completing, when everything is done
|
||||
transaction.oncomplete = function (event) {
|
||||
logger('info', 'Write Transaction complete ' + event);
|
||||
thisPostMessage(['progress', 1]);
|
||||
resolve("Stored " + filename[1]);
|
||||
};
|
||||
|
||||
@@ -470,7 +517,7 @@ async function readGroundnet(f, features) {
|
||||
};
|
||||
}
|
||||
objectStoreRequest.onerror = function (event) {
|
||||
logger('info', "Read Errpr : " + event);
|
||||
logger('info', "Read Error : " + event);
|
||||
resolve(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ function errorReceiver(event) {
|
||||
|
||||
onmessage = function (event) {
|
||||
postMessage('scanStarted');
|
||||
logger('info', 'Scan Started');
|
||||
console.log(event.data);
|
||||
if (event.data[0] === 'scan') {
|
||||
loggerInit(event.data[2]);
|
||||
logger('info', 'Scan Groundnet Started');
|
||||
scanGroundnet(event.data[1]).then(result => {
|
||||
console.log("DONE Scanning");
|
||||
postMessage('DONE');
|
||||
@@ -30,8 +31,13 @@ onmessage = function (event) {
|
||||
).catch(result => {
|
||||
console.log('Crashed');
|
||||
console.log(result);
|
||||
logger('error', 'crashed');
|
||||
logger('error', result);
|
||||
postMessage('DONE');
|
||||
});
|
||||
} else if (event.data[0] === 'scanai') {
|
||||
loggerInit(event.data[2]);
|
||||
logger('info', 'Scan AI Started');
|
||||
scanai(event.data[1]).then(result => {
|
||||
console.log("DONE Scanning");
|
||||
postMessage('DONE');
|
||||
@@ -40,9 +46,14 @@ onmessage = function (event) {
|
||||
).catch(result => {
|
||||
console.log('Crashed');
|
||||
console.log(result);
|
||||
logger('error', 'crashed');
|
||||
logger('error', result);
|
||||
postMessage('DONE');
|
||||
});
|
||||
}
|
||||
else if (event.data[0] === 'scanapt') {
|
||||
loggerInit(event.data[2]);
|
||||
logger('info', 'Scan APT Started');
|
||||
scanAPT(event.data[1]).then(result => {
|
||||
console.log("DONE Scanning");
|
||||
postMessage('DONE');
|
||||
@@ -51,6 +62,9 @@ onmessage = function (event) {
|
||||
).catch(result => {
|
||||
console.log('Crashed');
|
||||
console.log(result);
|
||||
logger('error', 'crashed');
|
||||
logger('error', result);
|
||||
postMessage('DONE');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
20
static/Airplane_silhouette.svg
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.0"
|
||||
width="400"
|
||||
height="400">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<g
|
||||
transform="translate(-147.06733,-109.44716)">
|
||||
<path
|
||||
d="M 157.98695,184.38488 L 173.37483,168.20017 C 182.38616,159.18884 197.56012,162.31477 197.56012,162.31477 L 242.58958,168.47612 L 265.39575,146.16045 C 277.41087,134.35989 288.26269,152.4142 283.54247,158.63631 L 271.83305,172.24635 L 320.32641,181.22794 L 336.78707,162.03882 C 354.38063,141.01237 367.47041,159.95529 359.53185,171.11218 L 348.89521,184.56906 L 421.75804,194.07153 C 484.40828,133.78139 509.98537,108.77262 526.46939,123.63021 C 543.05967,138.5836 513.71315,168.38877 456.64135,227.17701 L 467.00204,302.24678 L 482.26714,289.52597 C 491.27847,282.01653 507.27901,294.06392 490.75822,309.72648 L 469.76089,329.52825 L 478.61969,378.66527 L 491.73923,368.58052 C 503.32523,359.35463 517.39476,371.55518 501.7322,388.29052 L 480.88803,409.28786 C 480.02981,409.93153 487.69305,452.38631 487.69305,452.38631 C 492.41327,473.19821 480.67347,480.80195 480.67347,480.80195 L 466.35838,493.27782 L 411.97962,339.67439 C 407.47395,326.15738 396.0546,311.47862 376.97351,313.22076 C 366.8894,314.29354 341.41552,331.49026 337.98263,335.56682 L 279.00579,392.27531 C 277.5039,393.34809 288.07915,465.99635 288.07915,465.99635 C 288.07915,468.14191 269.38054,492.66454 269.38054,492.66454 L 232.01433,426.14725 L 213.56128,434.7301 L 224.35108,417.93211 L 157.06733,379.9526 L 182.29502,361.49956 C 194.31014,364.28878 257.3034,371.36975 258.59073,370.72608 C 258.59073,370.72608 309.88762,319.85344 312.81633,316.77643 C 329.76623,298.96831 335.46935,292.31456 338.04402,283.51778 C 340.6208,274.71377 336.23117,261.81195 309.62838,245.4769 C 272.93937,222.94855 157.98695,184.38488 157.98695,184.38488 z"
|
||||
id="path3166"
|
||||
style="fill:#000000;stroke:none;" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
68
static/Black_aircraft_icon.svg
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
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"
|
||||
version="1.0"
|
||||
width="20"
|
||||
height="20"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:docname="Aero-stub_img.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<metadata
|
||||
id="metadata16">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
inkscape:window-height="675"
|
||||
inkscape:window-width="640"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
guidetolerance="10.0"
|
||||
gridtolerance="10.0"
|
||||
objecttolerance="10.0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
showgrid="false"
|
||||
inkscape:zoom="11.55"
|
||||
inkscape:cx="16.576935"
|
||||
inkscape:cy="10.772134"
|
||||
inkscape:window-x="110"
|
||||
inkscape:window-y="110"
|
||||
inkscape:current-layer="svg2" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 10 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="20 : 10 : 1"
|
||||
inkscape:persp3d-origin="10 : 6.6666667 : 1"
|
||||
id="perspective18" />
|
||||
<filter
|
||||
id="filter">
|
||||
<feGaussianBlur
|
||||
stdDeviation="0.4858"
|
||||
id="feGaussianBlur7" />
|
||||
</filter>
|
||||
</defs>
|
||||
<path
|
||||
style="fill:#000000"
|
||||
id="path13"
|
||||
d="M 4.7932777,4.7812376 C 4.7259064,4.8486085 4.7323964,4.9347702 4.9650313,5.4373336 C 4.9924894,5.4966515 5.1453716,5.7138571 5.1453716,5.7138571 C 5.1453723,5.7138561 5.0426847,5.8268489 5.0148394,5.8546943 C 4.9610053,5.9085284 4.9361984,6.0293335 4.958161,6.1243469 C 5.026297,6.4191302 5.8480608,7.5947712 6.3081405,8.0548517 C 6.593652,8.3403629 6.7408456,8.5354068 6.730653,8.6147666 C 6.7220521,8.6817367 6.6138788,8.9698607 6.4901987,9.2536889 C 6.2719706,9.7544933 6.1902268,9.8530093 3.7284084,12.592571 C 1.7788774,14.76205 1.1823532,15.462131 1.1469587,15.620578 C 1.0488216,16.059908 1.4289737,16.468046 2.4110617,16.977428 L 2.9177343,17.24021 C 2.9177343,17.24021 10.306553,11.950215 10.306553,11.950215 L 14.736066,15.314858 L 14.634732,15.495198 C 14.578751,15.594046 14.11587,16.171307 13.60593,16.778194 C 13.095992,17.385083 12.673006,17.939029 12.666441,18.009665 C 12.640049,18.293626 13.777085,19.186772 13.947719,19.016137 C 14.217037,18.74682 15.346696,17.884968 15.441971,17.875697 C 15.509995,17.869079 16.481025,17.128624 16.810843,16.798805 C 17.140662,16.468987 17.881117,15.497956 17.887735,15.429933 C 17.897006,15.334658 18.758859,14.204999 19.028176,13.93568 C 19.198811,13.765045 18.305664,12.62801 18.021702,12.654403 C 17.951067,12.660967 17.397123,13.083953 16.790233,13.593891 C 16.183346,14.103831 15.606085,14.566712 15.507236,14.622693 L 15.326897,14.724027 L 11.962253,10.294514 C 11.962253,10.294514 17.252249,2.9056938 17.25225,2.9056938 L 16.989466,2.3990218 C 16.480084,1.416933 16.071947,1.0367811 15.632617,1.1349189 C 15.474169,1.1703136 14.774089,1.7668355 12.60461,3.7163677 C 9.8650471,6.1781859 9.7665321,6.2599294 9.2657298,6.4781579 C 8.9819013,6.601838 8.6937782,6.7100098 8.6268071,6.7186131 C 8.5474478,6.7288044 8.352405,6.5816098 8.0668925,6.2960996 C 7.6068129,5.8360191 6.4311712,5.0142561 6.1363875,4.9461203 C 6.0413739,4.9241577 5.92057,4.9489642 5.8667352,5.0027982 C 5.8388891,5.0306446 5.7276147,5.1316136 5.7276147,5.1316136 C 5.7276147,5.1316136 5.5104099,4.9787304 5.4510923,4.9512732 C 4.9485278,4.7186391 4.8606505,4.7138647 4.7932777,4.7812376 z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
2
static/FGA_ACT_A_GA.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="150mm" height="150mm" version="1.1" viewBox="0 0 150 150" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-1.6394e-5 -147)"><g transform="translate(-512.5 -153)"><path d="m587.5 347.75c-0.32736 0-0.75863 2.023-0.97757 3.043 0 0-8.7023-0.47356-8.7023 0.14107 0 0.61461 8.733 0.36873 8.733 0.36873 0.0812 0.14151 0.22163 0.15914 0.368 0.18528v0.21306c-0.57176 0.16009-1.4739 0.31231-2.5099 0.41186-1.036 0.0995-1.1332 0.93371-1.1332 0.93371-0.70455 4.8918-0.96276 10.026-1.2071 14.632-0.012 0.0118-0.0165 1.6e-4 -0.0369 9e-3l-20.112 2e-3 -27.221 1.9869c-2.1208 0.16639-2.2014 1.5529-2.2014 3.2272v8.0906l29.858 3.5196 19.67 0.0146c1.2567 9.6974 3.6713 28.109 3.6713 28.109l-12.803 2.1075c-0.75926 0.18181-1.8746 0.23703-2.1181 1.0313-0.3756 1.9795-0.35641 4.2182-0.24741 6.0605 0.0369 0.68858 0.16248 1.2114 0.8672 1.354l13.439 2.401c0.39078 0.0865 0.49893-0.13326 0.58873-0.48422l1.3408-4.2669s-0.081 7.3888 0.73272 9.0111c0.81369-1.6224 0.73271-9.0111 0.73271-9.0111l1.3412 4.2669c0.0898 0.35096 0.19795 0.57077 0.58874 0.48422l13.439-2.401c0.70472-0.14253 0.83032-0.6654 0.8672-1.354 0.10899-1.8424 0.12819-4.081-0.24741-6.0605-0.24351-0.79425-1.3589-0.84947-2.1181-1.0313l-12.803-2.1075s2.4149-18.412 3.6716-28.109l19.67-0.0146 29.859-3.5196v-8.0906c5.8e-4 -1.6743-0.081-3.0608-2.2018-3.2272l-27.221-1.9869-20.112-2e-3c-0.0204-9e-3 -0.0249 3e-3 -0.0369-9e-3 -0.2443-4.6057-0.50251-9.7399-1.2071-14.632 0 0-0.0972-0.83417-1.1332-0.93371-1.036-0.0996-1.9381-0.25177-2.5099-0.41186v-0.21307c0.14636-0.0262 0.28682-0.0438 0.368-0.18528 0 0 8.733 0.24589 8.733-0.36873s-8.7023-0.14106-8.7023-0.14106c-0.21894-1.0201-0.65058-3.0431-0.97793-3.0431zm0 9.0766c0.34605 0 0.71407-1.3e-4 0.71408 0.5394v2.36c0 0.54212-0.36803 0.54196-0.71408 0.54196-0.34606 0-0.7192 1.6e-4 -0.7192-0.54196v-2.36c-1e-5 -0.53953 0.37314-0.5394 0.7192-0.5394zm-12.73 16.475c0.34605 0 0.71407-1.3e-4 0.71407 0.5394v2.36c0 0.54211-0.36802 0.54196-0.71407 0.54196-0.34606 0-0.7192 1.5e-4 -0.7192-0.54196v-2.36c0-0.53953 0.37314-0.5394 0.7192-0.5394zm25.474 0c0.34606 0 0.71408-1.3e-4 0.71408 0.5394v2.36c0 0.54211-0.36802 0.54196-0.71408 0.54196-0.34605 0-0.71919 1.5e-4 -0.71919-0.54196v-2.36c-1e-5 -0.53953 0.37314-0.5394 0.71919-0.5394z" fill="#3296ff"/><circle cx="587.5" cy="375" r="74.595" fill="none" stroke="#3296ff" stroke-linecap="square" stroke-linejoin="round" stroke-width=".811" style="paint-order:normal"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
2
static/FGA_ACT_B_PROP.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="280mm" height="282.66mm" version="1.1" viewBox="0 0 280 282.66" xmlns="http://www.w3.org/2000/svg"><g transform="translate(35 -7.171)"><g transform="translate(-7.6294e-6 7.3444)"><g transform="matrix(4.5516 0 0 4.5516 -372.53 -527.39)" fill="#3296ff"><path transform="matrix(.26458 0 0 .26458 -7.9725e-5 4.7925e-5)" d="m396.53 449.99c-6.703 0-12.091 16.285-12.119 29.002l-0.17578 54.354-2.8828 7.209-14.512-0.18945c0.6477-4.764 1.2976-11.043-1.4473-15.457l-0.0469-1.3477 14.395 0.83985 0.16797-1.9668-14.578 0.97461c0-1.4239-1.0254-4.1602-2.3457-4.1602-1.4366 0-2.2472 2.4804-2.4375 4.1211l-14.088-1.1582-4e-3 2.4609 14.047-0.9668-0.1914 1.3164c-2.3109 4.8272-1.8613 10.199-0.92774 15.412-46.681 3.307-70.422 5.1355-71.252 5.2051-0.82972 0.0695-1.8463 0.90433-1.9707 2.293-0.0556 0.59954-0.16605 0.90065-0.33008 0.90039-0.16479-1e-3 -0.35633 0.0276-0.57422 0.082-0.21808 0.0533-0.43767 0.32575-0.6582 0.81641-0.67616 2.9741-0.27076 5.9302-0.0977 8.7734 0.0552 0.10885 12.16 0.73137 36.314 1.8672 24.156 1.1349 36.316 1.7029 36.48 1.7031 0.16403 3.7e-4 6.0384 0.17301 24.84 0.20703l2.123 5.0859c-0.0302 21.998 0.0965 58.62 7.0059 86.129-15.285 2.3628-23.055 3.6526-23.314 3.8594-2.0877 2.7596-2.3172 6.879-1.8203 9.998 0.0556 1e-3 4.4001 0.33632 13.033 1.0059l13.115 0.92578c0.10923-0.0544 1.4785-2.0469 1.4785-2.0469 0.21947 1.7517 0.2277 5.2639 2.7734 5.2676h2e-3c2.5457-4e-3 2.552-3.5159 2.7715-5.2676 0 0 1.3693 1.9924 1.4785 2.0469l13.115-0.92578c8.6331-0.66954 12.978-1.0047 13.033-1.0059 0.49693-3.119 0.26734-7.2384-1.8203-9.998-0.25928-0.20674-8.0293-1.4966-23.314-3.8594 6.9093-27.509 7.0361-64.131 7.0059-86.129l2.123-5.0859c18.801-0.034 24.678-0.20666 24.842-0.20703 0.16404-2.3e-4 12.323-0.56825 36.479-1.7031 24.155-1.1358 36.259-1.7583 36.314-1.8672 0.17311-2.8432 0.5785-5.7993-0.0976-8.7734-0.22035-0.49066-0.44013-0.76312-0.65821-0.81641-0.21807-0.0544-0.40943-0.0832-0.57421-0.082-0.16404 2.6e-4 -0.27257-0.30085-0.32813-0.90039-0.12435-1.3886-1.141-2.2234-1.9707-2.293-0.82972-0.0695-24.573-1.8981-71.254-5.2051 0.93358-5.2134 1.3832-10.585-0.92773-15.412l-0.19141-1.3164 14.047 0.9668-4e-3 -2.4609-14.088 1.1582c-0.19049-1.6407-1.0009-4.1211-2.4375-4.1211-1.3203 0-2.3457 2.7363-2.3457 4.1602l-14.576-0.97461 0.16602 1.9668 14.395-0.83985-0.0469 1.3477c-2.7449 4.4137-2.095 10.693-1.4473 15.457l-14.512 0.18945-2.8809-7.209-0.17578-54.354c0-12.782-5.4181-29.002-12.121-29.002zm-2.207 19.031h1.6133v4.8184h-1.6133zm2.8008 0h1.6133v4.8184h-1.6133zm-20.578 81.467h2.7774v7.1152h-2.7774zm3.8789 0h2.7773v7.1152h-2.7773zm29.434 0h2.7774v7.1152h-2.7774zm3.8789 0h2.7773v7.1152h-2.7773z" fill="#3296ff"/></g><circle cx="105" cy="139.83" r="139.18" fill="none" stroke="#3296ff" stroke-linecap="square" stroke-linejoin="round" stroke-width="1.6438" style="paint-order:normal"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
2
static/FGA_ACT_B_SHORTEN.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="280mm" height="311.54mm" version="1.1" viewBox="0 0 280 311.54" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-6.4969e-6 14.543)"><circle cx="140" cy="141.28" r="139.36" fill="none" stroke="#3296ff" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="4.3333" stroke-width="1.2759" style="paint-order:normal"/><path d="m152.63 24.911c-0.0267-25.744-10.66-39.454-12.634-39.454h1e-5c-1.9741 0-12.608 13.71-12.634 39.454l0.0182 79.957-1.6403 1.3481s-84.993 49.186-89.398 51.752-4.5756 5.1873-4.5756 5.1873-7.5179 14.841-7.7484 15.302c-0.23052 0.4615-0.27144 1.1507-0.27144 1.1507l0.1078 2.3443s6.6825-7.4591 6.8393-7.6432c0.1568-0.18415 0.32861-0.34095 0.7442-0.33769 0.41558 3e-3 1.0215 0.0362 1.4196-0.32729 0.93562-1.1932 2.1371-2.6676 3.9093-3.1924 1.7722-0.52482 39.634-11.689 59.608-17.581l31.015-1.8624v47.86l-0.95849 1.5429h-1.3832c-0.24979-1.7755-0.85068-1.9326-0.85068-1.9326l-11.633 0.12468s-1.2585 0.79803-1.2585 6.6315c0 10.609 1.3118 13.973 1.3118 13.973s0.30131 0.16754 1.2416 0.16754l2.5625 10.064s0.46106 0.0701 0.9494 0.0701l1.7637 5.2665 0.71822-0.0351 1.3923-5.3548c0.55067 0 0.99225-0.16884 0.99225-0.16884l0.0714-0.44288 9.2212 6.0198 5.3548 27.175s-33.731 22.555-34.623 23.158c-0.89108 0.60283-1.4159 2.6639-1.565 4.3768l-0.65199 7.4952 38.872-12.307 1.0494 5.3873 1.1104-5.3873 38.871 12.307-0.65198-7.4952c-0.14909-1.7129-0.67393-3.774-1.565-4.3768-0.8911-0.60285-34.623-23.158-34.623-23.158l5.3561-27.175 9.2199-6.0198 0.0714 0.44288s0.4429 0.16884 0.99356 0.16884l1.391 5.3548 0.71822 0.0351 1.765-5.2665c0.48833 0 0.9481-0.0701 0.9481-0.0701l2.5625-10.064c0.9403 0 1.2416-0.16754 1.2416-0.16754s1.3118-3.3645 1.3118-13.973c0-5.8335-1.2585-6.6315-1.2585-6.6315l-11.633-0.12468s-0.6009 0.15707-0.8507 1.9326h-1.3832l-0.95719-1.5429v-47.86l31.013 1.8624c19.974 5.8921 57.836 17.057 59.608 17.581 1.7722 0.5248 2.9749 1.9992 3.9106 3.1924 0.39808 0.36352 1.0027 0.33031 1.4182 0.32729 0.4156-3e-3 0.58741 0.15355 0.74421 0.33769 0.1568 0.18415 6.8393 7.6432 6.8393 7.6432l0.10781-2.3443s-0.0397-0.68921-0.27015-1.1507c-0.23051-0.4615-7.7497-15.302-7.7497-15.302s-0.16886-2.6209-4.5743-5.1873c-4.4054-2.5664-89.399-51.752-89.399-51.752l-1.639-1.3481 0.0169-79.957m-34.454 111.65c0.78911 0 1.6055 0.23981 1.6053 1.2949v6.738c2.3e-4 0.93982-0.81617 1.2949-1.6053 1.2949-0.78909 0-1.6053-0.35505-1.6053-1.2949v-6.738c0-1.0551 0.81618-1.2949 1.6053-1.2949zm5.0002 0c0.78909 0 1.6055 0.23981 1.6053 1.2949v6.738c2.4e-4 0.93982-0.81619 1.2949-1.6053 1.2949s-1.6053-0.35505-1.6053-1.2949v-6.738c0-1.0551 0.81618-1.2949 1.6053-1.2949zm33.577 0c0.78909 0 1.6053 0.23981 1.6053 1.2949v6.738c0 0.93982-0.81618 1.2949-1.6053 1.2949-0.7891 0-1.6055-0.35505-1.6053-1.2949v-6.738c-2.4e-4 -1.055 0.81618-1.2949 1.6053-1.2949zm5.0002 0c0.78909 1e-5 1.6053 0.2398 1.6053 1.2949v6.738c0 0.93982-0.81618 1.2949-1.6053 1.2949s-1.6055-0.35505-1.6053-1.2949v-6.738c-2.4e-4 -1.0551 0.81619-1.2949 1.6053-1.2949z" fill="#3296ff"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
3
static/FGA_ACT_C.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="360mm" height="369.09mm" version="1.1" viewBox="0 0 360 369.09" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><metadata><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><g transform="translate(75 36.046)"><g transform="translate(-65.5 -28.331)"><path d="m170.5-0.026086c-7.0846 9.35e-6 -19.026 24.031-19.062 58.205l0.0362 54.388-1.9176 10.818s-0.10598 1.4555-0.99653 1.9124-25.868 13.39-25.868 13.39c0.89235-6.9871 2.094-27.847-0.25947-27.847h-15.911c-3.162 1e-5 -2.337 31.287-0.34733 31.287h1.0188l1.163 3.968-94.45 48.717c-4.8538 2.6647-11.085 6.7435-12.179 12.611l-1.7264 14.181v2.7208l1.8819-8.6075c0.26207-1.101 1.0968-1.7912 2.1833-2.0856l48.418-14.553 1.5222 5.4184 1.2943-6.2934 32.906-10.202 1.2591 4.6033 1.4023-5.4184-0.02378-0.0238 17.489-5.4184h13.63v0.0238l1.1754 4.6751 1.1268-4.6989 27.248-0.014 0.0594 84.392c0.23612 14.268 3.6729 28.282 6.066 42.28 0 0-0.48489 3.4026-4.915 6.2216 0 0-36.324 23.321-38.756 24.91-2.4318 1.5884-3.5142 3.8978-3.5142 8.6897l0.0961 5.1067 52.194-11.616c1.3933 6.3589 5.2092 17.812 5.3703 18.305 0.16114 0.49226 0.88696 1.043 0.88696 1.043s0.44043 0.31323 0.75567 0.31323h1.486c0.31524 0 0.75567-0.31323 0.75567-0.31323s0.72582-0.55079 0.88695-1.043c0.16114-0.49225 3.977-11.946 5.3703-18.305l52.194 11.616 0.0956-5.1067c0-4.7918-1.0819-7.1013-3.5137-8.6897s-38.756-24.91-38.756-24.91c-4.4301-2.8189-4.915-6.2216-4.915-6.2216 2.3931-13.998 5.8299-28.012 6.066-42.28l0.06-84.392 27.248 0.014 1.1273 4.6989 1.1748-4.6751v-0.0238h13.63l17.49 5.4184-0.0238 0.0238 1.4023 5.4184 1.2586-4.6033 32.906 10.202 1.2948 6.2934 1.5222-5.4184 48.418 14.553c1.0865 0.29433 1.9212 0.98458 2.1833 2.0856l1.8824 8.6075v-2.7208l-1.7263-14.181c-1.0936-5.8671-7.3253-9.946-12.179-12.611l-94.45-48.717 1.163-3.968h1.0188c1.9896 0 2.8147-31.287-0.34734-31.287h-15.911c-2.3535 0-1.1518 20.86-0.25947 27.847 0 0-24.977-12.933-25.867-13.39-0.89055-0.45697-0.99705-1.9124-0.99705-1.9124l-1.9176-10.818 0.0362-54.388c-0.03593-34.174-11.977-58.205-19.062-58.205zm-2.373 45.661c0.8389 4.8e-5 1.0544 0.39604 1.0544 1.0673v3.692c0 0.68329-0.21552 1.0792-1.0544 1.0792-0.8389-6e-6 -1.0441-0.39594-1.0441-1.0792v-3.692c0-0.6713 0.20519-1.0673 1.0441-1.0673zm4.7454 0c0.8389 4.8e-5 1.0446 0.39604 1.0446 1.0673v3.692c0 0.68329-0.2057 1.0792-1.0446 1.0792-0.8389-6e-6 -1.0539-0.39594-1.0539-1.0792v-3.692c0-0.6713 0.215-1.0673 1.0539-1.0673zm-46.369 122.62c0.87915-2e-3 1.44 0.52759 1.44 1.4746v5.0349c0 0.82604-0.55805 1.4757-1.44 1.4757-0.88197 0-1.4379-0.64964-1.4379-1.4757v-5.0349c-2e-5 -0.93514 0.55878-1.4724 1.4379-1.4746zm87.992 0c0.87916 2e-3 1.4385 0.5395 1.4385 1.4746v5.0349c0 0.82604-0.55649 1.4757-1.4385 1.4757s-1.44-0.64964-1.44-1.4757v-5.0349c5e-5 -0.94705 0.56085-1.4766 1.44-1.4746zm-81.29 0.0476c0.87915-2e-3 1.4394 0.52759 1.4395 1.4746v5.0349c0 0.82603-0.55752 1.4757-1.4395 1.4757s-1.4385-0.64964-1.4385-1.4757v-5.0349c-2e-5 -0.93514 0.5593-1.4724 1.4385-1.4746zm74.589 0c0.87915 2e-3 1.4385 0.5395 1.4384 1.4746v5.0349c0 0.82603-0.55649 1.4757-1.4384 1.4757-0.88197 0-1.44-0.64964-1.44-1.4757v-5.0349c5e-5 -0.94705 0.56085-1.4766 1.44-1.4746z" fill="#3296ff" fill-rule="evenodd"/><circle cx="170.5" cy="172.29" r="179.31" fill="none" stroke="#3296ff" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="3" stroke-width="1.371" style="paint-order:normal"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
2
static/FGA_ACT_D.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="5203mm" height="5463.5mm" version="1.1" viewBox="0 0 5203 5463.5" xmlns="http://www.w3.org/2000/svg"><g transform="translate(2496.5 2583.2)"><path d="m103.62-2580.1c-130.08 0-255.75 434.93-255.75 588.23l-0.125 1240.4s-55.621 87.016-114.96 127.88c-59.342 40.86-294.12 203.78-294.12 203.78l12.788-24.751s2e-4 -204.6 0-255.75c-1e-4 -51.151-12.788-63.938-25.575-63.938-12.787 1e-4 -204.6 0-204.6 0-25.575 0-38.363 12.788-38.363 63.938 0 0-0.399 257.75 0 281.33 0.399 23.577 12.788 51.151 12.788 51.151h25.575l-0.62501 98.405s-1405.1 961.43-1444.4 988.54c-39.261 27.115-51.15 42.459-51.15 63.938v217.39l575.44-242.96 869.56-306.9 179.03-51.151 498.74-62.464s-0.736 1167.2-0.02 1290.1c0.706 122.92 63.489 432.48 63.489 432.48l-702.87 539.38-38.363 51.15v166.24l869.78-212.97 12.563 46.73 25.575 89.513 12.788 102.3 12.788 38.363 12.788-38.363 12.788-102.3 25.575-89.513 12.563-46.73 869.78 212.97v-166.24l-38.363-51.15-702.87-539.38s62.783-309.56 63.488-432.48c0.711-122.92-0.05-1290.1-0.05-1290.1l498.77 62.464 179.03 51.151 869.56 306.9 575.44 242.96v-217.39c0-21.479-11.889-36.823-51.151-63.938-39.261-27.115-1444.4-988.54-1444.4-988.54l-0.60001-98.405h25.575s12.389-27.573 12.788-51.151c0.399-23.577 0-281.33 0-281.33 0-51.15-12.788-63.938-38.363-63.938 0 0-191.81 1e-4 -204.6 0-12.788-1e-4 -25.575 12.788-25.575 63.938-2e-4 51.151 0 255.75 0 255.75l12.788 24.751s-234.77-162.92-294.12-203.78c-59.342-40.86-114.99-127.88-114.99-127.88l-0.104-1240.4c-1e-4 -153.3-125.68-588.23-255.75-588.23zm-38.363 409.2c6.347 2e-4 12.787 5.5342 12.787 11.064v67.809c0 5.4289-6.4405 10.865-12.787 10.864-6.3906 2e-4 -12.788-5.4355-12.788-10.864v-67.809c1e-4 -5.5302 6.3971-11.013 12.788-11.064zm76.726 0c6.3906 0.05 12.788 5.5342 12.788 11.064v67.809c-1e-4 5.4289-6.397 10.865-12.788 10.864-6.347 2e-4 -12.788-5.4355-12.788-10.864v-67.809c0-5.5302 6.4406-11.064 12.788-11.064zm-575.44 2186.7h25.575c6.347 2.01e-4 12.788 6.393 12.788 12.788v76.726c0 6.3929-6.4406 12.788-12.788 12.788h-25.575c-6.3906 1e-4 -12.787-6.3947-12.788-12.788v-76.726c1e-4 -6.3947 6.397-12.736 12.788-12.788zm115.09 0h25.575c6.347 2.01e-4 12.788 6.393 12.788 12.788v76.726c0 6.3929-6.4406 12.788-12.788 12.788h-25.575c-6.3906 1e-4 -12.787-6.3947-12.788-12.788v-76.726c2e-4 -6.3947 6.3971-12.736 12.788-12.788zm818.41 0h25.575c6.3907 0.05 12.788 6.393 12.788 12.788v76.726c-2e-4 6.3929-6.397 12.788-12.788 12.788h-25.575c-6.347 1e-4 -12.788-6.3947-12.788-12.788v-76.726c0-6.3947 6.4406-12.787 12.788-12.788zm115.09 0h25.575c6.3906 0.05 12.788 6.393 12.788 12.788v76.726c-1e-4 6.3929-6.3971 12.788-12.788 12.788h-25.575c-6.347 1e-4 -12.788-6.3947-12.788-12.788v-76.726c0-6.3947 6.4406-12.787 12.788-12.788zm-1048.6 140.66h25.575c6.347 1e-4 12.788 6.3929 12.788 12.787v76.726c0 6.3929-6.4406 12.788-12.788 12.788h-25.575c-6.3906 1e-4 -12.787-6.3947-12.788-12.788v-76.726c1e-4 -6.3946 6.397-12.736 12.788-12.787zm115.09 0h25.575c6.347 1e-4 12.788 6.3929 12.788 12.787v76.726c0 6.3929-6.4406 12.788-12.788 12.788h-25.575c-6.3906 1e-4 -12.787-6.3947-12.788-12.788v-76.726c2e-4 -6.3946 6.3971-12.736 12.788-12.787zm818.41 0h25.575c6.3907 0.05 12.788 6.3929 12.788 12.787v76.726c-2e-4 6.3929-6.397 12.788-12.788 12.788h-25.575c-6.347 1e-4 -12.788-6.3947-12.788-12.788v-76.726c0-6.3946 6.4406-12.787 12.788-12.787zm115.09 0h25.575c6.3906 0.05 12.788 6.3929 12.788 12.787v76.726c-1e-4 6.3929-6.3971 12.788-12.788 12.788h-25.575c-6.347 1e-4 -12.788-6.3947-12.788-12.788v-76.726c0-6.3946 6.4406-12.787 12.788-12.787z" fill="#3296ff" fill-rule="evenodd"/><circle cx="105" cy="135.8" r="2582.6" fill="none" stroke="#3296ff" stroke-linecap="square" stroke-linejoin="round" stroke-width="37.746" style="paint-order:normal"/></g></svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
2
static/FGA_ACT_E.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="660mm" height="735.62mm" version="1.1" viewBox="0 0 660 735.62" xmlns="http://www.w3.org/2000/svg"><g transform="translate(227.07 219.31)"><g transform="translate(-220.16 -219.35)"><path d="m323.98 0.041596c-12.621 1.1404-32.35 58.556-32.35 95.304v172.91l-46.402 31.844c1.7124-7.7226 3.623-25.137-0.66208-43.984h-33.315c-3.6679 12.285-5.2993 33.094 0.0391 51.47l3.3026 0.0898 3.0428 11.261c-67.538 46.949-135.82 92.856-204.08 138.75-2.0153 1.3847-2.119 1.8573-2.119 1.8573l-11.437 22.93v8.1344l26.342-17.935 71.254-28.565 34-11.466 0.69527 3.201 1.5605-3.992 51.247-17.319 1.0976 3.6346 1.041-4.3845 29.414-9.9624 21.011-3.2655 0.82027 6e-3 1.3632 4.7322 1.7772-4.7341 50.009-0.0273s-0.0109 126.27 0 148.94c0.0156 32.451 7.5281 73.581 8.5445 79.039s3.3484 11.282-3.1483 16.589c-6.4967 5.3071-71.763 58.406-77.1 62.77-5.3362 4.364-4.9704 10.253-4.7556 11.913s1.9276 15.884 1.9276 15.884l98.173-36.949 7.8414 28.559 1.7675 4e-3 7.8414-28.559 98.171 36.949s1.7128-14.223 1.9276-15.884 0.58251-7.5514-4.7536-11.915c-5.3362-4.3639-70.605-57.461-77.102-62.768-6.4967-5.3071-4.1647-11.131-3.1483-16.589s8.5308-46.587 8.5464-79.039c0.0109-22.668 0-148.94 0-148.94l50.007 0.0273 1.7773 4.7341 1.3632-4.7322 0.82222-8e-3 21.011 3.2674 29.413 9.9624 1.041 4.3826 1.0976-3.6326 51.249 17.319 1.5605 3.992 0.69331-3.201 34.002 11.464 71.252 28.567 26.344 17.935-2e-3 -8.1344-11.435-22.93s-0.1057-0.47265-2.121-1.8573c-68.258-45.89-136.54-91.8-204.08-138.75l3.0409-11.259 3.3045-0.0918c5.3383-18.376 3.705-39.185 0.0371-51.47h-33.315c-4.2851 18.847-2.3726 36.264-0.66013 43.986l-46.402-31.846v-172.91c0-36.748-19.762-94.167-32.383-95.308zm-4.3806 54.566h2.0546c0.8995-7e-6 1.2851 0.38391 1.2851 1.2812v7.5582c-4e-5 0.89669-0.38558 1.2812-1.2851 1.2812h-2.0546c-0.89949-9e-6 -1.2246-0.38449-1.2206-1.2812v-7.5582c-4e-3 -0.89728 0.32117-1.2812 1.2206-1.2812zm6.6422 0h2.0546c0.8995-7e-6 1.2851 0.38391 1.2851 1.2812v7.5582c-4e-5 0.89669-0.38558 1.2812-1.2851 1.2812h-2.0546c-0.89948-9e-6 -1.2246-0.38449-1.2206-1.2812v-7.5582c-4e-3 -0.89728 0.32117-1.2812 1.2206-1.2812zm43.543 294.97h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89668-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89676 0.38559-1.2813 1.2851-1.2812zm13.968 0h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89668-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89958-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89676 0.38559-1.2813 1.2851-1.2812zm-122 0.0488h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-8e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm13.97 0h2.5057c0.89955-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38558-1.2813 1.2851-1.2812zm94.048 13.818h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89668-0.38552 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm13.97 0h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89668-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm-122 0.0488h2.5057c0.89955-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm13.97 0h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38558-1.2813 1.2851-1.2812zm97.866 6.2614h8.8667zm-108.03 0.0488h8.8667zm104.23 7.5406h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38552 1.2792-1.2851 1.2792h-2.5057c-0.89957-5e-5 -1.2852-0.38261-1.2851-1.2792v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm13.97 0h2.5057c0.89954-6e-5 1.2831 0.38451 1.2831 1.2812v8.8394c2e-5 0.89667-0.38357 1.2792-1.2831 1.2792h-2.5057c-0.89957-5e-5 -1.2852-0.38261-1.2851-1.2792v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm-122 0.0488h2.5057c0.89955-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c1e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38559-1.2813 1.2851-1.2812zm13.97 0h2.5057c0.89954-6e-5 1.2851 0.38451 1.2851 1.2812v8.8394c2e-5 0.89667-0.38553 1.2812-1.2851 1.2812h-2.5057c-0.89957-5e-5 -1.2852-0.38456-1.2851-1.2812v-8.8394c-7e-5 -0.89675 0.38558-1.2813 1.2851-1.2812z" fill="#3296ff"/><circle cx="323.1" cy="368.73" r="328.11" fill="none" stroke="#3296ff" stroke-width="3.7896" style="paint-order:normal"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
17
static/FGA_ACT_F.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg width="211.67mm" height="211.67mm" version="1.1" viewBox="0 0 211.67 211.67" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g transform="translate(953.33 -995.17)">
|
||||
<path d="m-742.19 1101c0 27.929-11.095 54.714-30.844 74.463-19.749 19.749-46.534 30.844-74.463 30.844-27.929 0-54.714-11.095-74.463-30.844-19.749-19.749-30.844-46.534-30.844-74.463 0-27.929 11.095-54.714 30.844-74.463 19.749-19.749 46.534-30.844 74.463-30.844 27.929 0 54.714 11.095 74.463 30.844 19.749 19.749 30.844 46.534 30.844 74.463z" fill="none" stroke="#3296ff" stroke-linejoin="round" stroke-width="1.0531"/>
|
||||
<path d="m-847.5 1004.7c-7.4097 0-9.4794 27.242-9.4556 35.842v13.103l-1.2407 2.0809-2.6718 3.1116-5.7373 4.7856-15.217 12.445c0.26327-2.4217 0.81772-10.57-0.18346-11.848l-8.6782 0.072c-0.70678 0.8906-1.6381 10.501 0.13788 15.728h1.1029l0.38829 1.823-21.816 16.071c0.5494-2.3946 1.2496-11.314 0.25043-13.182l-8.8583 0.014c-1.0492 4.8589-1.1533 10.88-0.0459 15.696l1.2043 0.04 0.50012 2.5271s-28.608 21.118-31.045 22.91c-2.4373 1.7913-3.8489 5.5589-3.8729 8.2254-0.0241 2.6665-0.0401 5.2116-0.0401 5.2116l35.659-15.492 0.65645 4.4375 1.1948-5.2253 9.3938-3.722 0.4792 5.7045 1.5361-6.4857 9.1575-3.7024 0.83374 5.6914 1.1619-6.4791 8.8095-3.6302 0.53827 2.4748 1.0438-3.1115 9.1247-2.9869 0.64327 2.4748 0.93875-2.9147 12.853-3.4791 0.32163 5.0153 1.4704 10.352 0.033 19.858c0.17362 4.5575 0.64186 9.1069 1.287 13.621l1.477 6.7877c0.23946 1.6304-0.74861 3.3195-1.8528 4.424 0 0-27.318 20.921-28.298 21.678-0.98046 0.7565-1.2339 2.0863-1.2339 2.0863l-2.2479 10.338 25.84-9.5902 11.73-4.0193 2.1403 6.7961 0.58694 6.9848 0.58694-6.9848 2.1403-6.7961 11.73 4.0193 25.84 9.5902-2.2479-10.338s-0.25346-1.3298-1.2339-2.0863c-0.98047-0.7566-28.298-21.678-28.298-21.678-1.1042-1.1045-2.0923-2.7936-1.8528-4.4239l1.477-6.7877c0.64515-4.5145 1.1134-9.0639 1.287-13.621l0.033-19.858 1.4705-10.352 0.32163-5.0153 12.853 3.4791 0.93876 2.9147 0.64326-2.4748 9.1247 2.9869 1.0438 3.1115 0.53826-2.4748 8.8095 3.6302 1.1619 6.4791 0.83375-5.6914 9.1575 3.7024 1.5361 6.4857 0.4792-5.7045 9.3938 3.722 1.1948 5.2253 0.65644-4.4375 35.659 15.492s-0.016-2.5452-0.0401-5.2117-1.4357-6.4341-3.8729-8.2254c-2.4373-1.7912-31.045-22.91-31.045-22.91l0.50013-2.5271 1.2043-0.04c1.1074-4.816 1.0033-10.837-0.0459-15.696l-8.8583-0.014c-0.99921 1.8687-0.29898 10.788 0.25042 13.182l-21.816-16.071 0.3883-1.8229h1.1029c1.776-5.2277 0.84466-14.838 0.13787-15.728l-8.6782-0.072c-1.0012 1.2776-0.44672 9.4259-0.18345 11.848l-15.217-12.445-5.7373-4.7856-2.6718-3.1116-1.2407-2.0809v-13.103c0.0237-8.6006-2.046-35.842-9.4556-35.842zm-2.0804 12.256h1.3916v3.5317h-1.3916zm2.8227 0h1.4048v3.5317h-1.4048zm-19.766 73.142h1.3982v3.5317h-1.3982zm3.5777 0h1.3917v3.5317h-1.3917zm29.501 0h1.3916v3.5317h-1.3916zm3.5645 0h1.4048v3.5317h-1.4048zm-36.643 4.2932h1.3982v3.5251h-1.3982zm3.5777 0h1.3917v3.5251h-1.3917zm29.501 0h1.3916v3.5251h-1.3916zm3.5645 0h1.4048v3.5251h-1.4048zm-27.426 2.0481h1.3983v3.5186h-1.3983zm14.015 0h1.4048v3.5186h-1.4048zm-9.919 0.01h1.3983v3.5251h-1.3983zm14.015 0h1.4048v3.5251h-1.4048zm-18.112 4.4901h1.3983v3.5251h-1.3983zm4.0962 0h1.3983v3.5251h-1.3983zm9.919 0h1.4048v3.5251h-1.4048zm4.0963 0h1.4048v3.5251h-1.4048zm-18.112 4.5033h1.3983v3.5316h-1.3983zm4.0962 0h1.3983v3.5316h-1.3983zm9.919 0h1.4048v3.5316h-1.4048zm4.0963 0h1.4048v3.5316h-1.4048z" fill="#3296ff"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |