def mouseReleaseEvent(self, event):
     rxy = RadarCoords.fromQPointF(event.scenePos())
     if self.measuring_tool.isVisible() and event.button() in [
             Qt.LeftButton, Qt.RightButton
     ]:
         if self.using_special_tool:
             stxy = RadarCoords.fromQPointF(self.measuring_tool.pos())
             signals.specialTool.emit(EarthCoords.fromRadarCoords(stxy),
                                      self.measuring_tool.measuredHeading())
             self.measuring_tool.stop(False)
         else:  # using normal measuring tool
             if settings.measuring_tool_logs_coordinates:
                 print('RELEASE: %s' %
                       EarthCoords.fromRadarCoords(rxy).toString())
                 text, ok = QInputDialog.getText(
                     self.parent(), 'Logging coordinates',
                     'Text label for logged coordinates (optional):')
                 if ok:
                     print('TEXT: %s' % text)
             self.measuring_tool.stop(True)
     elif event.button() == Qt.LeftButton:
         if self.prevent_mouse_release_deselect or self.mouseGrabberItem(
         ) != None:
             self.prevent_mouse_release_deselect = False
         else:
             selection.deselect()
     self._mouseInfo_flyToMouse(rxy)
     QGraphicsScene.mouseReleaseEvent(self, event)
Пример #2
0
def get_airport_data(icao):
    result = AirportData()
    result.navpoint = world_navpoint_db.findAirfield(icao)

    # START WITH SIMPLE ONE-LINERS
    with open_airport_file(icao) as f:
        for line in f:
            row_type = line_code(line)

            if is_xplane_airport_header(line):  # HEADER LINE; get elevation
                tokens = line.split(maxsplit=2)
                result.field_elevation = float(tokens[1])

            elif row_type == 100:  # RUNWAY
                tokens = line.split()
                width = float(tokens[1])
                surface = int(tokens[2])
                name, lat, lon, disp_thr = tokens[8:12]
                rwy1 = DirRunway(name, EarthCoords(float(lat), float(lon)),
                                 float(disp_thr))
                name, lat, lon, disp_thr = tokens[17:21]
                rwy2 = DirRunway(name, EarthCoords(float(lat), float(lon)),
                                 float(disp_thr))
                result.addPhysicalRunway(width, surface, rwy1, rwy2)

            elif row_type == 102:  # HELIPAD
                tokens = line.split()
                row_code, name, lat, lon, ori, l, w, surface = tokens[:8]
                centre = EarthCoords(float(lat), float(lon))
                result.helipads.append(
                    Helipad(name, centre, int(surface), float(l), float(w),
                            Heading(float(ori), True)))

            elif row_type == 14:  # VIEWPOINT (NOTE: ATC-pie allows for more than one, though X-plane specifies one or zero)
                row_code, lat, lon, height, ignore, name = line.split(
                    maxsplit=5)
                result.viewpoints.append(
                    (EarthCoords(float(lat),
                                 float(lon)), float(height), name.strip()))

            elif row_type == 19:  # WINDSOCK
                row_code, lat, lon, ignore_rest_of_line = line.split(
                    maxsplit=3)
                result.windsocks.append(EarthCoords(float(lat), float(lon)))

            elif row_type == 1302:  # METADATA RECORD
                tokens = line.split()
                if len(tokens) == 3 and tokens[1] == 'transition_alt':
                    result.transition_altitude = int(tokens[2])

    # NOW COMPLEX MULTI-LINE READS
    result.ground_net = get_ground_network(icao)

    return result
