Esempio n. 1
0
 def on_simstream_received(self, streamname, data, sender_id):
     if streamname == b'SIMINFO':
         speed, simdt, simt, simtclock, ntraf, state, scenname = data
         simt = tim2txt(simt)[:-3]
         simtclock = tim2txt(simtclock)[:-3]
         self.setNodeInfo(sender_id, simt, scenname)
         if sender_id == bs.net.actnode():
             self.siminfoLabel.setText(u'<b>t:</b> %s, <b>\u0394t:</b> %.2f, <b>Speed:</b> %.1fx, <b>UTC:</b> %s, <b>Mode:</b> %s, <b>Aircraft:</b> %d, <b>Conflicts:</b> %d/%d, <b>LoS:</b> %d/%d'
                 % (simt, simdt, speed, simtclock, self.modes[state], ntraf, self.nconf_cur, self.nconf_tot, self.nlos_cur, self.nlos_tot))
     elif streamname == b'ACDATA':
         self.nconf_cur = data['nconf_cur']
         self.nconf_tot = data['nconf_tot']
         self.nlos_cur = data['nlos_cur']
         self.nlos_tot = data['nlos_tot']
Esempio n. 2
0
 def on_simstream_received(self, streamname, data, sender_id):
     if streamname == b'SIMINFO':
         speed, simdt, simt, simtclock, ntraf, state, scenname = data
         simt = tim2txt(simt)[:-3]
         simtclock = tim2txt(simtclock)[:-3]
         self.setNodeInfo(sender_id, simt, scenname)
         if sender_id == bs.net.actnode():
             self.siminfoLabel.setText(u'<b>t:</b> %s, <b>\u0394t:</b> %.2f, <b>Speed:</b> %.1fx, <b>UTC:</b> %s, <b>Mode:</b> %s, <b>Aircraft:</b> %d, <b>Conflicts:</b> %d/%d, <b>LoS:</b> %d/%d'
                 % (simt, simdt, speed, simtclock, self.modes[state], ntraf, self.nconf_cur, self.nconf_tot, self.nlos_cur, self.nlos_tot))
     elif streamname == b'ACDATA':
         self.nconf_cur = data['nconf_cur']
         self.nconf_tot = data['nconf_tot']
         self.nlos_cur = data['nlos_cur']
         self.nlos_tot = data['nlos_tot']
Esempio n. 3
0
    def setclock(self, txt=""):
        """ Set simulated clock time offset"""
        if txt == "":
            pass  # avoid error message, just give time

        elif txt.upper() == "RUN":
            self.deltclock = 0.0
            self.simtclock = self.simt

        elif txt.upper() == "REAL":
            tclock = time.localtime()
            self.simtclock = tclock.tm_hour * 3600. + tclock.tm_min * 60. + tclock.tm_sec
            self.deltclock = self.simtclock - self.simt

        elif txt.upper() == "UTC":
            utclock = time.gmtime()
            self.simtclock = utclock.tm_hour * 3600. + utclock.tm_min * 60. + utclock.tm_sec
            self.deltclock = self.simtclock - self.simt

        elif txt.replace(":", "").replace(".", "").isdigit():
            self.simtclock = txt2tim(txt)
            self.deltclock = self.simtclock - self.simt
        else:
            return False, "Time syntax error"

        return True, "Time is now " + tim2txt(self.simtclock)
Esempio n. 4
0
    def setclock(self,txt=""):
        """ Set simulated clock time offset"""
        if txt == "":
            pass # avoid error message, just give time

        elif txt.upper()== "RUN":
            self.deltclock = 0.0
            self.simtclock = self.simt

        elif txt.upper()== "REAL":
            tclock = time.localtime()
            self.simtclock = tclock.tm_hour*3600. + tclock.tm_min*60. + tclock.tm_sec
            self.deltclock = self.simtclock - self.simt

        elif txt.upper()== "UTC":
            utclock = time.gmtime()
            self.simtclock = utclock.tm_hour*3600. + utclock.tm_min*60. + utclock.tm_sec
            self.deltclock = self.simtclock - self.simt

        elif txt.replace(":","").replace(".","").isdigit():
            self.simtclock = txt2tim(txt)
            self.deltclock = self.simtclock - self.simt
        else:
            return False,"Time syntax error"


        return True,"Time is now "+tim2txt(self.simtclock)
Esempio n. 5
0
def savecmd(cmd, line):
    ''' Save command line to file if SAVEIC is turned on. '''
    if savefile is None or cmd in saveexcl:
        return

    # Write in format "HH:MM:SS.hh>
    timtxt = tim2txt(bs.sim.simt - saveict0)
    savefile.write(f'{timtxt}>{line}\n')
Esempio n. 6
0
 def on_simstream_received(self, streamname, data, sender_id):
     if streamname == b'SIMINFO':
         speed, simdt, simt, simutc, ntraf, state, scenname = data
         simt = tim2txt(simt)[:-3]
         self.setNodeInfo(sender_id, simt, scenname)
         if sender_id == bs.net.actnode():
             acdata = bs.net.get_nodedata().acdata
             self.siminfoLabel.setText(u'<b>t:</b> %s, <b>\u0394t:</b> %.2f, <b>Speed:</b> %.1fx, <b>UTC:</b> %s, <b>Mode:</b> %s, <b>Aircraft:</b> %d, <b>Conflicts:</b> %d/%d, <b>LoS:</b> %d/%d'
                 % (simt, simdt, speed, simutc, self.modes[state], ntraf, acdata.nconf_cur, acdata.nconf_tot, acdata.nlos_cur, acdata.nlos_tot))
Esempio n. 7
0
    def stream(self, name, data, sender_id):

        if name == b'SIMINFO' and ConsoleUI.instance is not None:
            speed, simdt, simt, simutc, ntraf, state, scenname = data
            simt = tim2txt(simt)[:-3]
            self.setNodeInfo(sender_id, simt, scenname)
            if sender_id == bs.net.actnode():
                ConsoleUI.instance.set_infoline(
                    f'[b]t:[/b] {simt} [b]dt:[/b] {simdt} [b]Speed:[/b] {speed:.1f} [b]UTC:[/b] {simutc} [b]Mode:[/b] {self.modes[state]} [b]Aircraft:[/b] {ntraf}'
                )

            # concate times of all nodes
            node_times = "".join(
                [self.nodes[key]['time'] for key in self.nodes])

            # send to tui
            ConsoleUI.instance.set_nodes(copy.deepcopy(self.nodes), node_times)

        if name == b'ACDATA':
            self.extend_node_data(data, sender_id)
            if sender_id == bs.net.actnode():
                gen_data, table_data = self.get_traffic(data)
                ConsoleUI.instance.set_traffic(gen_data, table_data, sender_id)
