Compare commits

..

45 Commits

Author SHA1 Message Date
2378cd5eaa 更新 'src/renderer/components/FlightgearMap.vue' 2022-11-25 18:23:10 +08:00
portree_kid
4fff310d76 API Key 2021-06-29 08:17:30 +02:00
portree_kid
09b0cba5b0 Auth Key for com not org 2021-06-29 07:07:34 +02:00
portree_kid
f5930e2039 API Token 2021-06-28 17:04:17 +02:00
portree_kid
cc80726ec7 Merge branch 'master' of https://github.com/Portree-Kid/flightgear-airports 2021-06-28 13:56:05 +02:00
portree_kid
b73f0bb1a1 New token 2021-06-28 13:38:47 +02:00
Keith Paterson
1ac67e1e18 Bump to 0.0.34 2021-06-25 08:54:43 +02:00
Keith Paterson
7a58b4bde1 Change Type via multiselect 2021-06-24 08:00:05 +02:00
Keith Paterson
ba533e8942 #142 2021-06-23 16:47:55 +02:00
Keith Paterson
8b0afa9fcb #141 2021-06-23 15:59:25 +02:00
Keith Paterson
8a4820d23c Version 0.0.33 2021-06-11 13:55:28 +02:00
Keith Paterson
da597f80e4 #139 2021-06-09 16:29:20 +02:00
Keith Paterson
1bd3b3b2e4 #139 2021-06-09 16:27:35 +02:00
Keith Paterson
b9b6574614 #140 2021-06-07 14:40:04 +02:00
Keith Paterson
089ce029ec Check for double edges 2021-06-04 09:16:58 +02:00
Keith Paterson
9e7f41a5c9 Check for double edges 2021-06-04 09:16:15 +02:00
Keith Paterson
60881eaf3e Logfile in user dir 2021-06-03 16:00:46 +02:00
Keith Paterson
0f4b82807e #133 2021-06-03 15:35:44 +02:00
Keith Paterson
f9d0469466 Unique Trafficlist 2021-06-03 15:03:22 +02:00
Keith Paterson
f56d8ad926 Check 2021-06-03 11:32:48 +02:00
Keith Paterson
b2ddb08374 #130 2021-06-02 12:12:52 +02:00
Keith Paterson
091e7853eb #138 2021-06-01 14:44:43 +02:00
Keith Paterson
e52fcf9572 #137 2021-05-31 17:21:14 +02:00
Keith Paterson
055897c0f6 Bump to 0.0.32 2021-05-28 16:55:00 +02:00
Keith Paterson
cf2e5150e8 Tooltip for Airports in overview 2021-05-28 16:54:18 +02:00
Keith Paterson
d8417c7fd9 #134 2021-05-28 12:58:54 +02:00
Keith Paterson
ed25672448 NPE when editing 2021-05-28 10:22:30 +02:00
Keith Paterson
5e0e2c9ea5 try catch in upload 2021-05-28 10:22:08 +02:00
Keith Paterson
d7ffe7bcec Version 0.0.31 2021-04-21 10:54:16 +02:00
Keith Paterson
cf1c829c11 Improved Tooltips 2021-04-21 10:53:11 +02:00
Keith Paterson
cfa7a1bf3b Rollback Electron upgrade 2021-04-16 14:45:28 +02:00
Keith Paterson
fd40bc76aa Logging 2021-04-16 14:44:43 +02:00
Keith Paterson
281e4b1339 Merge branch 'dependabot/npm_and_yarn/electron-9.4.0' of https://github.com/Portree-Kid/flightgear-airports.git
# Conflicts:
#	package-lock.json
2021-04-15 11:31:43 +02:00
Keith Paterson
77b8d81378 Updated element ui 2021-04-15 11:29:30 +02:00
Keith Paterson
21e27bf913 #124 Editable Tower height 2021-04-14 16:56:30 +02:00
Keith Paterson
92a39591b5 Fixed #128 2021-03-02 13:53:20 +01:00
Keith Paterson
ec700c2ed7 osx-binaries 2021-02-15 09:08:41 +01:00
Keith Paterson
c161b38664 Removed unpacking of osx tgz 2021-02-05 07:36:37 +01:00
Keith Paterson
fd2017624b v 0.30 2021-02-04 11:08:43 +01:00
Keith Paterson
41b7b0498f #126 2021-02-04 08:13:43 +01:00
Keith Paterson
737f9a7b56 #76 2021-01-29 22:38:40 +01:00
Keith Paterson
bd4bdd6b51 Traffic Generator 2021-01-29 17:03:11 +01:00
dependabot[bot]
b95a468cdc build(deps-dev): bump electron from 7.2.4 to 9.4.0
Bumps [electron](https://github.com/electron/electron) from 7.2.4 to 9.4.0.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v7.2.4...v9.4.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-01-28 20:49:16 +00:00
Keith Paterson
9f6a9a0943 Add ICAO even if one find 2021-01-27 15:35:10 +01:00
Keith Paterson
bf56736ab9 Fix gaps in IDs 2021-01-21 07:55:37 +01:00
40 changed files with 1686 additions and 701 deletions

View File

@@ -54,6 +54,7 @@ jobs:
- stage: Deploy
install:
- pwd
- find -name *osx-binaries*
- tar -xzf ${CASHER_DIR}/osx-binaries-fetch.tgz
- find -name flightgear-airports*
- cp ./Users/travis/build/Portree-Kid/flightgear-airports/osx-binaries/*.dmg build/
@@ -70,12 +71,12 @@ jobs:
skip_cleanup: true
overwrite: true
draft: true
name: '0.0.29'
name: '0.0.33'
provider: releases
api_key:
secure: xBF7Jld2WbEXVg5QOxZIC/T2hlKOkajebrNi7kfE8vGVRuZG1cbHWEtBVPxggxmIWvzSyKOACSufFywx8rjgXNP3e310+dp1WuEnOBlkTr6HO3FneTue5gKoPsFB8/r8/BMPWqY50lS2Vei367eINsdNiw4wWv2bzbB6uNBlo9ILRZjbyWnUv+j8+h9gmCg2nHLmHBGhXRMLqYFEHYvq1LrV+tjMNtMBdNiRVYBjpeWI1y7TMsxpdwKvrYF84L7r9IOkjg2DHIACy4SMnIeKi6b7Lr83aK5QwksHByMETxjaNPxgvmg9hPFaRoJsvwOLdgSDU/VpEar8uweOnumt2bdqdwV2t+99A1g41KcvbUI1aATPOWhpGxW+WLBBz40hpDBBwWJ/Il4rMUHfsQ162xoO9NvlKp4IE7pgK3ydGlJx6mYzMx3QB2eKnTFySaIekrkzZPIS3GX50cMclRw6jS3fueUmtNxjIv4hNHgRqE6pQfxhQnaUkHjdP7nglYs0muJotM2Tksyw3YRlLoFzc/siktCDr8ZXxj+rlV3TeoH2vba7f4zr0tYY9vlGAUlcrkBoJ4kDeA8Hm0GnbpWHBsSY4g199jOkgbr/kJ0HDrELv/JJl1c8yp3uSlcN82UgNS15H60D+0zg3Ls4KxvqXslrPh815Se5FqKoEpvZ5VQ=
file_glob: true
secure: FElxoWQZKIcc9gHFY4yp1CsqvJr76BWdDrp7VsgPN7PuEoZht5Boic3fWbxKyT1fKGr8Yem6CJBXQjaqIZiWWMxuF3KYmsdOK0YRpj6WCePpl0AdZcnWDMsAGuC3ornb1CB3R6x8fx7SMMl8Ghc9/JFDUdjduvT9A0KZ1JrTZLYpP1iOq+aAW0H3byu+tNfTDvee9MzMAtjKriDz0L5z94VQ1lEmuc79qUmNvv9gIJUoNOI58QCDUuOEz2eZPooMz5cOdaupzBK130V7ki/UWbP3meXmzRKN6/iSA9iXiIrBerFtA4wG6hVvKMvKP7d7NalWAtpzOElFivlo7tp+Z1SfjSfZHmZG/PMyndVh1VPmMzX6a76qLyJFGIvOZKOkzzmVyGSVGlUHm8GCkw5wd0S3m6f1eA/YJO5c8aduC7M+qZSuEVdzaAW5xf8Fb1/rs7jELZPxuzio9i+T7vRQ1OFrCBtExQAuO9EyfaIvaVQAImvhOPiza6zkfEkF622LIQZIBL9HZ1OeKKrdWaWG98nUGWDIFXb+B4IBM1cJIPRYmaAbnWVVCBzIGxcb1pMb/zzSocu9poEWCY/CVHuOG7Xg45pghTunPS54E9qxvBx8jDIGz4s3bRwWnBI0DJ5b6aBNqMpghmpKYMCoviT+RwCIKOENlFdrPWH5pk9CmRc=wYHBe6BJtqhkjodvabd6fSX5blecd/y9sSfHV9prk7PRFxkpkp4Fw/sp086SFlunTGmTn359T1mhgr0MD/VDRXu34PEdn47Jpu8CTPfnihiK/3iRaGqW0qLqhmpd6GYc1ecm9sahxYwXgWyCtGZQbdHvrCIiS/Zm1hQtg3Q0O3eYeF+zQXrfCCTIhLLy2egID4Z23RbK620y3dqcSfbWfLzPpXr+2MYVrNZ3gukKiVauf2kBYPNzMTKEtIBfAGHiwQwlCm/fRN5NcL9bwMGmMGktJkIHgpAa2A9nnyw7EadKEKqVw4tI/j1813/FDWlJZBg89RNsZJ0QGSMQcMB0h1XkWZFPV02gqMN2z2eNXsvTJ882g8UkCBzPWYsRQGNKEx9FUFtZO9HAjOnnpAsdTcaQYTow7BiVmPBePtCFKsPyqMgJUsuz6WhUmfJ5FMbMDKn1N6ymyBYmTic5KrT3FRR3s7vFyTNdfNfwd7aNMnZSGb2uHLZyGjrC2QFK3AE/F+jP2bMu/9rcuLcp/CSLpxpN5F6RpVVfqY8X9joEUeXOSd4kO7OPBsg4lxDCqzVmER/X+MEwM57cmyutTtaREZEDTKCoEhWtcMHqLpCojPWbMsKnMh7NRARNWETe76tcwO88K2LqQFvhhILeTXKlWDpNcbGwqSinF62RXG4DxUQ=
file_glob: true
file: build/*
on:
branches: '0.0.29'
branches: '0.0.33'
repo: Portree-Kid/flightgear-airports

137
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "flightgear-airports",
"version": "0.0.28",
"version": "0.0.33",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -188,9 +188,9 @@
}
},
"@electron/get": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.2.tgz",
"integrity": "sha512-vAuHUbfvBQpYTJ5wB7uVIDq5c/Ry0fiTBMs7lnEYAo/qXXppIVcWdfBr57u6eRnKdVso7KSiH6p/LbQAG6Izrg==",
"version": "1.12.4",
"resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.4.tgz",
"integrity": "sha512-6nr9DbJPUR9Xujw6zD3y+rS95TyItEVM0NVjt1EehY2vUWfIgPiIPVHxCvaTS0xr2B+DRxovYVKbuOWqC35kjg==",
"dev": true,
"requires": {
"debug": "^4.1.1",
@@ -200,23 +200,23 @@
"global-tunnel-ng": "^2.7.1",
"got": "^9.6.0",
"progress": "^2.0.3",
"sanitize-filename": "^1.6.2",
"semver": "^6.2.0",
"sumchecker": "^3.0.1"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
"ms": "2.1.2"
}
},
"env-paths": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz",
"integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"dev": true
},
"fs-extra": {
@@ -235,6 +235,12 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
}
}
},
@@ -4470,9 +4476,9 @@
"dev": true
},
"boolean": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.1.tgz",
"integrity": "sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.3.tgz",
"integrity": "sha512-EqrTKXQX6Z3A2nRmMEIlAIfjQOgFnVO2nqZGpbcsPnYGWBwpFqzlrozU1dy+S2iqfYDLh26ef4KrgTxu9xQrxA==",
"dev": true,
"optional": true
},
@@ -7272,9 +7278,9 @@
}
},
"electron": {
"version": "7.2.4",
"resolved": "https://registry.npmjs.org/electron/-/electron-7.2.4.tgz",
"integrity": "sha512-Z+R692uTzXgP8AHrabE+kkrMlQJ6pnAYoINenwj9QSqaD2YbO8IuXU9DMCcUY0+VpA91ee09wFZJNUKYPMnCKg==",
"version": "7.3.3",
"resolved": "https://registry.npmjs.org/electron/-/electron-7.3.3.tgz",
"integrity": "sha512-PrJEsuRiaAhTDHtbH3EM+RIne+nZ6ifGChUadmtmPqHUQ+rIhf4jSi2ZN768IgBDw4SidMJiCrvQRiuDha9+Ew==",
"dev": true,
"requires": {
"@electron/get": "^1.0.1",
@@ -7283,9 +7289,9 @@
},
"dependencies": {
"@types/node": {
"version": "12.12.48",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.48.tgz",
"integrity": "sha512-m3Nmo/YaDUfYzdCQlxjF5pIy7TNyDTAJhIa//xtHcF0dlgYIBKULKnmloCPtByDxtZXrWV8Pge1AKT6/lRvVWg==",
"version": "12.20.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.8.tgz",
"integrity": "sha512-uxDkaUGwXNDHu5MHqs+FAsmOjNoNibDF1cu4668QG96mQldQfgV3M+UyntXWWrtXSh13jFxEdNUdoLWH46mLKQ==",
"dev": true
}
}
@@ -7583,9 +7589,9 @@
"dev": true
},
"element-ui": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.15.0.tgz",
"integrity": "sha512-9z/1+b7V8fvp08OnKUEW4/BZ72kT+IhuKR9cTMz3XoCTKmEsqLLb32XjbO/DznSFaaiFbOYU93G7WtkvrCAL9A==",
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.15.1.tgz",
"integrity": "sha512-TqlScAKGH97XndSScUDeEHIzL1x7yg7DvQdKPEOUdiDcyIz3y3FJJBlpHYaJT96FOn1xpIcUZb+I2FJeU9EcrQ==",
"requires": {
"async-validator": "~1.8.1",
"babel-helper-vue-jsx-merge-props": "^2.0.0",
@@ -10024,9 +10030,9 @@
}
},
"global-agent": {
"version": "2.1.12",
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.12.tgz",
"integrity": "sha512-caAljRMS/qcDo69X9BfkgrihGUgGx44Fb4QQToNQjsiWh+YlQ66uqYVAdA8Olqit+5Ng0nkz09je3ZzANMZcjg==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.2.0.tgz",
"integrity": "sha512-+20KpaW6DDLqhG7JDiJpD1JvNvb8ts+TNl7BPOYcURqCrXqnN1Vf+XVOrkKJAFPqfX+oEhsdzOj1hLWkBTdNJg==",
"dev": true,
"optional": true,
"requires": {
@@ -10040,16 +10046,36 @@
},
"dependencies": {
"core-js": {
"version": "3.6.5",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
"integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==",
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.10.1.tgz",
"integrity": "sha512-pwCxEXnj27XG47mu7SXAwhLP3L5CrlvCB91ANUkIz40P27kUcvNfSdvyZJ9CLHiVoKSp+TTChMQMSKQEH/IQxA==",
"dev": true,
"optional": true
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"optional": true,
"requires": {
"yallist": "^4.0.0"
}
},
"semver": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dev": true,
"optional": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true,
"optional": true
}
@@ -10133,9 +10159,9 @@
"dev": true
},
"globalthis": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz",
"integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz",
"integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==",
"dev": true,
"optional": true,
"requires": {
@@ -12305,6 +12331,14 @@
"resolved": "https://registry.npmjs.org/leaflet-rotatedmarker/-/leaflet-rotatedmarker-0.2.0.tgz",
"integrity": "sha1-RGf0n5jRv9VpWb2cZwUgPdJgEnc="
},
"leaflet-search": {
"version": "2.9.9",
"resolved": "https://registry.npmjs.org/leaflet-search/-/leaflet-search-2.9.9.tgz",
"integrity": "sha512-sGPjkMz9gQP+CKrY0G/RjQFWHdt1/KDJQiouv1dWogtN66rcE/aPR/DOduCXM3Um+VgsAmr5+jRQ0iK3Fs9I8A==",
"requires": {
"leaflet": "*"
}
},
"leaflet-sidebar-v2": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/leaflet-sidebar-v2/-/leaflet-sidebar-v2-3.2.1.tgz",
@@ -12315,6 +12349,21 @@
"resolved": "https://registry.npmjs.org/leaflet-textpath/-/leaflet-textpath-1.2.0.tgz",
"integrity": "sha512-anLGWptWb916MhEXi4WewYe08YKCawRvEXsMGj9fuYnUGd+irV3VG4UXcdW1l+Oa/TZoCTLQsg3LNwvFcroVog=="
},
"leaflet.pattern": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/leaflet.pattern/-/leaflet.pattern-0.1.0.tgz",
"integrity": "sha512-E4sxvvK0XHi1EhE1yUTG1bzafXZoXUPqWPjHz5fSpv/pOcT4CtS0qR1lhFSRtSUYios8OwlZmUGB9n91zQEgcw==",
"requires": {
"leaflet": "~0.7.1"
},
"dependencies": {
"leaflet": {
"version": "0.7.7",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-0.7.7.tgz",
"integrity": "sha1-HjUrpU5j0HZFH6NjyQCJDLLPde4="
}
}
},
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
@@ -16627,13 +16676,13 @@
}
},
"roarr": {
"version": "2.15.3",
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.3.tgz",
"integrity": "sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA==",
"version": "2.15.4",
"resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
"integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==",
"dev": true,
"optional": true,
"requires": {
"boolean": "^3.0.0",
"boolean": "^3.0.1",
"detect-node": "^2.0.4",
"globalthis": "^1.0.1",
"json-stringify-safe": "^5.0.1",
@@ -18121,12 +18170,12 @@
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
"ms": "2.1.2"
}
},
"ms": {

View File

@@ -1,6 +1,6 @@
{
"name": "flightgear-airports",
"version": "0.0.29",
"version": "0.0.34",
"author": "portree_kid <keith.paterson@gmx.de>",
"description": "An software to design Flightgear groundnets",
"license": "GPL-3.0",
@@ -95,7 +95,7 @@
"coordinate-parser": "^1.0.3",
"dijkstrajs": "^1.0.1",
"electron-debug": "^3.0.1",
"element-ui": "^2.13.2",
"element-ui": "^2.15.1",
"file-url": "^3.0.0",
"fs": "0.0.1-security",
"fs-extra": "^9.0.1",
@@ -106,8 +106,10 @@
"leaflet": "^1.5.1",
"leaflet-editable": "^1.2.0",
"leaflet-polylinedecorator": "^1.6.0",
"leaflet-search": "^2.9.9",
"leaflet-sidebar-v2": "^3.2.1",
"leaflet-textpath": "^1.2.0",
"leaflet.pattern": "^0.1.0",
"lokijs": "^1.5.8",
"mathjs": "^6.2.5",
"path": "^0.12.7",

View File

@@ -31,6 +31,7 @@ function createWindow () {
nodeIntegration: true,
nodeIntegrationInWorker: true
},
closable: true,
width: 1000
})
mainWindow.loadURL(winURL)

View File

@@ -31,7 +31,7 @@ export function checkMapper(o) {
'box': o.box !== undefined ? o.box.getLatLngs() : null
};
} else if (o instanceof L.RunwayNode) {
console.log(o)
console.log(o)
return { 'index': Number(o['glueindex']), '_leaflet_id': o._leaflet_id, 'lat': o._latlng.lat, 'lng': o._latlng.lng, 'type': 'runway' };
} else if (o instanceof L.HoldNode) {
console.log(o)
@@ -41,6 +41,11 @@ export function checkMapper(o) {
'type': 'runway_poly',
'pavement': o.getLatLngs()
}
} else if (o instanceof L.TakeoffPolygon) {
return {
'type': 'takeoffpad_poly',
'pavement': o.getLatLngs()
}
} else if (o instanceof L.Polyline) {
console.log(o)
var latLngs = o.getLatLngs().map(l => ({ lat: l.lat, lng: l.lng, index: l.glueindex }));
@@ -56,7 +61,7 @@ export function checkMapper(o) {
}
export function groMapper(o) {
if (o instanceof L.Polygon) {
if (o instanceof L.Polygon) {
}
}

View File

@@ -0,0 +1,100 @@
<!--
Copyright 2021 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
-->
<template>
<div :key="airline.label + '-div'">
<div v-for="item in traffic" v-bind:key="airline.label + '-' + item.id + '-innerdiv'">
<div :key="item.id + '-dep'" v-if="direction == 0">{{ item.departure.time }} {{ item.callsign }} {{ item.departure.port }} --> {{ item.arrival.port }} {{ item['required-aircraft'] }} {{ item.flighttype }}</div>
<div :key="item.id + '-arr'" v-if="direction == 1">{{ item.arrival.time }} {{ item.callsign }} {{ item.departure.port }} --> {{ item.arrival.port }} {{ item['required-aircraft'] }} {{ item.flighttype }}</div>
</div>
</div>
</template>
<script lang="js">
import {readTrafficXML} from '../loaders/traffic_loader'
import ParkingItem from './ParkingItem'
const fs = require('fs')
const path = require('path')
export default {
name: 'airline-traffic',
components: {ParkingItem},
props: {airline: Object},
data () {
return {}
},
methods: {
traverseDir (dir, airline) {
var result = []
if (!fs.existsSync(dir)) {
return result
}
var iaco = airline.label
fs.readdirSync(dir).forEach(file => {
let fullPath = path.join(dir, file)
if (fs.lstatSync(fullPath).isDirectory()) {
var children = this.traverseDir(fullPath, airline)
result = result.concat(children)
} else {
if (file.match(new RegExp(`${iaco}.xml`, 'i'))) {
result.push(fullPath)
}
}
})
return result
}
},
computed: {
direction: function () {
return this.$parent.$parent.$parent.$data.direction
},
filename: function () {
var ret = this.traverseDir(this.$store.state.Settings.settings.flightgearDirectory_traffic, this.airline)
if (ret.length > 0) {
return ret[0]
}
},
trafficFile: function () {
return readTrafficXML(this.filename)
},
traffic: function () {
if (this.filename) {
var aircraftLookup = this.trafficFile.filter(a => a['required-aircraft'])
.reduce((req, acc) => {
req[acc['required-aircraft']] = acc
return req
}, {})
var ret = this.trafficFile.filter(f => f.callsign).filter(f =>
(f.departure.port === this.$store.state.Airports.currentAirport.icao && this.direction === 0) ||
(f.arrival.port === this.$store.state.Airports.currentAirport.icao && this.direction === 1))
.map(obj => ({ ...obj, flighttype: aircraftLookup[obj['required-aircraft']].flighttype }))
.filter((v, i, a) => a.findIndex(t => (t.id === v.id)) === i)
return ret
}
},
aircraft: function () {
if (this.filename) {
return this.trafficFile.filter(f => f.registration)
}
console.debug(this.filename)
}
}
}
</script>
<style>
div.row.div {
display: flex;
justify-content: space-between;
}
</style>

View File

@@ -16,12 +16,13 @@ You should have received a copy of the GNU General Public License along with FG
title="Add Airline"
:visible.sync="dialogVisible"
width="40%"
:before-close="handleClose">
:before-close="handleClose"
>
<span>Add an selectable airline to {{ icao }} {{ name }}</span>
<el-input
placeholder="Please input airline(s)"
v-model="airlineCode"
></el-input>
<el-input
placeholder="Please input airline(s)"
v-model="airlineCode"
></el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">Cancel</el-button>
<el-button type="primary" @click="addAirline">Confirm</el-button>
@@ -31,116 +32,143 @@ You should have received a copy of the GNU General Public License along with FG
title="Import File"
:visible.sync="showImportFile"
width="20%"
:before-close="handleClose">
<span>Beware wip will be overwritten</span>
<el-row>
<el-col :span="20">
<el-input
placeholder="Please input file"
v-model="fileImportName">
</el-input>
</el-col>
<el-col :span="4">
<file-select @input="fileImportFileName"></file-select>
</el-col>
</el-row>
:before-close="handleClose"
>
<span>Beware wip will be overwritten</span>
<el-row>
<el-col :span="20">
<el-input placeholder="Please input file" v-model="fileImportName">
</el-input>
</el-col>
<el-col :span="4">
<file-select @input="fileImportFileName"></file-select>
</el-col>
</el-row>
<span slot="footer" class="dialog-footer">
<el-button @click="showImportFile = false">Cancel</el-button>
<el-button type="primary" @click="importFile">Confirm</el-button>
</span>
</el-dialog>
<h1 class="leaflet-sidebar-header">{{ icao }} {{ name }}</h1>
<div width="100%" >
<el-row>
<el-popover
placement="top-start"
title="Description"
width="50"
trigger="hover"
content="Edit"
>
<el-button @click="edit" v-if="!editing" slot="reference"><i class="fas fa-edit"></i></el-button>
</el-popover>
<el-popover
placement="top-start"
title="Description"
width="200"
trigger="hover"
content="Import groundnet"
>
<el-button @click="showImportFile = true" v-if="!editing" slot="reference"><i class="fas fa-file-import"></i></el-button>
</el-popover>
<el-popover
placement="top-start"
title="Description"
width="220"
trigger="hover"
content="Export groundnet to export directory"
>
<el-button @click="test" v-if="!editing" slot="reference"><i class="fas fa-file-export"></i></el-button>
</el-popover>
<el-popover
placement="top-start"
title="Description"
width="200"
trigger="hover"
content="Upload Airport"
>
<el-button @click="upload" v-if="!editing" slot="reference"><i class="fas fa-upload"></i></el-button>
</el-popover>
</el-row>
<el-row>
<el-col :span="7"><span class="label"> Airlines :</span></el-col>
<el-col :span="15">
<el-tag v-for="item in airlines" :key="item.value">{{item.value}}</el-tag>
</el-col>
<el-col :span="2">
<el-button @click="dialogVisible = true" v-if="editing" ><i class="fas fa-plus"></i></el-button>
</el-col>
</el-row>
<div width="100%">
<el-row>
<el-popover
placement="top-start"
title="Description"
width="50"
trigger="hover"
content="Edit"
>
<el-button @click="edit" v-if="!editing" slot="reference"
><i class="fas fa-edit"></i
></el-button>
</el-popover>
<el-popover
placement="top-start"
title="Description"
width="200"
trigger="hover"
content="Import groundnet"
>
<el-button
@click="showImportFile = true"
v-if="!editing"
slot="reference"
><i class="fas fa-file-import"></i
></el-button>
</el-popover>
<el-popover
placement="top-start"
title="Description"
width="220"
trigger="hover"
content="Export groundnet to export directory"
>
<el-button @click="test" v-if="!editing" slot="reference"
><i class="fas fa-file-export"></i
></el-button>
</el-popover>
<el-popover
placement="top-start"
title="Description"
width="200"
trigger="hover"
content="Upload Airport"
>
<el-button @click="upload" v-if="!editing" slot="reference"
><i class="fas fa-upload"></i
></el-button>
</el-popover>
</el-row>
<el-row>
<el-col :span="7"><span class="label"> Airlines :</span></el-col>
<el-col :span="15">
<el-tag v-for="item in airlines" :key="item.value">{{
item.value
}}</el-tag>
</el-col>
<el-col :span="2">
<el-button @click="dialogVisible = true" v-if="editing"
><i class="fas fa-plus"></i
></el-button>
</el-col>
</el-row>
</div>
<el-tabs v-model="activeTab" >
<el-tab-pane label="Frequencies" name="first">
<div>
<el-row v-for="f in frequencyList" :key="f.index">
<Frequency :frequency="f"></Frequency>
</el-row>
<el-button @click="addFrequency" v-if="editing" >Add</el-button>
<el-tabs v-model="activeTab">
<el-tab-pane label="Frequencies" name="first">
<div>
<el-row v-for="f in frequencyList" :key="f.index">
<Frequency :frequency="f"></Frequency>
</el-row>
<el-button @click="addFrequency" v-if="editing">Add</el-button>
</div>
</el-tab-pane>
<el-tab-pane label="Parkings" name="second">
<ParkingList></ParkingList>
</el-tab-pane>
<el-tab-pane label="Statistics" name="third">
<el-row><el-col :span="8"><span class="label">Traffic :</span></el-col></el-row>
</el-tab-pane>
<el-tab-pane label="Parkings" name="second">
<ParkingList></ParkingList>
</el-tab-pane>
<el-tab-pane label="Statistics" name="third">
<el-row
><el-col :span="8"
><span class="label">Traffic :</span></el-col
></el-row
>
<el-row>
<el-col :span="8">Flights :</el-col>
<el-col :span="4">{{ flights }}</el-col>
<el-col :span="8"></el-col>
<el-col :span="4"></el-col>
</el-row>
<el-row><el-col :span="16"><span class="label">GIT/Terrasync :</span></el-col></el-row>
<el-row
><el-col :span="16"
><span class="label">GIT/Terrasync :</span></el-col
></el-row
>
<el-row>
<el-col :span="8">Parking Positions :</el-col>
<el-col :span="4">{{ parking }}</el-col>
<el-col :span="8">Groundnet Nodes :</el-col>
<el-col :span="4">{{groundnet}}</el-col>
<el-col :span="4">{{ groundnet }}</el-col>
</el-row>
<el-row><el-col :span="8"><span class="label">Work :</span></el-col></el-row>
<el-row
><el-col :span="8"><span class="label">Work :</span></el-col></el-row
>
<el-row v-if="wip">
<el-col :span="8">Work Parking Positions :</el-col>
<el-col :span="4">{{ wipparking }}</el-col>
<el-col :span="8">Work Groundnet Nodes :</el-col>
<el-col :span="4">{{wipgroundnet}}</el-col>
<el-col :span="4">{{ wipgroundnet }}</el-col>
</el-row>
<el-row v-if="wip">
<el-col :span="4">Saved :</el-col>
<el-col :span="8" class="text">{{date}}</el-col>
<el-col :span="8" class="text">{{ date }}</el-col>
<el-col :span="4">Uploaded :</el-col>
<el-col :span="8" class="text">{{upload_date}}</el-col>
<el-col :span="8" class="text">{{ upload_date }}</el-col>
</el-row>
</el-tab-pane>
</el-tabs>
</el-tab-pane>
<el-tab-pane label="Traffic" name="fourth">
<TrafficList></TrafficList>
</el-tab-pane>
</el-tabs>
</div>
</template>
@@ -149,8 +177,9 @@ You should have received a copy of the GNU General Public License along with FG
import FileSelect from './FileSelect'
import Frequency from './Frequency'
import ParkingList from './ParkingList'
import TrafficList from './TrafficList'
import Upload from './Upload'
const fs = require('fs')
const path = require('path')
@@ -159,7 +188,7 @@ export default {
return {showImportFile: false, activeTab: 'first', editing: false, uploadVisible: false, dialogVisible: false, airlineCode: '', fileImport: null}
},
components: {
EditButton, FileSelect, Frequency, ParkingList, Upload
EditButton, FileSelect, Frequency, ParkingList, TrafficList, Upload
},
methods: {
fileImportFileName (f) {
@@ -291,10 +320,10 @@ export default {
</script>
<style lang="scss" scoped>
.el-row {
padding: 0em;
margin-bottom: 5px;
}
.el-row {
padding: 0em;
margin-bottom: 5px;
}
.label {
display: flex;
justify-content: left;

View File

@@ -5,24 +5,26 @@
<div class="leaflet-sidebar-close">
<i class="fa fa-caret-left"></i>
</div>
</h1>
</h1>
<div id="panel" width="100%">
<el-row v-if="!results || results.length === 0 "><h3>Check not run</h3></el-row>
<el-row v-for="(result,idx) in results" :key="idx">
<el-col :span="2" v-if="result.id<0"><span class="label"><i class="far fa-check-circle"></i></span></el-col>
<el-col :span="2" v-if="result.id>=0"><span class="label"><i class="fas fa-exclamation-triangle"></i></span></el-col>
<el-col :span="2" v-if="result.id==-1"><span class="label"><i class="far fa-check-circle"></i></span></el-col>
<el-col :span="2" v-if="result.id>=0"><span class="label"><i class="fas fa-exclamation-triangle"></i></span></el-col>
<el-col :span="2" v-if="result.id==-2"><span class="label"><i class="fas fa-exclamation-triangle"></i></span></el-col>
<el-col :span="15">
<el-popover
placement="top-start"
title="Description"
width="200"
trigger="hover"
v-if="result.message"
:content=result.message[1]
>
<span class="label" slot="reference">{{ result.message[0] }}</span>
</el-popover>
</el-col>
<el-col :span="4" v-if="result.id>=0"><el-button v-on:click="show(result.id)" class="button"><i class="fas fa-bullseye"></i></el-button></el-col>
<el-col :span="4" v-if="result.id>=0"><el-button v-on:click="show(result.id)" class="button"><i class="fas fa-bullseye"></i></el-button></el-col>
</el-row>
</div>
</div>

View File

@@ -145,7 +145,7 @@ You should have received a copy of the GNU General Public License along with FG
},
methods: {
cancel () {
this.centerDialogVisible = false
this.centerDialogVisible = false
},
zoomout() {
this.$parent.$parent.$refs.editLayer.stopDrawing()
@@ -195,7 +195,7 @@ You should have received a copy of the GNU General Public License along with FG
this.$parent.$parent.$refs.towerLayer.disableEdit()
this.$parent.$parent.$refs.thresholdLayer.disableEdit()
this.rescanCurrentGroundnet()
Vue.set(this, 'saveDialogVisible', false)
Vue.set(this, 'saveDialogVisible', false)
},
save () {
Vue.set(this, 'saveDialogVisible', true)
@@ -209,7 +209,7 @@ You should have received a copy of the GNU General Public License along with FG
this.$parent.$parent.$refs.towerLayer.save()
this.$parent.$parent.$refs.thresholdLayer.save()
this.rescanCurrentGroundnet()
Vue.set(this, 'saveDialogVisible', false)
Vue.set(this, 'saveDialogVisible', false)
},
rescanCurrentGroundnet () {
try {
@@ -220,7 +220,7 @@ You should have received a copy of the GNU General Public License along with FG
var icao = this.$parent.$parent.$refs.editLayer.icao
const worker = new Worker(winURL)
var aptDir = path.join(this.$store.state.Settings.settings.airportsDirectory, icao[0], icao[1], icao[2]);
worker.postMessage(['scan', aptDir ])
// the reply
@@ -276,7 +276,7 @@ You should have received a copy of the GNU General Public License along with FG
const worker = new Worker(winURL)
worker.onerror = function(e) {
worker.terminate()
worker.terminate()
worker.view.max = 0
worker.view.checkDialogVisible = false
e.preventDefault(); // <-- "Hey browser, I handled it!"
@@ -302,9 +302,16 @@ You should have received a copy of the GNU General Public License along with FG
console.log(l)
pavement.push(l)
})
var features2 = pavement.map(mapper.checkMapper).filter(n => n)
var thresholds = []
this.$parent.$parent.$refs.thresholdLayer.getLayer().eachLayer(l => {
console.log(l)
thresholds.push(l)
})
var pavementFeatures = pavement.map(mapper.checkMapper).filter(n => n)
//TODO
var thresholdFeatures = thresholds.map(mapper.checkMapper).filter(n => n)
worker.postMessage(['check', features.concat(features2) ] )
worker.postMessage(['check', features.concat(pavementFeatures).concat(thresholdFeatures) ] )
this.pollData()
// the reply
var store = this.$store

View File

@@ -39,9 +39,8 @@ You should have received a copy of the GNU General Public License along with FG
components: {},
props: [],
created () {
[LMap, LMarker, L, LEdit, L2]
console.log('Created Editlayer')
console.debug('Created Editlayer')
// console.log(LSymbol)
},
mounted () {
@@ -51,8 +50,6 @@ You should have received a copy of the GNU General Public License along with FG
this.$parent.mapObject.createPane('route-pane')
this.$parent.mapObject.getPane('route-pane').style.zIndex = 511
this.selectionLayerGroup = L.layerGroup();
this.selectionLayerGroup.addTo(this.$parent.mapObject)
this.$store.watch(
function (state) {
return state.Editable.data.node;
@@ -113,6 +110,12 @@ You should have received a copy of the GNU General Public License along with FG
}
},
methods: {
getLayer () {
return this.groundnetLayerGroup;
},
getIdLayerGroup() {
return this.idLayerGroup;
},
getParkings(ring) {
var poly = turf.polygon(ring);
var parkings = []
@@ -122,16 +125,16 @@ You should have received a copy of the GNU General Public License along with FG
var tp = turf.point([l.getLatLng().lat, l.getLatLng().lng]);
if (turf.booleanPointInPolygon(tp, poly)) {
parkings.push(l);
}
}
}
})
this.selection = parkings;
return parkings;
},
load (icao, filename) {
load (icao, filename) {
if (this.groundnetLayerGroup !== undefined) {
this.groundnetLayerGroup.removeFrom(this.$parent.mapObject)
}
}
this.$parent.$parent.setIcao(icao)
this.icao = icao
var f = '';
@@ -156,7 +159,7 @@ You should have received a copy of the GNU General Public License along with FG
}
this.groundnetLayerGroup.eachLayer(l => {
if (l instanceof L.TaxiwaySegment) {
l.addListeners()
l.addListeners()
}
if (l.updateArrows !== undefined) {
l.updateArrows(this.$store.state.Settings.zoom)
@@ -166,7 +169,7 @@ You should have received a copy of the GNU General Public License along with FG
}
})
console.log(this.groundnetLayerGroup.maxId)
console.debug(`MaxId : ${this.groundnetLayerGroup.maxId}`)
this.buildLookup()
this.groundnetLayerGroup.addTo(this.$parent.mapObject)
@@ -212,7 +215,12 @@ You should have received a copy of the GNU General Public License along with FG
this.selection.forEach(element => {
element.updateRadius(event.wingspan/2)
});
break;
break;
case 'parking-group-type':
this.selection.forEach(element => {
element.updateType(event.parking_type)
});
break;
default:
break;
}
@@ -222,8 +230,11 @@ You should have received a copy of the GNU General Public License along with FG
this.editable = true
this.editing = true
this.$store.commit('SET_EDIT', true)
this.featureLookup = [];
if(!this.groundnetLayerGroup) {
return;
}
this.groundnetLayerGroup.eachLayer(l => {
l.enableEdit()
l.featureLookup = this.featureLookup;
@@ -240,7 +251,49 @@ You should have received a copy of the GNU General Public License along with FG
l.setInteractive(true)
}
})
this.$store.dispatch('addWip', {icao: this.icao});
this.$store.dispatch('addWip', {icao: this.icao});
},
showTooltips() {
this.groundnetLayerGroup.eachLayer(l => {
if (l instanceof L.Polyline) {
l.getLatLngs().forEach(l => {
if (this.$parent.mapObject.getBounds().contains(l)) {
if (l.__vertex && !l.__vertex.getTooltip()) {
l.__vertex.bindTooltip(l.glueindex, {permanent: true});
}
}
});
}
if (l instanceof L.ParkingSpot) {
if (this.$parent.mapObject.getBounds().contains(l.getLatLng())) {
var parkingHub = l.glueindex + " " + l.options.attributes.name + " " + l.options.attributes.number;
if(l.box) {
l.box.bindTooltip(parkingHub, {permanent: true, direction: 'right'});
} else {
l.bindTooltip(parkingHub, {permanent: true, direction: 'right'});
}
}
}
});
setTimeout(this.closeTooltips.bind(this), 2000);
},
closeTooltips() {
this.groundnetLayerGroup.eachLayer(l => {
if (l instanceof L.Polyline) {
l.getLatLngs().forEach(l => {
if (l.__vertex && l.__vertex.getTooltip()) {
l.__vertex.unbindTooltip();
}
});
}
if (l instanceof L.ParkingSpot) {
if(l.box) {
l.box.unbindTooltip();
} else {
l.unbindTooltip();
}
}
});
},
disableEdit () {
this.editable = false
@@ -278,7 +331,7 @@ You should have received a copy of the GNU General Public License along with FG
if (this.featureLookup===undefined || this.featureLookup[index]===undefined) {
return
}
var parking = this.featureLookup[index].filter(n => n instanceof L.ParkingSpot)
var parking = this.featureLookup[index].filter(n => n instanceof L.ParkingSpot)
var walkedNodes = [index]
var pushBackNodes = []
this.walkPushbackRoute(index, walkedNodes, pushBackNodes)
@@ -304,29 +357,44 @@ You should have received a copy of the GNU General Public License along with FG
}
});
},
removeArc (arc) {
removeArc (arc) {
console.debug('Remove Arc : ' + arc);
var arcLayer = this.groundnetLayerGroup.getLayer(this.$store.state.Editable.index);
arcLayer.removeFrom(this.groundnetLayerGroup);
arcLayer.removeFrom(this.groundnetLayerGroup);
},
removeParking (index) {
if(this.featureLookup[index]===undefined) {
console.error("Lookup " + index + " failed ");
console.error("Lookup " + index + " failed ");
return;
}
this.featureLookup[index].forEach((element, i) => {
if (element instanceof L.ParkingSpot) {
element.removeFrom(this.groundnetLayerGroup);
element.removeFrom(this.groundnetLayerGroup);
}
});
},
show (index) {
if(Number.isNaN(index)) {
return;
}
if(this.featureLookup===undefined || this.featureLookup[index]===undefined) {
console.error("Lookup " + index + " failed ");
this.buildLookup()
}
if (this.featureLookup===undefined || this.featureLookup[index]===undefined) {
var found = false;
this.groundnetLayerGroup.eachLayer((layer) => {
if (layer instanceof L.Polyline && layer._leaflet_id == index) {
layer.select();
this.$store.dispatch('setCenter', layer.getCenter());
found = true;
} else {
layer.deselect();
}
});
if (found) {
return;
} else {
console.error("Lookup " + index + " failed ");
this.buildLookup();
return;
}
}
if (Number(this.$store.state.Editable.index) >= 0 &&
this.featureLookup[this.$store.state.Editable.index]!==undefined) {
@@ -338,7 +406,6 @@ You should have received a copy of the GNU General Public License along with FG
this.featureLookup[index].forEach((element, i) => {
if (element instanceof L.Polyline) {
element._latlngs.forEach((e1, index1) => {
console.log(e1);
if (e1.attributes.index===Number(index)) {
var latlng = {};
latlng.lat = e1.lat;
@@ -394,12 +461,12 @@ You should have received a copy of the GNU General Public License along with FG
this.featureLookup[layer.glueindex].push(layer);
} else {
console.warn(layer)
}
}
})
},
getPointCoords (index) {
if(this.featureLookup[index]===undefined) {
console.error("Lookup " + index + " failed ");
console.error("Lookup " + index + " failed ");
return;
}
return this.featureLookup[index].map((element, i) => {
@@ -429,14 +496,14 @@ You should have received a copy of the GNU General Public License along with FG
}).filter(n => n);
},
/**
*
*
*/
setPointCoords (index, coordinates) {
var position = new Coordinates(coordinates);
var latlng = {lat: position.latitude, lng: position.longitude };
if(this.featureLookup[index]===undefined) {
console.error("Lookup " + index + " failed ");
console.error("Lookup " + index + " failed ");
return;
}
return this.featureLookup[index].map((element, i) => {
@@ -459,7 +526,7 @@ You should have received a copy of the GNU General Public License along with FG
else if (element instanceof L.Polyline) {
element._latlngs.forEach((e1, index1) => {
if (e1.attributes.index===index && (
latlng.lat !== element.getLatLngs()[index1].lat ||
latlng.lat !== element.getLatLngs()[index1].lat ||
latlng.lng !== element.getLatLngs()[index1].lng
)
) {
@@ -484,12 +551,12 @@ You should have received a copy of the GNU General Public License along with FG
element.editor.feature.setLatLngs(element.latlngs);
element.editor.feature.updateMiddle();
*/
}
}
});
},
refreshLookup(index) {
//element.__vertex
this.featureLookup[index] = this.featureLookup[index].filter(item => {
this.featureLookup[index] = this.featureLookup[index].filter(item => {
return !(item instanceof L.Editable.VertexMarker && item.editor.__vertex === undefined)
}
);
@@ -502,7 +569,7 @@ You should have received a copy of the GNU General Public License along with FG
},
removeNode (index) {
if(this.featureLookup[index]===undefined) {
console.error("Lookup " + index + " failed ");
console.error("Lookup " + index + " failed ");
return;
}
try {
@@ -520,31 +587,31 @@ You should have received a copy of the GNU General Public License along with FG
this.featureLookup[Number(element.end)] = this.featureLookup[Number(element.end)].filter(item => item !== element);
this.refreshLookup(Number(element.end))
}
element.removeFrom(this.groundnetLayerGroup);
element.removeFrom(this.groundnetLayerGroup);
element.removeFrom(this.$parent.mapObject);
}
else {
element.getLatLngs().forEach((e1, index1) => {
console.debug('Remove Long' + index1 + ' ' + e1);
if (e1.attributes.index===index) {
var splitOffNodes = element.getLatLngs().splice(index1);
var splitOffNodes = element.getLatLngs().splice(index1);
element.editor.refresh();
element.editor.reset();
splitOffNodes.splice(0, 1);
if( splitOffNodes.length>1) {
var polyline = new L.Polyline(splitOffNodes, { attributes: {} }).addTo(layerGroup);
extendTaxiSegment(polyline);
polyline.addListeners();
polyline.addListeners();
polyline.setEditlayer(this);
polyline.enableEdit();
polyline.editor.refresh();
polyline.editor.reset();
polyline.addTo(this.groundnetLayerGroup);
polyline.addTo(this.groundnetLayerGroup);
polyline.end = element.end;
// Remove from end lookup
this.featureLookup[element.options.attributes.end] = this.featureLookup[element.options.attributes.end].filter(item => item !== element);
// push to the end lookup
this.featureLookup[element.options.attributes.end].push(polyline);
this.featureLookup[element.options.attributes.end].push(polyline);
}
if(element.getLatLngs().length === 1) {
this.featureLookup[index] = this.featureLookup[index].filter(item => item !== element);
@@ -561,8 +628,8 @@ You should have received a copy of the GNU General Public License along with FG
element.removeFrom(this.groundnetLayerGroup);
} else {
console.warn('WTF' + element);
}
});
}
});
} catch (error) {
console.error(error);
}
@@ -602,7 +669,7 @@ You should have received a copy of the GNU General Public License along with FG
console.debug(event)
event.target.addTo(this.groundnetLayerGroup)
})
},
},
drawPushbackPolyline () {
var polyLine = this.$parent.mapObject.editTools.startPolyline()
polyLine.addTo(this.groundnetLayerGroup)
@@ -619,7 +686,7 @@ You should have received a copy of the GNU General Public License along with FG
polyLine.on('editable:drawing:end', event => {
console.debug(event)
event.target.addTo(this.groundnetLayerGroup)
var pt = event.sourceTarget._latlngs[event.sourceTarget._latlngs.length-1];
var pt = event.sourceTarget._latlngs[event.sourceTarget._latlngs.length-1];
pt.attributes['holdPointType'] = 'PushBack'
var nIndex = pt.attributes.index
var fa_icon = "<div style='background-color:#4838cc;' class='marker-pin'></div><i class='fas fa-arrows-alt-h'></i>";
@@ -645,7 +712,7 @@ You should have received a copy of the GNU General Public License along with FG
this.featureLookup===undefined) {
return
}
console.log('Edited Parking : ' + this.$store.state.Editable.data.parking)
console.debug('Edited Parking : ' + this.$store.state.Editable.data.parking)
//Notify list
if (this.featureLookup[this.$store.state.Editable.index]===undefined) {
return
@@ -653,18 +720,18 @@ You should have received a copy of the GNU General Public License along with FG
this.featureLookup[this.$store.state.Editable.index].forEach((element,index) => {
if (element instanceof L.ParkingSpot) {
element.options.attributes = Object.assign({}, this.$store.state.Editable.data.parking)
element.updateVertexFromDirection();
element.updateWheelPos();
element.updateBox();
element.updateVertexFromDirection();
element.updateWheelPos();
element.updateBox();
}
})
if (this.$store.state.Editable.data.parking.coords) {
this.setPointCoords(this.$store.state.Editable.index, this.$store.state.Editable.data.parking.coords)
this.setPointCoords(this.$store.state.Editable.index, this.$store.state.Editable.data.parking.coords)
}
},
editedParkings() {
if (this.featureLookup===undefined) {
console.warn("Lookup undefined");
console.warn("Lookup undefined");
this.buildLookup()
}
if (this.featureLookup===undefined) {
@@ -679,7 +746,7 @@ You should have received a copy of the GNU General Public License along with FG
element.options.attributes.name = newElement.name
element.options.attributes.number = newElement.number
element.options.attributes.type = newElement.type
//element.updateVertexFromDirection();
//element.updateVertexFromDirection();
}
})
}
@@ -690,10 +757,10 @@ You should have received a copy of the GNU General Public License along with FG
this.featureLookup[this.$store.state.Editable.index].forEach((element,index) => {
if (element instanceof L.ParkingSpot) {
element.options.attributes = Object.assign({}, this.$store.state.Editable.data.parking)
element.updateVertexFromDirection();
element.updateVertexFromDirection();
}
})
*/
*/
},
editedArc() {
if (!this.groundnetLayerGroup ||
@@ -709,7 +776,7 @@ You should have received a copy of the GNU General Public License along with FG
console.log('Edited Arc : ' + this.$store.state.Editable.index);
arc.options.attributes = Object.assign({}, this.$store.state.Editable.data.arc)
arc.updateStyle();
}
}
},
editedMultiArc() {
if (!this.groundnetLayerGroup ||
@@ -729,7 +796,7 @@ You should have received a copy of the GNU General Public License along with FG
arc.options.attributes.name = String(this.$store.state.Editable.data.multiarc.name)
arc.options.attributes.isPushBackRoute = Number(this.$store.state.Editable.data.multiarc.isPushBackRoute)
arc.updateStyle();
}
}
});
},
//Update Node
@@ -739,11 +806,11 @@ You should have received a copy of the GNU General Public License along with FG
this.featureLookup===undefined ||
!this.editing) {
return;
}
}
var isOnRunway = Number(this.$store.state.Editable.data.node.isOnRunway);
var isHoldPoint = this.$store.state.Editable.data.node.holdPointType !== 'none' &&
this.$store.state.Editable.data.node.holdPointType !== undefined;
var nIndex = this.$store.state.Editable.index;
var nIndex = this.$store.state.Editable.index;
var hasRunwayNode = false;
var hasHoldPointNode = false;
var latlng;
@@ -752,14 +819,14 @@ You should have received a copy of the GNU General Public License along with FG
if (isOnRunway === 0) {
// We shouldn't have a RunwayNode
element.removeFrom(this.groundnetLayerGroup);
this.featureLookup[nIndex].splice(index,1);
this.featureLookup[nIndex].splice(index,1);
}
hasRunwayNode = true;
} else if (element instanceof L.HoldNode) {
if (!isHoldPoint) {
// We shouldn't have a RunwayNode
element.removeFrom(this.groundnetLayerGroup);
this.featureLookup[nIndex].splice(index,1);
this.featureLookup[nIndex].splice(index,1);
} else {
var fa_icon;
if (this.$store.state.Editable.data.node.holdPointType === 'PushBack') {
@@ -792,17 +859,17 @@ You should have received a copy of the GNU General Public License along with FG
latlng = element._latlngs[1];
}
} else if (element instanceof L.Polyline) {
element._latlngs.forEach(element => {
if(element.__vertex && Number(element.glueindex) === Number(nIndex)){
element._latlngs.forEach(element => {
if(element.__vertex && Number(element.glueindex) === Number(nIndex)){
if (this.$store.state.Editable.data.node.coords) {
this.setPointCoords(this.$store.state.Editable.index, this.$store.state.Editable.data.node.coords)
this.setPointCoords(this.$store.state.Editable.index, this.$store.state.Editable.data.node.coords)
var position = new Coordinates(this.$store.state.Editable.data.node.coords);
latlng = {lat: position.latitude, lng: position.longitude };
}
}
});
}
}
})
if (!hasRunwayNode && isOnRunway && latlng !== undefined) {
this.addRunwayNode(latlng, nIndex)
@@ -881,7 +948,7 @@ You should have received a copy of the GNU General Public License along with FG
}
} else {
console.log(layer)
}
}
})
layers.sort((l1, l2) => l1.d - l2.d)
if (layers.length > 0) {
@@ -910,9 +977,9 @@ You should have received a copy of the GNU General Public License along with FG
circle.addListeners()
circle.enableEdit()
circle.extensions()
circle.updateVertexFromDirection();
circle.updateWheelPos();
circle.updateBox();
circle.updateVertexFromDirection();
circle.updateWheelPos();
circle.updateBox();
if (Number(this.$store.state.Editable.index) >= 0 &&
this.featureLookup[this.$store.state.Editable.index]!==undefined) {
this.featureLookup[this.$store.state.Editable.index].forEach(element => {
@@ -934,7 +1001,7 @@ You should have received a copy of the GNU General Public License along with FG
},
link (index) {
var layers = []
var centerLatLng = null
var centerLatLng = null
this.featureLookup[index].forEach(layer => {
if (layer instanceof L.Polyline) {
// console.log(layer._latlngs)
@@ -943,7 +1010,7 @@ You should have received a copy of the GNU General Public License along with FG
if (Number.isNaN(latlng.glueindex)) {
console.warn('No glueindex : ' + latlng.__vertex);
}
if (Number(latlng.glueindex) === index) {
centerLatLng = latlng;
}
@@ -1014,9 +1081,9 @@ You should have received a copy of the GNU General Public License along with FG
}
})
}
})
})
featureLookup[glueindex] = [];
});
});
},
save () {
var xml = []
@@ -1024,7 +1091,7 @@ You should have received a copy of the GNU General Public License along with FG
//console.debug(l)
xml.push(l)
})
writeGroundnetXML(this.$store.state.Settings.settings.airportsDirectory, this.icao, xml)
writeGroundnetXML(this.$store.state.Settings.settings.airportsDirectory, this.icao, xml)
},
//Copy to test directory
test() {
@@ -1040,16 +1107,16 @@ You should have received a copy of the GNU General Public License along with FG
this.$message({
type: 'info',
message: `Copied to ${fNew}`
});
});
} catch (error) {
this.$message({
type: 'error',
message: `Copy error : ${error}`
});
});
}
},
setVisible(visible) {
if (this.layerGroup) {
if (this.layerGroup) {
if (visible) {
this.layerGroup.addTo(this.$parent.mapObject)
} else {

View File

@@ -29,7 +29,7 @@ You should have received a copy of the GNU General Public License along with FG
-->
<!--<l-marker :lat-lng="marker"></l-marker>-->
<LeafletSidebar ref="sidebar" @editParking="onEditSidebar" @edit="onEdit($event)"></LeafletSidebar>
<AiLayer ref="aiLayer"></AiLayer>
<AiLayer ref="aiLayer"></AiLayer>
<l-layer-group layerType="overlay" name="airports" ref="airportLayer">
<l-circle
v-for="(item, index) in this.$store.state.Airports.airports"
@@ -42,7 +42,7 @@ You should have received a copy of the GNU General Public License along with FG
></l-circle>
</l-layer-group>
<EditLayer ref="editLayer"></EditLayer>
<PavementLayer ref="pavementLayer"></PavementLayer>
<PavementLayer ref="pavementLayer"></PavementLayer>
<ThresholdLayer ref="thresholdLayer"></ThresholdLayer>
<TowerLayer ref="towerLayer"></TowerLayer>
<ToolLayer ref="toolLayer" @select-poly="onSelectedPolygon"></ToolLayer>
@@ -53,8 +53,9 @@ You should have received a copy of the GNU General Public License along with FG
<script lang="js">
import 'leaflet/dist/leaflet.css'
import 'leaflet-search/dist/leaflet-search.src.css'
import '@/assets/button.css'
import { LMap, LTileLayer, LMarker, LCircle, LLayerGroup, LControl } from 'vue2-leaflet'
import { LMap, LTileLayer, LMarker, LCircle, LLayerGroup, LControl, LTooltip } from 'vue2-leaflet'
import LeafletSidebar from './LeafletSidebar'
import AiLayer from './AiLayer'
import EditBar from './EditBar'
@@ -67,6 +68,7 @@ You should have received a copy of the GNU General Public License along with FG
import { Loading } from 'element-ui'
import L from 'leaflet'
import { LeafletSearch } from 'leaflet-search'
// https://github.com/KoRiGaN/Vue2Leaflet/issues/103
delete L.Icon.Default.prototype._getIconUrl
@@ -77,7 +79,7 @@ You should have received a copy of the GNU General Public License along with FG
})
export default {
name: 'flightgear-map',
components: { LMap, LTileLayer, LMarker, LCircle, LeafletSidebar, AiLayer, EditBar, ToolBar, EditLayer, TowerLayer, PavementLayer, LLayerGroup, LControl, ThresholdLayer, ToolLayer },
components: { LMap, LTileLayer, LMarker, LCircle, LTooltip, LeafletSidebar, AiLayer, EditBar, ToolBar, EditLayer, TowerLayer, PavementLayer, LLayerGroup, LControl, ThresholdLayer, ToolLayer, LeafletSearch },
props: [],
created () {
this.loadingInstance = null
@@ -183,7 +185,7 @@ You should have received a copy of the GNU General Public License along with FG
loadingInstance: Object,
groundnetLoaded: false,
pavementLoaded: false,
url: 'https://a.tile.openstreetmap.de/{z}/{x}/{y}.png',
url: 'http://xjsjc.kongjian.xin:4200/tile/{z}/{x}/{y}.png',
attribution: '<A href="https://github.com/Portree-Kid/flightgear-airports" target="_blank">Flightgear Airports ' + require('electron').remote.app.getVersion() +
'</A> <A href="https://www.electronjs.org/" target="_blank">Electron</A> ' +
' <A href="https://element.eleme.io/#/en-US/" target="_blank">element.io</A> ' +
@@ -241,6 +243,16 @@ You should have received a copy of the GNU General Public License along with FG
}
this.$refs.towerLayer.zoomUpdated()
}
if (this.$refs.editLayer !== undefined && this.searchControl === undefined && this.$refs.editLayer.getLayer() === e.layer) {
this.searchControl = new L.Control.Search({
layer: this.$refs.editLayer.getLayer(),
position: 'topleft',
propertyName: 'searchTerm',
marker: {animate: false},
initial: false
})
this.searchControl.addTo(this.$refs.map.mapObject)
}
},
onSelectedPolygon (ring) {
var parkings = this.$refs.editLayer.getParkings(ring)
@@ -324,6 +336,7 @@ You should have received a copy of the GNU General Public License along with FG
event.target.airport = item
// console.log(event, item)
this.normalStyle(event.target)
event.target.bindTooltip(event.target.airport.properties.icao + ' ' + event.target.airport.properties.name)
},
onClick (event, item) {
console.log(item)
@@ -366,7 +379,7 @@ You should have received a copy of the GNU General Public License along with FG
},
async centerUpdated (center) {
if (center !== this.$store.state.Settings.center) {
this.$store.dispatch('setCenter', center)
this.$store.dispatch('setCenter', {lat: Number(center.lat), lng: Number(center.lng)})
this.$refs.airportLayer.setVisible(this.zoom < 12)
if (this.$refs.thresholdLayer) {
this.$refs.thresholdLayer.setVisible(this.zoom >= 12)

View File

@@ -16,13 +16,21 @@
<span class="label">Name :</span>
</el-col>
<el-col :span="8">
<el-input placeholder="Name" v-model="name" :disabled="!editing"></el-input>
<el-input
placeholder="Name"
v-model="name"
:disabled="!editing"
></el-input>
</el-col>
<el-col :span="5">
<span class="label">Number :</span>
</el-col>
<el-col :span="7">
<el-input placeholder="Number" v-model="number" :disabled="!editing"></el-input>
<el-input
placeholder="Number"
v-model="number"
:disabled="!editing"
></el-input>
</el-col>
</el-row>
<el-row>
@@ -40,7 +48,11 @@
-->
<el-radio-group v-model="wingspan" :disabled="!editing">
<el-tooltip content="PIPER PA-31/CESSNA 404 Titan" placement="top" effect="light">
<el-tooltip
content="PIPER PA-31/CESSNA 404 Titan"
placement="top"
effect="light"
>
<el-radio :label="15">A (7.5)</el-radio>
</el-tooltip>
<el-tooltip
@@ -48,14 +60,14 @@
placement="top"
effect="light"
>
<el-radio :label="20">- (10)</el-radio>
<el-radio :label="20">- (10)</el-radio>
</el-tooltip>
<el-tooltip
content="BOMBARDIER Regional Jet CRJ-200/DE HAVILLAND CANADA DHC-6"
placement="top"
effect="light"
>
<el-radio :label="28">B (14)</el-radio>
<el-radio :label="28">B (14)</el-radio>
</el-tooltip>
<el-tooltip
content="BOEING 737-700/AIRBUS A-320/EMBRAER ERJ 190-100"
@@ -64,13 +76,25 @@
>
<el-radio :label="36">C (18)</el-radio>
</el-tooltip>
<el-tooltip content="B767 Series/AIRBUS A-310" placement="top" effect="light">
<el-tooltip
content="B767 Series/AIRBUS A-310"
placement="top"
effect="light"
>
<el-radio :label="52">D (26)</el-radio>
</el-tooltip>
<el-tooltip content="B777 Series/B787 Series/A330 Family" placement="top" effect="light">
<el-tooltip
content="B777 Series/B787 Series/A330 Family"
placement="top"
effect="light"
>
<el-radio :label="66">E (33)</el-radio>
</el-tooltip>
<el-tooltip content="BOEING 747-8/AIRBUS A-380-800" placement="top" effect="light">
<el-tooltip
content="BOEING 747-8/AIRBUS A-380-800"
placement="top"
effect="light"
>
<el-radio :label="80">F (40)</el-radio>
</el-tooltip>
</el-radio-group>
@@ -80,9 +104,9 @@
<el-col :span="7">
<span class="label">Aircraft :</span>
</el-col>
<el-col :span="17">{{type}}</el-col>
<el-col :span="17">{{ type }}</el-col>
</el-row>
<el-row v-if="editing">
<el-row v-if="editing">
<el-col :span="7">
<span class="label">Calculate :</span>
</el-col>
@@ -91,7 +115,6 @@
<el-radio-button label="Nose Wheel"></el-radio-button>
<el-radio-button label="Center"></el-radio-button>
</el-radio-group>
</el-col>
</el-row>
<el-row>
@@ -107,7 +130,14 @@
content="D.DDD, DMS, DM supported"
:disabled="!editing || calculate === 'Center'"
>
<el-input placeholder="Please input" v-model="coordinates" slot="reference" :disabled="!editing || calculate ==='Center'"></el-input>
<el-input
placeholder="Please input"
v-model="coordinates"
slot="reference"
:disabled="!editing || calculate === 'Center'"
@focus="coordFocussed = true"
@blur="coordFocussed = false"
></el-input>
</el-popover>
</el-col>
</el-row>
@@ -124,7 +154,14 @@
content="D.DDD, DMS, DM supported"
:disabled="!editing || calculate === 'Nose Wheel'"
>
<el-input placeholder="Please input" v-model="noseCoordinates" slot="reference" :disabled="!editing || calculate === 'Nose Wheel'"></el-input>
<el-input
placeholder="Please input"
v-model="noseCoordinates"
slot="reference"
:disabled="!editing || calculate === 'Nose Wheel'"
@focus="noseCoordFocussed = true"
@blur="noseCoordFocussed = false"
></el-input>
</el-popover>
</el-col>
</el-row>
@@ -139,13 +176,14 @@
:max="720"
:step="0.1"
:precision="1"
:disabled="!editing || calculate ==='Heading'"
:disabled="!editing || calculate === 'Heading'"
@change="headingChange"
></el-input-number>
</el-col>
<el-col :span="4">
<el-button @click="rotate" class="button">
<i class="fas fa-ruler-combined"></i>
</el-button>
<el-button @click="rotate" class="button">
<i class="fas fa-ruler-combined"></i>
</el-button>
</el-col>
</el-row>
<el-row>
@@ -153,7 +191,11 @@
<span class="label">Parking Type :</span>
</el-col>
<el-col :span="17">
<el-select v-model="parking_type" placeholder="Select" :disabled="!editing">
<el-select
v-model="parking_type"
placeholder="Select"
:disabled="!editing"
>
<el-option
v-for="type in options"
:key="type.value"
@@ -169,7 +211,12 @@
<span class="label">Airline :</span>
</el-col>
<el-col :span="17">
<el-select v-model="airlineCodes" multiple placeholder="Select" :disabled="!editing">
<el-select
v-model="airlineCodes"
multiple
placeholder="Select"
:disabled="!editing"
>
<el-option
v-for="item in airlines"
:key="item.value"
@@ -183,7 +230,7 @@
<el-col :span="7">
<span class="label">Pushback Route End :</span>
</el-col>
<el-col :span="17">{{pushbackEnd}}</el-col>
<el-col :span="17">{{ pushbackEnd }}</el-col>
</el-row>
</div>
</template>
@@ -191,13 +238,30 @@
<script lang="js">
/* eslint-disable */
const convert = require('geo-coordinates-parser');
const turf = require('@turf/turf');
const turfOptions = { units: 'kilometers' };
export default {
mounted() {
this.$store.watch(
function (state) {
return state.Editable.data.parking;
},
() => { this.editedParking() }
,
{
deep: true //add this if u need to watch object properties change etc.
}
);
},
methods: {
editedParking() {
this.externalChange = true
this.heading = Number(this.$store.state.Editable.data.parking.heading);
this.externalChange = false
},
rotate() {
var heading = this.$store.state.Editable.data.parking.heading + 90;
while (heading>=360) {
@@ -215,18 +279,21 @@
while (newValue<0) {
newValue += 360
}
if (Number(this.$store.state.Editable.data.parking.heading) !== newValue) {
this.$store.commit('SET_EDIT_PARKING_HEADING', newValue)
}
if(this.calculate === 'Center') {
// we change center
const noseWheelLatLng = convert(this.noseWheel);
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
if (parkingSize>=0) {
var reverseHeading = this.normalizeAngle(this.$store.state.Editable.data.parking.heading+180);
var newCenter = turf.destination(this.latToTurf(noseWheelLatLng), this.validN2M[parkingSize]/1000, reverseHeading, turfOptions);
this.$store.commit('SET_EDIT_PARKING_COORDS', this.turfToLatLng(newCenter));
}
if ( ( Math.abs( this.$store.state.Editable.data.parking.heading - newValue ) >= 0 && Math.abs( this.$store.state.Editable.data.parking.heading - newValue ) <= 0.1 )
|| !this.externalChange) {
if (Number(this.$store.state.Editable.data.parking.heading) !== newValue) {
this.$store.commit('SET_EDIT_PARKING_HEADING', newValue)
}
if(this.calculate === 'Center') {
// we change center
const noseWheelLatLng = convert(this.$store.state.Editable.data.parking.nosecoords);
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
if (parkingSize>=0) {
var reverseHeading = this.normalizeAngle(this.$store.state.Editable.data.parking.heading+180);
var newCenter = turf.destination(this.latToTurf(noseWheelLatLng), this.validN2M[parkingSize]/1000, reverseHeading, turfOptions);
this.$store.commit('SET_EDIT_PARKING_COORDS', this.turfToLatLng(newCenter));
}
}
}
},
show (idx) {
@@ -244,35 +311,41 @@
latToTurf (turfPoint) {
return [turfPoint.decimalLongitude, turfPoint.decimalLatitude];
},
turfToLatLng: function (turfPoint) {
turfToLatLng (turfPoint) {
return '' + turfPoint.geometry.coordinates[1].toFixed(6) + ',' + turfPoint.geometry.coordinates[0].toFixed(6);
},
beautify (coordString) {
var a = coordString.split(' ');
if (a.length === 2) {
return '' + Number(a[0]).toFixed(6) + ' ' + Number(a[1]).toFixed(6);
} else {
return coordString;
}
},
calcWheel () {
var centerCoords = convert(this.$store.state.Editable.data.parking.coords);
if(this.calculate === 'Nose Wheel') {
// we change center
const centerLatLng = convert(this.$store.state.Editable.data.parking.coords);
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
if(this.calculate === 'Nose Wheel') {
// we change nosewheel
const centerLatLng = convert(this.beautify(this.$store.state.Editable.data.parking.coords));
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
if (parkingSize>=0) {
var newNoseWheel = turf.destination(this.latToTurf(centerLatLng), this.validN2M[parkingSize]/1000, this.$store.state.Editable.data.parking.heading, turfOptions);
this.$store.commit('SET_EDIT_PARKING_NOSE_COORDS', this.turfToLatLng(newNoseWheel));
}
}
}
},
calcCenter () {
var centerCoords = convert(this.$store.state.Editable.data.parking.coords);
if (this.calculate === 'Center') {
if (this.calculate === 'Center') {
// we change center
const noseWheelLatLng = convert(this.$store.state.Editable.data.parking.nosecoords);
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
const noseWheelLatLng = convert(this.beautify(this.$store.state.Editable.data.parking.nosecoords));
const parkingSize = this.validRadii.indexOf(this.$store.state.Editable.data.parking.radius);
if (parkingSize>=0) {
var newCenter = turf.destination(this.latToTurf(noseWheelLatLng), this.validN2M[parkingSize]/1000, this.$store.state.Editable.data.parking.heading - 180, turfOptions);
this.$store.commit('SET_EDIT_PARKING_COORDS', this.turfToLatLng(newCenter));
}
}
}
}
},
data () { return {calculateState: 'Nose Wheel', noseWheel: '', validRadii: [7.5, 10, 14, 18, 26, 33, 40], validN2M: [5, 5, 6, 10, 15, 24, 24] } },
data () { return {rotateFocussed: false, externalChange: false, coordFocussed: false, noseCoordFocussed: false, calculateState: 'Nose Wheel', noseWheel: '', validRadii: [7.5, 10, 14, 18, 26, 33, 40], validN2M: [5, 5, 6, 10, 15, 24, 24], heading: 0 }},
computed: {
editing: {
get: function () {
@@ -298,16 +371,16 @@
},
airlineCodes: {
// getter
get: function () {
get: function () {
var codes = this.$store.state.Editable.data.parking.airlineCodes
if (Array.isArray(codes)) {
return codes
} else if (codes !== undefined && typeof codes === 'string') {
return codes.split(',')
return codes.split(',')
} else {
return []
}
return
return
},
// setter
set: function (newValue) {
@@ -341,9 +414,9 @@
set: function (newValue) {
this.calculateState = newValue;
if (newValue==='Center') {
this.calcWheel();
} else {
this.calcCenter();
} else {
this.calcWheel();
}
}
},
@@ -357,12 +430,14 @@
// setter
set: function (newValue) {
if (newValue==='unknown') {
}
}
if( newValue.match(/,/g) !== null && newValue.match(/,/g).length === 3) {
newValue = newValue.replace(', ', ' ').replace(/,/g, '.').replace(' ', ', ');
}
this.$store.commit('SET_EDIT_PARKING_COORDS', newValue)
}
if (this.coordFocussed) {
this.$store.commit('SET_EDIT_PARKING_COORDS', newValue)
}
this.calcWheel();
}
},
@@ -370,31 +445,26 @@
// getter
get: function () {
if(this.$store.state.Editable.index!==undefined) {
if(!this.$store.state.Editable.data.parking.nosecoords && this.calculate === 'Nose Wheel') {
this.calcWheel();
}
return this.$store.state.Editable.data.parking.nosecoords;
}
},
// setter
set: function (newValue) {
if (newValue==='unknown') {
}
}
if( newValue.match(/,/g) !== null && newValue.match(/,/g).length === 3) {
newValue = newValue.replace(', ', ' ').replace(/,/g, '.').replace(' ', ', ');
}
this.$store.commit('SET_EDIT_PARKING_NOSE_COORDS', newValue);
if (this.noseCoordFocussed) {
this.$store.commit('SET_EDIT_PARKING_NOSE_COORDS', newValue);
}
this.calcCenter();
}
},
heading: {
// getter
get: function () {
return Number(this.$store.state.Editable.data.parking.heading)
},
// setter
set: function (newValue) {
this.headingChange(newValue)
}
},
wingspan: {
// getter
get: function () {

View File

@@ -11,7 +11,7 @@
radius: 18
type: "gate"
-->
<!--
<!--
<el-row>
<el-col :span="4">
<span class="label">Name :</span>
@@ -90,13 +90,12 @@
</el-button>
</el-col>
</el-row>
<!--
<el-row>
<el-col :span="7">
<span class="label">Parking Type :</span>
</el-col>
<el-col :span="17">
<el-select v-model="parking_type" placeholder="Select" :disabled="!editing">
<el-select v-model="parking_type" @change="typeChange" placeholder="Select" :disabled="!editing">
<el-option
v-for="type in options"
:key="type.value"
@@ -107,6 +106,7 @@
</el-select>
</el-col>
</el-row>
<!--
<el-row>
<el-col :span="7">
<span class="label">Airline :</span>
@@ -128,15 +128,15 @@
<script lang="js">
/* eslint-disable */
import Vue from 'vue'
import Vue from 'vue'
const convert = require('geo-coordinates-parser');
const Coordinates = require('coordinate-parser');
export default {
export default {
data () {
return {
data: Object, avgHeading: 5, editing: Boolean, wingspan: 0
data: Object, avgHeading: 5, editing: Boolean, wingspan: 0, parking_type: ''
}
},
@@ -153,10 +153,11 @@ const convert = require('geo-coordinates-parser');
},
show (idx) {
this.$parent.$parent.$parent.$refs.editLayer.show(idx)
},
},
setData (data) {
this.data = data;
this.setAvgHeading();
this.setAvgType();
},
setEditing(editing) {
this.editing = editing
@@ -164,18 +165,29 @@ const convert = require('geo-coordinates-parser');
setAvgHeading() {
if( this.data === null || this.data === undefined) {
return 0
}
}
this.avgHeading = Number( this.data.reduce(function (r, parking) {
r.sum = r.sum + parking.options.attributes.heading;
r.avg = r.sum / ++r.count;
return r;
}, { sum: 0, count: 0, avg: 0 }).avg);
},
}, { sum: 0, count: 0, avg: 0 }).avg);
},
setAvgType() {
if( this.data === null || this.data === undefined) {
return 0
}
var types = this.data.map(parking => parking.options.attributes.type).filter((v, i, a) => a.indexOf(v) === i);
if (types.length == 1) {
this.parking_type = types[0];
} else {
this.parking_type = '';
}
},
wingspanChange( newValue ) {
if ( newValue ) {
this.$emit('editParking', {type: 'parking-group-wingspan', wingspan: newValue} )
}
},
},
headingChange( newValue ) {
while (newValue>=360) {
newValue -= 360
@@ -186,9 +198,14 @@ const convert = require('geo-coordinates-parser');
if ( newValue ) {
this.$emit('editParking', {type: 'parking-group-angle', angle: newValue} )
}
},
typeChange( newValue ) {
if ( newValue ) {
this.$emit('editParking', {type: 'parking-group-type', parking_type: newValue} )
}
}
},
computed: {
computed: {
parking: function () {
return this.data !== null && this.$store.state.Editable.type === 'parking-group'
@@ -209,7 +226,7 @@ const convert = require('geo-coordinates-parser');
},
airlineCodes: {
// getter
get: function () {
get: function () {
},
// setter
set: function (newValue) {
@@ -271,19 +288,6 @@ const convert = require('geo-coordinates-parser');
{value: 'mil-fighter', label: 'military fighter'},
{value: 'mil-cargo', label: 'military cargo'}
]
},
parking_type: {
// getter
get: function () {
if (this.$store.state.Editable.data.parking.type === undefined) {
return 'none'
}
return this.$store.state.Editable.data.parking.type
},
// setter
set: function (newValue) {
this.$store.commit('SET_EDIT_PARKING_TYPE', newValue)
}
}
}
}

View File

@@ -1,6 +1,17 @@
<!--
Copyright 2021 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
-->
<template>
<div>
<el-link v-if="!editing" type="primary" @click="show(parking.index)">{{parking.name}} {{number}} {{parking.type}}</el-link>
<el-link v-if="!editing" type="primary" @click="show(parking.index)">{{parking.name}} {{number}} {{parking.type}} {{type}}</el-link>
<el-input @focus="show(parking.index)" v-if="editing" placeholder="Name" v-model="name" class="wide"></el-input>
<el-input @focus="show(parking.index)" v-if="editing" placeholder="Number" v-model="number" class="narrow"></el-input>
<el-select @focus="show(parking.index)" v-if="editing" v-model="parking_type" placeholder="Select">
@@ -73,7 +84,11 @@
number: {
// getter
get: function () {
return this.parking.number
if (this.parking.number && this.parking.number !== 'undefined') {
return this.parking.number
} else {
return ''
}
},
// setter
set: function (newValue) {
@@ -92,8 +107,36 @@
set: function (newValue) {
this.$store.commit('SET_EDIT_PARKING_ITEM_TYPE', [this.parking.index, newValue])
}
}
},
type: function () {
/**
* Cat Models FG Radii N2M Radii
* B Small Regionals ERJ CRJ ATR 14 6
* C A319 A320 A321 B737 18 10
* D B757, B767 26 15
* E B777 B787 A330 A340 A360 33 24
* F A380 40 24
*/
switch (this.parking.radius * 2) {
case 15:
return 'Piper J-3 Cub/Cessna 172'
case 20:
return 'Beech 200/Cessna 425'
case 28:
return 'BOMBARDIER Regional Jet CRJ-200/DE HAVILLAND CANADA DHC-6'
case 36:
return 'BOEING 737-700/AIRBUS A-320/EMBRAER ERJ 190-100'
case 52:
return 'B767 Series/AIRBUS A-310'
case 66:
return 'B777 Series/B787 Series/A330 Family'
case 80:
return 'BOEING 747-8/AIRBUS A-380-800'
default:
return 'Unknown radius : ' + this.parking.radius
}
}
}
}
</script>

View File

@@ -16,11 +16,8 @@
<script lang="js">
// import scanner from '../utils/scan'
import fileUrl from 'file-url'
import {Table, TableColumn} from 'element-ui'
const path = require('path')
export default {
name: 'search',
components: { [Table.name]: Table,
@@ -36,7 +33,7 @@
},
methods: {
goto (icao) {
console.log(icao)
console.debug('Goto : ' + icao)
let airports = this.$store.state.Airports.airports
.filter(a => a.properties.icao.match(icao))
if (airports.length > 0) {
@@ -46,87 +43,11 @@
formatter (row, column) {
console.log('Row ' + row)
return row
},
scanAPT () {
try {
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080/src/renderer/utils/worker.js`
: `file://${__dirname}/worker.js`
console.log('make a worker: ', path.resolve(__dirname, 'worker.js'))
const worker = new Worker(winURL)
console.log(fileUrl('src/renderer/utils/worker.js'))
// var worker = new Worker(fileUrl('src/renderer/utils/worker.js'))
worker.postMessage(['scanapt'])
// the reply
var store = this.$store
worker.onmessage = function (e) {
if (e.data === 'DONE') {
console.log('DONE')
store.dispatch('getAirports')
worker.terminate()
}
console.log(e.data)
}
} catch (err) {
console.error(err)
}
},
scanGroundnets () {
try {
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080/src/renderer/utils/worker.js`
: `file://${__dirname}/worker.js`
console.log('make a worker: ', path.resolve(__dirname, 'worker.js'))
const worker = new Worker(winURL)
console.log(fileUrl('src/renderer/utils/worker.js'))
worker.postMessage(['scan', this.$store.state.Settings.settings.airportsDirectory])
// the reply
var store = this.$store
worker.onmessage = function (e) {
if (e.data === 'DONE') {
console.log('DONE')
store.dispatch('getAirports')
worker.terminate()
}
console.log(e.data)
}
} catch (err) {
console.error(err)
}
},
scanTraffic () {
// let flightgearDirectory = this.$store.state.settings.flightgearDirectory
try {
const winURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080/src/renderer/utils/worker.js`
: `file://${__dirname}/worker.js`
console.log('make a worker: ', path.resolve(__dirname, 'worker.js'))
const worker = new Worker(winURL)
console.log(fileUrl('src/renderer/utils/worker.js'))
worker.postMessage(['scanai', this.$store.state.Settings.settings.flightgearDirectory])
// the reply
var store = this.$store
worker.onmessage = function (e) {
if (e.data === 'DONE') {
console.log('DONE')
store.dispatch('getAirports')
worker.terminate()
}
console.log(e.data)
}
} catch (err) {
console.error(err)
}
}
},
computed: {
searched: function () {
console.log(this.searchterm)
console.debug('Search : ' + this.searchterm)
if (this.searchterm !== this.lastSearchTerm) {
let searchRegex = new RegExp(this.searchterm, 'i')
let result = this.$store.state.Airports.airports
@@ -136,10 +57,14 @@
.filter(a => searchRegex.test(a.properties.icao) || searchRegex.test(a.properties.name))
// .map(a => console.log(a.properties))
.map(a => ({ icao: a.properties.icao, name: a.properties.name }))
.filter((v, i, a) => a.findIndex(t => (t.icao === v.icao)) === i)
let icaoResult = result.filter(a => a.icao === this.searchterm).filter((v, i, a) => a.findIndex(t => (t.icao === v.icao)) === i)
if (result !== undefined &&
result.length === 0 &&
icaoResult.length === 0 &&
this.searchterm !== undefined &&
this.searchterm.length >= 3) {
this.searchterm.length >= 3 &&
this.searchterm.length <= 4) {
// Not found so it might have been excluded due to no traffic
this.$store.dispatch('getAirport', this.searchterm)
}
this.lastResult = result

View File

@@ -219,13 +219,25 @@
name: 'settings-panel',
components: { DirectorySelect, FileSelect },
props: [],
mounted () {
},
data () {
return { ok: true, activeName: '0' }
return { ok: true, activeName: '0', scanStoreLogging: false }
},
mounted () {
this.$store.watch(
function (state) {
return state.Settings.settings
},
() => { this.loggingChanged() }
,
{
deep: true // add this if u need to watch object properties change etc.
}
)
},
methods: {
loggingChanged () {
this.scanStoreLogging = this.$store.state.Settings.settings.scanLogging === 1
},
flightgearDirectorySelect: function (flightgearDirectory) {
console.log(flightgearDirectory)
this.$store.commit('FLIGHTGEAR_DIRECTORY', flightgearDirectory)
@@ -344,7 +356,7 @@
scanLogging: {
// getter
get: function () {
return this.$store.state.Settings.settings.scanLogging === 1
return this.scanStoreLogging
},
// setter
set: function (newValue) {

View File

@@ -3,6 +3,7 @@
<script lang="js">
import { LMap, LMarker } from 'vue2-leaflet'
import L from 'leaflet'
import leafletPattern from 'leaflet.pattern'
import LEdit from 'leaflet-editable/src/Leaflet.Editable.js'
import {readThresholdXML} from '../loaders/threshold_loader'
import {writeThresholdXML} from '../loaders/threshold_writer'
@@ -13,7 +14,7 @@
created () {
},
mounted () {
console.debug(LMap, LMarker, L, LEdit)
console.debug(LMap, LMarker, L, LEdit, leafletPattern)
this.$store.watch(
function (state) {
return state.Editable.data.threshold
@@ -24,6 +25,8 @@
deep: true
}
)
var stripes = new L.StripePattern({color: 'yellow'})
stripes.addTo(this.$parent.mapObject)
},
beforeDestroy () {
this.remove()
@@ -55,8 +58,11 @@
if (this.layerGroup) {
this.layerGroup.removeFrom(this.$parent.mapObject)
}
var stripes = new L.StripePattern({color: 'yellow'})
stripes.addTo(this.$parent.mapObject)
// Callback for add
this.layerGroup = readThresholdXML(this.$store.state.Settings.settings.airportsDirectory, icao, this.read)
this.layerGroup = readThresholdXML(this.$store.state.Settings.settings.airportsDirectory, icao, this.read, stripes)
if (!this.layerGroup) {
console.warn('Threshold for ICAO not loaded ' + icao)
return

View File

@@ -11,6 +11,12 @@ You should have received a copy of the GNU General Public License along with FG
-->
<template>
<div id="ToolBar">
<ToolButton
icon="far fa-eye"
v-on:click="showTooltips"
:show="editing"
tooltip="Show Tooltips"
></ToolButton>
<ToolButton
icon="fas fa-draw-polygon"
v-on:click="drawPolyline"
@@ -23,7 +29,7 @@ You should have received a copy of the GNU General Public License along with FG
<script lang="js">
/* eslint-disable */
import ToolButton from './ToolButton'
import Vue from 'vue'
import Vue from 'vue'
import fileUrl from 'file-url'
const path = require('path')
@@ -42,6 +48,9 @@ You should have received a copy of the GNU General Public License along with FG
this.$parent.$parent.$refs.toolLayer.stopDrawing()
this.$parent.$parent.$refs.toolLayer.drawPolyline()
},
showTooltips () {
this.$parent.$parent.$refs.editLayer.showTooltips()
},
setEditing (edit) {
this.isEditing = edit;
if(!this.isEditing) {

View File

@@ -6,6 +6,7 @@
import ToolControl from '../leaflet/ToolControl.js'
export default {
name: 'edit-bar',
components: { ToolControl, L },
props: {
icon: String,
show: Boolean,
@@ -22,8 +23,6 @@
}
},
mounted () {
console.debug(L)
console.debug(ToolControl)
this.add()
},
beforeDestroy () {

View File

@@ -6,8 +6,8 @@
<span class="label">Latitude :</span>
</el-col>
<el-col :span="17">
<el-input placeholder="Please input" v-model="latitude" :disabled="!editing"
@focus="coordFocussed = true"
<el-input placeholder="Please input" v-model="latitude" :disabled="true"
@focus="coordFocussed = true"
@blur="coordFocussed = false"></el-input>
</el-col>
</el-row>
@@ -16,8 +16,8 @@
<span class="label">Longitude :</span>
</el-col>
<el-col :span="17">
<el-input placeholder="Please input" v-model="longitude" :disabled="!editing"
@focus="coordFocussed = true"
<el-input placeholder="Please input" v-model="longitude" :disabled="true"
@focus="coordFocussed = true"
@blur="coordFocussed = false"></el-input>
</el-col>
</el-row>
@@ -26,9 +26,9 @@
<span class="label">Height :</span>
</el-col>
<el-col :span="17">
<el-input placeholder="Please input" v-model="height" :disabled="!editing"
@focus="coordFocussed = true"
@blur="coordFocussed = false"></el-input>
<el-input-number placeholder="Please input" @change="handleChange" v-model="height" :disabled="!editing" :step="0.01"
@focus="coordFocussed = true"
@blur="coordFocussed = false"></el-input-number>
</el-col>
</el-row>
</div>
@@ -59,12 +59,15 @@
save () {
var o = {latitude: this.latitude, longitude: this.longitude, height: this.height};
writeTowerXML(this.$store.state.Settings.settings.airportsDirectory, this.$parent.$parent.$parent.icao, o)
},
handleChange (newValue) {
this.$store.dispatch('setTowerHeight', newValue);
}
},
computed: {
editing: {
get: function () {
return false //this.$parent.$parent.$parent.$refs.editLayer.editing
return this.$parent.$parent.$parent.$refs.editLayer.editing
}
},
tower: function () {
@@ -77,8 +80,13 @@
longitude: function () {
return this.$store.state.Editable.data.tower.coords.longitude;
},
height: function () {
return this.$store.state.Editable.data.tower.coords.height;
height: {
get: function () {
return this.$store.state.Editable.data.tower.height;
},
set: function (newValue) {
this.$store.dispatch('setTowerHeight', newValue);
}
}
}
}

View File

@@ -25,7 +25,16 @@ You should have received a copy of the GNU General Public License along with FG
console.debug([LMap, LMarker, L, LEdit])
},
mounted () {
this.$store.watch(
function (state) {
return state.Editable.data.tower
},
() => { this.editedTower() }
,
{
deep: true
}
)
},
beforeDestroy () {
this.remove()
@@ -35,6 +44,15 @@ You should have received a copy of the GNU General Public License along with FG
}
},
methods: {
editedTower () {
if (this.$store.state.Editable.data.tower) {
this.layerGroup.eachLayer(l => {
if (l instanceof L.TowerMarker) {
l.setTowerHeight(this.$store.state.Editable.data.tower.height)
}
})
}
},
getLayer () {
return this.layerGroup
},
@@ -71,7 +89,7 @@ You should have received a copy of the GNU General Public License along with FG
if (this.layerGroup) {
this.layerGroup.eachLayer(l => {
if (l instanceof L.TowerMarker) {
l.enableEdit(this.$parent.mapObject)
l.setInteractive(true)
}
})
}
@@ -80,7 +98,7 @@ You should have received a copy of the GNU General Public License along with FG
if (this.layerGroup) {
this.layerGroup.eachLayer(l => {
if (l instanceof L.TowerMarker) {
l.enableEdit(this.$parent.mapObject)
l.setInteractive(false)
}
})
}

View File

@@ -0,0 +1,97 @@
<!--
Copyright 2021 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
-->
<template>
<div>
<el-radio-group v-model="direction">
<el-radio :label="departure"
><i class="fas fa-plane-departure"></i
></el-radio>
<el-radio :label="arrival"><i class="fas fa-plane-arrival"></i></el-radio>
</el-radio-group>
<el-collapse v-model="activeName" accordion ref="collapse">
<el-collapse-item
v-for="a in airlines"
v-bind:key="a.index"
class="row"
:title="a.label"
:name="a.label"
>
<AirlineItem :airline="a" ref="airline"></AirlineItem>
</el-collapse-item>
</el-collapse>
<el-popover
placement="top-start"
title="Add Test Traffic"
width="200"
trigger="hover"
content="Generate Testtraffic"
>
<el-button @click="generate" class="button" slot="reference">
<i class="fas fa-notes-medical"></i>
</el-button>
</el-popover>
</div>
</template>
<script lang="js">
import AirlineItem from './AirlineItem'
import {writeTrafficXML} from '../loaders/traffic_writer'
export default {
name: 'traffic-list',
components: {AirlineItem},
props: [],
data () {
return {
activeName: '',
departure: 0,
arrival: 1,
direction: 0,
activeIndex: '1',
activeIndex2: '1'
}
},
methods: {
generate () {
// .filter((f) => f.$children[0])
var aircraft = this.$refs.airline.flatMap((f) => {
console.debug(f.aircraft)
return f.aircraft
}
).filter(f => f)
writeTrafficXML(this.$store.state.Settings.settings.flightgearDirectory_traffic, this.$store.state.Parkings.items, aircraft)
}
},
computed: {
airlines: function () {
var airlineCodes = []
if (this.$store.state.Airports.currentAirport !== undefined && this.$store.state.Airports.currentAirport.airlines) {
var storedairlineCodes = this.$store.state.Airports.currentAirport.airlines
storedairlineCodes.forEach(element => {
airlineCodes.push({value: element, label: element})
})
}
return airlineCodes.filter((v, i, a) => a.indexOf(v) === i)
}
}
}
</script>
<style>
div.row.div {
display: flex;
justify-content: space-between;
}
</style>

View File

@@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with FG
<span class="center">E-Mail : {{this.$store.state.Settings.settings.email}}</span><br/>
<span class="center"><el-checkbox v-model="gplv2" class="center">I agree to release the groundnet under GPL v2</el-checkbox></span><br/>
<span :class="textClass" v-if="message">{{message}}</span><br/>
<el-button @click="handleOkClicked('twr')" :disabled="!tower_comittable" >Upload Tower</el-button>
<el-button @click="handleOkClicked('groundnet')" :disabled="!groundnet_comittable" >Upload Groundnet</el-button>
<el-button @click="handleOkClicked('threshold')" :disabled="!threshold_comittable" >Upload Threshold</el-button>
@@ -47,8 +47,8 @@ You should have received a copy of the GNU General Public License along with FG
function (state) {
return state.Loading.groundnetLoaded;
},
() => { if(this.$store.state.Loading.groundnetLoaded &&
this.$store.state.Loading.pavementLoaded &&
() => { if(this.$store.state.Loading.groundnetLoaded &&
this.$store.state.Loading.pavementLoaded &&
this.visible) this.check() }
,
{
@@ -59,8 +59,8 @@ You should have received a copy of the GNU General Public License along with FG
function (state) {
return state.Loading.pavementLoaded;
},
() => { if(this.$store.state.Loading.groundnetLoaded &&
this.$store.state.Loading.pavementLoaded &&
() => { if(this.$store.state.Loading.groundnetLoaded &&
this.$store.state.Loading.pavementLoaded &&
this.visible) this.check() }
,
{
@@ -76,13 +76,17 @@ You should have received a copy of the GNU General Public License along with FG
},
methods: {
reqListener(e) {
if(JSON.parse(e.srcElement.response).status==='OK') {
this.message = null;
this.azure = true;
this.error = false;
} else {
this.message = 'Azure down';
}
try {
if(JSON.parse(e.srcElement.response).status==='OK') {
this.message = null;
this.azure = true;
this.error = false;
} else {
this.message = 'Azure down';
}
} catch (error) {
console.error(error);
}
},
status () {
@@ -96,15 +100,15 @@ You should have received a copy of the GNU General Public License along with FG
if (xhr.status !== 200){
parent.$refs.upload.message = 'Azure down';
parent.$refs.upload.error = true;
console.error(xhr);
console.error(xhr);
}
}
xhr.addEventListener("load", this.reqListener);
xhr.addEventListener("load", this.reqListener);
try {
xhr.send();
xhr.send();
} catch (err) {
console.error(err);
this.error = true;
this.error = true;
}
},
closeClicked () {
@@ -113,10 +117,10 @@ You should have received a copy of the GNU General Public License along with FG
},
handleOkClicked (type) {
this.uploading = true;
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
this.icao + `.${type}.new.xml`);
if (f == null || !fs.existsSync(f)) {
@@ -136,7 +140,7 @@ You should have received a copy of the GNU General Public License along with FG
formData.append("gpl", this.gplv2 )
formData.append("user_email", this.$store.state.Settings.settings.email)
formData.append('groundnet', blob, this.icao + `.${type}.xml`);
var parent = this.$parent;
var messageField = this.message;
// action after uploading happens
@@ -144,7 +148,7 @@ You should have received a copy of the GNU General Public License along with FG
if (xhr.status !== 200){
parent.$refs.upload.message = 'Upload Error'
parent.$refs.upload.error = true;
console.error(xhr);
console.error(xhr);
}
}
xhr.onload = function(e) {
@@ -157,7 +161,7 @@ You should have received a copy of the GNU General Public License along with FG
parent.$refs.upload.success = true
parent.$refs.upload.message = `${type} Uploaded Successfully`
parent.$store.commit('UPLOAD_WIP', parent.$store.state.Airports.currentAirport.icao)
} else if(JSON.parse(e.srcElement.response).message === 'XML Errors') {
var response = JSON.parse(e.srcElement.response);
if (response.validationErrors) {
@@ -169,7 +173,7 @@ You should have received a copy of the GNU General Public License along with FG
} else if(JSON.parse(e.srcElement.response) !== undefined) {
var response = JSON.parse(e.srcElement.response);
parent.$refs.upload.message = response.err;
} else {
} else {
parent.$refs.upload.message = response.message;
}
};
@@ -177,7 +181,7 @@ You should have received a copy of the GNU General Public License along with FG
// do the uploading
console.log("File uploading started!");
xhr.send(formData);
xhr.send(formData);
},
pollData () {
var workery = this.worker
@@ -193,7 +197,7 @@ You should have received a copy of the GNU General Public License along with FG
},
check () {
try {
if(!(this.$store.state.Loading.groundnetLoaded &&
if(!(this.$store.state.Loading.groundnetLoaded &&
this.$store.state.Loading.pavementLoaded)) {
return
}
@@ -236,7 +240,7 @@ You should have received a copy of the GNU General Public License along with FG
console.log(l)
pavement.push(l)
})
var features2 = pavement.map(mapper.checkMapper).filter(n => n)
var features2 = pavement.map(mapper.checkMapper).filter(n => n)
worker.postMessage(['check', features.concat(features2) ] )
this.pollData()
@@ -251,7 +255,7 @@ You should have received a copy of the GNU General Public License along with FG
worker.terminate()
worker.view.max = 0
worker.view.checkDialogVisible = false
clearInterval(this.polling)
clearInterval(this.polling)
this.checking = false
} else if (e.data.length > 0) {
if (e.data[0] === 'max') {
@@ -275,7 +279,7 @@ You should have received a copy of the GNU General Public License along with FG
return parent.$refs.editLayer;
}
}
},
},
pavementLayer () {
var parent = this.$parent;
while (!parent.icao||parent.$refs.pavementLayer==undefined) {
@@ -284,7 +288,7 @@ You should have received a copy of the GNU General Public License along with FG
return parent.$refs.pavementLayer;
}
}
}
}
},
computed: {
visible: {
@@ -300,7 +304,7 @@ You should have received a copy of the GNU General Public License along with FG
textClass: function () {
return !this.error?'centermessage':'error'
},
title: function () {
title: function () {
return `Upload ${this.icao} to groundweb.`
},
icao: {
@@ -319,26 +323,26 @@ You should have received a copy of the GNU General Public License along with FG
}
},
tower_comittable: function () {
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
this.icao + '.twr.new.xml');
return fs.existsSync(f) && this.gplv2 && this.max === 0 && this.azure && !this.uploading;
},
groundnet_comittable: function () {
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
this.icao + '.groundnet.new.xml');
return fs.existsSync(f) && this.$store.state.Check.results.filter(a => a.id>=0).length === 0 && this.gplv2 && this.max === 0 && this.azure && !this.uploading
},
threshold_comittable: function () {
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
var f = path.join(this.$store.state.Settings.settings.airportsDirectory,
this.icao[0],
this.icao[1],
this.icao[2],
this.icao + '.threshold.new.xml');
return fs.existsSync(f) && this.gplv2 && this.max === 0 && this.azure && !this.uploading
},
@@ -354,8 +358,8 @@ You should have received a copy of the GNU General Public License along with FG
<style scoped lang="scss">
.el-dialog__body {padding: 10px;}
.center { text-align: center; vertical-align: middle; padding: 5px; font-size: 12pt; font-weight: normal}
.centermessage { text-align: left; vertical-align: middle; padding: 5px; font-size: 12pt; font-weight: normal; white-space: pre-line;}
.center { text-align: center; vertical-align: middle; padding: 5px; font-size: 12pt; font-weight: normal}
.centermessage { text-align: left; vertical-align: middle; padding: 5px; font-size: 12pt; font-weight: normal; white-space: pre-line;}
.error { text-align: center; color: red; padding: 5px; font-size: 12pt; font-weight: normal;}
.el-dialog--center .el-dialog__body { padding: 5px;}
</style>

View File

@@ -0,0 +1,41 @@
/*
Copyright 2021 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
*/
/* eslint-disable */
const turf = require('@turf/turf')
L.TakeoffPolygon = L.Polygon.extend({
turfyRunway: [],
setTurfy: function (padPoints) {
var latLngs = padPoints.map(this.turfToLatLng);
latLngs.push(latLngs[0]);
this.turfyRunway = turf.polygon([latLngs]);
},
turfToLatLng: function (turfPoint) {
return [turfPoint.lng, turfPoint.lat];
}
});
var takeoffPadPoly = function (padPoints) {
var takeoffPadPoly = new L.TakeoffPolygon(padPoints);
takeoffPadPoly.setStyle({ color: 'black', fillColor: '', opacity: 1.0, fillOpacity: 0.0, interactive: false });
takeoffPadPoly.setTurfy(padPoints);
console.debug(padPoints);
return takeoffPadPoly;
}
module.exports = takeoffPadPoly;

View File

@@ -11,7 +11,7 @@ L.HoldNode = L.Marker.extend({
if(this._icon!==null) {
this._icon.childNodes[0].style['background-color'] = 'red';
}
},
},
deselect() {
if(this._icon!==null) {
this._icon.childNodes[0].style['background-color'] = '#4838cc';
@@ -31,7 +31,7 @@ L.HoldNode = L.Marker.extend({
this.featureLookup[this.glueindex].push(this);
},
/**
*
*
*/
follow(dragIndex, event) {
@@ -61,18 +61,18 @@ L.HoldNode = L.Marker.extend({
element.updateEndVertex(event.latlng);
element.updateMiddle();
}
} else if (element instanceof L.Editable.VertexMarker) {
} else if (element instanceof L.Editable.VertexMarker) {
console.log(element);
element.setLatLng(event.latlng);
element.latlngs.forEach((latlng, index) => {
console.log(latlng);
console.log(latlng);
if(latlng.__vertex === element) {
latlng.update(event.latlng);
}
});
element.editor.feature.setLatLngs(element.latlngs);
element.editor.feature.updateMiddle();
}
}
}
})
}
@@ -80,7 +80,7 @@ L.HoldNode = L.Marker.extend({
var holdNode = function (n, layerGroup) {
//console.log(n.attr('lat') + " " + n.attr('lon'));
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
var fa_icon = null;
if (n.attr('holdPointType') === 'PushBack') {
fa_icon = "<div style='background-color:#4838cc;' class='marker-pin'></div><i class='fas fa-arrows-alt-h'></i>";
@@ -93,8 +93,9 @@ var holdNode = function (n, layerGroup) {
iconSize: [30, 42],
iconAnchor: [15, 42]
});
const node = new L.HoldNode([latlon.decimalLatitude, latlon.decimalLongitude], { icon: icon });
const node = new L.HoldNode([latlon.decimalLatitude, latlon.decimalLongitude], { icon: icon });
node.glueindex = n.attr('index');
node.feature = { properties: { searchTerm: n.attr('index')}};
node.holdPointType = n.attr('holdPointType');
node.addTo(layerGroup);
node.addListeners();

View File

@@ -25,10 +25,10 @@ L.ParkingSpot = L.Circle.extend({
if (this.direction === undefined ) {
var center = this._latlng;
var options = { units: 'kilometers' };
var start = turf.destination([center.lng, center.lat], this.options.attributes.radius / 1000, this.normalizeAngle(this.options.attributes.heading+180), options);
var end = turf.destination([center.lng, center.lat], this.options.attributes.radius / 1000, this.normalizeAngle(this.options.attributes.heading), options);
// Resize, since leaflet is wrong
// Resize, since leaflet is wrong
var rad2 = center.distanceTo(this.turfToLatLng(end), options);
console.debug('Dist ', center, [center.lng, center.lat], end.geometry.coordinates, this.options.attributes.radius, rad2);
this.setRadius(rad2);
@@ -53,7 +53,7 @@ L.ParkingSpot = L.Circle.extend({
try {
console.debug("Update Middle ", this.editor.editLayer._layers[0]);
var o = this.editor.editLayer._layers;
console.debug(o);
for (var key in o) {
if (o.hasOwnProperty(key)) {
@@ -63,7 +63,7 @@ L.ParkingSpot = L.Circle.extend({
console.debug(o[key] == this.direction);
if (this.editor._resizeLatLng.__vertex!=o[key] &&
o[key] != this.direction &&
o[key] != this.frontWheel &&
o[key] != this.frontWheel &&
o[key] != this.box) {
o[key].setLatLng(this.getLatLng());
}
@@ -72,9 +72,9 @@ L.ParkingSpot = L.Circle.extend({
//Object.values(o);
/*
.forEach(vertex => {
console.debug(this.editor._resizeLatLng.__vertex==vertex);
console.debug(this.editor._resizeLatLng.__vertex==vertex);
});
*/
*/
} catch (error) {
console.error(error);
}
@@ -85,17 +85,21 @@ L.ParkingSpot = L.Circle.extend({
},
updateHeading(heading) {
this.options.attributes.heading = heading;
this.updateVertexFromDirection();
this.updateWheelPos();
this.updateVertexFromDirection();
this.updateWheelPos();
this.updateBox();
},
updateRadius(radius) {
this._mRadius = radius;
this.updateDirectionFromVertex();
this.updateVertexFromDirection();
this.updateWheelPos();
this.updateDirectionFromVertex();
this.updateVertexFromDirection();
this.updateWheelPos();
this.updateBox();
},
updateType(type) {
this.options.attributes.type = type;
this.deselect();
},
// Update the direction vertex from the direction
updateVertexFromDirection() {
if (this.editEnabled()) {
@@ -131,14 +135,15 @@ L.ParkingSpot = L.Circle.extend({
updateWheelPos() {
var start = this._latlng;
var options = { units: 'kilometers' };
const parkingSize = validRadii.indexOf(this.options.attributes.radius);
const parkingSize = validRadii.indexOf(this.options.attributes.radius);
if (parkingSize>=0) {
var frontWheelEnd = turf.destination([start.lng, start.lat], validN2M[parkingSize] / 1000, this.options.attributes.heading, options);
if(this.frontWheel!==undefined) {
this.frontWheel.setLatLng(this.turfToLatLng(frontWheelEnd));
return this.turfToLatLng(frontWheelEnd);
}
}
}
},
updateBox() {
var start = [this._latlng.lng, this._latlng.lat];
@@ -176,7 +181,7 @@ L.ParkingSpot = L.Circle.extend({
var latlngs = [leftBack, rightBack, rightMiddle, rightIntermediate, rightFront, leftFront, leftIntermediate, leftMiddle].map(l => this.turfToLatLng(l));
this.box = L.polygon(latlngs);
//this.box.addTo(this.editor.editLayer);
this.box._parkingSpot = this;
this.box._parkingSpot = this;
this.box.on('click', function (event) {
console.debug("Click Parking Box : " + event.target);
if (Number(store.default.state.Editable.index) >= 0 &&
@@ -188,7 +193,7 @@ L.ParkingSpot = L.Circle.extend({
}
});
}
event.target._parkingSpot.select();
event.target._parkingSpot.select();
});
if(this.editor && this.editor.editLayer) {
this.box.addTo(this.editor.editLayer);
@@ -199,7 +204,7 @@ L.ParkingSpot = L.Circle.extend({
console.debug(latlngs);
this.box.setLatLngs(latlngs);
}
}
}
},
normalizeAngle( angle ) {
if(angle >= 180) {
@@ -217,21 +222,37 @@ L.ParkingSpot = L.Circle.extend({
style['color'] = 'red';
this.setStyle(style);
if(this.direction) {
this.direction.setStyle(style);
this.direction.setStyle(style);
this.frontWheel.setStyle(style);
}
this.updateWheelPos();
var wheelPos = this.updateWheelPos();
if(wheelPos) {
store.default.dispatch('setParkingNoseCoords', wheelPos.lat.toFixed(6) + ' ' + wheelPos.lng.toFixed(6));
}
this.updateBox();
if(this.box) {
if(this.box) {
this.box.setStyle(style);
}
},
},
deselect() {
var style = {};
style['color'] = '#3388ff';
if(this.options.attributes.type == 'ga') {
style['color'] = 'green';
} else if(this.options.attributes.type == 'cargo') {
style['color'] = 'yellow';
} else if(this.options.attributes.type == 'gate') {
style['color'] = '#3388ff';
} else if(this.options.attributes.type == 'mil-fighter') {
style['color'] = 'red';
} else if(this.options.attributes.type == 'mil-cargo') {
style['color'] = 'DarkRed';
} else {
style['color'] = '#3388ff';
}
this.setStyle(style);
if(this.direction) {
this.direction.setStyle(style);
this.direction.setStyle(style);
this.frontWheel.setStyle(style);
}
this.updateWheelPos();
@@ -242,17 +263,17 @@ L.ParkingSpot = L.Circle.extend({
},
setInteractive(interactive) {
if (interactive) {
if(this.direction) {
if(this.direction&&this.direction._path) {
L.DomUtil.addClass(this.direction._path, 'leaflet-interactive');
}
if(this.box) {
if(this.box&&this.box._path) {
L.DomUtil.addClass(this.box._path, 'leaflet-interactive');
}
} else {
if(this.direction) {
if(this.direction&&this.direction._path) {
L.DomUtil.removeClass(this.direction._path, 'leaflet-interactive');
}
if(this.box) {
if(this.box&&this.box._path) {
L.DomUtil.removeClass(this.box._path, 'leaflet-interactive');
}
}
@@ -267,11 +288,11 @@ L.ParkingSpot = L.Circle.extend({
event.target.updateVertexFromDirection();
event.target.updateWheelPos();
event.target.updateBox();
this.follow(event.target.id, event);
this.follow(event.target.id, event);
}
else if(event.target.editor._resizeLatLng.__vertex._icon === event.sourceTarget._element) {
event.target.updateDirectionFromVertex();
event.target.updateVertexFromDirection();
event.target.updateDirectionFromVertex();
event.target.updateVertexFromDirection();
event.target.updateWheelPos();
event.target.updateBox();
}
@@ -290,14 +311,15 @@ L.ParkingSpot = L.Circle.extend({
event.target.box.removeFrom(event.target._map);
}
});
this.on('editable:vertex:drag', function (event) {
this.on('editable:vertex:drag', function (event) {
console.debug("Drag Parking : ", event);
});
this.on('editable:vertex:dragend', function (event) {
console.debug("DragEnd Parking : ", event);
store.default.dispatch('setParking', event.target.options.attributes);
store.default.dispatch('setParkingCoords', event.target.getLatLng().lat.toFixed(6) + ' ' + event.target.getLatLng().lng.toFixed(6));
event.target.updateWheelPos();
var wheelPos = event.target.updateWheelPos();
store.default.dispatch('setParkingNoseCoords', wheelPos.lat.toFixed(6) + ' ' + wheelPos.lng.toFixed(6));
event.target.updateBox();
/*
store.default.dispatch('setParkingHeading', this.options.attributes.heading)
@@ -314,8 +336,8 @@ L.ParkingSpot = L.Circle.extend({
}
});
}
event.target.select();
});
event.target.select();
});
this.on('editable:vertex:clicked', function (event) {
console.debug(this.featureLookup[event.vertex.glueindex]);
if (Number(store.default.state.Editable.index) >= 0 &&
@@ -330,14 +352,14 @@ L.ParkingSpot = L.Circle.extend({
if(event.target.editor._resizeLatLng.__vertex._icon !== event.sourceTarget._element){
event.vertex._icon.style['background-color'] = 'red';
store.default.dispatch('setParking', event.target.options.attributes);
this.select();
this.select();
}
});
this.on('editable:disable', function (event) {
event.target.removeDirection();
});
});
},
updateStyle: function () {
@@ -357,14 +379,14 @@ L.ParkingSpot = L.Circle.extend({
return {lat: turfPoint.geometry.coordinates[1], lng: turfPoint.geometry.coordinates[0]};
},
extensions: function (editLayer) {
this.createDirection();
this.createDirection();
if (typeof this.featureLookup[this.id] === 'undefined') {
this.featureLookup[this.id] = [];
}
this.featureLookup[this.id].push(this);
},
/**
*
*
*/
follow (dragIndex, event) {
@@ -410,7 +432,7 @@ L.ParkingSpot = L.Circle.extend({
});
element.editor.feature.setLatLngs(element.latlngs);
element.editor.feature.updateMiddle();
}
}
}
})
},
@@ -430,12 +452,14 @@ var parkingSpot = function (n, layerGroup) {
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
//console.log(latlon.decimalLatitude);
//console.log(convert(n.attr('lat') + " " + n.attr('lon')).decimalLongitude);
const circle = new L.ParkingSpot([latlon.decimalLatitude, latlon.decimalLongitude], { radius: n.attr('radius'), attributes: {} });
circle.on('editable:enable', function (event) {
const parking = new L.ParkingSpot([latlon.decimalLatitude, latlon.decimalLongitude], { radius: n.attr('radius'), attributes: {} });
parking.on('editable:enable', function (event) {
// event.target.createDirection();
});
circle.id = n.attr('index');
circle.glueindex = n.attr('index');
parking.id = n.attr('index');
parking.glueindex = n.attr('index');
parking.feature = { properties: { searchTerm: n.attr('index') + ' ' + n.attr('name')}};
/*
<Parking index="2"
type="gate"
@@ -445,23 +469,24 @@ lat="N44 52.799"
lon="W93 11.947"
heading="-147.51"
radius="18"
pushBackRoute="541"
pushBackRoute="541"
airlineCodes="VIR,KAL,DAL,KLM" />
*/
//circle.attributes = { type: n.attr('type'), name: n.attr('name'), radius: Number(n.attr('radius')), airlineCodes: n.attr('airlineCodes'), heading: Number(n.attr('heading')) };
$.each( n.attrs, function( key, value ) {
console.debug( '$', circle.id, key , value);
console.debug( '$', parking.id, key , value);
if(isNaN(value))
circle.options.attributes[ key ] = value;
parking.options.attributes[ key ] = value;
else
circle.options.attributes[ key ] = Number( value);
parking.options.attributes[ key ] = Number( value);
});
circle.addListeners();
circle.addTo(layerGroup);
return circle;
parking.addListeners();
parking.addTo(layerGroup);
parking.deselect();
return parking;
}
module.exports = parkingSpot;

View File

@@ -43,18 +43,18 @@ L.RunwayNode = L.Marker.extend({
},
select() {
try {
this._icon.style['color'] = 'red';
this._icon.style['color'] = 'red';
} catch (error) {
console.error(error);
}
},
},
deselect() {
try {
this._icon.style['color'] = 'black';
this._icon.style['color'] = 'black';
} catch (error) {
console.error(error);
}
},
},
extensions: function (editLayer) {
this.options.attributes = {};
if (typeof this.featureLookup[this.glueindex] === 'undefined') {
@@ -63,7 +63,7 @@ L.RunwayNode = L.Marker.extend({
this.featureLookup[this.glueindex].push(this);
},
/**
*
*
*/
follow(dragIndex, event) {
@@ -93,18 +93,18 @@ L.RunwayNode = L.Marker.extend({
element.updateEndVertex(event.latlng);
element.updateMiddle();
}
} else if (element instanceof L.Editable.VertexMarker) {
} else if (element instanceof L.Editable.VertexMarker) {
console.log(element);
element.setLatLng(event.latlng);
element.latlngs.forEach((latlng, index) => {
console.log(latlng);
console.log(latlng);
if(latlng.__vertex === element) {
latlng.update(event.latlng);
}
});
element.editor.feature.setLatLngs(element.latlngs);
element.editor.feature.updateMiddle();
}
}
}
})
}
@@ -120,7 +120,9 @@ var runwayNode = function (n, layerGroup) {
});
var node = new L.RunwayNode([latlon.decimalLatitude, latlon.decimalLongitude], { icon: icon, attributes: {} });
node.glueindex = n.attr('index');
$.each( n.attrs, function( key, value ) {
node.feature = n.attr('index');
$.each( n.attrs, function( key, value ) {
if(isNaN(value))
node.options.attributes[ key ] = value;
else

View File

@@ -10,11 +10,13 @@ const extendTaxiSegment = function (taxiwaySegment) {
taxiwaySegment.__proto__.begin;
taxiwaySegment.__proto__.end;
taxiwaySegment.__proto__.bidirectional;
taxiwaySegment.__proto__.updateBeginVertex = function (latlng) {
if (this._latlngs[0].__vertex) {
this._latlngs[0].__vertex.setLatLng(latlng);
this.selectVertex(Number(this._latlngs[0].glueindex));
}
};
taxiwaySegment.__proto__.updateEndVertex = function (latlng) {
if (this._latlngs[1].__vertex) {
@@ -194,7 +196,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
});
this.on('editable:middlemarker:mousedown', event => {
console.debug('editable:middlemarker:mousedown');
}),
});
this.on('editable:vertex:new', event => {
console.debug('editable:vertex:new ' + event.vertex.getIndex() + '\t' + event.vertex.getLastIndex() + '\t');
// Find nearest node
@@ -243,6 +245,8 @@ const extendTaxiSegment = function (taxiwaySegment) {
polyline.editor.refresh();
//polyline.editor.reset();
polyline.featureLookup = this.featureLookup;
polyline.feature = { properties: {searchTerm: 'Arc ' + nextIndex + '-' + taxiwaySegment.end}};
polyline.options.attributes.name = taxiwaySegment.options.attributes.name;
polyline.options.attributes.direction = taxiwaySegment.options.attributes.direction;
polyline.options.attributes.isPushBackRoute = taxiwaySegment.options.attributes.isPushBackRoute;
@@ -266,8 +270,8 @@ const extendTaxiSegment = function (taxiwaySegment) {
event.latlng.attributes = { index: event.latlng.glueindex, isOnRunway: isOnRunwayNum };
// Push Vertex to lookup
this.editLayer.featureLookup[event.latlng.glueindex].push(event.latlng.__vertex);
if (isOnRunwayNum==1) {
this.editLayer.addRunwayNode(event.latlng, event.latlng['glueindex'])
if (isOnRunwayNum == 1) {
this.editLayer.addRunwayNode(event.latlng, event.latlng['glueindex'])
}
if (taxiwaySegment.options.attributes.begin === undefined) {
taxiwaySegment.options.attributes.begin = event.latlng['glueindex']
@@ -285,8 +289,8 @@ const extendTaxiSegment = function (taxiwaySegment) {
this.editLayer.featureLookup[event.vertex.latlng.glueindex] = [];
this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(event.vertex);
this.editLayer.featureLookup[event.vertex.latlng.glueindex].push(taxiwaySegment);
if (isOnRunwayNum==1) {
this.editLayer.addRunwayNode(event.latlng, event.vertex.latlng['glueindex'])
if (isOnRunwayNum == 1) {
this.editLayer.addRunwayNode(event.latlng, event.vertex.latlng['glueindex'])
}
// taxiwaySegment.editor.refresh();
//taxiwaySegment.editor.reset();
@@ -464,7 +468,7 @@ const extendTaxiSegment = function (taxiwaySegment) {
}
/**
*
*
*/
taxiwaySegment.__proto__.follow = function (dragIndex, event) {

View File

@@ -21,7 +21,7 @@ const store = require('../store');
L.TowerMarker = L.Marker.extend({
options: {
zIndexOffset: 10000,
zIndexOffset: 10000, draggable: 'true'
},
stripSVG: function(fName) {
var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm;
@@ -35,15 +35,16 @@ L.TowerMarker = L.Marker.extend({
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) {
if(this._metersPP != metersPP) {
var pixelSize = this.iconSize / metersPP;
var scale = pixelSize/this.iconSize;
var offset = 0;//-(this.iconSize/2);
var offset = 0;//-(this.iconSize/2);
this.setIcon(L.divIcon({
iconSize: 32,
className: 'threshold-marker-icon',
html: `<div style=\'transform: translateX(${offset}px) translateY(${offset}px) scale(${scale}); border: 1px red\'>${this.svg}</div>`,
}));
}));
this.setInteractive(this.interactive);
this.update(this.getLatLng());
console.debug();
@@ -51,38 +52,64 @@ L.TowerMarker = L.Marker.extend({
this._metersPP = metersPP;
}
}
},
},
setInteractive(interactive) {
if (interactive) {
if(this._icon) {
L.DomUtil.addClass(this._icon, 'leaflet-interactive');
}
} else {
if(this._icon) {
L.DomUtil.removeClass(this._icon, 'leaflet-interactive');
}
}
this.interactive = interactive;
},
metersPerPixel: function (latitude, zoomLevel) {
var earthCircumference = 40075017;
var latitudeRadians = latitude * (Math.PI / 180);
return earthCircumference * Math.cos(latitudeRadians) / Math.pow(2, zoomLevel + 8);
},
pixelValue: function (latitude, meters, zoomLevel) {
return meters / metersPerPixel(latitude, zoomLevel);
},
setTowerHeight: function (height) {
this.elev_m = height;
}
});
L.TowerMarker.addInitHook(function(){
this.svg = this.stripSVG('tower.svg');
this.iconSize = 32;
this.on('dragstart', function (event) {
this.on('click', function (event) {
store.default.dispatch('setTowerCoords',
event.target.getLatLng().lat.toFixed(6) + ' ' +
event.target.getLatLng().lng.toFixed(6) + ' ' +
event.target.elev_m);
store.default.dispatch('setTowerHeight', event.target.elev_m );
});
this.on('dragstart', function (event) {
console.debug("Drag Tower : ", event);
});
this.on('dragend', function (event) {
console.debug("DragEnd Tower : ", event);
store.default.dispatch('setTowerCoords',
event.target.getLatLng().lat.toFixed(6) + ' ' +
event.target.getLatLng().lng.toFixed(6) + ' ' +
store.default.dispatch('setTowerCoords',
event.target.getLatLng().lat.toFixed(6) + ' ' +
event.target.getLatLng().lng.toFixed(6) + ' ' +
event.target.elev_m);
store.default.dispatch('setTowerHeight', event.target.elev_m );
});
this.on('add', function (event) {
event.target.setInteractive(false);
});
});
//Builds a marker for a ai or multiplayer aircraft
var tower = function (n, options) {
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
var marker = new L.TowerMarker([latlon.decimalLatitude, latlon.decimalLongitude], {pane: 'tower-pane'});
marker.elev_m = n.find('elev-m/text()').text();
var tower = function (n, options) {
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
var marker = new L.TowerMarker([latlon.decimalLatitude, latlon.decimalLongitude], {pane: 'tower-pane'});
marker.elev_m = n.find('elev-m/text()').text();
return marker;
}

View File

@@ -23,9 +23,9 @@ function addFrequencies (type, value) {
value.split(' ').forEach(frequencyValue => {
if( value.length > 0) {
var frequency = {type: type, value: frequencyValue};
frequencies.push(frequency);
frequencies.push(frequency);
}
})
})
}
exports.addFeature = function (feature) {
@@ -38,10 +38,10 @@ exports.listSaves = function (fDir, icao) {
var ret = files
.filter(f => f.includes(icao) )
.filter(f => f.includes('groundnet') )
.map(f => {
.map(f => {
try {
var fileDate = fs.lstatSync(path.join(directory, f));
return {file: f, mtime: `${fileDate.mtime}`, mtimeMs: `${fileDate.mtimeMs}`};
return {file: f, mtime: `${fileDate.mtime}`, mtimeMs: `${fileDate.mtimeMs}`};
} catch (error) {
console.error(error);
}
@@ -56,6 +56,7 @@ exports.readGroundnetXML = function (fDir, icao, f) {
try {
store.default.dispatch('setGroundnetLoaded', false);
var layerGroup = L.layerGroup();
layerGroup.minId = 9999999999;
layerGroup.maxId = 0;
if (f == null || (!fs.existsSync(f) ))
@@ -98,7 +99,7 @@ exports.readGroundnetXML = function (fDir, icao, f) {
addFrequencies('UNICOM', unicom);
store.default.dispatch('setFrequencies', frequencies);
var parkingNodes = xml.find('groundnet/parkingList/Parking');
console.debug("Parking Nodes length" + parkingNodes.length);
@@ -113,12 +114,13 @@ exports.readGroundnetXML = function (fDir, icao, f) {
nodesLookup[n.attr('index')] = n;
featureLookup[n.attr('index')] = new Array();
featureLookup[n.attr('index')].push(circle);
layerGroup.minId = Math.min(layerGroup.minId, Number(n.attr('index')))
layerGroup.maxId = Math.max(layerGroup.maxId, Number(n.attr('index')))
features.push(circle);
}).sort();
store.default.dispatch('setParkings', parkingNodes.map(
p => ({index: Number(p.attrs.index), name: String(p.attrs.name), number: String(p.attrs.number), type: String(p.attrs.type)}
store.default.dispatch('setParkings', parkingNodes.map(
p => ({index: Number(p.attrs.index), radius: Number(p.attrs.radius), name: String(p.attrs.name), number: String(p.attrs.number), type: String(p.attrs.type)}
)).sort((p1, p2) => {
if (p1.name === p2.name) {
return p1.number?p1.number.localeCompare(p2.number):-1;
@@ -132,14 +134,16 @@ exports.readGroundnetXML = function (fDir, icao, f) {
//attrs.lat
//console.log(n.attr('lat') + " " + n.attr('lon'));
try {
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
} catch (error) {
console.warn(n.attr('lat') + " " + n.attr('lon'));
convert(n.attr('lat') + " " + n.attr('lon'));
}
//console.log(latlon.decimalLatitude);
layerGroup.minId = Math.min(layerGroup.minId, Number(n.attr('index')))
layerGroup.maxId = Math.max(layerGroup.maxId, Number(n.attr('index')))
console.debug(`Min Id : ${layerGroup.minId} Max Id : ${layerGroup.maxId} `);
nodesLookup[n.attr('index')] = n;
if (n.attr('isOnRunway') === '1') {
@@ -182,7 +186,7 @@ exports.readGroundnetXML = function (fDir, icao, f) {
if (element instanceof L.Polyline && element.end === n.attr('begin') && element.begin === n.attr('end')) {
element.bidirectional = true;
element.options.attributes.direction = 'bi-directional'
bidirectional = true;
bidirectional = true;
element.updateStyle();
}
});
@@ -190,11 +194,11 @@ exports.readGroundnetXML = function (fDir, icao, f) {
if (!bidirectional) {
var beginlatlon = convert(beginNode.attr('lat') + " " + beginNode.attr('lon'));
var endlatlon = convert(endNode.attr('lat') + " " + endNode.attr('lon'));
var pane = 'route-pane';
if(n.attr('isPushBackRoute') === '1') {
pane = 'pushback-pane';
}
}
var polyline = new L.Polyline([[beginlatlon.decimalLatitude, beginlatlon.decimalLongitude], [endlatlon.decimalLatitude, endlatlon.decimalLongitude]], { pane: pane, attributes: {} }).addTo(layerGroup);
extendTaxiSegment(polyline);
@@ -230,6 +234,8 @@ exports.readGroundnetXML = function (fDir, icao, f) {
polyline.begin = beginNode.attr('index');
polyline.end = endNode.attr('index');
polyline.feature = { properties: { searchTerm: 'Arc ' + beginNode.attr('index') + '-' + endNode.attr('index')}};
// polyline.enableEdit();
// polyline.on('dblclick', function (event) { L.DomEvent.stop; polyline.toggleEdit; });

View File

@@ -14,13 +14,13 @@ const mathjs = require('mathjs');
var builder = require('xmlbuilder');
var featureLookup = [];
var featureLookup = [];
var parkings = [];
var pushBackNodeLookup = [];
/**
* Walk nodes until the pushback node is found.
* @param {*} index
* Walk nodes until the pushback node is found.
* @param {*} index
*/
function findRouteToPushback (index) {
@@ -57,6 +57,12 @@ function walkPushbackRoute (index, walkedNodes, pushBackNodes) {
});
}
/**
*
* @param {*} fDir The directory
* @param {*} icao
* @param {*} featureList
*/
exports.writeGroundnetXML = function (fDir, icao, featureList) {
try {
@@ -67,13 +73,13 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
var fileNames = [];
for (let index = 1; index <= store.default.state.Settings.settings.numberOfSaves; index++) {
fileNames.push(path.join(fDir, icao[0], icao[1], icao[2], icao + `.groundnet.bak.${index}.xml`));
fileNames.push(path.join(fDir, icao[0], icao[1], icao[2], icao + `.groundnet.bak.${index}.xml`));
}
var f = path.join(fDir, icao[0], icao[1], icao[2], icao + '.groundnet.new.xml');
if( fs.existsSync(f) ) {
var previous = '';
fileNames.reverse().forEach(fBak => {
fileNames.reverse().forEach(fBak => {
if (fs.existsSync(fBak) && previous !== '') {
console.debug( `Copy ${fBak} to ${previous}`);
fs.copyFileSync(fBak, previous);
@@ -84,25 +90,27 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
}
if (f == null)
return;
pushBackNodeLookup = [];
pushBackNodeLookup = [];
console.debug(featureList);
var parkings = featureList.map(mapParkings).filter(n => n);
var runwayNodes = featureList.map(mapRunwayNodes).filter(n => n);
var holdNodes = featureList.map(mapHoldPoint).filter(n => n);
holdNodes.forEach(n => {
pushBackNodeLookup[n['@index']] = n;
});
var nodes = [];
var arcList = [];
var frequencies = [];
var version = new Date().toUTCString() + ' by FlightgearAirports ' + require('electron').remote.app.getVersion();
var name = store.default.state.Settings.settings.name;
var name = store.default.state.Settings.settings.name;
featureLookup = [];
featureLookup = [];
// Loaded segments
featureList.filter(o => o instanceof L.TaxiwaySegment).filter(n => n).forEach(element => {
var begin = mapBeginNode(element);
@@ -114,9 +122,9 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
console.warn("End missing");
nodes[end['@index']] = end;
});
// New segments
// New segments
featureList.filter(o => o instanceof L.Polyline).filter(n => n).forEach(arcElement => {
// element._latlngs.forEach(latlng => { nodes[latlng.glueindex] = mapVertexNode(latlng) });
// element._latlngs.forEach(latlng => { nodes[latlng.glueindex] = mapVertexNode(latlng) });
var startIndex = -1;
console.debug(arcElement.options.attributes);
var currentArc = arcElement.options.attributes;
@@ -134,7 +142,7 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
arc = { '@begin': startIndex, '@end': String(latlng.glueindex) };
styleArc(currentArc, arc);
arcList.push(arc);
featureLookup[startIndex][latlng.glueindex] = arc;
featureLookup[startIndex][latlng.glueindex] = arc;
}
if( currentArc.direction === 'bi-directional' || currentArc.direction === 'backward' ){
arc = { '@begin': String(latlng.glueindex), '@end': startIndex };
@@ -143,7 +151,7 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
featureLookup[latlng.glueindex][startIndex] = arc;
}
if (currentArc.direction === '' || !currentArc.direction) {
console.error( "Arc without direction " + util.inspect(currentArc) );
console.error( "Arc without direction " + util.inspect(currentArc) );
}
}
startIndex = latlng.glueindex;
@@ -154,12 +162,12 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
});
runwayNodes.forEach(element => {
if (nodes[element['@index']] != undefined) {
nodes[element['@index']]['@isOnRunway'] = "1";
nodes[element['@index']]['@isOnRunway'] = "1";
}
});
// Find the index of the pushback node
// Find the index of the pushback node
parkings.forEach(n => {
nodes[n['@index']] = null;
var pushBackNode = findRouteToPushback(Number(n['@index']))[0];
@@ -189,7 +197,54 @@ exports.writeGroundnetXML = function (fDir, icao, featureList) {
var unicomList = store.default.state.Frequencies.items.filter(f => f.type === 'UNICOM').map(mapFrequency);
var xmlObj = { groundnet: { version: 1, fgaversion: version, name: name,
var gapStart = -1;
var gapEnd = -1;
do {
gapStart = -1;
gapEnd = -1;
var allIds = parkings.map(n => Number(n['@index']))
.concat(uniqueNodes.map(n => Number(n['@index'])))
.sort((a, b) => a - b);
allIds.forEach((element, index, array) => {
if (index > 0 && array[index-1] + 1 != element && gapStart == -1 ) {
gapStart = array[index-1];
gapEnd = element;
}
});
var gap = gapEnd - gapStart -1;
if ( gap >= 0 ) {
parkings = parkings.map(n => {
if (n['@index']>gapStart) {
n['@index'] = String(n['@index'] - gap);
}
if (n['@pushbackRoute']>gapStart) {
n['@pushbackRoute'] = String(n['@pushbackRoute'] - gap);
}
return n;
});
uniqueNodes = uniqueNodes.map(n => {
if (n['@index']>gapStart) {
n['@index'] = String(n['@index'] - gap);
}
return n;
});
arcList = arcList.map(n => {
if (n['@begin']>gapStart) {
n['@begin'] = String(n['@begin'] - gap);
}
if (n['@end']>gapStart) {
n['@end'] = String(n['@end'] - gap);
}
return n;
});
}
} while( gapStart > 0 && gapEnd > 0);
var xmlObj = { groundnet: { version: 1, fgaversion: version, name: name,
'frequencies': { APPROACH: approachList, DEPARTURE: departureList, AWOS: awosList, CLEARANCE: clearanceList, GROUND: groundList, TOWER: towerList, UNICOM: unicomList },
parkingList: { Parking: parkings }, TaxiNodes: { node: uniqueNodes }, TaxiWaySegments: { arc: arcList } } };
@@ -220,7 +275,7 @@ var mapParkings = function (o) {
console.debug(o.options.attributes.airlineCodes);
parking['@airlineCodes'] = o.options.attributes.airlineCodes;
}
if(o.options.attributes.number !== undefined &&
if(o.options.attributes.number !== undefined &&
typeof o.options.attributes.number === 'number' || (
typeof o.options.attributes.number === 'string' &&
o.options.attributes.number.trim() !== ''
@@ -237,10 +292,10 @@ var mapParkings = function (o) {
var mapRunwayNodes = function (o) {
console.debug(o);
if (o instanceof L.RunwayNode) {
var runwayNode = { '@index': String(o['glueindex']),
'@lat': convertLat(o._latlng),
'@lon': convertLon(o._latlng),
'@isOnRunway': '1',
var runwayNode = { '@index': String(o['glueindex']),
'@lat': convertLat(o._latlng),
'@lon': convertLon(o._latlng),
'@isOnRunway': '1',
'@holdPointType': 'none' };
return runwayNode;
}
@@ -310,7 +365,7 @@ var styleArc = function (attributes, arc) {
arc['@isPushBackRoute'] = "0";
}
if ( attributes.name !== '' && attributes.name !== 'undefined') {
arc['@name'] = attributes.name;
arc['@name'] = attributes.name;
}
}
}

View File

@@ -1,19 +1,22 @@
/* eslint-disable */
const fs = require('fs');
const path = require('path');
var xamel = require('xamel');
const xamel = require('xamel');
const convert = require('geo-coordinates-parser');
const LatLonEllipsoidal = require('geodesy/latlon-ellipsoidal-vincenty.js').default;
const store = require('../store');
const util = require('util');
const takeoffPadPoly = require('../leaflet/TakeoffPad.js');
const threshold = require('./Threshold.js');
var $ = require('jquery');
exports.readThresholdXML = function (fDir, icao, force) {
exports.readThresholdXML = function (fDir, icao, force, stripes) {
try {
var layerGroup = L.layerGroup();
layerGroup.maxId = 0;
@@ -48,12 +51,30 @@ exports.readThresholdXML = function (fDir, icao, force) {
var index = 0;
runwayNodes.map(r => {
var thresholds = r.find('threshold');
thresholds.map(t => {
var icon = threshold(t);
thresholds.map(n => {
var icon = threshold(n);
icon.index = index;
icon.addTo(layerGroup);
}
// Width in m
var runwayWidth = 20;
var latlon = convert(n.find('lat/text()').text() + " " + n.find('lon/text()').text());
var displ_m = Number(n.find('displ-m/text()').text());
var pointMiddle = new LatLonEllipsoidal(latlon.decimalLatitude, latlon.decimalLongitude);
var heading = Number(n.find('hdg-deg/text()').text());
var point1 = pointMiddle.destinationPoint(displ_m, heading);
var point2 = pointMiddle.destinationPoint(displ_m + 80, heading);
var runwayPoints = [];
runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (heading + 90)));
runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (heading + 90)));
runwayPoints.push(point2.destinationPoint(runwayWidth / 2, (heading - 90)));
runwayPoints.push(point1.destinationPoint(runwayWidth / 2, (heading - 90)));
var runwayPoly = takeoffPadPoly(runwayPoints);
runwayPoly.addTo(layerGroup);
}
)
index+=1;
}).sort();
@@ -65,4 +86,4 @@ exports.readThresholdXML = function (fDir, icao, force) {
console.error(error);
}
return layerGroup;
};
};

View File

@@ -0,0 +1,123 @@
/*
Copyright 2021 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
*/
/* eslint-disable */
const fs = require('fs');
const path = require('path');
var xamel = require('xamel');
const store = require('../store');
const util = require('util');
exports.readTrafficXML = function (f) {
try {
var ret = [];
var xmlTraffic = fs.readFileSync(f, 'utf8').toString();
xamel.parse(xmlTraffic, function (err, xml) {
console.debug("parsed " + path.basename(f));
if (err !== null) {
console.error("Error in " + airline);
throw err;
}
var requiredAircraft = xml.find('trafficlist/aircraft');
console.log("Aircraft " + requiredAircraft.length);
ret.concat(requiredAircraft);
var flights = xml.find('trafficlist/flight');
console.log("Flights " + flights.length);
ret.concat(flights);
console.log(ret.length);
ret = ret.concat(flights.map(flightMapper)).concat(requiredAircraft.map(aircraftMapper))
return ret;
});
return ret;
} catch (error) {
console.error(error);
}
};
/*
* <flight>
<callsign>Hebridean_1047</callsign>
<required-aircraft>HBR_BN_2</required-aircraft>
<fltrules>VFR</fltrules>
<departure>
<port>EGPU</port>
<time>4/14:50:00</time>
</departure>
<cruise-alt>50</cruise-alt>
<arrival>
<port>EGEO</port>
<time>4/15:50:00</time>
</arrival>
<repeat>WEEK</repeat>
</flight>
*/
function flightMapper(params) {
return {
id: `${btoa(buildId(params))}`,
callsign: params.find('callsign').text(),
'required-aircraft': params.find('required-aircraft').text(),
arrival: {
port: params.find('arrival/port').text(),
time: params.find('arrival/time').text()
},
departure: {
port: params.find('departure/port').text(),
time: params.find('departure/time').text()
}
};
}
function buildId(params) {
return `${params.find('callsign').text()}_`+
`${params.find('arrival/port').text()}_`+
`${params.find('arrival/time').text()}_`+
`${params.find('departure/port').text()}_` +
`${params.find('departure/time').text()}`;
}
/*
<aircraft>
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
<livery>HBR</livery>
<airline>HBR</airline>
<home-port>EGEO</home-port>
<required-aircraft>HBR_BN_2</required-aircraft>
<actype>BN2</actype>
<offset>0</offset>
<radius>8</radius>
<flighttype>gate</flighttype>
<performance-class>turboprop_transport</performance-class>
<registration>G-HEBO</registration>
<heavy>false</heavy>
</aircraft>
*/
function aircraftMapper(params) {
return {
model: params.find('model').text(),
livery: params.find('livery').text(),
airline: params.find('airline').text(),
'home-port': params.find('home-port').text(),
'required-aircraft': params.find('required-aircraft').text(),
actype: params.find('actype').text(),
offset: params.find('offset').text(),
radius: params.find('radius').text(),
flighttype: params.find('flighttype').text(),
'performance-class': params.find('performance-class').text(),
'registration': params.find('registration').text(),
'heavy': params.find('heavy').text(),
};
}

View File

@@ -0,0 +1,180 @@
/*
Copyright 2021 Keith Paterson
This file is part of FG Airports.
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
*/
/* eslint-disable */
const fs = require('fs');
const path = require('path');
const store = require('../store');
const util = require('util');
const mathjs = require('mathjs');
var builder = require('xmlbuilder');
var parkingStats = (acc, cur) => {
if (!acc[cur.radius]) {
acc[cur.radius] = { count: 0, radius: cur.radius }
}
acc[cur.radius].count += 1
return acc
};
/**
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<trafficlist xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="traffic.xsd">
<aircraft>
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
<livery>HBR</livery>
<airline>HBR</airline>
<home-port>EGEO</home-port>
<required-aircraft>HBR_BN_2</required-aircraft>
<actype>BN2</actype>
<offset>0</offset>
<radius>8</radius>
<flighttype>gate</flighttype>
<performance-class>turboprop_transport</performance-class>
<registration>G-HEBS</registration>
<heavy>false</heavy>
</aircraft>
<flight>
<callsign>Hebridean_1047</callsign>
<required-aircraft>HBR_BN_2</required-aircraft>
<fltrules>VFR</fltrules>
<departure>
<port>EGPU</port>
<time>4/14:50:00</time>
</departure>
<cruise-alt>50</cruise-alt>
<arrival>
<port>EGEO</port>
<time>4/15:50:00</time>
</arrival>
<repeat>WEEK</repeat>
</flight>
</trafficlist>
*/
var writeTrafficXML = function (fDir, parkings, aircraft) {
try {
var icao = store.default.state.Airports.currentAirport.icao;
var aircraftList = aircraft;
try { fs.mkdirSync(path.join(fDir), { recursive: true }) } catch (err) { }
try { fs.mkdirSync(path.join(fDir, 'TST'), { recursive: true }) } catch (err) { }
var f = path.join(fDir, 'TST', icao + '.xml');
var parkingData = parkings.reduce(parkingStats, {});
/*
*
<flight>
<callsign>Hebridean_1001</callsign>
<required-aircraft>HBR_BN_2</required-aircraft>
<fltrules>VFR</fltrules>
<departure>
<port>EGEO</port>
<time>2/14:10:00</time>
</departure>
<cruise-alt>50</cruise-alt>
<arrival>
<port>EGEY</port>
<time>2/15:20:00</time>
</arrival>
<repeat>WEEK</repeat>
</flight>
*/
var flightMapper = function (pStat) {
var ret = [];
var blockSize = Math.min( pStat[1].count/6, 6);
for (let index = 0; index < pStat[1].count; index++) {
var aircraft = this[index];
var minutes = `${Math.floor(index/blockSize)}`.padStart(2, '0');
var seconds = `${index}`.padStart(2, '0');
for (let weekday = 0; weekday < 7; weekday++) {
ret.push({
callsign: `Test_${index}_${weekday}`,
'required-aircraft': aircraft['required-aircraft'],
fltrules: 'VFR',
departure: {
port: icao,
time: `${weekday}/12:${minutes}:${seconds}`
},
'cruise-alt': 50,
arrival: {
port: icao,
time: `${weekday}/13:${minutes}:${seconds}`
},
repeat: 'WEEK'
});
}
}
return ret;
}
/*
<aircraft>
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
<livery>HBR</livery>
<airline>HBR</airline>
<home-port>EGEO</home-port>
<required-aircraft>HBR_BN_2</required-aircraft>
<actype>BN2</actype>
<offset>0</offset>
<radius>8</radius>
<flighttype>gate</flighttype>
<performance-class>turboprop_transport</performance-class>
<registration>G-HEBO</registration>
<heavy>false</heavy>
</aircraft>
*/
var aircraftMapper = function (pStat) {
var ret = [];
if (typeof this === 'undefined') {
return;
}
var possibleAircraft = this.filter(a => a.radius <= pStat[1].radius);
for (let index = 0; index < pStat[1].count; index++) {
var aircraft = possibleAircraft[Math.floor(Math.random() * possibleAircraft.length)];
aircraft['required-aircraft'] = `GG-${index}`;
aircraft.registration = `GG-${index}`;
aircraft['home-port'] = icao;
ret.push(aircraft);
}
return ret;
}
var aircraftList = Object.entries(parkingData).flatMap(aircraftMapper, aircraft).sort();
var flightList = Object.entries(parkingData).flatMap(flightMapper, aircraftList).sort();
var xmlObj = { trafficList: { aircraft: aircraftList, flight: flightList } };
var xmlString = builder.create(xmlObj).end({ pretty: true });
fs.writeFileSync(f, xmlString);
console.debug(xmlString);
} catch (error) {
console.error(error);
}
return;
}
export { writeTrafficXML as writeTrafficXML };

View File

@@ -14,6 +14,10 @@ Vue.config.productionTip = false
Vue.use(ElementUI)
Vue.config.errorHandler = (err, vm, info) => {
console.error(err)
}
/* eslint-disable no-new */
new Vue({
components: { App },

View File

@@ -16,7 +16,7 @@ const state = {
type: 'none',
index: 'none',
editing: false,
data: {airports: {}, parking: {}, arc: {}, multiarc: {}, node: {}, runway: {}, threshold: {}}
data: {airports: {}, parking: {}, arc: {}, multiarc: {}, node: {}, runway: {}, threshold: {}, tower: {}}
}
const SET_EDIT_AIRPORT = 'SET_EDIT_AIRPORT'
@@ -38,7 +38,6 @@ const mutations = {
state.type = 'airport'
},
SET_EDIT_PARKING (state, parking) {
Vue.set(state, 'data', {})
var p = Object.assign({}, parking)
Vue.set(state.data, 'parking', p)
Vue.set(state, 'index', p.index)
@@ -48,15 +47,11 @@ const mutations = {
if (node === undefined) {
return
}
if (!state.data || state.type !== 'node') {
Vue.set(state, 'data', {})
}
Vue.set(state.data, 'node', node)
Vue.set(state, 'index', node.index)
Vue.set(state, 'type', 'node')
},
SET_EDIT_RUNWAY (state, runway) {
Vue.set(state, 'data', {})
Vue.set(state.data, 'node', runway)
Vue.set(state, 'index', runway.index)
Vue.set(state, 'type', 'runway')
@@ -65,9 +60,6 @@ const mutations = {
if (arc === undefined) {
return
}
if (!state.data || state.type !== 'arc') {
Vue.set(state, 'data', {})
}
Vue.set(state.data, 'arc', arc)
if (state.data.arc.name === undefined) {
Vue.set(state.data.arc, 'name', '')
@@ -79,9 +71,6 @@ const mutations = {
if (arc === undefined) {
return
}
if (!state.data || state.type !== 'multiarc') {
Vue.set(state, 'data', {multiarc: {}})
}
Vue.set(state.data.multiarc, 'isPushBackRoute', arc.isPushBackRoute)
Vue.set(state.data.multiarc, 'direction', arc.direction)
if (state.data.multiarc.name === undefined) {
@@ -163,10 +152,17 @@ const mutations = {
},
'SET_EDIT_TOWER_COORDS' (state, coords) {
state.type = 'tower'
state.data.tower = { coords: {} }
if (!state.data.tower) {
state.data.tower = {}
}
if (!state.data.tower.coords) {
state.data.tower.coords = {}
}
Vue.set(state.data.tower.coords, 'latitude', coords.split(' ')[0])
Vue.set(state.data.tower.coords, 'longitude', coords.split(' ')[1])
Vue.set(state.data.tower.coords, 'height', coords.split(' ')[2])
},
'SET_EDIT_TOWER_HEIGHT' (state, height) {
Vue.set(state.data.tower, 'height', height)
},
'SET_EDIT_THRESHOLD_COORDS' (state, threshold) {
state.type = 'threshold'
@@ -219,6 +215,9 @@ const actions = {
async setTowerCoords (context, node) {
context.commit('SET_EDIT_TOWER_COORDS', node)
},
async setTowerHeight (context, height) {
context.commit('SET_EDIT_TOWER_HEIGHT', height)
},
async setThreshold (context, node) {
context.commit('SET_EDIT_THRESHOLD_COORDS', node)
},

View File

@@ -43,7 +43,7 @@ const mutations = {
const actions = {
async addParking (context, p) {
context.commit('ADD_FREADD_PARKINGQUENCY', p)
context.commit('ADD_PARKING', p)
},
async updatedParking (context, p) {
context.commit('UPDATE_PARKING', p)

View File

@@ -43,22 +43,22 @@ onmessage = function (event) {
).catch(result => {
console.error('Crashed');
console.error(result);
postMessage(['DONE', [{id: -1, message: ['Crashed', result ]}]]);
postMessage(['DONE', [{ id: -1, message: ['Crashed', result] }]]);
});
}
};
/**
* Implements the checks of the groundnet
* @param {*} data
* @param {*} data
*/
async function checkGroundnet(data) {
var promise = new Promise(function (resolve, reject) {
try {
const fName = process.env.NODE_ENV === 'development'
? './src/renderer/utils/check_msg.json'
: path.join(`${process.resourcesPath}`, 'workers','check_msg.json');
? './src/renderer/utils/check_msg.json'
: path.join(`${process.resourcesPath}`, 'workers', 'check_msg.json');
check_msg = JSON.parse(fs.readFileSync(fName, 'utf8').toString());
//debugger;
var parkings = data.map(mapParkings).filter(n => n !== undefined);
@@ -68,9 +68,9 @@ async function checkGroundnet(data) {
var edges = data.map(mapEdges).filter(n => n !== undefined);
var normalNodes = data.map(mapEdges).filter(n => n !== undefined)
.flatMap(m => m.latLngs).filter(n => runwayNodeIDs.indexOf(Number(n.index)) < 0);
.flatMap(m => m.latLngs).filter(n => runwayNodeIDs.indexOf(Number(n.index)) < 0);
var runways = data.map(mapRunways).filter(n => n !== undefined);
var takeoffPads = data.map(mapTakeoffPads).filter(n => n !== undefined);
this.max = 30;
this.postMessage(['max', this.max]);
@@ -104,7 +104,8 @@ async function checkGroundnet(data) {
resolve([{ id: -1, message: check_msg.NO_EDGES }]);
}
this.postMessage(['progress', 1]);
if (runways.length === 0) {
//debugger;
if (takeoffPads.length === 0) {
resolve([{ id: -1, message: check_msg.NO_RUNWAYS }]);
}
this.postMessage(['progress', 1]);
@@ -135,7 +136,7 @@ async function checkGroundnet(data) {
var node2 = directionalGraph[element.end];
if (element.direction === undefined) {
notOkNodes.push({ id: Number(element._leaflet_id), message: check_msg.EDGE_MISSING_DIRECTION });
}
}
if (element.direction === 'bi-directional' || element.direction === 'forward') {
node1[Number(element.end)] = 1;
}
@@ -150,6 +151,9 @@ async function checkGroundnet(data) {
});
this.postMessage(['progress', 1]);
var isLegitEnd = function (v) {
if (bidirectionalGraph[v] === undefined) {
debugger;
}
if (Object.keys(bidirectionalGraph[v]).length <= 1) {
return true;
}
@@ -158,7 +162,7 @@ async function checkGroundnet(data) {
runwayNodeIDs = runwayNodeIDs.filter(
(v, i) => isLegitEnd(v)
);
// Check if there is a route from every parking to every runway node
// Check if there is a route from every parking to every runway node
var okNodes = [];
logger('info', directionalGraph);
parkings.forEach(parkingNode => {
@@ -170,7 +174,7 @@ async function checkGroundnet(data) {
} else {
console.log(`No route from Parking ${parkingNode} to Runwaynode ${runwayNode}`);
}
});
});
// Build pushback directionalGraph
@@ -203,7 +207,7 @@ async function checkGroundnet(data) {
if (numRoutes === 0) {
if (multiplePushbackRoutes[parkingNode] === undefined &&
Object.keys(noPushbackGraph[parkingNode]) > 0) {
// Only when there is a edge leaving
// Only when there is a edge leaving
multiplePushbackRoutes[parkingNode] = [];
}
} else if (numRoutes === 1) {
@@ -219,37 +223,41 @@ async function checkGroundnet(data) {
multiplePushbackRoutes[parkingNode].push(pushbackNode);
}
}
});
});
var notConnectedToPushback = pushbackNodes.map(
id => {
var normalRoutes = bidirectionalGraph[id];
var pushbackRoutes = noPushbackGraph[id];
if (Object.keys(pushbackRoutes).length < 1)
return { id: id, message: check_msg.PUSHBACK_NOT_CONNECTED }
}).filter(n => n !== undefined);
var normalRoutes = bidirectionalGraph[id];
var pushbackRoutes = noPushbackGraph[id];
if (Object.keys(pushbackRoutes).length < 1)
return { id: id, message: check_msg.PUSHBACK_NOT_CONNECTED }
}).filter(n => n !== undefined);
this.postMessage(['progress', 1]);
var multipleTaxiRoutes = pushbackNodes.map(
id => {
var normalRoutes = bidirectionalGraph[id];
var pushbackRoutes = noPushbackGraph[id];
var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined);
if (nonPushbackRoutes.length > 1)
return { id: id, message: check_msg.TO_MANY_PUSHBACK_TAXI_ROUTES }
}).filter(n => n !== undefined);
var normalRoutes = bidirectionalGraph[id];
var pushbackRoutes = noPushbackGraph[id];
if (normalRoutes !== undefined) {
var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined);
if (nonPushbackRoutes.length > 1)
return { id: id, message: check_msg.TO_MANY_PUSHBACK_TAXI_ROUTES }
}
}).filter(n => n !== undefined);
this.postMessage(['progress', 1]);
var pushbackExitNotBidirectional = pushbackNodes.map(
id => {
var normalRoutes = bidirectionalGraph[id];
var pushbackRoutes = noPushbackGraph[id];
var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined);
if(nonPushbackRoutes.length > 0) {
var returnRoute = Object.keys(bidirectionalGraph[nonPushbackRoutes[0]]).map(id => Number(id)).filter(retId =>id === retId);
if (returnRoute.length === 0)
return { id: id, message: check_msg.PUSHBACK_EXIT_NOT_BIDRECTIONAL }
}
}).filter(n => n !== undefined);
var normalRoutes = bidirectionalGraph[id];
var pushbackRoutes = noPushbackGraph[id];
if (normalRoutes !== undefined) {
var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined);
if(nonPushbackRoutes.length > 0) {
var returnRoute = Object.keys(bidirectionalGraph[nonPushbackRoutes[0]]).map(id => Number(id)).filter(retId =>id === retId);
if (returnRoute.length === 0)
return { id: id, message: check_msg.PUSHBACK_EXIT_NOT_BIDRECTIONAL }
}
}
}).filter(n => n !== undefined);
this.postMessage(['progress', 1]);
var rogueHoldPoints = pushbackNodes.map(
id => {
@@ -290,16 +298,16 @@ async function checkGroundnet(data) {
var notOkNodesRunways = runwayNodeIDs.filter(
(v, i) => okNodes.indexOf(v) < 0
).map(
id => { return { id: id, message: check_msg.NO_RUNWAY_ROUTE } }
id => { return { id: id, message: check_msg.NO_PARKING_ROUTE } }
);
this.postMessage(['progress', 1]);
if (parkings.length === 0) {
notOkNodes.push({ id: 0, message: check_msg.NO_PARKINGS });
notOkNodes.push({ id: -2, message: check_msg.NO_PARKINGS });
}
this.postMessage(['progress', 1]);
if (runwayNodeIDs.length === 0) {
notOkNodes.push({ id: 0, message: check_msg.NO_RUNWAY_NODES });
notOkNodes.push({ id: -2, message: check_msg.NO_RUNWAY_NODES });
}
this.postMessage(['progress', 1]);
var allEnds = Object.entries(bidirectionalGraph).filter(
@@ -344,7 +352,7 @@ async function checkGroundnet(data) {
}
}
}
});
});
this.postMessage(['progress', 1]);
@@ -353,14 +361,14 @@ async function checkGroundnet(data) {
parkingNodes.forEach(parkingNode => {
if (!parkingNode.name || /^\s*$/.test(parkingNode.name)) {
invalidParkings.push({ id: parkingNode.index, message: check_msg.NAME_EMPTY });
}
if (!parkingNode.type) {
invalidParkings.push({ id: parkingNode.index, message: check_msg.TYPE_EMPTY });
}
if (['ga', 'cargo', 'gate', 'mil-fighter', 'mil-cargo'].indexOf(parkingNode.parkingType) < 0) {
invalidParkings.push({ id: parkingNode.index, message: check_msg.PARKING_TYPE_INVALID });
invalidParkings.push({ id: parkingNode.index, message: check_msg.PARKING_TYPE_INVALID });
}
});
this.postMessage(['progress', 1]);
@@ -375,21 +383,29 @@ async function checkGroundnet(data) {
this.postMessage(['progress', 1]);
//Check if runwaynodes are on runway
runwayNodes.forEach(runwayNode => {
if( runways.filter(r => turf.booleanContains(r, latToTurf(runwayNode))).length === 0 ) {
// debugger;
if (takeoffPads.filter(r => turf.booleanContains(r, latToTurf(runwayNode))).length === 0) {
notOkNodes.push({ id: runwayNode.index, message: check_msg.RUNWAY_NODE_NOT_ON_RUNWAY });
}
}
});
this.postMessage(['progress', 1]);
//Check if nodes no normal nodes are on runway
normalNodes.forEach(normalNode => {
//debugger;
if( runways.filter(r => turf.booleanContains(r, latToTurf(normalNode))).length > 0 ) {
if (takeoffPads.filter(r => turf.booleanContains(r, latToTurf(normalNode))).length > 0) {
notOkNodes.push({ id: normalNode.index, message: check_msg.NON_RUNWAYNODE_ON_RUNWAY });
}
}
});
this.postMessage(['progress', 1]);
var doubleEdges = edges.filter((v, i, a) => a.findIndex(t => (t.start === v.start && t.end === v.end) ) !== i);
doubleEdges.forEach(e => {
notOkNodes.push({ id: e.id, message: check_msg.DOUBLE_EDGE });
});
// debugger;
notOkNodes = notOkNodes.concat(invalidParkings);
if (invalidParkings.length === 0) {
notOkNodes.push({ id: -1, message: check_msg.PARKINGS_VALID });
@@ -415,8 +431,8 @@ async function checkGroundnet(data) {
notOkNodes = notOkNodes.concat(notConnectedToPushback);
notOkNodes = notOkNodes.concat(multipleTaxiRoutes);
notOkNodes = notOkNodes.concat(pushbackExitNotBidirectional);
if (wrongPushbackRoutes.length === 0 &&
notConnectedToPushback.length === 0 &&
if (wrongPushbackRoutes.length === 0 &&
notConnectedToPushback.length === 0 &&
multipleTaxiRoutes.length === 0 &&
pushbackExitNotBidirectional.length === 0
) {
@@ -496,12 +512,12 @@ var mapRunwayNodeId = function (o) {
var mapRunwayNode = function (o) {
if (o.type === 'runway') {
return {index:o.index, lat: o.lat, lng: o.lng};
return { index: o.index, lat: o.lat, lng: o.lng };
}
}
var mapRunways = function (o) {
if (o.type === 'runway_poly') {
var mapTakeoffPads = function (o) {
if (o.type === 'takeoffpad_poly') {
var pts = o.pavement[0].map(latLngToArray);
pts.push(pts[0]);
return turf.polygon([pts]);
@@ -510,12 +526,10 @@ var mapRunways = function (o) {
var mapEdges = function (o) {
if (o.type === 'poly')
// debugger;
return {
start: o.start, end: o.end, isPushBackRoute: o.isPushBackRoute !== undefined &&
id: o._leaflet_id, start: o.start, end: o.end, isPushBackRoute: o.isPushBackRoute !== undefined &&
o.isPushBackRoute !== 0, direction: o.direction, latLngs: o.latLngs
};
console.debug(o);
}
var latToTurf = function (turfPoint) {

View File

@@ -1,32 +1,33 @@
{
"LONG_ROUTE_START" : ["Start of long route", "Route segments of >2km are Taxidraw artefacts"],
"LONG_ROUTE_END": ["End of long route", "Route segments of >2km are Taxidraw artefacts"],
"EDGE_MISSING_DIRECTION": ["Edge missing direction", ""],
"NO_RUNWAY_ROUTE": ["No way from parking to each runway", ""],
"NO_PARKING_ROUTE": ["No way from runway to each parking", ""],
"EDGE_MISSING_DIRECTION": ["Edge missing direction", "Each edge must have a direction (forward, backward, bi-directional)"],
"NO_RUNWAY_ROUTE": ["No way from parking to each runway", "There must be a route from each parking to each runway."],
"NO_PARKING_ROUTE": ["No way from runway to each parking", "There must be a route from each runway to each parking."],
"NO_PARKINGS": ["No parkings", ""],
"NO_RUNWAYNODES": ["No Runwaynodes", ""],
"NO_RUNWAY_NODES": ["No Runwaynodes", "Fine for parking only"],
"NOT_LEGIT_END": ["Node not a legimate end", "Taxiroutes must end either at a parking or on a runway"],
"UNKNOWN_RADIUS" :["Unknown radius", "Radii must be one from the list"],
"OVERLAPPING_PARKINGS" :["Overlapping parkings", ""],
"NAME_EMPTY" :["Name empty", ""],
"TYPE_EMPTY" :["Parking type empty", ""],
"PARKING_TYPE_INVALID" :["Parking type not valid", ""],
"OVERLAPPING_PARKINGS" :["Overlapping parkings", "Parkings must not overlap"],
"NAME_EMPTY" :["Name empty", "Name of parking must not be empty"],
"TYPE_EMPTY" :["Parking type empty", "The parking type must not be empty"],
"PARKING_TYPE_INVALID" :["Parking type not valid", "The type of parking must be one of ()"],
"DUAL_PUSHBACK": ["Dual runway/ pushback node", "A runway node can not be a hold node at the same time"],
"RUNWAY_NODE_NOT_ON_RUNWAY" : ["Runwaynode not on runway", ""],
"NON_RUNWAYNODE_ON_RUNWAY": ["Non Runwaynode on runway", ""],
"PARKINGS_VALID": ["Parkings valid", ""],
"NO_OVERLAPPING_PARKINGS": ["No parkings overlapping", ""],
"RUNWAY_NODE_NOT_ON_RUNWAY" : ["Runwaynode not in takeoff pad", ""],
"NON_RUNWAYNODE_ON_RUNWAY": ["Non Runwaynode in takeoff pad", ""],
"PARKINGS_VALID": ["Parkings valid", "All Ok"],
"NO_OVERLAPPING_PARKINGS": ["No parkings overlapping", "Parking positions may not overlap. Reduce the radius or move."],
"NO_INVALID_ENDS": ["No invalid ends", ""],
"ROUTES_FROM_PARKINGS_OK": ["Routes from parkings OK", ""],
"ROUTES_FROM_RUNWAYS_OK": ["Routes from runways OK", ""],
"PUSHBACK_ROUTES_OK": ["Pushback routes OK", ""],
"UNCONNECTED_PUSHBACK": ["Unconnected Pushbacknode", ""],
"NO_WAY_TO_HOLDPOINT":["No way to pushback holdpoint", ""],
"MULTIPLE_PUSHBACK": ["Multiple connected pushback points", ""],
"NO_WAY_TO_HOLDPOINT":["No way to pushback holdpoint", "There is no route from the parking to the pushback hold point-"],
"MULTIPLE_PUSHBACK": ["Multiple connected pushback points", "There are more than one possible pushback holdpoint routes."],
"PUSHBACK_NOT_CONNECTED": ["Pushback Holding Point not Connected to Pushback Route", ""],
"TO_MANY_PUSHBACK_TAXI_ROUTES": ["Too many Taxi routes from Pushback Holding Point", ""],
"TO_MANY_PUSHBACK_TAXI_ROUTES": ["Too many Taxi routes from Pushback Holding Point", "There must be only one pushback point reachable from the parking."],
"PUSHBACK_EXIT_NOT_BIDRECTIONAL": ["Pushback Holding Point Exit route is not bidirectional", ""],
"NO_EDGES": ["No Edges", "No checks are run if there are no edges present"],
"NO_RUNWAYS": ["No Runways", "No checks are run if there are no runways present. APT layer visible?"]
"NO_RUNWAYS": ["No Runways", "No checks are run if there are no runways present. APT layer visible?"],
"DOUBLE_EDGE": ["No Double Edges", "This edge is doubled"]
}

View File

@@ -1,29 +1,40 @@
var util = require("util");
/* eslint-disable no-unused-vars */
var util = require('util');
const d = new Date();
const fName = 'scan_' + d.getFullYear()
+ d.getMonth()
+ d.getDay()
+ d.getHours()
+ d.getMinutes()
+ d.getSeconds()
+ d.getMilliseconds() + '.log';
const fName = 'scan_' + d.getFullYear() +
d.getMonth() +
d.getDay() +
d.getHours() +
d.getMinutes() +
d.getSeconds() +
d.getMilliseconds() + '.log';
var logStream = null;
var loggerInit = function (logging) {
if (logging) {
logStream = require('fs').createWriteStream( fName, {autoClose: true});
try {
const homedir = require('os').homedir();
const logFileName = require('path').join(homedir, fName);
logStream = require('fs').createWriteStream( logFileName, {autoClose: true});
} catch (error) {
console.error('Logging not possible ' + error);
}
}
}
var logger = function (level, msg, o) {
var d = new Date();
if(logStream!==null) {
var d = new Date();
try {
if (logStream !== null) {
logStream.write(d.toUTCString() + '|' + level + ' | ' + msg + '\r\n');
}
if (o != undefined && logStream!==null) {
logStream.write( util.inspect(o,{depth: 2}) + '\r\n');
}
} catch (error) {
console.error('Logging not possible ' + error);
}
}