Пример #3
0
def open_ad_positions_file():
    try:
        return open(custom_ad_pos_file, encoding='utf8')
    except FileNotFoundError:  # No custom airfield position file found; fall back on extracted X-plane inventory.
        try:
            return open(extracted_ad_pos_file, encoding='utf8')
        except FileNotFoundError:  # Airport positions not extracted yet; build file from packaged X-plane world file.
            with open(fallback_world_apt_dat_file, encoding='iso-8859-15'
                      ) as f:  # WARNING: X-plane data encoded in ISO-8859-15
                with open(extracted_ad_pos_file, 'w', encoding='utf8') as exf:
                    line = f.readline()
                    ad_count = 0
                    while line != '':  # not EOF
                        if is_xplane_airport_header(line):
                            row_code, ignore1, ignore2, ignore3, icao_code, long_name = line.split(
                                maxsplit=5)
                            if icao_code.isalpha(
                            ):  # Ignoring airports with numbers in them---to many of them, hardly ever useful
                                # we are inside the airport section looking for its coordinates
                                coords = None
                                line = f.readline()
                                while line != '' and not is_xplane_airport_header(
                                        line):
                                    if line_code(
                                            line
                                    ) == 14:  # X-plane viewpoint, unconditionally used as coords
                                        row_code, lat, lon, ignore_rest_of_line = line.split(
                                            maxsplit=3)
                                        coords = EarthCoords(
                                            float(lat), float(lon))
                                    elif coords == None and line_code(
                                            line
                                    ) == 100:  # falls back near a RWY end if no viewpoint for AD
                                        tokens = line.split()
                                        coords = EarthCoords(
                                            float(tokens[9]),
                                            float(tokens[10])).moved(
                                                Heading(360, True), .15)
                                    line = f.readline()
                                if coords != None:  # Airfields with unknown world coordinates are ignored
                                    exf.write('%s %s %s\n' %
                                              (icao_code, coords.toString(),
                                               long_name.strip()))
                                    ad_count += 1
                            else:
                                line = f.readline()
                        else:
                            line = f.readline()
                    # Terminate with the footer to mark a finished process
                    exf.write('%d\n' % ad_count)
            # Now file should exist
            return open(extracted_ad_pos_file, encoding='utf8')
Пример #4
0
def get_ground_network(icao):
    with open_airport_file(icao) as f:
        ground_net = GroundNetwork()
        source_edges = [
        ]  # GroundNetwork pretty labelling breaks if we add duplicate edges
        line = f.readline()
        line_number = 1
        while line != '':  # not EOF
            if line_code(line) == 1201:  # TWY node
                tokens = line.strip().split(maxsplit=5)
                lat, lon, ignore, nid = tokens[1:5]
                ground_net.addNode(nid, EarthCoords(float(lat), float(lon)))
            elif line_code(line) == 1202:  # TWY edge
                tokens = line.strip().split(maxsplit=5)
                v1, v2 = tokens[1:3]
                twy_name = rwy_spec = None
                if len(tokens) == 6:
                    if tokens[4] == 'runway':
                        rwy_spec = tokens[5].rstrip()
                    elif tokens[4].startswith(
                            'taxiway'
                    ):  # can be suffixed with "_X" to specify wing span
                        twy_name = tokens[5].rstrip()
                if {v1, v2} in source_edges:
                    print(
                        'WARNING: Ignoring duplicate ground route edge (%s, %s) in airport data file.'
                        % (v1, v2))
                else:
                    source_edges.append({v1, v2})
                    try:
                        ground_net.addEdge(v1, v2, rwy_spec, twy_name)
                    except KeyError:
                        print('Line %d: Invalid node for taxiway edge spec' %
                              line_number)
            elif line_code(line) == 1300:  # parking_position
                tokens = line.strip().split(maxsplit=6)
                if len(tokens) == 7:
                    lat, lon, hdg, typ, who, pkid = tokens[1:7]
                    if typ in ['gate', 'hangar', 'tie-down']:
                        pos = EarthCoords(float(lat), float(lon))
                        cats = [] if who == 'all' else who.split('|')
                        ground_net.addParkingPosition(
                            pkid, pos, Heading(float(hdg), True), typ, cats)
                else:
                    print('Line %d: Invalid parking position spec' %
                          line_number)
            line = f.readline()  # for new loop (more TWYs)
            line_number += 1
        return ground_net