Esempio n. 8
0
    def notify(self, receiver, event):
        # Keep track of event processing
        event_processed = False

        # Events from the simulation threads
        if receiver is self:
            if event.type() == PanZoomEventType:
                if event.zoom is not None:
                    event.origin = (self.radarwidget.width / 2,
                                    self.radarwidget.height / 2)

                if event.pan is not None and not event.absolute:
                    event.pan = (
                        2.0 * event.pan[0] /
                        (self.radarwidget.zoom * self.radarwidget.ar),
                        2.0 * event.pan[1] /
                        (self.radarwidget.zoom * self.radarwidget.flat_earth))

                # send the pan/zoom event to the radarwidget
                self.radarwidget.event(event)

            elif event.type() == ACDataEventType:
                self.acdata = event
                self.radarwidget.update_aircraft_data(event)
                if self.nd.ac_id in event.id:
                    idx = event.id.index(self.nd.ac_id.upper())
                    lat = event.lat[idx]
                    lon = event.lon[idx]
                    trk = event.trk[idx]
                    tas = event.tas[idx]
                    self.nd.update_aircraft_data(idx, lat, lon, tas, trk,
                                                 len(event.lat))
                return True

            elif event.type() == RouteDataEventType:
                self.routedata = event
                self.radarwidget.update_route_data(event)
                return True

            elif event.type() == DisplayShapeEventType:
                self.radarwidget.updatePolygon(event.name, event.data)

            elif event.type() == SimInfoEventType:
                simt = tim2txt(event.simt)[:-3]
                simtclock = tim2txt(event.simtclock)[:-3]
                self.win.setNodeInfo(manager.sender()[0], simt, event.scenname)
                if manager.sender()[0] == manager.actnode():
                    self.simt = event.simt
                    self.win.siminfoLabel.setText(
                        u'<b>t:</b> %s, <b>\u0394t:</b> %.2f, <b>Speed:</b> %.1fx, <b>UTC:</b> %s, <b>Mode:</b> %s, <b>Aircraft:</b> %d, <b>Conflicts:</b> %d/%d, <b>LoS:</b> %d/%d'
                        % (simt, event.simdt, event.sys_freq, simtclock,
                           self.modes[event.mode], event.n_ac,
                           self.acdata.nconf_cur, self.acdata.nconf_tot,
                           self.acdata.nlos_cur, self.acdata.nlos_tot))
                return True

            elif event.type() == StackTextEventType:
                event_processed = True
                if event.disptext:
                    self.win.console.echo(event.disptext)
                if event.cmdtext:
                    self.win.console.setCmdline(event.cmdtext)

            elif event.type() == StackInitEventType:
                event_processed = True
                self.win.console.addStackHelp(manager.sender()[0],
                                              event.stackdict)

            elif event.type() == ShowDialogEventType:
                if event.dialog_type == event.filedialog_type:
                    self.show_file_dialog()
                elif event.dialog_type == event.docwin_type:
                    self.show_doc_window(event.cmd)
                return True

            elif event.type() == DisplayFlagEventType:
                # Switch/toggle/cycle radar screen features e.g. from SWRAD command
                if event.switch == 'RESET':
                    self.radarwidget.clearNodeData()
                # Coastlines
                elif event.switch == "GEO":
                    self.radarwidget.show_coast = not self.radarwidget.show_coast

                # FIR boundaries
                elif event.switch == "FIR":
                    self.radarwidget.showfir = not self.radarwidget.showfir

                # Airport: 0 = None, 1 = Large, 2= All
                elif event.switch == "APT":
                    self.radarwidget.show_apt = not self.radarwidget.show_apt

                # Waypoint: 0 = None, 1 = VOR, 2 = also WPT, 3 = Also terminal area wpts
                elif event.switch == "VOR" or event.switch == "WPT" or event.switch == "WP" or event.switch == "NAV":
                    self.radarwidget.show_apt = not self.radarwidget.show_apt

                # Satellite image background on/off
                elif event.switch == "SAT":
                    self.radarwidget.show_map = not self.radarwidget.show_map

                # Satellite image background on/off
                elif event.switch == "TRAF":
                    self.radarwidget.show_traf = not self.radarwidget.show_traf

                # ND window for selected aircraft
                elif event.switch == "ND":
                    self.nd.setAircraftID(event.argument)
                    self.nd.setVisible(not self.nd.isVisible())

                elif event.switch == "SSD":
                    self.radarwidget.show_ssd(event.argument)

                elif event.switch == "SYM":
                    # For now only toggle PZ
                    self.radarwidget.show_pz = not self.radarwidget.show_pz

                elif event.switch == "DEFWPT":
                    self.radarwidget.defwpt(event.argument)

                elif event.switch == "FILTERALT":
                    # First argument is an on/off flag
                    nact = self.radarwidget.nodedata[manager.sender()[0]]
                    if event.argument[0]:
                        nact.filteralt = event.argument[1:]
                    else:
                        nact.filteralt = False

                return True

            elif event.type() == AMANEventType:
                # self.aman.update(self.simt, event)
                pass

        # Mouse/trackpad event handling for the Radar widget
        elif receiver is self.radarwidget and self.radarwidget.initialized:
            panzoom = None
            if event.type() == QEvent.Wheel:
                # For mice we zoom with control/command and the scrolwheel
                if event.modifiers() & Qt.ControlModifier:
                    origin = (event.pos().x(), event.pos().y())
                    zoom = 1.0
                    try:
                        if event.pixelDelta():
                            # High resolution scroll
                            zoom *= (1.0 + 0.01 * event.pixelDelta().y())
                        else:
                            # Low resolution scroll
                            zoom *= (1.0 + 0.001 * event.angleDelta().y())
                    except:
                        zoom *= (1.0 + 0.001 * event.delta())
                    panzoom = PanZoomEvent(zoom=zoom, origin=origin)

                # For touchpad scroll (2D) is used for panning
                else:
                    try:
                        dlat = 0.01 * event.pixelDelta().y() / (
                            self.radarwidget.zoom * self.radarwidget.ar)
                        dlon = -0.01 * event.pixelDelta().x() / (
                            self.radarwidget.zoom *
                            self.radarwidget.flat_earth)
                        panzoom = PanZoomEvent(pan=(dlat, dlon))
                    except:
                        pass

            # For touchpad, pinch gesture is used for zoom
            elif event.type() == QEvent.Gesture:
                zoom = None
                pan = None
                dlat = 0.0
                dlon = 0.0
                for g in event.gestures():
                    if g.gestureType() == Qt.PinchGesture:
                        if zoom is None:
                            zoom = 1.0
                        zoom *= g.scaleFactor()
                        if correct_pinch:
                            zoom /= g.lastScaleFactor()
                    elif g.gestureType() == Qt.PanGesture:
                        if abs(g.delta().y() + g.delta().x()) > 1e-1:
                            dlat += 0.005 * g.delta().y() / (
                                self.radarwidget.zoom * self.radarwidget.ar)
                            dlon -= 0.005 * g.delta().x() / (
                                self.radarwidget.zoom *
                                self.radarwidget.flat_earth)
                            pan = (dlat, dlon)
                if pan is not None or zoom is not None:
                    panzoom = PanZoomEvent(pan, zoom, self.mousepos)

            elif event.type(
            ) == QEvent.MouseButtonPress and event.button() & Qt.LeftButton:
                event_processed = True
                self.mousedragged = False
                # For mice we pan with control/command and mouse movement. Mouse button press marks the beginning of a pan
                self.prevmousepos = (event.x(), event.y())

            elif event.type() == QEvent.MouseButtonRelease and event.button(
            ) & Qt.LeftButton and not self.mousedragged:
                event_processed = True
                lat, lon = self.radarwidget.pixelCoordsToLatLon(
                    event.x(), event.y())
                tostack, tocmdline = radarclick(self.win.console.command_line,
                                                lat, lon, self.acdata,
                                                self.routedata)
                if len(tocmdline) > 0:
                    if '\n' in tocmdline:
                        self.win.console.setCmdline('')
                        # Clear any shape command preview on the radar display
                        self.radarwidget.previewpoly(None)
                    else:
                        self.win.console.appendCmdline(tocmdline)
                    if len(tostack) > 0:
                        self.win.console.stack(tostack)

            elif event.type() == QEvent.MouseMove:
                event_processed = True
                self.mousedragged = True
                self.mousepos = (event.x(), event.y())
                if event.buttons() & Qt.LeftButton:
                    dlat = 0.003 * (event.y() - self.prevmousepos[1]) / (
                        self.radarwidget.zoom * self.radarwidget.ar)
                    dlon = 0.003 * (self.prevmousepos[0] - event.x()) / (
                        self.radarwidget.zoom * self.radarwidget.flat_earth)
                    self.prevmousepos = (event.x(), event.y())
                    panzoom = PanZoomEvent(pan=(dlat, dlon))

            # Update pan/zoom to simulation thread only when the pan/zoom gesture is finished
            elif (event.type() == QEvent.MouseButtonRelease
                  or event.type() == QEvent.TouchEnd) and self.panzoomchanged:
                self.panzoomchanged = False
                manager.sendEvent(
                    PanZoomEvent(pan=(self.radarwidget.panlat,
                                      self.radarwidget.panlon),
                                 zoom=self.radarwidget.zoom,
                                 absolute=True))

            # If we've just processed a change to pan and/or zoom, send the event to the radarwidget
            if panzoom is not None:
                self.panzoomchanged = True
                return self.radarwidget.event(panzoom)

        # Send all key presses directly to the main window
        if event.type() == QEvent.KeyPress:
            self.win.keyPressEvent(event)
            return True

        # If we haven't processed the event: call Base Class Method to Continue Normal Event Processing
        if not event_processed:
            return super(Gui, self).notify(receiver, event)

        if self.win.console.cmd in [
                'AREA', 'BOX', 'POLY', 'POLYALT', 'POLYGON', 'CIRCLE', 'LINE'
        ]:
            if self.mousepos != self.prevmousepos and len(
                    self.win.console.args) >= 2:
                self.prevmousepos = self.mousepos
                try:
                    # get the largest even number of points
                    start = 0 if self.win.console.cmd == 'AREA' else 3 if self.win.console.cmd == 'POLYALT' else 1
                    end = (
                        (len(self.win.console.args) - start) / 2) * 2 + start
                    data = [float(v) for v in self.win.console.args[start:end]]
                    data += self.radarwidget.pixelCoordsToLatLon(
                        *self.mousepos)
                    self.radarwidget.previewpoly(self.win.console.cmd, data)

                except ValueError:
                    pass

        event.accept()
        return True
