SctEseFormat.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #!/usr/bin/env python
  2. import sys
  3. from aman.types.ArrivalRoute import ArrivalRoute
  4. from aman.types.Exception import FormatError, InputError
  5. from aman.types.Waypoint import Waypoint
  6. class SctEseFormat:
  7. def readFile(filename : str):
  8. fileBlocks = {}
  9. block = None
  10. # read the file line by line and create segments based on []-entries
  11. with open(filename) as file:
  12. for line in file:
  13. line = line.strip()
  14. # found a new segment
  15. if line.startswith('['):
  16. block = line[1:-1]
  17. fileBlocks.setdefault(block, [])
  18. # append the last backend
  19. elif None != block and 0 != len(line):
  20. fileBlocks[block].append(line)
  21. return fileBlocks
  22. def parseWaypoint(waypoint : str, nameIdx : int, latitudeIdx : int, longitudeIdx : int):
  23. split = list(filter(None, waypoint.split(' ')))
  24. if len(split) <= longitudeIdx:
  25. raise FormatError('Invalid waypoint format: ' + waypoint)
  26. return Waypoint(split[nameIdx], Waypoint.dms2dd(split[latitudeIdx]), Waypoint.dms2dd(split[longitudeIdx]))
  27. def extractWaypoints(self, sctFilepath : str):
  28. config = SctEseFormat.readFile(sctFilepath)
  29. foundAirports = False
  30. foundVOR = False
  31. foundNDB = False
  32. foundFix = False
  33. for key in config:
  34. if 'VOR' == key:
  35. foundVOR = True
  36. elif 'NDB' == key:
  37. foundNDB = True
  38. elif 'FIXES' == key:
  39. foundFix = True
  40. elif 'AIRPORT' == key:
  41. foundAirports = True
  42. if False == foundVOR:
  43. raise FormatError('Unable to find VOR-entries in the sector file')
  44. if False == foundNDB:
  45. raise FormatError('Unable to find NDB-entries in the sector file')
  46. if False == foundFix:
  47. raise FormatError('Unable to find FIX-entries in the sector file')
  48. if False == foundAirports:
  49. raise FormatError('Unable to find AIRPORT-entries in the sector file')
  50. # extract all waypoints
  51. for waypoint in config['VOR']:
  52. waypoint = SctEseFormat.parseWaypoint(waypoint, 0, 2, 3)
  53. self.waypoints.setdefault(waypoint.name, []).append(waypoint)
  54. for waypoint in config['NDB']:
  55. waypoint = SctEseFormat.parseWaypoint(waypoint, 0, 1, 2)
  56. self.waypoints.setdefault(waypoint.name, []).append(waypoint)
  57. for waypoint in config['FIXES']:
  58. waypoint = SctEseFormat.parseWaypoint(waypoint, 0, 1, 2)
  59. self.waypoints.setdefault(waypoint.name, []).append(waypoint)
  60. # extract the airports
  61. for airport in config['AIRPORT']:
  62. airport = SctEseFormat.parseWaypoint(airport,0, 2, 3)
  63. self.airports.setdefault(airport.name, []).append(airport)
  64. def parseArrivalRoute(self, route : str, airport : Waypoint):
  65. # split the route and validate that it is a STAR for the airport
  66. split = route.split(':')
  67. if 5 != len(split) or 'STAR' != split[0] or split[1] != airport.name:
  68. return None
  69. # find all waypoints
  70. waypoints = []
  71. route = list(filter(None, split[4].split(' ')))
  72. for waypoint in route:
  73. # find the waypoint in the route
  74. coordinates = self.waypoints[waypoint]
  75. # no waypoint with this name defined
  76. if None == coordinates:
  77. raise FormatError('Unable to find waypoint ' + waypoint)
  78. # multiple waypoints, but use Haversine distance to distinct between candidates
  79. elif 1 != len(coordinates):
  80. minDistance = sys.float_info.max
  81. nearest = None
  82. # we assume that waypoints with the same name are not close each other
  83. for coordinate in coordinates:
  84. distance = coordinate.haversine(airport)
  85. # found a closer waypoint
  86. if minDistance > distance:
  87. minDistance = distance
  88. nearest = coordinate
  89. if None == nearest:
  90. raise InputError('Unable to find a close waypoint for ' + waypoint)
  91. waypoints.append(nearest)
  92. # extend the list of waypoints
  93. else:
  94. waypoints.append(coordinates[0])
  95. # create the arrival route
  96. return ArrivalRoute(split[3], split[2], waypoints)
  97. def extractArrivalRoutes(self, eseFilepath : str, airport : str, allowedRoutes : list):
  98. config = SctEseFormat.readFile(eseFilepath)
  99. foundSidsStars = False
  100. # search the airport in the extracted list
  101. if not airport in self.airports:
  102. raise InputError(airport + 'in self.airports', 'Unable to find the requested airport')
  103. airport = self.airports[airport][0]
  104. for key in config:
  105. if 'SIDSSTARS' == key:
  106. foundSidsStars = True
  107. if False == foundSidsStars:
  108. raise FormatError('Unable to find SIDSSTARS-entries in the sector file')
  109. # parse all arrival routes
  110. for line in config['SIDSSTARS']:
  111. route = self.parseArrivalRoute(line, airport)
  112. if None != route and route.name in allowedRoutes:
  113. self.arrivalRoutes.setdefault(route.name, []).append(route)
  114. def __init__(self, sctFilepath : str, eseFilepath : str, airport : str, allowedRoutes : list):
  115. self.arrivalRoutes = {}
  116. self.waypoints = {}
  117. self.airports = {}
  118. self.extractWaypoints(sctFilepath)
  119. print('Extracted ' + str(len(self.waypoints)) + ' waypoints')
  120. self.extractArrivalRoutes(eseFilepath, airport, allowedRoutes)
  121. print('Extracted ' + str(len(self.arrivalRoutes)) + ' arrival routes for ' + airport)