Пример #5
0
def import_airfield_data():
    footer_line_count = None
    ad_added = 0
    with open_ad_positions_file() as f:
        for line in f:
            if line.startswith('#'):
                continue
            split = line.split(maxsplit=2)
            if len(split) == 3:
                icao_code, lat_lon, name = split
                coords = EarthCoords.fromString(lat_lon)
                world_navpoint_db.add(Airfield(icao_code, coords,
                                               name.strip()))
                ad_added += 1
            elif len(split) == 0:
                continue
            elif len(split) == 1 and footer_line_count == None:
                footer_line_count = int(split[0])
            else:
                raise ValueError(
                    'Bad or illegal spec line in AD positions file: %s' %
                    line.strip())
    if footer_line_count == None or footer_line_count != ad_added:
        print('ERROR: inconsistencies detected in the AD positions file.')
        print('This is usually caused by an interrupted extraction process. ' \
         'Running the "cleanUp.sh" script should solve the problem in this case.')
        raise ValueError('AD data corrupt')
Пример #6
0
	def closeEvent(self, event):
		if settings.session_manager.isRunning():
			settings.session_manager.stop()
		if settings.controlled_tower_viewer.running:
			settings.controlled_tower_viewer.stop(wait=True)
		if speech_recognition_available:
			cleanup_SR_language_files()
		print('Closing main window.')
		settings.saved_strip_racks = env.strips.rackNames()
		settings.saved_strip_dock_state = self.strip_pane.stateSave()
		settings.saved_workspace_windowed_view = self.central_workspace.windowedView()
		settings.saved_workspace_windows = self.central_workspace.workspaceWindowsStateSave()
		signals.mainWindowClosing.emit()
		signals.disconnect()
		settings.saveGeneralAndSystemSettings()
		settings.saveLocalSettings(env.airport_data)
		settings.savePresetChatMessages()
		env.resetEnv()
		settings.resetSession()
		EarthCoords.clearRadarPos()
		QMainWindow.closeEvent(self, event)
Пример #7
0
def import_ILS_capabilities(airport_data):
    with open_data_file_fallback(custom_navaid_file,
                                 fallback_navaid_file) as f:
        for line in f:
            # all lines with ILS codes [4..9] have similar structure:
            tokens = line.split(maxsplit=10)
            if not (len(tokens) == 11 and tokens[0] in '456789'):
                continue
            row_code, lat, lon, elev, frq, rng, qdm, ignore, ad, rwy, last_to_strip = tokens
            if ad == airport_data.navpoint.code:
                try:
                    drwy = airport_data.runway(rwy)
                    coords = EarthCoords(float(lat), float(lon))
                except KeyError:  # unknown RWY
                    print('Unknown RWY %s or bad LOC spec' % rwy)
                else:  # we are interested in the line spec
                    if row_code in ['4', '5']:  # LOC
                        drwy.ILS_cat = last_to_strip.strip()
                        drwy.LOC_freq = '%s.%s' % (frq[:3], frq[3:])
                        drwy.LOC_bearing = Heading(float(qdm), True)
                        drwy.LOC_range = drwy.threshold(dthr=True).distanceTo(
                            coords.moved(drwy.LOC_bearing.opposite(),
                                         float(rng)))
                    elif row_code == '6':  # GS (angle prefixes the bearing)
                        try:
                            iqdm = qdm.index('.') - 3
                        except ValueError:
                            iqdm = len(qdm) - 3
                        fpa_degrees = int(qdm[:iqdm]) / 100
                        drwy.param_FPA = 100 * tan(radians(fpa_degrees))
                        drwy.GS_range = drwy.threshold(dthr=True).distanceTo(
                            coords.moved(
                                Heading(float(qdm[iqdm:]), True).opposite(),
                                float(rng)))
                    elif row_code == '7':  # OM
                        drwy.OM_pos = coords
                    elif row_code == '8':  # MM
                        drwy.MM_pos = coords
                    elif row_code == '9':  # IM
                        drwy.IM_pos = coords