Esempio n. 9
0
    def update(self):
        """Draw a new frame"""
        # First check for keys & mouse
        self.keyb.update()
        # Navdisp mode: get center:
        if self.swnavdisp:
            i = bs.traf.id2idx(self.ndacid)
            if i >= 0:
                self.ndlat = bs.traf.lat[i]
                self.ndlon = bs.traf.lon[i]
                self.ndcrs = bs.traf.hdg[i]
            else:
                self.swnavdisp = False
        else:
            self.ndcrs = 0.0


        # Radar window
        # --------------Background--------------

        if self.redrawradbg or self.swnavdisp:
            if self.swnavdisp or not self.swsat:
                self.radbmp.fill(darkgrey)

            else:
                #--------------Satellite image--------------
                navsel = (self.lat0, self.lat1, \
                          self.lon0, self.lon1)
                if not self.satsel == navsel:
                    # Map cutting and scaling: normal case
                    if self.lon1 > self.lon0:
                        x0 = max(0, self.lon0 * self.mapax + self.mapbx)
                        x1 = min(self.mapbmp.get_width() - 1, \
                                 self.lon1 * self.mapax + self.mapbx)

                        y1 = min(self.mapbmp.get_height() - 1, \
                                 self.lat0 * self.mapay + self.mapby)
                        y0 = max(0, self.lat1 * self.mapay + self.mapby)

                        selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0))
                        mapsel = self.mapbmp.subsurface(selrect)
                        self.submap = pg.transform.scale(mapsel, \
                                                         (self.width, self.height))

                        self.radbmp.blit(self.submap, (0, 0))

                    else:
                        # Wrap around case: clip two segments
                        w0 = int(self.width * (180. - self.lon0) / \
                                 (180.0 - self.lon0 + self.lon1 + 180.))
                        w1 = int(self.width - w0)

                        # Left part
                        x0 = max(0, self.lon0 * self.mapax + self.mapbx)
                        x1 = self.mapbmp.get_width() - 1

                        y1 = min(self.mapbmp.get_height() - 1, \
                                 self.lat0 * self.mapay + self.mapby)
                        y0 = max(0, self.lat1 * self.mapay + self.mapby)

                        selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0))
                        mapsel = self.mapbmp.subsurface(selrect)
                        self.submap = pg.transform.scale(mapsel, \
                                                         (w0, self.height))
                        self.radbmp.blit(self.submap, (0, 0))

                        # Right half
                        x0 = 0
                        x1 = min(self.mapbmp.get_width() - 1, \
                                 self.lon1 * self.mapax + self.mapbx)

                        selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0))
                        mapsel = self.mapbmp.subsurface(selrect)
                        self.submap = pg.transform.scale(mapsel, \
                                                         (w1, self.height))
                        self.radbmp.blit(self.submap, (w0, 0))
                        self.submap = self.radbmp.copy()

                    self.satsel = navsel

                else:
                    # Map blit only
                    self.radbmp.blit(self.submap, (0, 0))


            if self.swgrid and not self.swnavdisp:
                # ------Draw lat/lon grid------
                ngrad = int(self.lon1 - self.lon0)

                if ngrad >= 10:
                    step = 10
                    i0 = step * int(self.lon0 / step)
                    j0 = step * int(self.lat0 / step)
                else:
                    step = 1
                    i0 = int(self.lon0)
                    j0 = int(self.lon0)

                for i in range(i0, int(self.lon1 + 1.), step):
                    x, y = self.ll2xy(self.ctrlat, i)
                    pg.draw.line(self.radbmp, lightgreygreen, \
                                 (x, 0), (x, self.height))

                for j in range(j0, int(self.lat1 + 1.), step):
                    x, y = self.ll2xy(j, self.ctrlon)
                    pg.draw.line(self.radbmp, lightgreygreen, \
                                 (0, y), (self.width, y))

            #------ Draw coastlines ------
            if self.swgeo:
                # cx,cy = -1,-1
                geosel = (self.lat0, self.lon0, self.lat1, self.lon1)
                if self.geosel != geosel:
                    self.geosel = geosel

                    self.cstsel = np.where(
                        self.onradar(self.coastlat0, self.coastlon0) + \
                        self.onradar(self.coastlat1, self.coastlon1))

                    # print len(self.cstsel[0])," coastlines"
                    self.cx0, self.cy0 = self.ll2xy(self.coastlat0, self.coastlon0)
                    self.cx1, self.cy1 = self.ll2xy(self.coastlat1, self.coastlon1)

                for i in list(self.cstsel[0]):
                    pg.draw.line(self.radbmp, grey, (self.cx0[i], self.cy0[i]), \
                                 (self.cx1[i], self.cy1[i]))

            #------ Draw FIRs ------
            if self.swfir:
                self.firx0, self.firy0 = self.ll2xy(bs.navdb.firlat0, \
                                                    bs.navdb.firlon0)

                self.firx1, self.firy1 = self.ll2xy(bs.navdb.firlat1, \
                                                    bs.navdb.firlon1)

                for i in range(len(self.firx0)):
                    pg.draw.line(self.radbmp, lightcyan,
                                 (self.firx0[i], self.firy0[i]),
                                 (self.firx1[i], self.firy1[i]))

            # -----------------Waypoint & airport symbols-----------------
            # Check whether we need to reselect waypoint set to be drawn

            navsel = (self.lat0, self.lat1, \
                      self.lon0, self.lon1)
            if self.navsel != navsel:
                self.navsel = navsel

                # Make list of indices of waypoints & airports on screen

                self.wpinside = list(np.where(self.onradar(bs.navdb.wplat, \
                                                           bs.navdb.wplon))[0])

                self.wptsel = []
                for i in self.wpinside:
                    if self.wpsw == 3 or \
                            (self.wpsw == 1 and len(bs.navdb.wpid[i]) == 3) or \
                            (self.wpsw == 2 and bs.navdb.wpid[i].isalpha()):
                        self.wptsel.append(i)
                self.wptx, self.wpty = self.ll2xy(bs.navdb.wplat, bs.navdb.wplon)

                self.apinside = list(np.where(self.onradar(bs.navdb.aptlat, \
                                                           bs.navdb.aptlon))[0])

                self.aptsel = []
                for i in self.apinside:
                    if self.apsw == 2 or (self.apsw == 1 and \
                                                      bs.navdb.aptmaxrwy[i] > 1000.):
                        self.aptsel.append(i)
                self.aptx, self.apty = self.ll2xy(bs.navdb.aptlat, bs.navdb.aptlon)


            #------- Draw waypoints -------
            if self.wpsw > 0:
                # print len(self.wptsel)," waypoints"
                if len(self.wptsel) < self.maxnrwp:
                    wptrect = self.wptsymbol.get_rect()
                    for i in self.wptsel:
                        # wptrect.center = self.ll2xy(bs.navdb.wplat[i],  \
                        #     bs.navdb.wplon[i])
                        wptrect.center = self.wptx[i], self.wpty[i]
                        self.radbmp.blit(self.wptsymbol, wptrect)

                        # If waypoint label bitmap does not yet exist, make it
                        if not self.wpswbmp[i]:
                            self.wplabel[i] = pg.Surface((80, 30), 0, self.win)
                            self.fontnav.printat(self.wplabel[i], 0, 0, \
                                                 bs.navdb.wpid[i])
                            self.wpswbmp[i] = True

                        # In any case, blit it
                        xtxt = wptrect.right + 2
                        ytxt = wptrect.top
                        self.radbmp.blit(self.wplabel[i], (xtxt, ytxt), \
                                         None, pg.BLEND_ADD)

                        if not self.wpswbmp[i]:
                            xtxt = wptrect.right + 2
                            ytxt = wptrect.top

                            # self.fontnav.printat(self.radbmp,xtxt,ytxt, \
                            #     bs.navdb.wpid[i])

            #------- Draw airports -------
            if self.apsw > 0:
                # if len(self.aptsel)<800:
                aptrect = self.aptsymbol.get_rect()

                # print len(self.aptsel)," airports"

                for i in self.aptsel:
                    # aptrect.center = self.ll2xy(bs.navdb.aptlat[i],  \
                    #                            bs.navdb.aptlon[i])
                    aptrect.center = self.aptx[i], self.apty[i]
                    self.radbmp.blit(self.aptsymbol, aptrect)

                    # If airport label bitmap does not yet exist, make it
                    if not self.apswbmp[i]:
                        self.aplabel[i] = pg.Surface((50, 30), 0, self.win)
                        self.fontnav.printat(self.aplabel[i], 0, 0, \
                                             bs.navdb.aptid[i])
                        self.apswbmp[i] = True

                    # In either case, blit it
                    xtxt = aptrect.right + 2
                    ytxt = aptrect.top
                    self.radbmp.blit(self.aplabel[i], (xtxt, ytxt), \
                                     None, pg.BLEND_ADD)

                    # self.fontnav.printat(self.radbmp,xtxt,ytxt, \
                    #     bs.navdb.aptid[i])


            #---------- Draw background trails ----------
            if bs.traf.trails.active:
                bs.traf.trails.buffer()  # move all new trails to background

                trlsel = list(np.where(
                    self.onradar(bs.traf.trails.bglat0, bs.traf.trails.bglon0) + \
                    self.onradar(bs.traf.trails.bglat1, bs.traf.trails.bglon1))[0])

                x0, y0 = self.ll2xy(bs.traf.trails.bglat0, bs.traf.trails.bglon0)
                x1, y1 = self.ll2xy(bs.traf.trails.bglat1, bs.traf.trails.bglon1)

                for i in trlsel:
                    pg.draw.aaline(self.radbmp, bs.traf.trails.bgcol[i], \
                                   (x0[i], y0[i]), (x1[i], y1[i]))

            #---------- Draw ADSB Coverage Area
            if self.swAdsbCoverage:
                # These points are based on the positions of the antennas with range = 200km
                adsbCoverageLat = [53.7863,53.5362,52.8604,51.9538,51.2285,50.8249,50.7382,
                                   50.9701,51.6096,52.498,53.4047,53.6402]
                adsbCoverageLon = [4.3757,5.8869,6.9529,7.2913,6.9312,6.251,5.7218,4.2955,
                                   3.2162,2.7701,3.1117,3.4891]

                for i in range(0,len(adsbCoverageLat)):
                    if i == len(adsbCoverageLat)-1:
                        x0, y0 = self.ll2xy(adsbCoverageLat[i],adsbCoverageLon[i])
                        x1, y1 = self.ll2xy(adsbCoverageLat[0],adsbCoverageLon[0])

                    else:
                        x0, y0 = self.ll2xy(adsbCoverageLat[i],adsbCoverageLon[i])
                        x1, y1 = self.ll2xy(adsbCoverageLat[i+1],adsbCoverageLon[i+1])

                    pg.draw.line(self.radbmp, red,(x0, y0), (x1, y1))

            # User defined objects
            for i in range(len(self.objtype)):

                # Draw LINE or POLYGON with objdata = [lat0,lon,lat1,lon1,lat2,lon2,..]
                if self.objtype[i]=='LINE' or self.objtype[i]=="POLY":
                    npoints = len(self.objdata[i])/2
                    print(npoints)
                    x0,y0 = self.ll2xy(self.objdata[i][0],self.objdata[i][1])
                    for j in range(1,npoints):
                        x1,y1 = self.ll2xy(self.objdata[i][j*2],self.objdata[i][j*2+1])
                        pg.draw.line(self.radbmp,self.objcolor[i],(x0, y0), (x1, y1))
                        x0,y0 = x1,y1

                    if self.objtype[i]=="POLY":
                        x1,y1 = self.ll2xy(self.objdata[i][0],self.objdata[i][1])
                        pg.draw.line(self.radbmp,self.objcolor[i],(x0, y0), (x1, y1))

                # Draw bounding box of objdata = [lat0,lon0,lat1,lon1]
                elif self.objtype[i]=='BOX':
                    lat0 = min(self.objdata[i][0],self.objdata[i][2])
                    lon0 = min(self.objdata[i][1],self.objdata[i][3])
                    lat1 = max(self.objdata[i][0],self.objdata[i][2])
                    lon1 = max(self.objdata[i][1],self.objdata[i][3])

                    x0,y0 = self.ll2xy(lat1,lon0)
                    x1,y1 = self.ll2xy(lat0,lon1)
                    pg.draw.rect(self.radbmp,self.objcolor[i],pg.Rect(x0, y0, x1-x0, y1-y0),1)

                # Draw circle with objdata = [latcenter,loncenter,radiusnm]
                elif self.objtype[i]=='CIRCLE':
                    pass
                    xm,ym     = self.ll2xy(self.objdata[i][0],self.objdata[i][1])
                    xtop,ytop = self.ll2xy(self.objdata[i][0]+self.objdata[i][2]/60.,self.objdata[i][1])
                    radius    = int(round(abs(ytop-ym)))
                    pg.draw.circle(self.radbmp, self.objcolor[i], (int(xm),int(ym)), radius, 1)

            # Reset background drawing switch
            self.redrawradbg = False

        ##############################################################################
        #                          END OF BACKGROUND DRAWING                         #
        ##############################################################################

        # Blit background
        self.win.blit(self.radbmp, (0, 0))

        # Decide to redraw radar picture of a/c
        syst = pg.time.get_ticks() * 0.001
        redrawrad = self.redrawradbg or abs(syst - self.radt0) >= self.radardt

        if redrawrad:
            self.radt0 = syst  # Update lats drawing time of radar


            # Select which aircraft are within screen area
            trafsel = np.where((bs.traf.lat > self.lat0) * (bs.traf.lat < self.lat1) * \
                               (bs.traf.lon > self.lon0) * (bs.traf.lon < self.lon1))[0]

            # ------------------- Draw aircraft -------------------
            # Convert lat,lon to x,y

            trafx, trafy = self.ll2xy(bs.traf.lat, bs.traf.lon)
            trafy -= bs.traf.alt*self.isoalt

            if bs.traf.trails.active:
                ltx, lty = self.ll2xy(bs.traf.trails.lastlat, bs.traf.trails.lastlon)

            # Find pixel size of horizontal separation on screen
            pixelrad=self.dtopix_eq(bs.traf.asas.R/2)

            # Loop through all traffic indices which we found on screen
            for i in trafsel:

                # Get index of ac symbol, based on heading and its rect object
                isymb = int(round((bs.traf.hdg[i] - self.ndcrs) / 6.)) % 60
                pos = self.acsymbol[isymb].get_rect()

                # Draw aircraft symbol
                pos.centerx = trafx[i]
                pos.centery = trafy[i]
                dy = self.fontrad.linedy * 7 / 6

                # Draw aircraft altitude line
                if self.isoalt>1e-7:
                    pg.draw.line(self.win,white,(int(trafx[i]),int(trafy[i])),(int(trafx[i]),int(trafy[i]+bs.traf.alt[i]*self.isoalt)))

                # Normal symbol if no conflict else amber
                toosmall=self.lat1-self.lat0>6 #don't draw circles if zoomed out too much

                if len(bs.traf.asas.iconf[i]) == 0:
                    self.win.blit(self.acsymbol[isymb], pos)
                    if self.swsep and not toosmall:
                        pg.draw.circle(self.win,green,(int(trafx[i]),int(trafy[i])),pixelrad,1)
                else:
                    self.win.blit(self.ambacsymbol[isymb], pos)
                    if self.swsep and not toosmall:
                        pg.draw.circle(self.win,amber,(int(trafx[i]),int(trafy[i])),pixelrad,1)


                # Draw last trail part
                if bs.traf.trails.active:
                    pg.draw.line(self.win, tuple(bs.traf.trails.accolor[i]),
                                 (ltx[i], lty[i]), (trafx[i], trafy[i]))

                # Label text
                label = []
                if self.swlabel > 0:
                    label.append(bs.traf.id[i])  # Line 1 of label: id
                else:
                    label.append(" ")
                if self.swlabel > 1:
                    label.append(str(int(bs.traf.alt[i] / ft)))  # Line 2 of label: altitude
                else:
                    label.append(" ")
                if self.swlabel > 2:
                    cas = bs.traf.cas[i] / kts
                    label.append(str(int(round(cas))))  # line 3 of label: speed
                else:
                    label.append(" ")


                # Check for changes in traffic label text
                if  not (type(bs.traf.label[i])==list) or \
                      not (type(bs.traf.label[i][3])==str) or \
                        not (label[:3] == bs.traf.label[i][:3]):
                            
                    bs.traf.label[i] = []
                    labelbmp = pg.Surface((100, 60), 0, self.win)
                    if len(bs.traf.asas.iconf[i]) == 0:
                        acfont = self.fontrad
                    else:
                        acfont = self.fontamb

                    acfont.printat(labelbmp, 0, 0, label[0])
                    acfont.printat(labelbmp, 0, dy, label[1])
                    acfont.printat(labelbmp, 0, 2 * dy, label[2])

                    bs.traf.label[i].append(label[0])
                    bs.traf.label[i].append(label[1])
                    bs.traf.label[i].append(label[2])
                    bs.traf.label[i].append(labelbmp)

                # Blit label
                dest = bs.traf.label[i][3].get_rect()
                dest.top = trafy[i] - 5
                dest.left = trafx[i] + 15
                self.win.blit(bs.traf.label[i][3], dest, None, pg.BLEND_ADD)

                # Draw aircraft speed vectors
                if self.swspd:
                    # just a nominal length: a speed of 150 kts will be displayed
                    # as an arrow of 30 pixels long on screen
                    nomlength    = 30
                    nomspeed     = 150.

                    vectorlength = float(nomlength)*bs.traf.tas[i]/nomspeed

                    spdvcx = trafx[i] + np.sin(np.radians(bs.traf.trk[i])) * vectorlength
                    spdvcy = trafy[i] - np.cos(np.radians(bs.traf.trk[i])) * vectorlength \
                                - bs.traf.vs[i]/nomspeed*nomlength*self.isoalt /   \
                                            self.dtopix_eq(1e5)*1e5

                    pg.draw.line(self.win,green,(trafx[i],trafy[i]),(spdvcx,spdvcy))

            # ---- End of per aircraft i loop


            # Draw conflicts: line from a/c to closest point of approach
            if bs.traf.asas.nconf>0:
                xc,yc = self.ll2xy(bs.traf.asas.latowncpa,bs.traf.asas.lonowncpa)
                yc    = yc - bs.traf.asas.altowncpa*self.isoalt

                for j in range(bs.traf.asas.nconf):
                    i = bs.traf.id2idx(bs.traf.asas.confpairs[j][0])
                    if i>=0 and i<bs.traf.ntraf and (i in trafsel):
                        pg.draw.line(self.win,amber,(xc[j],yc[j]),(trafx[i],trafy[i]))

            # Draw selected route:
            if self.acidrte != "":
                i = bs.traf.id2idx(self.acidrte)
                if i >= 0:
                    for j in range(0,bs.traf.ap.route[i].nwp):
                        if j==0:
                            x1,y1 = self.ll2xy(bs.traf.ap.route[i].wplat[j], \
                                               bs.traf.ap.route[i].wplon[j])
                        else:
                            x0,y0 = x1,y1
                            x1,y1 = self.ll2xy(bs.traf.ap.route[i].wplat[j], \
                                               bs.traf.ap.route[i].wplon[j])
                            pg.draw.line(self.win, magenta,(x0,y0),(x1,y1))

                        if j>=len(self.rtewpid) or not self.rtewpid[j]== bs.traf.ap.route[i].wpname[j]:
                            # Waypoint name labels
                            # If waypoint label bitmap does not yet exist, make it

                            # Waypoint name and constraint(s), if there are any
                            txt = bs.traf.ap.route[i].wpname[j]

                            alt = bs.traf.ap.route[i].wpalt[j]
                            spd = bs.traf.ap.route[i].wpspd[j]

                            if alt>=0. or spd >=0.:
                                # Altitude
                                if alt < 0:
                                    txt = txt + " -----/"

                                elif alt > 4500 * ft:
                                    FL = int(round((alt/(100.*ft))))
                                    txt = txt+" FL"+str(FL)+"/"

                                else:
                                    txt = txt+" "+str(int(round(alt / ft))) + "/"

                                # Speed
                                if spd < 0:
                                    txt = txt+"---"
                                else:
                                    txt = txt+str(int(round(spd / kts)))

                            wplabel = pg.Surface((128, 32), 0, self.win)
                            self.fontnav.printat(wplabel, 0, 0, \
                                                 txt)

                            if j>=len(self.rtewpid):
                                self.rtewpid.append(txt)
                                self.rtewplabel.append(wplabel)
                            else:
                                self.rtewpid[j]    = txt
                                self.rtewplabel[j] = wplabel

                        # In any case, blit the waypoint name
                        xtxt = x1 + 7
                        ytxt = y1 - 3
                        self.radbmp.blit(self.rtewplabel[j], (xtxt, ytxt), \
                                         None, pg.BLEND_ADD)

                        # Line from aircraft to active waypoint
                        if bs.traf.ap.route[i].iactwp == j:
                            x0,y0 = self.ll2xy(bs.traf.lat[i],bs.traf.lon[i])
                            pg.draw.line(self.win, magenta,(x0,y0),(x1,y1))



            # Draw aircraft trails which are on screen
            if bs.traf.trails.active:
                trlsel = list(np.where(
                    self.onradar(bs.traf.trails.lat0, bs.traf.trails.lon0) + \
                    self.onradar(bs.traf.trails.lat1, bs.traf.trails.lon1))[0])

                x0, y0 = self.ll2xy(bs.traf.trails.lat0, bs.traf.trails.lon0)
                x1, y1 = self.ll2xy(bs.traf.trails.lat1, bs.traf.trails.lon1)

                for i in trlsel:
                    pg.draw.line(self.win, bs.traf.trails.col[i], \
                                 (x0[i], y0[i]), (x1[i], y1[i]))

                # Redraw background => buffer ; if >1500 foreground linepieces on screen
                if len(trlsel) > 1500:
                    self.redrawradbg = True

        # Draw edit window
        self.editwin.update()

        if self.redrawradbg or redrawrad or self.editwin.redraw:
            self.win.blit(self.menu.bmps[self.menu.ipage], \
                           (self.menu.x, self.menu.y))
            self.win.blit(self.editwin.bmp, (self.editwin.winx, self.editwin.winy))

            # Draw frames
            pg.draw.rect(self.win, white, self.editwin.rect, 1)
            pg.draw.rect(self.win, white, pg.Rect(1, 1, self.width - 1, self.height - 1), 1)

            # Add debug line
            self.fontsys.printat(self.win, 10, 2, tim2txt(bs.sim.simtclock))
            self.fontsys.printat(self.win, 10, 18, tim2txt(bs.sim.simt))
            self.fontsys.printat(self.win, 10+80, 2, \
                                 "ntraf = " + str(bs.traf.ntraf))
            self.fontsys.printat(self.win, 10+160, 2, \
                                 "Freq=" + str(int(len(bs.sim.dts) / max(0.001, sum(bs.sim.dts)))))

            self.fontsys.printat(self.win, 10+240, 2, \
                                 "#LOS      = " + str(len(bs.traf.asas.LOSlist_now)))
            self.fontsys.printat(self.win, 10+240, 18, \
                                 "Total LOS = " + str(len(bs.traf.asas.LOSlist_all)))
            self.fontsys.printat(self.win, 10+240, 34, \
                                 "#Con      = " + str(len(bs.traf.asas.conflist_now)))
            self.fontsys.printat(self.win, 10+240, 50, \
                                 "Total Con = " + str(len(bs.traf.asas.conflist_all)))

            # Frame ready, flip to screen
            pg.display.flip()

            # If needed, take a screenshot
            if self.screenshot:
                pg.image.save(self.win,self.screenshotname)
                self.screenshot=False
        return