def get_ground_elevation_map(location_code):
    try:
        with open(elev_map_file_fmt % location_code, encoding='utf8') as f:
            nw = se = None
            line = f.readline()
            while nw == None and line != '':
                tokens = line.split('#', maxsplit=1)[0].split()
                if tokens == []:
                    line = f.readline()
                elif len(tokens) == 2:
                    nw = EarthCoords.fromString(tokens[0])
                    se = EarthCoords.fromString(tokens[1])
                else:
                    raise ValueError('invalid header line')
            if nw == None:
                raise ValueError('missing header line')
            matrix = []
            xprec = None
            line = f.readline()
            while line.strip() != '':
                values = [
                    float(token)
                    for token in line.split('#', maxsplit=1)[0].split()
                ]
                if xprec == None:
                    xprec = len(values)
                elif len(values) != xprec:
                    raise ValueError('expected %d values in row %d' %
                                     (xprec, len(matrix) + 1))
                matrix.append(values)  # add row
                line = f.readline()
        # Finished reading file.
        result = ElevationMap(nw.toRadarCoords(), se.toRadarCoords(),
                              len(matrix), xprec)
        for i, row in enumerate(matrix):
            for j, elev in enumerate(row):
                result.setElevation(i, j, elev)
        return result
    except ValueError as err:
        print('Error in elevation map: %s' % err)
Пример #9
0
def parse_xplane_node_line(line):
    '''
	returns a 5-value tuple:
	- node position
	- bezier ctrl point if not None
	- int paint type if not None
	- int light type if not None
	- bool if ending node (True if closes path), or None if path goes on
	'''
    if not is_xplane_node_line(line):
        raise ValueError('Not a node line: %s' % line)
    tokens = line.split()
    row_code = tokens[0]
    node_coords = EarthCoords(float(tokens[1]), float(tokens[2])).toQPointF()
    bezier_ctrl = EarthCoords(float(tokens[3]), float(
        tokens[4])).toQPointF() if row_code in ['112', '114', '116'] else None
    ending_spec = None if row_code in ['111', '112'
                                       ] else row_code in ['113', '114']
    paint_lights = [int(tk) for tk in tokens[3 if bezier_ctrl == None else 5:]]
    paint_type = next((t for t in paint_lights if t < 100), None)
    light_type = next((t for t in paint_lights if t >= 100), None)
    return node_coords, bezier_ctrl, paint_type, light_type, ending_spec
Пример #10
0
def import_navfix_data():
    with open_data_file_fallback(custom_navfix_file,
                                 fallback_navfix_file) as f:
        for line in f:
            match = navfix_line_regexp.search(line)
            if match:  # Fix spec line
                lat = float(match.group(1))
                lon = float(match.group(2))
                name = match.group(3)
                coordinates = EarthCoords(lat, lon)
                if name.isalpha() and len(name) == 5:
                    world_navpoint_db.add(Fix(name, coordinates))
                else:
                    world_navpoint_db.add(Rnav(name, coordinates))
Пример #11
0
def import_airway_data():
    with open_data_file_fallback(custom_airway_file,
                                 fallback_airway_file) as f:
        for line in f:
            tokens = line.split()
            if len(tokens) == 10:
                p1, lat1, lon1, p2, lat2, lon2, hi_lo, fl_lo, fl_hi, awy_name = tokens
                try:
                    navpoint1 = world_navpoint_db.findClosest(
                        EarthCoords(float(lat1), float(lon1)),
                        code=p1,
                        maxDist=awy_wp_max_dist)
                    navpoint2 = world_navpoint_db.findClosest(
                        EarthCoords(float(lat2), float(lon2)),
                        code=p2,
                        maxDist=awy_wp_max_dist)
                    world_routing_db.addAwy(navpoint1, navpoint2, awy_name,
                                            fl_lo, fl_hi)
                    world_routing_db.addAwy(
                        navpoint2, navpoint1, awy_name, fl_lo,
                        fl_hi)  # FUTURE better data with unidirectional AWYs
                except NavpointError:
                    #DEBUGprint('Ignoring AWY %s' % awy_name)
                    pass
Пример #12
0
def import_navaid_data():
    with open_data_file_fallback(custom_navaid_file,
                                 fallback_navaid_file) as f:
        dmelst = []  # list of DMEs to try to couple with NDBs/VOR(TAC)s
        for line in f:
            if line_code(line) in [2, 3]:  # NDB or VOR
                row_code, lat, lon, ignore1, frq, ignore2, ignore3, short_name, xplane_name = line.split(
                    maxsplit=8)
                long_name = xplane_name.strip()
                coords = EarthCoords(float(lat), float(lon))
                if row_code == '2':  # NDB
                    world_navpoint_db.add(
                        NDB(short_name, coords, frq, long_name))
                else:  # VOR/VORTAC
                    is_vortac = 'VORTAC' in long_name
                    world_navpoint_db.add(
                        VOR(short_name,
                            coords,
                            '%s.%s' % (frq[:3], frq[3:]),
                            long_name,
                            tacan=is_vortac))
            elif line_code(line) in [
                    12, 13
            ]:  # DME: 12 = coupled with VOR/VORTAC; 13 = standalone or coupled with NDB
                row_code, lat, lon, ignore1, ignore2, ignore3, ignore4, short_name, xplane_name = line.split(
                    maxsplit=8)
                coords = EarthCoords(float(lat), float(lon))
                t = Navpoint.VOR if row_code == '12' else Navpoint.NDB
                dmelst.append((short_name, coords, t))
        for name, pos, t in dmelst:
            try:
                p = world_navpoint_db.findClosest(pos, code=name, types=[t])
                p.dme = True
            except NavpointError:
                #debug('Not coupling DME for:', name, t)
                pass
Пример #13
0
def read_point(s):
    match = re_point.fullmatch(s)
    if match:
        if match.group('named') == None:  # lat/lon coordinates in SCT format
            lat, lon = s.split()
            lat_d, lat_m, lat_s = lat[1:].split('.', maxsplit=2)
            lon_d, lon_m, lon_s = lon[1:].split('.', maxsplit=2)
            return EarthCoords.fromString('%sd%sm%ss%s,%sd%sm%ss%s' \
             % (lat_d, lat_m, lat_s, lat[0].upper(), lon_d, lon_m, lon_s, lon[0].upper()))
        else:  # named point
            try:
                return env.navpoints.findUnique(
                    match.group('named')).coordinates
            except NavpointError as err:
                raise ValueError('Named point out of range or not unique: %s' %
                                 s)
    else:
        raise ValueError('Not a valid point spec: %s' % s)
 def mousePressEvent(self, event):
     QGraphicsScene.mousePressEvent(self, event)
     if not event.isAccepted():
         if event.button() == Qt.RightButton:
             self.using_special_tool = settings.session_manager.session_type == SessionType.TEACHER \
              and settings.session_manager.isRunning() and event.modifiers() & Qt.ShiftModifier
             self.measuring_tool.setPos(event.scenePos())
             if self.using_special_tool:  # using measuring tool with ulterior motive (creating teacher traffic)
                 self.measuring_tool.start(False)
             else:  # using normal measuring tool
                 self.measuring_tool.start(True)
                 rxy = RadarCoords.fromQPointF(event.scenePos())
                 self._mouseInfo_elevation(rxy)
                 if settings.measuring_tool_logs_coordinates:
                     print(
                         'Logging coordinates of new radar measurement...')
                     print('PRESS: %s' %
                           EarthCoords.fromRadarCoords(rxy).toString())
         if not event.button() == Qt.LeftButton or event.modifiers(
         ) & Qt.ShiftModifier:  # not panning
             event.accept()
def read_point_spec(specstr, db):
    mvlst = specstr.split('>')
    pbase = mvlst.pop(0)
    try:
        if ',' in pbase and '~' not in pbase:
            result = EarthCoords.fromString(pbase)
        else:
            result = navpointFromSpec(pbase, db).coordinates
    except NavpointError:
        raise ValueError(
            'No navpoint for "%s" or navpoint not unique (consider using `~\' operator)'
            % pbase)
    else:
        while mvlst != []:
            mv = mvlst.pop(0).split(',')
            if len(mv) == 2:
                radial = Heading(float(mv[0]), True)
                distance = float(mv[1])
                result = result.moved(radial, distance)
            else:
                raise ValueError('Bad use of `>\' in point spec "%s"' %
                                 specstr)
        return result
Пример #16
0
 def radarPos(self):
     return EarthCoords.getRadarPos()