Esempio n. 10
0
    def update(self):
        """Draw a new frame"""
        # First check for keys & mouse
        self.keyb.update()
        # Navdisp mode: get center:
        if self.swnavdisp:
            i = bs.traf.id2idx(self.ndacid)
            if i >= 0:
                self.ndlat = bs.traf.lat[i]
                self.ndlon = bs.traf.lon[i]
                self.ndcrs = bs.traf.hdg[i]
            else:
                self.swnavdisp = False
        else:
            self.ndcrs = 0.0

        # Radar window
        # --------------Background--------------

        if self.redrawradbg or self.swnavdisp:
            if self.swnavdisp or not self.swsat:
                self.radbmp.fill(darkgrey)

            else:
                #--------------Satellite image--------------
                navsel = (self.lat0, self.lat1, \
                          self.lon0, self.lon1)
                if not self.satsel == navsel:
                    # Map cutting and scaling: normal case
                    if self.lon1 > self.lon0:
                        x0 = max(0, self.lon0 * self.mapax + self.mapbx)
                        x1 = min(self.mapbmp.get_width() - 1, \
                                 self.lon1 * self.mapax + self.mapbx)

                        y1 = min(self.mapbmp.get_height() - 1, \
                                 self.lat0 * self.mapay + self.mapby)
                        y0 = max(0, self.lat1 * self.mapay + self.mapby)

                        selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0))
                        mapsel = self.mapbmp.subsurface(selrect)
                        self.submap = pg.transform.scale(mapsel, \
                                                         (self.width, self.height))

                        self.radbmp.blit(self.submap, (0, 0))

                    else:
                        # Wrap around case: clip two segments
                        w0 = int(self.width * (180. - self.lon0) / \
                                 (180.0 - self.lon0 + self.lon1 + 180.))
                        w1 = int(self.width - w0)

                        # Left part
                        x0 = max(0, self.lon0 * self.mapax + self.mapbx)
                        x1 = self.mapbmp.get_width() - 1

                        y1 = min(self.mapbmp.get_height() - 1, \
                                 self.lat0 * self.mapay + self.mapby)
                        y0 = max(0, self.lat1 * self.mapay + self.mapby)

                        selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0))
                        mapsel = self.mapbmp.subsurface(selrect)
                        self.submap = pg.transform.scale(mapsel, \
                                                         (w0, self.height))
                        self.radbmp.blit(self.submap, (0, 0))

                        # Right half
                        x0 = 0
                        x1 = min(self.mapbmp.get_width() - 1, \
                                 self.lon1 * self.mapax + self.mapbx)

                        selrect = pg.Rect(x0, y0, abs(x1 - x0), abs(y1 - y0))
                        mapsel = self.mapbmp.subsurface(selrect)
                        self.submap = pg.transform.scale(mapsel, \
                                                         (w1, self.height))
                        self.radbmp.blit(self.submap, (w0, 0))
                        self.submap = self.radbmp.copy()

                    self.satsel = navsel

                else:
                    # Map blit only
                    self.radbmp.blit(self.submap, (0, 0))

            if self.swgrid and not self.swnavdisp:
                # ------Draw lat/lon grid------
                ngrad = int(self.lon1 - self.lon0)

                if ngrad >= 10:
                    step = 10
                    i0 = step * int(self.lon0 / step)
                    j0 = step * int(self.lat0 / step)
                else:
                    step = 1
                    i0 = int(self.lon0)
                    j0 = int(self.lon0)

                for i in range(i0, int(self.lon1 + 1.), step):
                    x, y = self.ll2xy(self.ctrlat, i)
                    pg.draw.line(self.radbmp, lightgreygreen, \
                                 (x, 0), (x, self.height))

                for j in range(j0, int(self.lat1 + 1.), step):
                    x, y = self.ll2xy(j, self.ctrlon)
                    pg.draw.line(self.radbmp, lightgreygreen, \
                                 (0, y), (self.width, y))

            #------ Draw coastlines ------
            if self.swgeo:
                # cx,cy = -1,-1
                geosel = (self.lat0, self.lon0, self.lat1, self.lon1)
                if self.geosel != geosel:
                    self.geosel = geosel

                    self.cstsel = np.where(
                        self.onradar(self.coastlat0, self.coastlon0) + \
                        self.onradar(self.coastlat1, self.coastlon1))

                    # print len(self.cstsel[0])," coastlines"
                    self.cx0, self.cy0 = self.ll2xy(self.coastlat0,
                                                    self.coastlon0)
                    self.cx1, self.cy1 = self.ll2xy(self.coastlat1,
                                                    self.coastlon1)

                for i in list(self.cstsel[0]):
                    pg.draw.line(self.radbmp, grey, (self.cx0[i], self.cy0[i]), \
                                 (self.cx1[i], self.cy1[i]))

            #------ Draw FIRs ------
            if self.swfir:
                self.firx0, self.firy0 = self.ll2xy(bs.navdb.firlat0, \
                                                    bs.navdb.firlon0)

                self.firx1, self.firy1 = self.ll2xy(bs.navdb.firlat1, \
                                                    bs.navdb.firlon1)

                for i in range(len(self.firx0)):
                    pg.draw.line(self.radbmp, lightcyan,
                                 (self.firx0[i], self.firy0[i]),
                                 (self.firx1[i], self.firy1[i]))

            # -----------------Waypoint & airport symbols-----------------
            # Check whether we need to reselect waypoint set to be drawn

            navsel = (self.lat0, self.lat1, \
                      self.lon0, self.lon1)
            if self.navsel != navsel:
                self.navsel = navsel

                # Make list of indices of waypoints & airports on screen

                self.wpinside = list(np.where(self.onradar(bs.navdb.wplat, \
                                                           bs.navdb.wplon))[0])

                self.wptsel = []
                for i in self.wpinside:
                    if self.wpsw == 3 or \
                            (self.wpsw == 1 and len(bs.navdb.wpid[i]) == 3) or \
                            (self.wpsw == 2 and bs.navdb.wpid[i].isalpha()):
                        self.wptsel.append(i)
                self.wptx, self.wpty = self.ll2xy(bs.navdb.wplat,
                                                  bs.navdb.wplon)

                self.apinside = list(np.where(self.onradar(bs.navdb.aptlat, \
                                                           bs.navdb.aptlon))[0])

                self.aptsel = []
                for i in self.apinside:
                    if self.apsw == 2 or (self.apsw == 1 and \
                                                      bs.navdb.aptmaxrwy[i] > 1000.):
                        self.aptsel.append(i)
                self.aptx, self.apty = self.ll2xy(bs.navdb.aptlat,
                                                  bs.navdb.aptlon)

            #------- Draw waypoints -------
            if self.wpsw > 0:
                # print len(self.wptsel)," waypoints"
                if len(self.wptsel) < self.maxnrwp:
                    wptrect = self.wptsymbol.get_rect()
                    for i in self.wptsel:
                        # wptrect.center = self.ll2xy(bs.navdb.wplat[i],  \
                        #     bs.navdb.wplon[i])
                        wptrect.center = self.wptx[i], self.wpty[i]
                        self.radbmp.blit(self.wptsymbol, wptrect)

                        # If waypoint label bitmap does not yet exist, make it
                        if not self.wpswbmp[i]:
                            self.wplabel[i] = pg.Surface((80, 30), 0, self.win)
                            self.fontnav.printat(self.wplabel[i], 0, 0, \
                                                 bs.navdb.wpid[i])
                            self.wpswbmp[i] = True

                        # In any case, blit it
                        xtxt = wptrect.right + 2
                        ytxt = wptrect.top
                        self.radbmp.blit(self.wplabel[i], (xtxt, ytxt), \
                                         None, pg.BLEND_ADD)

                        if not self.wpswbmp[i]:
                            xtxt = wptrect.right + 2
                            ytxt = wptrect.top

                            # self.fontnav.printat(self.radbmp,xtxt,ytxt, \
                            #     bs.navdb.wpid[i])

            #------- Draw airports -------
            if self.apsw > 0:
                # if len(self.aptsel)<800:
                aptrect = self.aptsymbol.get_rect()

                # print len(self.aptsel)," airports"

                for i in self.aptsel:
                    # aptrect.center = self.ll2xy(bs.navdb.aptlat[i],  \
                    #                            bs.navdb.aptlon[i])
                    aptrect.center = self.aptx[i], self.apty[i]
                    self.radbmp.blit(self.aptsymbol, aptrect)

                    # If airport label bitmap does not yet exist, make it
                    if not self.apswbmp[i]:
                        self.aplabel[i] = pg.Surface((50, 30), 0, self.win)
                        self.fontnav.printat(self.aplabel[i], 0, 0, \
                                             bs.navdb.aptid[i])
                        self.apswbmp[i] = True

                    # In either case, blit it
                    xtxt = aptrect.right + 2
                    ytxt = aptrect.top
                    self.radbmp.blit(self.aplabel[i], (xtxt, ytxt), \
                                     None, pg.BLEND_ADD)

                    # self.fontnav.printat(self.radbmp,xtxt,ytxt, \
                    #     bs.navdb.aptid[i])

            #---------- Draw background trails ----------
            if bs.traf.trails.active:
                bs.traf.trails.buffer()  # move all new trails to background

                trlsel = list(np.where(
                    self.onradar(bs.traf.trails.bglat0, bs.traf.trails.bglon0) + \
                    self.onradar(bs.traf.trails.bglat1, bs.traf.trails.bglon1))[0])

                x0, y0 = self.ll2xy(bs.traf.trails.bglat0,
                                    bs.traf.trails.bglon0)
                x1, y1 = self.ll2xy(bs.traf.trails.bglat1,
                                    bs.traf.trails.bglon1)

                for i in trlsel:
                    pg.draw.aaline(self.radbmp, bs.traf.trails.bgcol[i], \
                                   (x0[i], y0[i]), (x1[i], y1[i]))

            #---------- Draw ADSB Coverage Area
            if self.swAdsbCoverage:
                # These points are based on the positions of the antennas with range = 200km
                adsbCoverageLat = [
                    53.7863, 53.5362, 52.8604, 51.9538, 51.2285, 50.8249,
                    50.7382, 50.9701, 51.6096, 52.498, 53.4047, 53.6402
                ]
                adsbCoverageLon = [
                    4.3757, 5.8869, 6.9529, 7.2913, 6.9312, 6.251, 5.7218,
                    4.2955, 3.2162, 2.7701, 3.1117, 3.4891
                ]

                for i in range(0, len(adsbCoverageLat)):
                    if i == len(adsbCoverageLat) - 1:
                        x0, y0 = self.ll2xy(adsbCoverageLat[i],
                                            adsbCoverageLon[i])
                        x1, y1 = self.ll2xy(adsbCoverageLat[0],
                                            adsbCoverageLon[0])

                    else:
                        x0, y0 = self.ll2xy(adsbCoverageLat[i],
                                            adsbCoverageLon[i])
                        x1, y1 = self.ll2xy(adsbCoverageLat[i + 1],
                                            adsbCoverageLon[i + 1])

                    pg.draw.line(self.radbmp, red, (x0, y0), (x1, y1))

            # User defined objects
            for i in range(len(self.objtype)):

                # Draw LINE or POLYGON with objdata = [lat0,lon,lat1,lon1,lat2,lon2,..]
                if self.objtype[i] == 'LINE' or self.objtype[i] == "POLY":
                    npoints = len(self.objdata[i]) / 2
                    print(npoints)
                    x0, y0 = self.ll2xy(self.objdata[i][0], self.objdata[i][1])
                    for j in range(1, npoints):
                        x1, y1 = self.ll2xy(self.objdata[i][j * 2],
                                            self.objdata[i][j * 2 + 1])
                        pg.draw.line(self.radbmp, self.objcolor[i], (x0, y0),
                                     (x1, y1))
                        x0, y0 = x1, y1

                    if self.objtype[i] == "POLY":
                        x1, y1 = self.ll2xy(self.objdata[i][0],
                                            self.objdata[i][1])
                        pg.draw.line(self.radbmp, self.objcolor[i], (x0, y0),
                                     (x1, y1))

                # Draw bounding box of objdata = [lat0,lon0,lat1,lon1]
                elif self.objtype[i] == 'BOX':
                    lat0 = min(self.objdata[i][0], self.objdata[i][2])
                    lon0 = min(self.objdata[i][1], self.objdata[i][3])
                    lat1 = max(self.objdata[i][0], self.objdata[i][2])
                    lon1 = max(self.objdata[i][1], self.objdata[i][3])

                    x0, y0 = self.ll2xy(lat1, lon0)
                    x1, y1 = self.ll2xy(lat0, lon1)
                    pg.draw.rect(self.radbmp, self.objcolor[i],
                                 pg.Rect(x0, y0, x1 - x0, y1 - y0), 1)

                # Draw circle with objdata = [latcenter,loncenter,radiusnm]
                elif self.objtype[i] == 'CIRCLE':
                    pass
                    xm, ym = self.ll2xy(self.objdata[i][0], self.objdata[i][1])
                    xtop, ytop = self.ll2xy(
                        self.objdata[i][0] + self.objdata[i][2] / 60.,
                        self.objdata[i][1])
                    radius = int(round(abs(ytop - ym)))
                    pg.draw.circle(self.radbmp, self.objcolor[i],
                                   (int(xm), int(ym)), radius, 1)

            # Reset background drawing switch
            self.redrawradbg = False

        ##############################################################################
        #                          END OF BACKGROUND DRAWING                         #
        ##############################################################################

        # Blit background
        self.win.blit(self.radbmp, (0, 0))

        # Decide to redraw radar picture of a/c
        syst = pg.time.get_ticks() * 0.001
        redrawrad = self.redrawradbg or abs(syst - self.radt0) >= self.radardt

        if redrawrad:
            self.radt0 = syst  # Update lats drawing time of radar

            # Select which aircraft are within screen area
            trafsel = np.where((bs.traf.lat > self.lat0) * (bs.traf.lat < self.lat1) * \
                               (bs.traf.lon > self.lon0) * (bs.traf.lon < self.lon1))[0]

            # ------------------- Draw aircraft -------------------
            # Convert lat,lon to x,y

            trafx, trafy = self.ll2xy(bs.traf.lat, bs.traf.lon)
            trafy -= bs.traf.alt * self.isoalt

            if bs.traf.trails.active:
                ltx, lty = self.ll2xy(bs.traf.trails.lastlat,
                                      bs.traf.trails.lastlon)

            # Find pixel size of horizontal separation on screen
            pixelrad = self.dtopix_eq(bs.traf.asas.R / 2)

            # Loop through all traffic indices which we found on screen
            for i in trafsel:

                # Get index of ac symbol, based on heading and its rect object
                isymb = int(round((bs.traf.hdg[i] - self.ndcrs) / 6.)) % 60
                pos = self.acsymbol[isymb].get_rect()

                # Draw aircraft symbol
                pos.centerx = trafx[i]
                pos.centery = trafy[i]
                dy = self.fontrad.linedy * 7 / 6

                # Draw aircraft altitude line
                if self.isoalt > 1e-7:
                    pg.draw.line(
                        self.win, white, (int(trafx[i]), int(trafy[i])),
                        (int(trafx[i]),
                         int(trafy[i] + bs.traf.alt[i] * self.isoalt)))

                # Normal symbol if no conflict else amber
                toosmall = self.lat1 - self.lat0 > 6  #don't draw circles if zoomed out too much

                if not bs.traf.asas.inconf[i]:
                    self.win.blit(self.acsymbol[isymb], pos)
                    if self.swsep and not toosmall:
                        pg.draw.circle(self.win, green,
                                       (int(trafx[i]), int(trafy[i])),
                                       pixelrad, 1)
                else:
                    self.win.blit(self.ambacsymbol[isymb], pos)
                    if self.swsep and not toosmall:
                        pg.draw.circle(self.win, amber,
                                       (int(trafx[i]), int(trafy[i])),
                                       pixelrad, 1)

                # Draw last trail part
                if bs.traf.trails.active:
                    pg.draw.line(self.win, tuple(bs.traf.trails.accolor[i]),
                                 (ltx[i], lty[i]), (trafx[i], trafy[i]))

                # Label text
                label = []
                if self.swlabel > 0:
                    label.append(bs.traf.id[i])  # Line 1 of label: id
                else:
                    label.append(" ")
                if self.swlabel > 1:
                    if bs.traf.alt[i] > bs.traf.translvl:
                        label.append(
                            "FL" + str(int(round(
                                bs.traf.alt[i] /
                                (100. * ft)))))  # Line 2 of label: altitude
                    else:
                        label.append(str(int(
                            round(bs.traf.alt[i] /
                                  ft))))  # Line 2 of label: altitude
                else:
                    label.append(" ")
                if self.swlabel > 2:
                    cas = bs.traf.cas[i] / kts
                    label.append(str(int(
                        round(cas))))  # line 3 of label: speed
                else:
                    label.append(" ")

                # Check for changes in traffic label text
                if  not (type(bs.traf.label[i])==list) or \
                      not (type(bs.traf.label[i][3])==str) or \
                        not (label[:3] == bs.traf.label[i][:3]):

                    bs.traf.label[i] = []
                    labelbmp = pg.Surface((100, 60), 0, self.win)
                    if not bs.traf.asas.inconf[i]:
                        acfont = self.fontrad
                    else:
                        acfont = self.fontamb

                    acfont.printat(labelbmp, 0, 0, label[0])
                    acfont.printat(labelbmp, 0, dy, label[1])
                    acfont.printat(labelbmp, 0, 2 * dy, label[2])

                    bs.traf.label[i].append(label[0])
                    bs.traf.label[i].append(label[1])
                    bs.traf.label[i].append(label[2])
                    bs.traf.label[i].append(labelbmp)

                # Blit label
                dest = bs.traf.label[i][3].get_rect()
                dest.top = trafy[i] - 5
                dest.left = trafx[i] + 15
                self.win.blit(bs.traf.label[i][3], dest, None, pg.BLEND_ADD)

                # Draw aircraft speed vectors
                if self.swspd:
                    # just a nominal length: a speed of 150 kts will be displayed
                    # as an arrow of 30 pixels long on screen
                    nomlength = 30
                    nomspeed = 150.

                    vectorlength = float(nomlength) * bs.traf.tas[i] / nomspeed

                    spdvcx = trafx[i] + np.sin(np.radians(
                        bs.traf.trk[i])) * vectorlength
                    spdvcy = trafy[i] - np.cos(np.radians(bs.traf.trk[i])) * vectorlength \
                                - bs.traf.vs[i]/nomspeed*nomlength*self.isoalt /   \
                                            self.dtopix_eq(1e5)*1e5

                    pg.draw.line(self.win, green, (trafx[i], trafy[i]),
                                 (spdvcx, spdvcy))

            # ---- End of per aircraft i loop

            # Draw conflicts: line from a/c to closest point of approach
            nconf = len(bs.traf.asas.confpairs_unique)
            n2conf = len(bs.traf.asas.confpairs)

            if nconf > 0:

                for j in range(n2conf):
                    i = bs.traf.id2idx(bs.traf.asas.confpairs[j][0])
                    if i >= 0 and i < bs.traf.ntraf and (i in trafsel):
                        latcpa, loncpa = geo.kwikpos(bs.traf.lat[i], bs.traf.lon[i], \
                                                    bs.traf.trk[i], bs.traf.asas.tcpa[j] * bs.traf.gs[i] / nm)
                        altcpa = bs.traf.lat[
                            i] + bs.traf.vs[i] * bs.traf.asas.tcpa[j]
                        xc, yc = self.ll2xy(latcpa, loncpa)
                        yc = yc - altcpa * self.isoalt
                        pg.draw.line(self.win, amber, (xc, yc),
                                     (trafx[i], trafy[i]))

            # Draw selected route:
            if self.acidrte != "":
                i = bs.traf.id2idx(self.acidrte)
                if i >= 0:
                    for j in range(0, bs.traf.ap.route[i].nwp):
                        if j == 0:
                            x1,y1 = self.ll2xy(bs.traf.ap.route[i].wplat[j], \
                                               bs.traf.ap.route[i].wplon[j])
                        else:
                            x0, y0 = x1, y1
                            x1,y1 = self.ll2xy(bs.traf.ap.route[i].wplat[j], \
                                               bs.traf.ap.route[i].wplon[j])
                            pg.draw.line(self.win, magenta, (x0, y0), (x1, y1))

                        if j >= len(self.rtewpid) or not self.rtewpid[
                                j] == bs.traf.ap.route[i].wpname[j]:
                            # Waypoint name labels
                            # If waypoint label bitmap does not yet exist, make it

                            # Waypoint name and constraint(s), if there are any
                            txt = bs.traf.ap.route[i].wpname[j]

                            alt = bs.traf.ap.route[i].wpalt[j]
                            spd = bs.traf.ap.route[i].wpspd[j]

                            if alt >= 0. or spd >= 0.:
                                # Altitude
                                if alt < 0:
                                    txt = txt + " -----/"

                                elif alt > 4500 * ft:
                                    FL = int(round((alt / (100. * ft))))
                                    txt = txt + " FL" + str(FL) + "/"

                                else:
                                    txt = txt + " " + str(int(round(
                                        alt / ft))) + "/"

                                # Speed
                                if spd < 0:
                                    txt = txt + "---"
                                else:
                                    txt = txt + str(int(round(spd / kts)))

                            wplabel = pg.Surface((128, 32), 0, self.win)
                            self.fontnav.printat(wplabel, 0, 0, \
                                                 txt)

                            if j >= len(self.rtewpid):
                                self.rtewpid.append(txt)
                                self.rtewplabel.append(wplabel)
                            else:
                                self.rtewpid[j] = txt
                                self.rtewplabel[j] = wplabel

                        # In any case, blit the waypoint name
                        xtxt = x1 + 7
                        ytxt = y1 - 3
                        self.radbmp.blit(self.rtewplabel[j], (xtxt, ytxt), \
                                         None, pg.BLEND_ADD)

                        # Line from aircraft to active waypoint
                        if bs.traf.ap.route[i].iactwp == j:
                            x0, y0 = self.ll2xy(bs.traf.lat[i], bs.traf.lon[i])
                            pg.draw.line(self.win, magenta, (x0, y0), (x1, y1))

            # Draw aircraft trails which are on screen
            if bs.traf.trails.active:
                trlsel = list(np.where(
                    self.onradar(bs.traf.trails.lat0, bs.traf.trails.lon0) + \
                    self.onradar(bs.traf.trails.lat1, bs.traf.trails.lon1))[0])

                x0, y0 = self.ll2xy(bs.traf.trails.lat0, bs.traf.trails.lon0)
                x1, y1 = self.ll2xy(bs.traf.trails.lat1, bs.traf.trails.lon1)

                for i in trlsel:
                    pg.draw.line(self.win, bs.traf.trails.col[i], \
                                 (x0[i], y0[i]), (x1[i], y1[i]))

                # Redraw background => buffer ; if >1500 foreground linepieces on screen
                if len(trlsel) > 1500:
                    self.redrawradbg = True

        # Draw edit window
        self.editwin.update()

        if self.redrawradbg or redrawrad or self.editwin.redraw:
            self.win.blit(self.menu.bmps[self.menu.ipage], \
                           (self.menu.x, self.menu.y))
            self.win.blit(self.editwin.bmp,
                          (self.editwin.winx, self.editwin.winy))

            # Draw frames
            pg.draw.rect(self.win, white, self.editwin.rect, 1)
            pg.draw.rect(self.win, white,
                         pg.Rect(1, 1, self.width - 1, self.height - 1), 1)

            # Add debug line
            self.fontsys.printat(self.win, 10, 2,
                                 str(bs.sim.utc.replace(microsecond=0)))
            self.fontsys.printat(self.win, 10, 18, tim2txt(bs.sim.simt))
            self.fontsys.printat(self.win, 10+80, 2, \
                                 "ntraf = " + str(bs.traf.ntraf))
            self.fontsys.printat(self.win, 10+160, 2, \
                                 "Freq=" + str(int(len(bs.sim.dts) / max(0.001, sum(bs.sim.dts)))))

            self.fontsys.printat(self.win, 10+240, 2, \
                                 "#LOS      = " + str(len(bs.traf.asas.lospairs_unique)))
            self.fontsys.printat(self.win, 10+240, 18, \
                                 "Total LOS = " + str(len(bs.traf.asas.lospairs_all)))
            self.fontsys.printat(self.win, 10+240, 34, \
                                 "#Con      = " + str(len(bs.traf.asas.confpairs_unique)))
            self.fontsys.printat(self.win, 10+240, 50, \
                                 "Total Con = " + str(len(bs.traf.asas.confpairs_all)))

            # Frame ready, flip to screen
            pg.display.flip()

            # If needed, take a screenshot
            if self.screenshot:
                pg.image.save(self.win, self.screenshotname)
                self.screenshot = False
        return