Пример #17
0
    def run(self):
        ## PREPARING QUERY
        pos = env.radarPos()
        qdict = {
            'username': settings.MP_social_name,
            'lon': pos.lon,
            'lat': pos.lat,
            'range': some(settings.ORSX_handover_range, settings.radar_range),
            'xmlVersion': '1.0',
            'contacts': ','.join(
                acft.identifier for acft in
                env.radar.contacts())  # should this be all FGMS connections?
        }
        if settings.publicised_frequency != None:
            qdict['frequency'] = str(settings.publicised_frequency)
        server_response = server_query('getFlightplans', qdict)
        ## USING RESPONSE
        if server_response != None:
            try:
                ww_root = ElementTree.fromstring(server_response)
            except ElementTree.ParseError as parse_error:
                print('Parse error in SX server data: %s' % parse_error)
                return
            new_ATCs = []

            # ATCs first
            for ww_atc in ww_root.find('atcsInRange').iter(
                    'atc'):  # NOTE the server sends the full list each time
                atc = ATC(ww_atc.find('callsign').text)
                atc.social_name = ww_atc.find('username').text
                atc.position = EarthCoords(float(ww_atc.find('lat').text),
                                           float(ww_atc.find('lon').text))
                ww_frq = ww_atc.find('frequency').text
                try:
                    atc.frequency = CommFrequency(ww_frq)
                except ValueError:
                    atc.frequency = None
                new_ATCs.append(atc)
            self.ATCs_on_last_run = new_ATCs

            # Then strip data (contact claims and handover)
            for ww_flightplan in ww_root.iter(
                    'flightplan'
            ):  # NOTE the server only sends those when something changes
                ww_header = ww_flightplan.find('header')
                ww_callsign = ww_header.find('callsign').text
                ww_owner = ww_header.find('owner').text
                if ww_owner == None:
                    if ww_callsign in self.current_contact_claims:
                        del self.current_contact_claims[ww_callsign]
                else:
                    self.current_contact_claims[ww_callsign] = ww_owner

                if ww_header.find(
                        'handover'
                ).text == settings.session_manager.myCallsign(
                ):  # RECEIVE A STRIP!
                    strip = Strip()
                    strip.writeDetail(received_from_detail, ww_owner)
                    strip.writeDetail(
                        assigned_SQ_detail,
                        ck_int(ww_header.find('squawk').text, base=8))
                    strip.writeDetail(assigned_altitude_detail,
                                      ww_header.find('assignedAlt').text)
                    # Ignored from WW header above: <flags>, <assignedRunway>, <assignedRoute>, <status>, <flight>
                    # Ignored from WW data below: <fuelTime>; used with ulterior motive: <pilot>
                    ww_data = ww_flightplan.find('data')
                    # ATC-pie hides a token in <pilot>, wake turb. on its left and callsign to its right
                    # e.g. <pilot>M__ATC-pie__X-FOO</pilot> for M turb. and X-FOO strip callsign
                    # If the token is absent, we know the strip is from OpenRadar
                    hidden_tokens = some(ww_data.find('pilot').text,
                                         '').split(ATCpie_hidden_string,
                                                   maxsplit=1)
                    if len(
                            hidden_tokens
                    ) == 1:  # hidden marker NOT present; previous strip editor was OpenRadar
                        strip.writeDetail(FPL.CALLSIGN, ww_callsign)
                    else:  # recognise strip edited with ATC-pie
                        strip.writeDetail(FPL.WTC, hidden_tokens[0])
                        strip.writeDetail(FPL.CALLSIGN, hidden_tokens[1])
                    strip.writeDetail(FPL.FLIGHT_RULES,
                                      ww_data.find('type').text)
                    strip.writeDetail(FPL.ACFT_TYPE,
                                      ww_data.find('aircraft').text)
                    strip.writeDetail(FPL.ICAO_DEP,
                                      ww_data.find('departure').text)
                    strip.writeDetail(FPL.ICAO_ARR,
                                      ww_data.find('destination').text)
                    strip.writeDetail(FPL.ROUTE, ww_data.find('route').text)
                    strip.writeDetail(FPL.CRUISE_ALT,
                                      ww_data.find('cruisingAlt').text)
                    spd = ck_int(ww_data.find('trueAirspeed').text)
                    if spd != None:
                        strip.writeDetail(FPL.TAS, Speed(spd))
                    strip.writeDetail(FPL.COMMENTS,
                                      ww_data.find('remarks').text)
                    # Possibly ignored details (OpenRadar confuses FPLs and strips): DEP time, EET, alt. AD, souls [*]
                    signals.receiveStrip.emit(strip)
                    send_update(ww_callsign, strip)  # Acknowledge strip
Пример #18
0
 def updateMouseXY(self, sceneXY):
     self.target_point = EarthCoords.fromRadarCoords(
         RadarCoords.fromQPointF(sceneXY))
     p_acft = self.acft.coords().toRadarCoords()
     acft_qpoint = p_acft.toQPointF()
     # Get node route sequence
     if QPointF.dotProduct(
             sceneXY - acft_qpoint, sceneXY - acft_qpoint
     ) < min_taxi_drag * min_taxi_drag:  # min mouse move not reached
         self.node_route = None
     else:  # get route end nodes
         src_node = None
         dest_node = None
         if env.airport_data != None:
             src_node = env.airport_data.ground_net.closestNode(
                 self.acft.coords())
             if src_node != None:
                 dest_node = env.airport_data.ground_net.closestNode(
                     self.target_point, maxdist=taxi_tool_snap_dist)
         if src_node == None or dest_node == None:
             self.node_route = None
         else:
             try:
                 self.node_route = env.airport_data.ground_net.shortestTaxiRoute(
                     src_node, dest_node,
                     settings.taxi_instructions_avoid_runways)
                 p_src = env.airport_data.ground_net.nodePosition(
                     src_node).toRadarCoords()
                 if self.node_route == []:  # src and dest nodes are identical
                     if p_acft.distanceTo(
                             p_src) > groundnet_pos_taxi_precision:
                         self.node_route = [src_node]
                 else:  # first node of list is the one following src; check if we must insert src
                     p_next = env.airport_data.ground_net.nodePosition(
                         self.node_route[0]).toRadarCoords()
                     if not p_acft.isBetween(p_src, p_next,
                                             groundnet_pos_taxi_precision):
                         self.node_route.insert(0, src_node)
             except ValueError:  # no taxi route found
                 self.node_route = None
         # Get parking position
         self.parking_position = None
         if self.node_route == None or self.node_route == []:
             d_max_snap = taxi_tool_snap_dist
         else:
             d_last_node = env.airport_data.ground_net.nodePosition(
                 self.node_route[-1]).distanceTo(self.target_point)
             d_max_snap = min(taxi_tool_snap_dist, d_last_node)
         self.parking_position = env.airport_data.ground_net.closestParkingPosition(
             self.target_point, maxdist=d_max_snap)
     # Update bounding box and specify the lines to draw
     self.prepareGeometryChange()
     if self.node_route == None and self.parking_position == None:
         self.snapped_OK = False
         line_tip = sceneXY - acft_qpoint
         self.lines = [(QPointF(0, 0), line_tip)]
         self.bbox = QRectF(QPointF(0, 0), line_tip).normalized()
     else:
         self.snapped_OK = True
         self.lines = []
         self.bbox = QRectF(0, 0, 0, 0)
         prev = QPointF(0, 0)
         if self.node_route != None:
             for n in self.node_route:
                 p = env.airport_data.ground_net.nodePosition(
                     n).toQPointF() - acft_qpoint
                 self.lines.append((prev, p))
                 self.bbox |= QRectF(prev, p).normalized()
                 prev = p
         if self.parking_position != None:
             pk_point = env.airport_data.ground_net.parkingPosition(
                 self.parking_position).toQPointF() - acft_qpoint
             self.lines.append((prev, pk_point))
             self.bbox |= QRectF(prev, pk_point).normalized()
     self.update()
Пример #19
0
 def earthCoords(self):
     return EarthCoords.fromRadarCoords(
         RadarCoords.fromQPointF(self.scenePos()))
Пример #20
0
 def SEcoords(self):
     return EarthCoords.fromRadarCoords(
         RadarCoords.fromQPointF(
             self.mapToScene(self.boundingRect().bottomRight())))