Esempio n. 11
0
    def notify(self, receiver, event):
        # Keep track of event processing
        event_processed = False

        # Events from the simulation threads
        if receiver is self:
            if event.type() == PanZoomEventType:
                if event.zoom is not None:
                    event.origin = (self.radarwidget.width / 2, self.radarwidget.height / 2)

                if event.pan is not None and not event.absolute:
                    event.pan = (2.0 * event.pan[0] / (self.radarwidget.zoom * self.radarwidget.ar),
                                 2.0 * event.pan[1] / (self.radarwidget.zoom * self.radarwidget.flat_earth))

                # send the pan/zoom event to the radarwidget
                self.radarwidget.event(event)

            elif event.type() == ACDataEventType:
                self.acdata = event
                self.radarwidget.update_aircraft_data(event)
                if self.nd.ac_id in event.id:
                    idx = event.id.index(self.nd.ac_id.upper())
                    lat = event.lat[idx]
                    lon = event.lon[idx]
                    trk = event.trk[idx]
                    tas = event.tas[idx]
                    self.nd.update_aircraft_data(idx, lat, lon, tas, trk, len(event.lat))
                return True

            elif event.type() == RouteDataEventType:
                self.routedata = event
                self.radarwidget.update_route_data(event)
                return True

            elif event.type() == DisplayShapeEventType:
                self.radarwidget.updatePolygon(event.name, event.data)

            elif event.type() == SimInfoEventType:
                simt = tim2txt(event.simt)[:-3]
                simtclock = tim2txt(event.simtclock)[:-3]
                self.win.setNodeInfo(manager.sender()[0], simt, event.scenname)
                if manager.sender()[0] == manager.actnode():
                    self.simt = event.simt
                    self.win.siminfoLabel.setText(u'<b>t:</b> %s, <b>\u0394t:</b> %.2f, <b>Speed:</b> %.1fx, <b>UTC:</b> %s, <b>Mode:</b> %s, <b>Aircraft:</b> %d, <b>Conflicts:</b> %d/%d, <b>LoS:</b> %d/%d'
                        % (simt, event.simdt, event.sys_freq, simtclock, self.modes[event.mode], event.n_ac, self.acdata.nconf_cur, self.acdata.nconf_tot, self.acdata.nlos_cur, self.acdata.nlos_tot))
                return True

            elif event.type() == StackTextEventType:
                event_processed = True
                if event.disptext:
                    self.win.console.echo(event.disptext)
                if event.cmdtext:
                    self.win.console.setCmdline(event.cmdtext)

            elif event.type() == StackInitEventType:
                event_processed = True
                self.win.console.addStackHelp(manager.sender()[0], event.stackdict)

            elif event.type() == ShowDialogEventType:
                if event.dialog_type == event.filedialog_type:
                    self.show_file_dialog()
                elif event.dialog_type == event.docwin_type:
                    self.show_doc_window(event.cmd)
                return True

            elif event.type() == DisplayFlagEventType:
                # Switch/toggle/cycle radar screen features e.g. from SWRAD command
                if event.switch == 'RESET':
                    self.radarwidget.clearNodeData()
                # Coastlines
                elif event.switch == "GEO":
                    self.radarwidget.show_coast = not self.radarwidget.show_coast

                # FIR boundaries
                elif event.switch == "FIR":
                    self.radarwidget.showfir = not self.radarwidget.showfir

                # Airport: 0 = None, 1 = Large, 2= All
                elif event.switch == "APT":
                    self.radarwidget.show_apt = not self.radarwidget.show_apt

                # Waypoint: 0 = None, 1 = VOR, 2 = also WPT, 3 = Also terminal area wpts
                elif event.switch == "VOR" or event.switch == "WPT" or event.switch == "WP" or event.switch == "NAV":
                    self.radarwidget.show_apt = not self.radarwidget.show_apt

                # Satellite image background on/off
                elif event.switch == "SAT":
                    self.radarwidget.show_map = not self.radarwidget.show_map

                # Satellite image background on/off
                elif event.switch == "TRAF":
                    self.radarwidget.show_traf = not self.radarwidget.show_traf

                # ND window for selected aircraft
                elif event.switch == "ND":
                    self.nd.setAircraftID(event.argument)
                    self.nd.setVisible(not self.nd.isVisible())

                elif event.switch == "SSD":
                    self.radarwidget.show_ssd(event.argument)

                elif event.switch == "SYM":
                    # For now only toggle PZ
                    self.radarwidget.show_pz = not self.radarwidget.show_pz

                elif event.switch == "DEFWPT":
                    self.radarwidget.defwpt(event.argument)

                elif event.switch == "FILTERALT":
                    # First argument is an on/off flag
                    nact = self.radarwidget.nodedata[manager.sender()[0]]
                    if event.argument[0]:
                        nact.filteralt = event.argument[1:]
                    else:
                        nact.filteralt = False

                return True

            elif event.type() == AMANEventType:
                # self.aman.update(self.simt, event)
                pass

        # Mouse/trackpad event handling for the Radar widget
        elif receiver is self.radarwidget and self.radarwidget.initialized:
            panzoom = None
            if event.type() == QEvent.Wheel:
                # For mice we zoom with control/command and the scrolwheel
                if event.modifiers() & Qt.ControlModifier:
                    origin = (event.pos().x(), event.pos().y())
                    zoom   = 1.0
                    try:
                        if event.pixelDelta():
                            # High resolution scroll
                            zoom *= (1.0 + 0.01 * event.pixelDelta().y())
                        else:
                            # Low resolution scroll
                            zoom *= (1.0 + 0.001 * event.angleDelta().y())
                    except:
                        zoom *= (1.0 + 0.001 * event.delta())
                    panzoom = PanZoomEvent(zoom=zoom, origin=origin)

                # For touchpad scroll (2D) is used for panning
                else:
                    try:
                        dlat =  0.01 * event.pixelDelta().y() / (self.radarwidget.zoom * self.radarwidget.ar)
                        dlon = -0.01 * event.pixelDelta().x() / (self.radarwidget.zoom * self.radarwidget.flat_earth)
                        panzoom = PanZoomEvent(pan=(dlat, dlon))
                    except:
                        pass

            # For touchpad, pinch gesture is used for zoom
            elif event.type() == QEvent.Gesture:
                zoom   = None
                pan    = None
                dlat   = 0.0
                dlon   = 0.0
                for g in event.gestures():
                    if g.gestureType() == Qt.PinchGesture:
                        if zoom is None:
                            zoom = 1.0
                        zoom  *= g.scaleFactor()
                        if correct_pinch:
                            zoom /= g.lastScaleFactor()
                    elif g.gestureType() == Qt.PanGesture:
                        if abs(g.delta().y() + g.delta().x()) > 1e-1:
                            dlat += 0.005 * g.delta().y() / (self.radarwidget.zoom * self.radarwidget.ar)
                            dlon -= 0.005 * g.delta().x() / (self.radarwidget.zoom * self.radarwidget.flat_earth)
                            pan = (dlat, dlon)
                if pan is not None or zoom is not None:
                    panzoom = PanZoomEvent(pan, zoom, self.mousepos)

            elif event.type() == QEvent.MouseButtonPress and event.button() & Qt.LeftButton:
                event_processed   = True
                self.mousedragged = False
                # For mice we pan with control/command and mouse movement. Mouse button press marks the beginning of a pan
                self.prevmousepos = (event.x(), event.y())

            elif event.type() == QEvent.MouseButtonRelease and event.button() & Qt.LeftButton and not self.mousedragged:
                event_processed = True
                lat, lon  = self.radarwidget.pixelCoordsToLatLon(event.x(), event.y())
                tostack, tocmdline = radarclick(self.win.console.command_line, lat, lon, self.acdata, self.routedata)
                if len(tocmdline) > 0:
                    if '\n' in tocmdline:
                        self.win.console.setCmdline('')
                        # Clear any shape command preview on the radar display
                        self.radarwidget.previewpoly(None)
                    else:
                        self.win.console.appendCmdline(tocmdline)
                    if len(tostack) > 0:
                        self.win.console.stack(tostack)

            elif event.type() == QEvent.MouseMove:
                event_processed   = True
                self.mousedragged = True
                self.mousepos = (event.x(), event.y())
                if event.buttons() & Qt.LeftButton:
                    dlat = 0.003 * (event.y() - self.prevmousepos[1]) / (self.radarwidget.zoom * self.radarwidget.ar)
                    dlon = 0.003 * (self.prevmousepos[0] - event.x()) / (self.radarwidget.zoom * self.radarwidget.flat_earth)
                    self.prevmousepos = (event.x(), event.y())
                    panzoom = PanZoomEvent(pan=(dlat, dlon))

            # Update pan/zoom to simulation thread only when the pan/zoom gesture is finished
            elif (event.type() == QEvent.MouseButtonRelease or event.type() == QEvent.TouchEnd) and self.panzoomchanged:
                self.panzoomchanged = False
                manager.sendEvent(PanZoomEvent( pan=(self.radarwidget.panlat, self.radarwidget.panlon),
                                                zoom=self.radarwidget.zoom, absolute=True))

            # If we've just processed a change to pan and/or zoom, send the event to the radarwidget
            if panzoom is not None:
                self.panzoomchanged = True
                return self.radarwidget.event(panzoom)

        # Send all key presses directly to the main window
        if event.type() == QEvent.KeyPress:
            self.win.keyPressEvent(event)
            return True

        # If we haven't processed the event: call Base Class Method to Continue Normal Event Processing
        if not event_processed:
            return super(Gui, self).notify(receiver, event)

        if self.win.console.cmd in ['AREA', 'BOX', 'POLY', 'POLYALT', 'POLYGON', 'CIRCLE', 'LINE']:
            if self.mousepos != self.prevmousepos and len(self.win.console.args) >= 2:
                self.prevmousepos = self.mousepos
                try:
                    # get the largest even number of points
                    start = 0 if self.win.console.cmd == 'AREA' else 3 if self.win.console.cmd == 'POLYALT' else 1
                    end   = ((len(self.win.console.args) - start) // 2) * 2 + start
                    data  = [float(v) for v in self.win.console.args[start:end]]
                    data += self.radarwidget.pixelCoordsToLatLon(*self.mousepos)
                    self.radarwidget.previewpoly(self.win.console.cmd, data)

                except ValueError:
                    pass

        event.accept()
        return True