Example #1
0
    def __init__(self, win, nch, nlin, winx, winy):
        # Was Helvetica,14
        self.fontedit = Fastfont(win, 'Courier New', 14, white, False,
                                 False)  # name, size, bold,italic

        # Edit window: 6 line of 64 chars
        self.content = []
        self.nch = nch  # number of chars per line
        self.nlin = nlin  # number of lines in windows
        self.winx = winx  # x-coordinate in pixels of left side
        self.winy = winy - self.nlin * self.fontedit.linedy  # y-coordinate in pixels of top
        self.msg = []  # Messages in edit window

        for i in range(self.nlin):
            line = self.nch * [' ']
            self.content.append(line)
        self.content0 = self.content

        self.xcursor = 0
        self.xedit = 0
        # self.printeditwin('Testing 1,2,3')
        self.bmpdy = self.nlin * self.fontedit.linedy
        self.bmpdx = self.nch * self.fontedit.linedy * 10 / 17 + 2  # Guess max aspect ratio
        self.bmp = pg.Surface([self.bmpdx, self.bmpdy], pg.SRCALPHA, 32)

        self.bmp.fill(darkblue)
        self.rect = pg.Rect(self.winx, self.winy, self.bmpdx, self.bmpdy)
        self.redraw = True

        return
Example #2
0
    def __init__(self,win,nch,nlin,winx,winy):
        # Was Helvetica,14
        self.fontedit = Fastfont(win,'Courier New',14,white,False,False) # name, size, bold,italic

        # Edit window: 6 line of 64 chars
        self.content = []
        self.nch = nch    # number of chars per line
        self.nlin = nlin   # number of lines in windows
        self.winx = winx   # x-coordinate in pixels of left side
        self.winy = winy - self.nlin*self.fontedit.linedy   # y-coordinate in pixels of top
        self.msg = []        # Messages in edit window
        
        for i in range(self.nlin):
            line= self.nch*[' ']
            self.content.append(line)
        self.content0 = self.content
        
        self.xcursor = 0
        self.xedit = 0
        # self.printeditwin('Testing 1,2,3')
        self.bmpdy = self.nlin*self.fontedit.linedy
        self.bmpdx = self.nch*self.fontedit.linedy*10/17 + 2 # Guess max aspect ratio
        self.bmp = pg.Surface([self.bmpdx,self.bmpdy],
                                   pg.SRCALPHA, 32)
                                   
        self.bmp.fill(darkblue)
        self.rect = pg.Rect(self.winx,self.winy,
                             self.bmpdx,self.bmpdy)
        self.redraw = True
     
        return
Example #3
0
class Console:
    """ 
    Console (aka EditWin) class definition : Edit window & console class

    Methods:
        echo(msg)         : Print a message
        insert(message)   : insert characters in current edit line
        backspace()       : process backspace
        getline()         : return current edit line
        enter()           : enter, end of edit line
        scroll()          : scroll up one line
        update()          : redraw update bitmap of edit window

    Created by  : Jacco M. Hoekstra (TU Delft)
    """

    def __init__(self,win,nch,nlin,winx,winy):
        # Was Helvetica,14
        self.fontedit = Fastfont(win,'Courier New',14,white,False,False) # name, size, bold,italic

        # Edit window: 6 line of 64 chars
        self.content = []
        self.nch = nch    # number of chars per line
        self.nlin = nlin   # number of lines in windows
        self.winx = winx   # x-coordinate in pixels of left side
        self.winy = winy - self.nlin*self.fontedit.linedy   # y-coordinate in pixels of top
        self.msg = []        # Messages in edit window
        
        for i in range(self.nlin):
            line= self.nch*[' ']
            self.content.append(line)
        self.content0 = self.content
        
        self.xcursor = 0
        self.xedit = 0
        # self.printeditwin('Testing 1,2,3')
        self.bmpdy = self.nlin*self.fontedit.linedy
        self.bmpdx = self.nch*self.fontedit.linedy*10/17 + 2 # Guess max aspect ratio
        self.bmp = pg.Surface([self.bmpdx,self.bmpdy],
                                   pg.SRCALPHA, 32)
                                   
        self.bmp.fill(darkblue)
        self.rect = pg.Rect(self.winx,self.winy,
                             self.bmpdx,self.bmpdy)
        self.redraw = True
     
        return


    def echo(self,msg): 
        """print a message to console window"""
        if self.xedit==self.xcursor:
            self.insert(msg)
            j = self.xcursor/self.nch        
            self.xcursor = (j+1)*self.nch
            self.xedit = self.xcursor
    
            # Check for End of window
            if self.xedit >= (self.nch-1)*(self.nlin-1):
                del self.content[0]
                self.content.append(self.nch*[' '])
                self.xcursor = j*self.nch
                self.xedit = self.xcursor
        else:
            self.msg.append(msg)   # buffer
        return


    def insert(self,message):
        i = self.xcursor%self.nch
        j = self.xcursor/self.nch
        for ich in range(len(message)):
            self.content[j][i]=message[ich]
            i = i+1
            # Check for end-of line
            if i>=self.nch:
                i = 0
                j = j+1
                # Check for end-of edit window
                if j>=self.nlin:
                    self.scroll()
                    j = j-1
        self.xcursor = j*self.nch+i
        self.redraw = True
        return

    def backspace(self):
        if self.xcursor>self.xedit:
            self.xcursor = self.xcursor-1
        self.redraw = True
        i = self.xcursor%self.nch
        j = self.xcursor/self.nch
        self.content[j][i]=" "
        return

    def getline(self): # enter was pressed ro we need current command line
        line = ""
        for idx in range(self.xedit,self.xcursor):        
            i = idx%self.nch
            j = idx/self.nch
            line = line+self.content[j][i]
        return line

    def enter(self):           
        j = self.xcursor/self.nch        
        self.xcursor = (j+1)*self.nch
        self.xedit = self.xcursor

        # End of window
        if self.xedit >= (self.nch-1)*(self.nlin-1):
            del self.content[0]
            self.content.append(self.nch*[' '])
            self.xcursor = j*self.nch
            self.xedit = self.xcursor

        # Print buffered messages
        self.redraw = True
        while len(self.msg)>0:
            self.echo(self.msg[0])  # No endless recursion becasue xedit==xcursor
            del self.msg[0]
        return

    def scroll(self):
        """Scroll window"""
        del self.content[0]
        self.content.append(self.nch*[' '])
        self.xcursor = self.xcursor-self.nch
        self.xedit = self.xedit-self.nch

    def update(self):
        """Update: Draw a new frame"""
        # Draw edit window
        if self.redraw:
            self.bmp.fill(darkgrey)
            
            for j in range(self.nlin):
                for i in range(self.nch):
                    if True or self.content[j][i] != self.content0[j][i]:
                        x = i*self.fontedit.linedy*10/17 + 1
                        y = j*self.fontedit.linedy+self.fontedit.linedy/6
                        self.fontedit.printat(self.bmp,
                                              x,y,
                                              self.content[j][i])
                        self.content0[j][i]=self.content[j][i]
            # Draw cursor
            i = self.xcursor%self.nch
            j = self.xcursor/self.nch
            x = i*self.fontedit.linedy*10/17
            y = j*self.fontedit.linedy+self.fontedit.linedy/6
            self.fontedit.printat(self.bmp,x,y,"_")
            self.bmp.set_alpha(127)    
            self.redraw = False

        return
Example #4
0
    def init(self):
        # Read Screen configuration file:
        print
        print "Setting up screen..."

        lst = np.genfromtxt("data/graphics/scr_cfg.dat",
                            comments='#',
                            dtype='i4')

        self.swfullscreen = int(lst[0]) == 0

        self.width = int(lst[1])  # default value to create variable
        self.height = int(lst[2])  # default value to create variable

        # Dimensions radar window
        self.lat1 = 53.  # [deg] upper limit display
        self.lat0 = 51.  # [deg] lowerlimit display
        self.lon0 = -1.  # [deg] left side of screen

        dellat = self.lat1 - self.lat0

        avelat = (self.lat0 + self.lat1) * 0.5

        dellon = dellat * self.width / (self.height * cos(radians(avelat)))
        avelon = (self.lon0 + dellon / 2. + 180.) % 360. - 180.

        self.lon1 = (self.lon0 + dellon + 180.) % 360. - 180.

        self.ctrlat = avelat
        self.ctrlon = avelon

        #----------------------------SYMBOLS-----------------------------
        # Read graphics for acsymbol (normal = green) + amber
        self.acsymbol = []
        for i in range(60):
            self.acsymbol.append(pg.image.load("data/graphics/acsymbol/acsymbol" \
                                  + str(i) + ".png"))

        self.ambacsymbol = []
        for i in range(60):
            self.ambacsymbol.append(pg.image.load("data/graphics/amb-acsymbol/amb-acsymbol" \
                                     + str(i) + ".png"))

        # Lable lines& default no trails
        self.swlabel = 3

        # Read and scale waypoint symbol
        wptgif = pg.image.load("data/graphics/waypoint.gif")
        self.wptsymbol = pg.transform.scale(wptgif, (10, 7))
        self.wpsw = 1  # 0=None, 1 = VOR 2 = non-digit ones, 3 =all

        # Read and scale airport symbol
        aptgif = pg.image.load("data/graphics/airport.gif")
        self.aptsymbol = pg.transform.scale(aptgif, (12, 9))
        self.apsw = 1  # 0 = None, 1 = Large, 2 = All

        # Free flight displays
        self.swsep = False  # To show circles of 2.5 nm radius around each aircraft
        # Note: circles will be distorted when away from equator
        self.swspd = False  # To show speed vectors of each aircraft
        self.swtestarea = False

        #--------------------------------MAPS---------------------------------
        # Read map of world
        self.mapbmp = pg.image.load("data/graphics/world.jpg")
        w, h = self.mapbmp.get_size()

        # Two ref positions for scaling, convert to scaling factors x=a*lat+b
        x1, y1, lat1, lon1 = 0., 0., 90., -180.
        x2, y2, lat2, lon2 = w, h, -90., 180.
        self.mapax = (x2 - x1) / (lon2 - lon1)
        self.mapbx = x2 - self.mapax * lon2
        self.mapay = (y2 - y1) / (lat2 - lat1)
        self.mapby = y2 - self.mapay * lat2

        self.swsat = True

        # Nav display projection mode
        self.swnavdisp = False
        self.ndacid = ""
        self.ndlat = 0.0
        self.ndlon = 0.0
        self.ndhdg = 0.0

        #------------------------WINDOW SETUP and scaling--------------------------
        # Empty tuple to force reselection waypoints & airports to be drawn
        self.navsel = (
        )  # Empty tuple to force reselection waypoints to be drawn
        self.satsel = (
        )  # Empty tuple to force reselection satellite imagery to be drawn

        # Set up window
        splash.destroy()  # does pg.display.quit()!
        pg.display.init()

        # Full screen
        di = pg.display.Info()
        if self.swfullscreen:
            self.width = di.current_w
            self.height = di.current_h
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso, pg.FULLSCREEN)
        else:
            # Windowed
            self.height = min(self.height, di.current_h * 90 / 100)
            self.width = min(self.width, di.current_w * 90 / 100)
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso)

        pg.display.set_caption(
            "BlueSky Open ATM Simulator (F11 = Full Screen)", "BlueSky")
        iconpath = imgpath = "data/graphics/icon.gif"
        iconbmp = pg.image.load(iconpath)
        pg.display.set_icon(iconbmp)

        self.radbmp = self.win.copy()
        self.redrawradbg = True  # Switch to redraw background

        #---------------------RADAR FONTS & EDIT WINDOW-----------------------------
        # Set up fonts
        self.fontrad = Fastfont(self.win, 'Arial', 14, green, False,
                                False)  # name, size, bold,italic
        self.fontamb = Fastfont(self.win, 'Arial', 14, amber, False,
                                False)  # name, size, bold,italic
        self.fontnav = Fastfont(self.win, 'Arial', 12, lightgreyblue, False,
                                False)  # name, size, bold,italic
        self.fontsys = Fastfont(self.win, 'Helvetica', 14, white, False,
                                False)  # name, size, bold,italic

        # Edit window: 6 line of 64 chars
        nch = lst[3]  # number of chars per line
        nlin = lst[4]  # number of lines in windows
        winx = lst[5]  # x-coordinate in pixels of left side
        winy = self.height - lst[6]  # y-coordinate in pixels of bottom
        self.editwin = Console(self.win, nch, nlin, winx, winy)

        # Menu button window
        self.menu = Menu(self.win, 10, 36)

        #-------------------------COASTLINE DATA--------------------------------------
        # Init geo (coastline)  data
        f = open("data/global/coastlines.dat", 'r')
        print "Reading coastlines.dat"
        lines = f.readlines()
        f.close()
        records = []
        for line in lines:
            if not (line.strip() == "" or line.strip()[0] == '#'):
                arg = line.split()
                if len(arg) == 3:
                    records.append([arg[0], float(arg[1]), float(arg[2])])

        # print len(records), " records read."
        # Convert pen up/pen down format of coastlines to numpy arrays with lat/lon

        coastlat0 = []
        coastlon0 = []
        coastlat1 = []
        coastlon1 = []
        clat, clon = -1, -1

        for rec in records:
            lat, lon = rec[1], rec[2]
            if rec[0] == 'D':
                coastlat0.append(clat)
                coastlon0.append(clon)
                coastlat1.append(lat)
                coastlon1.append(lon)
            clat, clon = lat, lon

        self.coastlat0 = np.array(coastlat0)
        self.coastlon0 = np.array(coastlon0)
        self.coastlat1 = np.array(coastlat1)
        self.coastlon1 = np.array(coastlon1)

        del coastlat0, coastlon0, coastlat1, coastlon1  # Clear memory

        self.geosel = ()  # Force reselect first time coastlines
        self.firsel = ()  # Force reselect first time FIR lines

        print "    ", len(self.coastlat0), " coastlines added."

        # Set default coastlines & FIRs on:
        self.swgeo = True
        self.swfir = True
        self.swgrid = False

        # Route drawing for which acid? "" =  None
        self.acidrte = ""
        self.rtewpid = []
        self.rtewplabel = []

        # User defined background objects
        self.objtype = []
        self.objcolor = []
        self.objdata = []
        self.objname = []

        # Wpt and apt drawing logic memory
        self.wpswbmp = []  # switch indicating whether label bmp is present
        self.wplabel = []  # List to store bitmaps of label
        self.apswbmp = []  # switch indicating whether label bmp is present
        self.aplabel = []  # List to store bitmaps of label

        self.updateNavBuffers()
        return
Example #5
0
class Screen:
    """
    Screen class definition : contains radar & edit screen data & methods

    Methods:
        Screen(tmx)         :  constructor

        echo(msg)           : print something at screen
        update()            : Draw a new frame of screen
        ll2xy(lat,lon)      : lat/lon[deg] to pixel coordinate conversion
        xy2ll(x,y)          : pixel to lat/lon[de]g conversion
        zoom(factor)        : zoom in/out
        pan(lat,lon,txt)    : pan to lat,lon position

    Members: see constructor

    Created by : Jacco M. Hoekstra (TU Delft)
    Updated by : Jerom Maas

    """
    def __init__(self):
        # processes input from keyboard & mouse
        self.keyb = Keyboard()

        # Parameters for making screenshots
        self.session = "new"
        self.folder = ""
        self.screenshot = False
        self.screenshotname = ""

        # Isometric display parameter
        self.isoalt = 0.  # how many meters one pixel is high

        # Display ADS-B range flag
        self.swAdsbCoverage = False

        # Update rate radar:
        self.radardt = 0.10  # 10x per sec 0.25  # 4x per second max
        self.radt0 = -999.  # last time drawn
        self.maxnrwp = 1000  # max nr apts+wpts to be drawn

    def init(self):
        # Read Screen configuration file:
        print
        print "Setting up screen..."

        lst = np.genfromtxt("data/graphics/scr_cfg.dat",
                            comments='#',
                            dtype='i4')

        self.swfullscreen = int(lst[0]) == 0

        self.width = int(lst[1])  # default value to create variable
        self.height = int(lst[2])  # default value to create variable

        # Dimensions radar window
        self.lat1 = 53.  # [deg] upper limit display
        self.lat0 = 51.  # [deg] lowerlimit display
        self.lon0 = -1.  # [deg] left side of screen

        dellat = self.lat1 - self.lat0

        avelat = (self.lat0 + self.lat1) * 0.5

        dellon = dellat * self.width / (self.height * cos(radians(avelat)))
        avelon = (self.lon0 + dellon / 2. + 180.) % 360. - 180.

        self.lon1 = (self.lon0 + dellon + 180.) % 360. - 180.

        self.ctrlat = avelat
        self.ctrlon = avelon

        #----------------------------SYMBOLS-----------------------------
        # Read graphics for acsymbol (normal = green) + amber
        self.acsymbol = []
        for i in range(60):
            self.acsymbol.append(pg.image.load("data/graphics/acsymbol/acsymbol" \
                                  + str(i) + ".png"))

        self.ambacsymbol = []
        for i in range(60):
            self.ambacsymbol.append(pg.image.load("data/graphics/amb-acsymbol/amb-acsymbol" \
                                     + str(i) + ".png"))

        # Lable lines& default no trails
        self.swlabel = 3

        # Read and scale waypoint symbol
        wptgif = pg.image.load("data/graphics/waypoint.gif")
        self.wptsymbol = pg.transform.scale(wptgif, (10, 7))
        self.wpsw = 1  # 0=None, 1 = VOR 2 = non-digit ones, 3 =all

        # Read and scale airport symbol
        aptgif = pg.image.load("data/graphics/airport.gif")
        self.aptsymbol = pg.transform.scale(aptgif, (12, 9))
        self.apsw = 1  # 0 = None, 1 = Large, 2 = All

        # Free flight displays
        self.swsep = False  # To show circles of 2.5 nm radius around each aircraft
        # Note: circles will be distorted when away from equator
        self.swspd = False  # To show speed vectors of each aircraft
        self.swtestarea = False

        #--------------------------------MAPS---------------------------------
        # Read map of world
        self.mapbmp = pg.image.load("data/graphics/world.jpg")
        w, h = self.mapbmp.get_size()

        # Two ref positions for scaling, convert to scaling factors x=a*lat+b
        x1, y1, lat1, lon1 = 0., 0., 90., -180.
        x2, y2, lat2, lon2 = w, h, -90., 180.
        self.mapax = (x2 - x1) / (lon2 - lon1)
        self.mapbx = x2 - self.mapax * lon2
        self.mapay = (y2 - y1) / (lat2 - lat1)
        self.mapby = y2 - self.mapay * lat2

        self.swsat = True

        # Nav display projection mode
        self.swnavdisp = False
        self.ndacid = ""
        self.ndlat = 0.0
        self.ndlon = 0.0
        self.ndhdg = 0.0

        #------------------------WINDOW SETUP and scaling--------------------------
        # Empty tuple to force reselection waypoints & airports to be drawn
        self.navsel = (
        )  # Empty tuple to force reselection waypoints to be drawn
        self.satsel = (
        )  # Empty tuple to force reselection satellite imagery to be drawn

        # Set up window
        splash.destroy()  # does pg.display.quit()!
        pg.display.init()

        # Full screen
        di = pg.display.Info()
        if self.swfullscreen:
            self.width = di.current_w
            self.height = di.current_h
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso, pg.FULLSCREEN)
        else:
            # Windowed
            self.height = min(self.height, di.current_h * 90 / 100)
            self.width = min(self.width, di.current_w * 90 / 100)
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso)

        pg.display.set_caption(
            "BlueSky Open ATM Simulator (F11 = Full Screen)", "BlueSky")
        iconpath = imgpath = "data/graphics/icon.gif"
        iconbmp = pg.image.load(iconpath)
        pg.display.set_icon(iconbmp)

        self.radbmp = self.win.copy()
        self.redrawradbg = True  # Switch to redraw background

        #---------------------RADAR FONTS & EDIT WINDOW-----------------------------
        # Set up fonts
        self.fontrad = Fastfont(self.win, 'Arial', 14, green, False,
                                False)  # name, size, bold,italic
        self.fontamb = Fastfont(self.win, 'Arial', 14, amber, False,
                                False)  # name, size, bold,italic
        self.fontnav = Fastfont(self.win, 'Arial', 12, lightgreyblue, False,
                                False)  # name, size, bold,italic
        self.fontsys = Fastfont(self.win, 'Helvetica', 14, white, False,
                                False)  # name, size, bold,italic

        # Edit window: 6 line of 64 chars
        nch = lst[3]  # number of chars per line
        nlin = lst[4]  # number of lines in windows
        winx = lst[5]  # x-coordinate in pixels of left side
        winy = self.height - lst[6]  # y-coordinate in pixels of bottom
        self.editwin = Console(self.win, nch, nlin, winx, winy)

        # Menu button window
        self.menu = Menu(self.win, 10, 36)

        #-------------------------COASTLINE DATA--------------------------------------
        # Init geo (coastline)  data
        f = open("data/global/coastlines.dat", 'r')
        print "Reading coastlines.dat"
        lines = f.readlines()
        f.close()
        records = []
        for line in lines:
            if not (line.strip() == "" or line.strip()[0] == '#'):
                arg = line.split()
                if len(arg) == 3:
                    records.append([arg[0], float(arg[1]), float(arg[2])])

        # print len(records), " records read."
        # Convert pen up/pen down format of coastlines to numpy arrays with lat/lon

        coastlat0 = []
        coastlon0 = []
        coastlat1 = []
        coastlon1 = []
        clat, clon = -1, -1

        for rec in records:
            lat, lon = rec[1], rec[2]
            if rec[0] == 'D':
                coastlat0.append(clat)
                coastlon0.append(clon)
                coastlat1.append(lat)
                coastlon1.append(lon)
            clat, clon = lat, lon

        self.coastlat0 = np.array(coastlat0)
        self.coastlon0 = np.array(coastlon0)
        self.coastlat1 = np.array(coastlat1)
        self.coastlon1 = np.array(coastlon1)

        del coastlat0, coastlon0, coastlat1, coastlon1  # Clear memory

        self.geosel = ()  # Force reselect first time coastlines
        self.firsel = ()  # Force reselect first time FIR lines

        print "    ", len(self.coastlat0), " coastlines added."

        # Set default coastlines & FIRs on:
        self.swgeo = True
        self.swfir = True
        self.swgrid = False

        # Route drawing for which acid? "" =  None
        self.acidrte = ""
        self.rtewpid = []
        self.rtewplabel = []

        # User defined background objects
        self.objtype = []
        self.objcolor = []
        self.objdata = []
        self.objname = []

        # Wpt and apt drawing logic memory
        self.wpswbmp = []  # switch indicating whether label bmp is present
        self.wplabel = []  # List to store bitmaps of label
        self.apswbmp = []  # switch indicating whether label bmp is present
        self.aplabel = []  # List to store bitmaps of label

        self.updateNavBuffers()
        return

    def updateNavBuffers(self):
        self.wpswbmp = len(bs.navdb.wplat) * [False]
        self.wplabel = len(bs.navdb.wplat) * [0]

        self.apswbmp = len(bs.navdb.aptlat) * [False]
        self.aplabel = len(bs.navdb.aptlat) * [0]

    def echo(self, msg):
        msgs = msg.split('\n')
        for m in msgs:
            self.editwin.echo(m)
        return

    def showssd(self, param):
        return False, "SSD visualization only available in QtGL GUI"

    def cmdline(self, text):
        self.editwin.insert(text)

    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 label[:3] == bs.traf.label[i][:3] or \
                                             type(bs.traf.label[i][3])==str:
                    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

    def ll2xy(self, lat, lon):
        if not self.swnavdisp:
            # RADAR mode:
            # Convert lat/lon to pixel x,y

            # Normal case
            if self.lon1 > self.lon0:
                x = self.width * (lon - self.lon0) / (self.lon1 - self.lon0)

            # Wrap around:
            else:
                dellon = 180. - self.lon0 + self.lon1 + 180.
                xlon = lon + (lon < 0.) * 360.
                x = (xlon - self.lon0) / dellon * self.width

            y = self.height * (self.lat1 - lat) / (self.lat1 - self.lat0)
        else:
            # NAVDISP mode:
            qdr, dist = geo.qdrdist(self.ndlat, self.ndlon, lat, lon)
            alpha = np.radians(qdr - self.ndcrs)
            base = 30. * (self.lat1 - self.lat0)
            x = dist * np.sin(alpha) / base * self.height + self.width / 2
            y = -dist * np.cos(alpha) / base * self.height + self.height / 2

        return np.rint(x), np.rint(y)

    def xy2ll(self, x, y):
        lat = self.lat0 + (self.lat1 - self.lat0) * (self.height -
                                                     y) / self.height

        if self.lon1 > self.lon0:
            # Normal case
            lon = self.lon0 + (self.lon1 - self.lon0) * x / self.width

        else:
            # Wrap around:
            dellon = 360. + self.lon1 - self.lon0
            xlon = self.lon0 + x / self.width
            lon = xlon - 360. * (lon > 180.)

        # Convert pixel x,y to lat/lan [deg]
        return lat, lon

    def onradar(self, lat, lon):
        """Return boolean (also numpy array) with on or off radar screen (range check)"""

        # Radar mode
        if not self.swnavdisp:
            # Normal case
            if self.lon1 > self.lon0:
                sw = (lat > self.lat0) * (lat < self.lat1) * \
                     (lon > self.lon0) * (lon < self.lon1) == 1

            # Wrap around:
            else:
                sw = (lat > self.lat0) * (lat < self.lat1) * \
                     ((lon > self.lon0) + (lon < self.lon1)) == 1
        # Else NAVDISP mode
        else:
            base = 30. * (self.lat1 - self.lat0)
            dist = geo.latlondist(self.ndlat, self.ndlon, lat, lon) / nm
            sw = dist < base

        return sw

    def zoom(self, factor, absolute=False):
        """Zoom function"""
        oldvalues = self.lat0, self.lat1, self.lon0, self.lon1

        # Zoom factor: 2.0 means halving the display size in degrees lat/lon
        # ZOom out with e.g. 0.5

        ctrlat = (self.lat0 + self.lat1) / 2.
        if not absolute:
            dellat2 = 0.5 * (self.lat1 - self.lat0) / factor
        else:
            dellat2 = 1.0 / factor

        self.lat0 = ctrlat - dellat2
        self.lat1 = ctrlat + dellat2

        # Normal case
        if self.lon1 > self.lon0:
            ctrlon = (self.lon0 + self.lon1) / 2.
            dellon2 = (self.lon1 - self.lon0) / 2. / factor

        # Wrap around
        else:
            ctrlon = (self.lon0 + self.lon1 + 360.) / 2
            dellon2 = (360. + self.lon1 - self.lon0) / 2. / factor

        if absolute:
            dellon2 = dellat2 * self.width /    \
                (self.height * cos(radians(ctrlat)))

        # Wrap around
        self.lon0 = (ctrlon - dellon2 + 180.) % 360. - 180.
        self.lon1 = (ctrlon + dellon2 + 180.) % 360. - 180.

        # Avoid getting out of range
        if self.lat0 < -90 or self.lat1 > 90.:
            self.lat0, self.lat1, self.lon0, self.lon1 = oldvalues

        self.redrawradbg = True
        self.navsel = ()
        self.satsel = ()
        self.geosel = ()

        return

    def pan(self, *args):
        """Pan function:
               absolute: lat,lon;
               relative: ABOVE/DOWN/LEFT/RIGHT"""
        lat, lon = self.ctrlat, self.ctrlon
        if type(args[0]) == str:
            if args[0].upper() == "LEFT":
                lon = lon - 0.5 * (self.lon1 - self.lon0)
            elif args[0].upper() == "RIGHT":
                lon = lon + 0.5 * (self.lon1 - self.lon0)
            elif args[0].upper() == "ABOVE" or args[0].upper() == "UP":
                lat = lat + 0.5 * (self.lat1 - self.lat0)
            elif args[0].upper() == "DOWN":
                lat = lat - 0.5 * (self.lat1 - self.lat0)
            else:
                i = bs.navdb.getwpidx(args[0], self.ctrlat, self.ctrlon)
                if i < 0:
                    i = bs.navdb.getaptidx(args[0], self.ctrlat, self.ctrlon)
                    if i > 0:
                        lat = bs.navdb.aptlat[i]
                        lon = bs.navdb.aptlon[i]
                else:
                    lat = bs.navdb.wplat[i]
                    lon = bs.navdb.wplon[i]

                if i < 0:
                    return False, args[0] + "not found."

        else:
            if len(args) > 1:
                lat, lon = args[:2]
            else:
                return False

        # Maintain size & avoid getting out of range
        dellat2 = (self.lat1 - self.lat0) * 0.5
        self.ctrlat = max(min(lat, 90. - dellat2), dellat2 - 90.)

        # Allow wrap around of longitude
        dellon2 = dellat2 * self.width /   \
                                    (self.height * cos(radians(self.ctrlat)))
        self.ctrlon = (lon + 180.) % 360 - 180.

        # Update edge coordinates
        self.lat0 = self.ctrlat - dellat2
        self.lat1 = self.ctrlat + dellat2
        self.lon0 = (self.ctrlon - dellon2 + 180.) % 360. - 180.
        self.lon1 = (self.ctrlon + dellon2 + 180.) % 360. - 180.

        # Redraw background
        self.redrawradbg = True
        self.navsel = ()
        self.satsel = ()
        self.geosel = ()

        # print "Pan lat,lon:",lat,lon
        # print "Latitude  range:",int(self.lat0),int(self.ctrlat),int(self.lat1)
        # print "Longitude range:",int(self.lon0),int(self.ctrlon),int(self.lon1)
        # print "dellon2 =",dellon2

        return True

    def fullscreen(self, switch):  # full screen switch
        """Switch to (True) /from (False) full screen mode"""

        # Reset screen
        pg.display.quit()
        pg.display.init()

        di = pg.display.Info()

        pg.display.set_caption(
            "BlueSky Open ATM Simulator (F11 = Full Screen)", "BlueSky")
        iconpath = imgpath = "data/graphics/icon.gif"
        iconbmp = pg.image.load(iconpath)
        pg.display.set_icon(iconbmp)

        if switch:
            # Full screen mode
            self.width = di.current_w
            self.height = di.current_h
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso, pg.FULLSCREEN | pg.HWSURFACE)
        else:
            # Windowed
            self.height = min(self.height, di.current_h * 90 / 100)
            self.width = min(self.width, di.current_w * 90 / 100)
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso)

        # Adjust scaling
        dellat = self.lat1 - self.lat0
        avelat = (self.lat0 + self.lat1) / 2.

        dellon = dellat * self.width / (self.height * cos(radians(avelat)))

        self.lon1 = self.lon0 + dellon

        self.radbmp = self.win.copy()

        # Force redraw and reselect
        self.redrawradbg = True
        self.satsel = ()
        self.navsel = ()
        self.geosel = ()

        return

    def savescreen(self):
        """Save a screenshoot"""
        now = datetime.datetime.now()
        date = "%s-%s-%s" % (now.year, now.month, now.day)
        time = "time=%sh %sm %ss" % (now.hour, now.minute, now.second)
        num = 1
        while self.session == "new":
            self.folder = "./screenshots/" + date + "-session-" + str(num)
            if os.path.exists(self.folder):
                num += 1
            else:
                os.makedirs(self.folder)
                self.session = num
        self.screenshotname = self.folder + "/" + time + ".bmp"
        self.screenshot = True

    def ltopix_eq(self, lat):
        """
        Latitude to pixel conversion. Compute how much pixels a
        degree in latlon is in longitudinal direction.
        """

        pwidth = self.width
        lwidth = self.lon1 - self.lon0

        return int(lat / lwidth * pwidth)

    def dtopix_eq(self, dist):
        """
        Distance to pixel conversion. Compute how much pixels a
        meter is in longitudinal direction
        """
        lat = dist / 111319.
        return self.ltopix_eq(lat)

    def objappend(self, itype, name, data):
        """Add user defined objects"""
        if data is None:
            return self.objdel()

        self.objname.append(name)
        self.objtype.append(itype)
        if self.objtype[-1] == 1:
            self.objtype[-1] = "LINE"  # Convert to string

        self.objcolor.append(cyan)
        self.objdata.append(data)

        self.redrawradbg = True  # redraw background

        return

    def objdel(self):
        """Add user defined objects"""
        self.objname = []
        self.objtype = []
        self.objcolor = []
        self.objdata = []
        self.redrawradbg = True  # redraw background
        return

    def showroute(self, acid):  # Toggle show route for an aircraft id
        if self.acidrte == acid:
            self.acidrte = ""  # Click twice on same: route disappear
        else:
            self.acidrte = acid  # Show this route
        return

    def addnavwpt(self, name, lat, lon):  # Draw new navdb waypoint
        # As in pygame navdb has already updated data, simply redraw background
        self.wpswbmp.append(False)  # Add cell to buffer
        self.wplabel.append(0)  # Add cell to buffer
        self.redrawradbg = True  # redraw background
        return

    def showacinfo(self, acid, infotext):
        self.echo(infotext)
        self.showroute(acid)
        return True

    def getviewlatlon(self):  # Return current viewing area in lat, lon
        return self.lat0, self.lat1, self.lon0, self.lon1

    def drawradbg(self):  # redraw radar background
        self.redrawradbg = True
        return

    def filteralt(self, *args):
        return False, 'Filteralt not implemented in Pygame gui'

    def feature(self, sw, arg=""):
        # Switch/toggle/cycle radar screen features e.g. from SWRAD command
        # Coastlines
        if sw == "GEO":
            self.swgeo = not self.swgeo

        # FIR boundaries
        elif sw == "FIR":
            self.swfir = not self.swfir

        # Airport: 0 = None, 1 = Large, 2= All
        elif sw == "APT":
            self.apsw = (self.apsw + 1) % 3
            if not (arg == ""):
                self.apsw = int(cmdargs[2])
            self.navsel = []

        # Waypoint: 0 = None, 1 = VOR, 2 = also WPT, 3 = Also terminal area wpts
        elif sw == "VOR" or sw == "WPT" or sw == "WP" or sw == "NAV":
            self.wpsw = (self.wpsw + 1) % 4
            if not (arg == ""):
                self.wpsw = int(arg)
            self.navsel = []

        # Satellite image background on/off
        elif sw == "SAT":
            self.swsat = not self.swsat

        elif sw[:4] == "ADSB":
            self.swAdsbCoverage = not self.swAdsbCoverage

        # Traffic labels: cycle nr of lines 0,1,2,3
        elif sw[:3] == "LAB":  # Nr lines in label
            self.swlabel = (self.swlabel + 1) % 4
            if not (arg == ""):
                self.swlabel = int(arg)

        else:
            self.redrawradbg = False
            return False  # switch not found

        self.redrawradbg = True
        return True  # Success

    def show_file_dialog(self):
        return opendialog()

    def symbol(self):
        self.swsep = not self.swsep
        return True

    def show_cmd_doc(self, cmd=''):
        # Show documentation on command
        if not cmd:
            cmd = 'Command-Reference'
        curdir = os.getcwd()
        os.chdir("data/html")
        htmlfile = cmd.lower() + ".html"
        if os.path.isfile(htmlfile):
            try:
                subprocess.Popen(htmlfile, shell=True)
            except:
                os.chdir(curdir)
                return False, "Opening " + htmlfile + " failed."
        else:
            os.chdir(curdir)
            return False, htmlfile + " is not yet available, try HELP PDF or check the wiki on Github."

        os.chdir(curdir)
        return True, "HTML window opened"
Example #6
0
    def __init__(self):
        pg.init()

        # Read Screen configuration file:
        print
        print "Setting up screen..."

        lst = np.genfromtxt("data/graphics/scr_cfg.dat", comments='#', dtype='i4')

        self.swfullscreen = int(lst[0]) == 0

        self.width = int(lst[1])  # default value to create variable
        self.height = int(lst[2])  # default value to create variable

        # Dimensions radar window
        self.lat1 = 53.  # [deg] upper limit display
        self.lat0 = 51.  # [deg] lowerlimit display
        self.lon0 = -1.  # [deg] left side of screen

        dellat = self.lat1 - self.lat0

        avelat = (self.lat0 + self.lat1) * 0.5

        dellon = dellat * self.width / (self.height * cos(radians(avelat)))
        avelon = (self.lon0 + dellon / 2. + 180.) % 360. - 180.

        self.lon1 = (self.lon0 + dellon + 180.) % 360. - 180.

        self.ctrlat = avelat
        self.ctrlon = avelon

        # Parameters for making screenshots
        self.session = "new"
        self.folder= ""
        self.screenshot = False
        self.screenshotname = ""

        # Isometric display parameter
        self.isoalt = 0.  # how many meters one pixel is high

        # Display ADS-B range flag
        self.swAdsbCoverage = False

        # Update rate radar:
        self.radardt = 0.10  # 10x per sec 0.25  # 4x per second max
        self.radt0 = -999.  # last time drawn
        self.maxnrwp = 1000  # max nr apts+wpts to be drawn

        #----------------------------SYMBOLS-----------------------------
        # Read graphics for acsymbol (normal = green) + amber
        self.acsymbol = []
        for i in range(60):
            self.acsymbol.append(pg.image.load("data/graphics/acsymbol/acsymbol" \
                                  + str(i) + ".png"))

        self.ambacsymbol = []
        for i in range(60):
            self.ambacsymbol.append(pg.image.load("data/graphics/amb-acsymbol/amb-acsymbol" \
                                     + str(i) + ".png"))

        # Lable lines& default no trails
        self.swlabel = 3


        # Read and scale waypoint symbol
        wptgif = pg.image.load("data/graphics/waypoint.gif")
        self.wptsymbol = pg.transform.scale(wptgif, (10, 7))
        self.wpsw = 1  # 0=None, 1 = VOR 2 = non-digit ones, 3 =all

        # Read and scale airport symbol
        aptgif = pg.image.load("data/graphics/airport.gif")
        self.aptsymbol = pg.transform.scale(aptgif, (12, 9))
        self.apsw = 1  # 0 = None, 1 = Large, 2 = All
        
        # Free flight displays
        self.swsep = False # To show circles of 2.5 nm radius around each aircraft
                           # Note: circles will be distorted when away from equator
        self.swspd = False # To show speed vectors of each aircraft
        self.swtestarea= False

        #--------------------------------MAPS---------------------------------
        # Read map of world
        self.mapbmp = pg.image.load("data/graphics/world.jpg")
        w, h = self.mapbmp.get_size()

        # Two ref positions for scaling, convert to scaling factors x=a*lat+b
        x1, y1, lat1, lon1 = 0., 0., 90., -180.
        x2, y2, lat2, lon2 = w, h, -90., 180.
        self.mapax = (x2 - x1) / (lon2 - lon1)
        self.mapbx = x2 - self.mapax * lon2
        self.mapay = (y2 - y1) / (lat2 - lat1)
        self.mapby = y2 - self.mapay * lat2

        self.swsat = True

        # Nav display projection mode
        self.swnavdisp = False
        self.ndacid = ""
        self.ndlat = 0.0
        self.ndlon = 0.0
        self.ndhdg = 0.0

        #------------------------WINDOW SETUP and scaling--------------------------
        # Empty tuple to force reselection waypoints & airports to be drawn
        self.navsel = ()  # Empty tuple to force reselection waypoints to be drawn
        self.satsel = ()  # Empty tuple to force reselection satellite imagery to be drawn


        # Set up window
        splash.destroy()  # does pg.display.quit()!
        pg.display.init()

        # Full screen
        di = pg.display.Info()
        if self.swfullscreen:
            self.width = di.current_w
            self.height = di.current_h
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso, pg.FULLSCREEN)
        else:
            # Windowed
            self.height = min(self.height, di.current_h * 90 / 100)
            self.width = min(self.width, di.current_w * 90 / 100)
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso)

        pg.display.set_caption("BlueSky Open ATM Simulator (F11 = Full Screen)", "BlueSky")
        iconpath = imgpath = "data/graphics/icon.gif"
        iconbmp = pg.image.load(iconpath)
        pg.display.set_icon(iconbmp)

        self.radbmp = self.win.copy()
        self.redrawradbg = True  # Switch to redraw background

        #---------------------RADAR FONTS & EDIT WINDOW-----------------------------
        # Set up fonts
        self.fontrad = Fastfont(self.win, 'Arial', 14, green, False, False)  # name, size, bold,italic
        self.fontamb = Fastfont(self.win, 'Arial', 14, amber, False, False)  # name, size, bold,italic
        self.fontnav = Fastfont(self.win, 'Arial', 12, lightgreyblue, False, False)  # name, size, bold,italic
        self.fontsys = Fastfont(self.win, 'Helvetica', 14, white, False, False)  # name, size, bold,italic

        # Edit window: 6 line of 64 chars
        nch = lst[3]  # number of chars per line
        nlin = lst[4]  # number of lines in windows
        winx = lst[5]  # x-coordinate in pixels of left side
        winy = self.height - lst[6]  # y-coordinate in pixels of bottom
        self.editwin = Console(self.win, nch, nlin, winx, winy)
   
        # Menu button window
        self.menu = Menu(self.win,10,20)
   

        #-------------------------COASTLINE DATA--------------------------------------
        # Init geo (coastline)  data
        f = open("data/global/coastlines.dat", 'r')
        print "Reading coastlines.dat"
        lines = f.readlines()
        f.close()
        records = []
        for line in lines:
            if not (line.strip() == "" or line.strip()[0] == '#'):
                arg = line.split()
                if len(arg) == 3:
                    records.append([arg[0], float(arg[1]), float(arg[2])])

        # print len(records), " records read."
        # Convert pen up/pen down format of coastlines to numpy arrays with lat/lon

        coastlat0 = []
        coastlon0 = []
        coastlat1 = []
        coastlon1 = []
        clat, clon = -1, -1

        for rec in records:
            lat, lon = rec[1], rec[2]
            if rec[0] == 'D':
                coastlat0.append(clat)
                coastlon0.append(clon)
                coastlat1.append(lat)
                coastlon1.append(lon)
            clat, clon = lat, lon

        self.coastlat0 = np.array(coastlat0)
        self.coastlon0 = np.array(coastlon0)
        self.coastlat1 = np.array(coastlat1)
        self.coastlon1 = np.array(coastlon1)

        del coastlat0, coastlon0, coastlat1, coastlon1  # Clear memory

        self.geosel = ()  # Force reselect first time coastlines
        self.firsel = ()  # Force reselect first time FIR lines

        print "    ", len(self.coastlat0), " coastlines added."

        # Set default coastlines & FIRs on:
        self.swgeo = True
        self.swfir = True
        self.swgrid = False

        # Route drawing for which acid? "" =  None
        self.acidrte = ""
        self.rtewpid = []
        self.rtewplabel = []

        # User defined background objects: 0 = None, 1 = line
        self.objtype    = []
        self.objcolor   = []
        self.objdata    = []

        # Wpt and apt drawing logic memory
        self.wpswbmp = []              # switch indicating whether label bmp is present
        self.wplabel = []              # List to store bitmaps of label
        self.apswbmp = []              # switch indicating whether label bmp is present
        self.aplabel = []              # List to store bitmaps of label

        return
Example #7
0
class Screen:
    """ 
    Screen class definition : contains radar & edit screen data & methods

    Methods:
        Screen(tmx)         :  constructor

        echo(msg)           : print something at screen
        update(sim,traf)    : Draw a new frame of screen
        ll2xy(lat,lon)      : lat/lon[deg] to pixel coordinate conversion
        xy2ll(x,y)          : pixel to lat/lon[de]g conversion    
        zoom(factor)        : zoom in/out
        pan(lat,lon)        : pan to lat,lon position

    Members: see constructor

    Created by : Jacco M. Hoekstra (TU Delft)
    Updated by : Jerom Maas 

    """
    def __init__(self):
        pg.init()

        # Read Screen configuration file:
        print
        print "Setting up screen..."

        lst = np.genfromtxt("data/graphics/scr_cfg.dat", comments='#', dtype='i4')

        self.swfullscreen = int(lst[0]) == 0

        self.width = int(lst[1])  # default value to create variable
        self.height = int(lst[2])  # default value to create variable

        # Dimensions radar window
        self.lat1 = 53.  # [deg] upper limit display
        self.lat0 = 51.  # [deg] lowerlimit display
        self.lon0 = -1.  # [deg] left side of screen

        dellat = self.lat1 - self.lat0

        avelat = (self.lat0 + self.lat1) * 0.5

        dellon = dellat * self.width / (self.height * cos(radians(avelat)))
        avelon = (self.lon0 + dellon / 2. + 180.) % 360. - 180.

        self.lon1 = (self.lon0 + dellon + 180.) % 360. - 180.

        self.ctrlat = avelat
        self.ctrlon = avelon

        # Parameters for making screenshots
        self.session = "new"
        self.folder= ""
        self.screenshot = False
        self.screenshotname = ""

        # Isometric display parameter
        self.isoalt = 0.  # how many meters one pixel is high

        # Display ADS-B range flag
        self.swAdsbCoverage = False

        # Update rate radar:
        self.radardt = 0.10  # 10x per sec 0.25  # 4x per second max
        self.radt0 = -999.  # last time drawn
        self.maxnrwp = 1000  # max nr apts+wpts to be drawn

        #----------------------------SYMBOLS-----------------------------
        # Read graphics for acsymbol (normal = green) + amber
        self.acsymbol = []
        for i in range(60):
            self.acsymbol.append(pg.image.load("data/graphics/acsymbol/acsymbol" \
                                  + str(i) + ".png"))

        self.ambacsymbol = []
        for i in range(60):
            self.ambacsymbol.append(pg.image.load("data/graphics/amb-acsymbol/amb-acsymbol" \
                                     + str(i) + ".png"))

        # Lable lines& default no trails
        self.swlabel = 3


        # Read and scale waypoint symbol
        wptgif = pg.image.load("data/graphics/waypoint.gif")
        self.wptsymbol = pg.transform.scale(wptgif, (10, 7))
        self.wpsw = 1  # 0=None, 1 = VOR 2 = non-digit ones, 3 =all

        # Read and scale airport symbol
        aptgif = pg.image.load("data/graphics/airport.gif")
        self.aptsymbol = pg.transform.scale(aptgif, (12, 9))
        self.apsw = 1  # 0 = None, 1 = Large, 2 = All
        
        # Free flight displays
        self.swsep = False # To show circles of 2.5 nm radius around each aircraft
                           # Note: circles will be distorted when away from equator
        self.swspd = False # To show speed vectors of each aircraft
        self.swtestarea= False

        #--------------------------------MAPS---------------------------------
        # Read map of world
        self.mapbmp = pg.image.load("data/graphics/world.jpg")
        w, h = self.mapbmp.get_size()

        # Two ref positions for scaling, convert to scaling factors x=a*lat+b
        x1, y1, lat1, lon1 = 0., 0., 90., -180.
        x2, y2, lat2, lon2 = w, h, -90., 180.
        self.mapax = (x2 - x1) / (lon2 - lon1)
        self.mapbx = x2 - self.mapax * lon2
        self.mapay = (y2 - y1) / (lat2 - lat1)
        self.mapby = y2 - self.mapay * lat2

        self.swsat = True

        # Nav display projection mode
        self.swnavdisp = False
        self.ndacid = ""
        self.ndlat = 0.0
        self.ndlon = 0.0
        self.ndhdg = 0.0

        #------------------------WINDOW SETUP and scaling--------------------------
        # Empty tuple to force reselection waypoints & airports to be drawn
        self.navsel = ()  # Empty tuple to force reselection waypoints to be drawn
        self.satsel = ()  # Empty tuple to force reselection satellite imagery to be drawn


        # Set up window
        splash.destroy()  # does pg.display.quit()!
        pg.display.init()

        # Full screen
        di = pg.display.Info()
        if self.swfullscreen:
            self.width = di.current_w
            self.height = di.current_h
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso, pg.FULLSCREEN)
        else:
            # Windowed
            self.height = min(self.height, di.current_h * 90 / 100)
            self.width = min(self.width, di.current_w * 90 / 100)
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso)

        pg.display.set_caption("BlueSky Open ATM Simulator (F11 = Full Screen)", "BlueSky")
        iconpath = imgpath = "data/graphics/icon.gif"
        iconbmp = pg.image.load(iconpath)
        pg.display.set_icon(iconbmp)

        self.radbmp = self.win.copy()
        self.redrawradbg = True  # Switch to redraw background

        #---------------------RADAR FONTS & EDIT WINDOW-----------------------------
        # Set up fonts
        self.fontrad = Fastfont(self.win, 'Arial', 14, green, False, False)  # name, size, bold,italic
        self.fontamb = Fastfont(self.win, 'Arial', 14, amber, False, False)  # name, size, bold,italic
        self.fontnav = Fastfont(self.win, 'Arial', 12, lightgreyblue, False, False)  # name, size, bold,italic
        self.fontsys = Fastfont(self.win, 'Helvetica', 14, white, False, False)  # name, size, bold,italic

        # Edit window: 6 line of 64 chars
        nch = lst[3]  # number of chars per line
        nlin = lst[4]  # number of lines in windows
        winx = lst[5]  # x-coordinate in pixels of left side
        winy = self.height - lst[6]  # y-coordinate in pixels of bottom
        self.editwin = Console(self.win, nch, nlin, winx, winy)
   
        # Menu button window
        self.menu = Menu(self.win,10,20)
   

        #-------------------------COASTLINE DATA--------------------------------------
        # Init geo (coastline)  data
        f = open("data/global/coastlines.dat", 'r')
        print "Reading coastlines.dat"
        lines = f.readlines()
        f.close()
        records = []
        for line in lines:
            if not (line.strip() == "" or line.strip()[0] == '#'):
                arg = line.split()
                if len(arg) == 3:
                    records.append([arg[0], float(arg[1]), float(arg[2])])

        # print len(records), " records read."
        # Convert pen up/pen down format of coastlines to numpy arrays with lat/lon

        coastlat0 = []
        coastlon0 = []
        coastlat1 = []
        coastlon1 = []
        clat, clon = -1, -1

        for rec in records:
            lat, lon = rec[1], rec[2]
            if rec[0] == 'D':
                coastlat0.append(clat)
                coastlon0.append(clon)
                coastlat1.append(lat)
                coastlon1.append(lon)
            clat, clon = lat, lon

        self.coastlat0 = np.array(coastlat0)
        self.coastlon0 = np.array(coastlon0)
        self.coastlat1 = np.array(coastlat1)
        self.coastlon1 = np.array(coastlon1)

        del coastlat0, coastlon0, coastlat1, coastlon1  # Clear memory

        self.geosel = ()  # Force reselect first time coastlines
        self.firsel = ()  # Force reselect first time FIR lines

        print "    ", len(self.coastlat0), " coastlines added."

        # Set default coastlines & FIRs on:
        self.swgeo = True
        self.swfir = True
        self.swgrid = False

        # Route drawing for which acid? "" =  None
        self.acidrte = ""
        self.rtewpid = []
        self.rtewplabel = []

        # User defined background objects: 0 = None, 1 = line
        self.objtype    = []
        self.objcolor   = []
        self.objdata    = []

        # Wpt and apt drawing logic memory
        self.wpswbmp = []              # switch indicating whether label bmp is present
        self.wplabel = []              # List to store bitmaps of label
        self.apswbmp = []              # switch indicating whether label bmp is present
        self.aplabel = []              # List to store bitmaps of label

        return

    def updateNavBuffers(self, navdb):
        self.wpswbmp = len(navdb.wplat) * [False]
        self.wplabel = len(navdb.wplat) * [0]

        self.apswbmp = len(navdb.aplat) * [False]
        self.aplabel = len(navdb.aplat) * [0]

    def echo(self, msg):
        msgs = msg.split('\n')
        for m in msgs:
            self.editwin.echo(m)
        return

    def showssd(self, param):
        return False,"SSD visualization only available in QtGL GUI"

    def cmdline(self, text):
        self.editwin.insert(text)

    def update(self, sim, traf):
        """Draw a new frame"""
        # Navdisp mode: get center:
        if self.swnavdisp:
            i = traf.id2idx(self.ndacid)
            if i >= 0:
                self.ndlat = traf.lat[i]
                self.ndlon = traf.lon[i]
                self.ndcrs = traf.trk[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(traf.navdb.firlat0, \
                                                    traf.navdb.firlon0)

                self.firx1, self.firy1 = self.ll2xy(traf.navdb.firlat1, \
                                                    traf.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(traf.navdb.wplat, \
                                                           traf.navdb.wplon))[0])

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

                self.apinside = list(np.where(self.onradar(traf.navdb.aplat, \
                                                           traf.navdb.aplon))[0])

                self.aptsel = []
                for i in self.apinside:
                    if self.apsw == 2 or (self.apsw == 1 and \
                                                      traf.navdb.apmaxrwy[i] > 1000.):
                        self.aptsel.append(i)
                self.aptx, self.apty = self.ll2xy(traf.navdb.aplat, traf.navdb.aplon)


            #------- 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(traf.navdb.wplat[i],  \
                        #     traf.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((50, 30), 0, self.win)
                            self.fontnav.printat(self.wplabel[i], 0, 0, \
                                                 traf.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, \
                            #     traf.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(traf.navdb.aplat[i],  \
                    #                            traf.navdb.aplon[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, \
                                             traf.navdb.apid[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, \
                    #     traf.navdb.apid[i])


            #--------- Draw traffic area ---------
            if traf.swarea and not self.swnavdisp:

                if traf.area == "Square":
                    x0, y0 = self.ll2xy(traf.arealat0, traf.arealon0)
                    x1, y1 = self.ll2xy(traf.arealat1, traf.arealon1)

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

                #FIR CIRCLE
                if traf.area == "Circle":
                    lat2_circle, lon2_circle = geo.qdrpos(sim.metric.fir_circle_point[0], sim.metric.fir_circle_point[1],
                                                      180, sim.metric.fir_circle_radius)

                    x_circle, y_circle = self.ll2xy(sim.metric.fir_circle_point[0], sim.metric.fir_circle_point[1])
                    x2_circle, y2_circle = self.ll2xy(lat2_circle, lon2_circle)
                    radius = int(abs(y2_circle - y_circle))

                    pg.draw.circle(self.radbmp, blue, (int(x_circle), int(y_circle)), radius, 2)


                # print pg.time.get_ticks()*0.001-t0," seconds to draw coastlines"

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

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

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

                for i in trlsel:
                    pg.draw.aaline(self.radbmp, 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)):
                if self.objtype[i]==1:  # 1 = line
                    x0,y0 = self.ll2xy(self.objdata[i][0],self.objdata[i][1])
                    x1,y1 = self.ll2xy(self.objdata[i][2],self.objdata[i][3])
                    pg.draw.line(self.radbmp,self.objcolor[i],(x0, y0), (x1, y1))

            # 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((traf.lat > self.lat0) * (traf.lat < self.lat1) * \
                               (traf.lon > self.lon0) * (traf.lon < self.lon1))[0]

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

            trafx, trafy = self.ll2xy(traf.lat, traf.lon)
            trafy -= traf.alt*self.isoalt
            
            if traf.swtrails:
                ltx, lty = self.ll2xy(traf.lastlat, traf.lastlon)

            # Find pixel size of horizontal separation on screen
            pixelrad=self.dtopix_eq(traf.dbconf.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((traf.trk[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]+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 traf.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 traf.swtrails:
                    pg.draw.line(self.win, tuple(traf.trailcol[i]),
                                 (ltx[i], lty[i]), (trafx[i], trafy[i]))

                # Label text
                label = []
                if self.swlabel > 0:
                    label.append(traf.id[i])  # Line 1 of label: id
                else:
                    label.append(" ")
                if self.swlabel > 1:
                    label.append(str(int(traf.alt[i] / ft)))  # Line 2 of label: altitude
                else:
                    label.append(" ")
                if self.swlabel > 2:
                    cas = 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 label[:3] == traf.label[i][:3]:
                    traf.label[i] = []
                    labelbmp = pg.Surface((100, 60), 0, self.win)
                    if traf.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])

                    traf.label[i].append(label[0])
                    traf.label[i].append(label[1])
                    traf.label[i].append(label[2])
                    traf.label[i].append(labelbmp)
                
                # Blit label
                dest = traf.label[i][3].get_rect()
                dest.top = trafy[i] - 5
                dest.left = trafx[i] + 15
                self.win.blit(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)*traf.tas[i]/nomspeed

                    spdvcx = trafx[i] + np.sin(np.radians(traf.trk[i])) * vectorlength
                    spdvcy = trafy[i] - np.cos(np.radians(traf.trk[i])) * vectorlength \
                                - 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 traf.dbconf.nconf>0:
                xc,yc = self.ll2xy(traf.dbconf.latowncpa,traf.dbconf.lonowncpa)
                yc    = yc - traf.dbconf.altowncpa*self.isoalt

                for j in range(traf.dbconf.nconf):
                    i = traf.id2idx(traf.dbconf.idown[j])
                    if i>=0 and i<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 = traf.id2idx(self.acidrte)
                if i >= 0:
                    for j in range(0,traf.route[i].nwp):
                        if j==0:
                            x1,y1 = self.ll2xy(traf.route[i].wplat[j], \
                                               traf.route[i].wplon[j])
                        else:
                            x0,y0 = x1,y1
                            x1,y1 = self.ll2xy(traf.route[i].wplat[j], \
                                               traf.route[i].wplon[j])
                            pg.draw.line(self.win, magenta,(x0,y0),(x1,y1))

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

                            wplabel = pg.Surface((50, 30), 0, self.win)
                            self.fontnav.printat(wplabel, 0, 0, \
                                                 traf.route[i].wpname[j])

                            if j>=len(self.rtewpid):                      
                                self.rtewpid.append(traf.route[i].wpname[j])
                                self.rtewplabel.append(wplabel)
                            else:
                                self.rtewpid[j]=traf.route[i].wpname[j]
                                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 traf.route[i].iactwp == j:
                            x0,y0 = self.ll2xy(traf.lat[i],traf.lon[i])
                            pg.draw.line(self.win, magenta,(x0,y0),(x1,y1))



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

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

                for i in trlsel:
                    pg.draw.line(self.win, 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(sim.simt))
            self.fontsys.printat(self.win, 10+80, 2, \
                                 "ntraf = " + str(traf.ntraf))
            self.fontsys.printat(self.win, 10+160, 2, \
                                 "Freq=" + str(int(len(sim.dts) / max(0.001, sum(sim.dts)))))
                                 
            self.fontsys.printat(self.win, 10+240, 2, \
                                 "#LOS      = " + str(len(traf.dbconf.LOSlist_now)))
            self.fontsys.printat(self.win, 10+240, 18, \
                                 "Total LOS = " + str(len(traf.dbconf.LOSlist_all)))
            self.fontsys.printat(self.win, 10+240, 34, \
                                 "#Con      = " + str(len(traf.dbconf.conflist_now)))
            self.fontsys.printat(self.win, 10+240, 50, \
                                 "Total Con = " + str(len(traf.dbconf.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


    def ll2xy(self, lat, lon):
        if not self.swnavdisp:
            # RADAR mode:
            # Convert lat/lon to pixel x,y

            # Normal case
            if self.lon1 > self.lon0:
                x = self.width * (lon - self.lon0) / (self.lon1 - self.lon0)

            # Wrap around:
            else:
                dellon = 180. - self.lon0 + self.lon1 + 180.
                xlon = lon + (lon < 0.) * 360.
                x = (xlon - self.lon0) / dellon * self.width

            y = self.height * (self.lat1 - lat) / (self.lat1 - self.lat0)
        else:
            # NAVDISP mode:
            qdr, dist = geo.qdrdist(self.ndlat, self.ndlon, lat, lon)
            alpha = np.radians(qdr - self.ndcrs)
            base = 30. * (self.lat1 - self.lat0)
            x = dist * np.sin(alpha) / base * self.height + self.width / 2
            y = -dist * np.cos(alpha) / base * self.height + self.height / 2

        return np.rint(x), np.rint(y)


    def xy2ll(self, x, y):
        lat = self.lat0 + (self.lat1 - self.lat0) * (self.height - y) / self.height

        if self.lon1 > self.lon0:
            # Normal case
            lon = self.lon0 + (self.lon1 - self.lon0) * x / self.width

        else:
            # Wrap around:
            dellon = 360. + self.lon1 - self.lon0
            xlon = self.lon0 + x / self.width
            lon = xlon - 360. * (lon > 180.)

        # Convert pixel x,y to lat/lan [deg]
        return lat, lon


    def onradar(self, lat, lon):
        """Return boolean (also numpy array) with on or off radar screen (range check)"""

        # Radar mode
        if not self.swnavdisp:
            # Normal case
            if self.lon1 > self.lon0:
                sw = (lat > self.lat0) * (lat < self.lat1) * \
                     (lon > self.lon0) * (lon < self.lon1) == 1

            # Wrap around:
            else:
                sw = (lat > self.lat0) * (lat < self.lat1) * \
                     ((lon > self.lon0) + (lon < self.lon1)) == 1
        # Else NAVDISP mode
        else:
            base = 30. * (self.lat1 - self.lat0)
            dist = geo.latlondist(self.ndlat, self.ndlon, lat, lon) / nm
            sw = dist < base

        return sw



    def zoom(self, factor, absolute = False):
        """Zoom function"""
        oldvalues = self.lat0, self.lat1, self.lon0, self.lon1


        # Zoom factor: 2.0 means halving the display size in degrees lat/lon
        # ZOom out with e.g. 0.5

        ctrlat = (self.lat0 + self.lat1) / 2.
        if not absolute:
             dellat2 = 0.5*(self.lat1 - self.lat0) / factor
        else:
             dellat2 = 1.0/factor
             
        self.lat0 = ctrlat - dellat2
        self.lat1 = ctrlat + dellat2

        # Normal case
        if self.lon1 > self.lon0:
            ctrlon = (self.lon0 + self.lon1) / 2.
            dellon2 = (self.lon1 - self.lon0) / 2. / factor

        # Wrap around
        else:
            ctrlon = (self.lon0 + self.lon1 + 360.) / 2
            dellon2 = (360. + self.lon1 - self.lon0) / 2. / factor

        if absolute: 
            dellon2 = dellat2 * self.width /    \
                (self.height * cos(radians(ctrlat)))

        # Wrap around
        self.lon0 = (ctrlon - dellon2 + 180.) % 360. - 180.
        self.lon1 = (ctrlon + dellon2 + 180.) % 360. - 180.

        # Avoid getting out of range
        if self.lat0 < -90 or self.lat1 > 90.:
            self.lat0, self.lat1, self.lon0, self.lon1 = oldvalues

        self.redrawradbg = True
        self.navsel = ()
        self.satsel = ()
        self.geosel = ()

        return

    def pan(self, *args):
        """Pan function:
               absolute: lat,lon;
               relative: UP/DOWN/LEFT/RIGHT"""
        lat, lon = self.ctrlat, self.ctrlon
        if args[0] == "LEFT":
            lon = self.ctrlon - 0.5 * (self.lon1 - self.lon0)
        elif args[0] == "RIGHT":
            lon = self.ctrlon + 0.5 * (self.lon1 - self.lon0)
        elif args[0] == "UP":
            lat = self.ctrlat + 0.5 * (self.lat1 - self.lat0)
        elif args[0] == "DOWN":
            lat = self.ctrlat - 0.5 * self.lat1 - self.lat0
        else:
            lat, lon = args

        # Maintain size
        dellat2 = (self.lat1 - self.lat0) * 0.5

        # Avoid getting out of range
        self.ctrlat = max(min(lat, 90. - dellat2), dellat2 - 90.)

        # Allow wrap around of longitude
        dellon2 = dellat2 * self.width /   \
                                    (self.height * cos(radians(self.ctrlat)))
        self.ctrlon = (lon + 180.) % 360 - 180.

        self.lat0 = self.ctrlat - dellat2
        self.lat1 = self.ctrlat + dellat2
        self.lon0 = (self.ctrlon - dellon2 + 180.) % 360. - 180.
        self.lon1 = (self.ctrlon + dellon2 + 180.) % 360. - 180.

        # Redraw background
        self.redrawradbg = True
        self.navsel = ()
        self.satsel = ()
        self.geosel = ()

        # print "Pan lat,lon:",lat,lon
        # print "Latitude  range:",int(self.lat0),int(self.ctrlat),int(self.lat1)
        # print "Longitude range:",int(self.lon0),int(self.ctrlon),int(self.lon1)
        # print "dellon2 =",dellon2

        return


    def fullscreen(self, switch):  # full screen switch
        """Switch to (True) /from (False) full screen mode"""
        
        # Reset screen
        pg.display.quit()
        pg.display.init()

        di = pg.display.Info()

        pg.display.set_caption("BlueSky Open ATM Simulator (F11 = Full Screen)",
                               "BlueSky")
        iconpath = imgpath = "data/graphics/icon.gif"
        iconbmp = pg.image.load(iconpath)
        pg.display.set_icon(iconbmp)

        if switch:
            # Full screen mode
            self.width = di.current_w
            self.height = di.current_h
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso, pg.FULLSCREEN | pg.HWSURFACE)
        else:
            # Windowed
            self.height = min(self.height, di.current_h * 90 / 100)
            self.width = min(self.width, di.current_w * 90 / 100)
            reso = (self.width, self.height)
            self.win = pg.display.set_mode(reso)

        # Adjust scaling
        dellat = self.lat1 - self.lat0
        avelat = (self.lat0 + self.lat1) / 2.

        dellon = dellat * self.width / (self.height * cos(radians(avelat)))

        self.lon1 = self.lon0 + dellon

        self.radbmp = self.win.copy()

        # Force redraw and reselect
        self.redrawradbg = True
        self.satsel = ()
        self.navsel = ()
        self.geosel = ()

        return
        
    def savescreen(self):
        """Save a screenshoot"""
        now=datetime.datetime.now()
        date="%s-%s-%s" % (now.year, now.month, now.day)
        time="time=%sh %sm %ss" % (now.hour, now.minute, now.second)
        num=1
        while self.session == "new":
            self.folder="./screenshots/"+date+"-session-"+str(num)
            if os.path.exists(self.folder):
                num+=1
            else:
                os.makedirs(self.folder)
                self.session=num
        self.screenshotname=self.folder+"/"+time+".bmp"        
        self.screenshot=True


    def ltopix_eq(self,lat): 
        """
        Latitude to pixel conversion. Compute how much pixels a 
        degree in latlon is in longitudinal direction.
        """
        
        pwidth=self.width
        lwidth=self.lon1-self.lon0

        return int(lat/lwidth*pwidth)


    def dtopix_eq(self,dist):
        """
        Distance to pixel conversion. Compute how much pixels a 
        meter is in longitudinal direction
        """
        lat=dist/111319.
        return self.ltopix_eq(lat)


    def objappend(self,itype,name,data):
        """Add user defined objects"""
        if data is None:
            return self.objdel()
        self.objtype.append(itype)
        self.objcolor.append(blue)
        self.objdata.append(data)

        self.redrawradbg = True  # redraw background

        return

    def objdel(self):
        """Add user defined objects"""
        self.objtype     = []
        self.objcolor    = []
        self.objdata     = []
        self.redrawradbg = True  # redraw background
        return

    def showroute(self, acid):  # Toggle show route for an aircraft id
        if self.acidrte == acid:
            self.acidrte = ""  # Click twice on same: route disappear
        else:
            self.acidrte = acid  # Show this route
        return

    def showacinfo(self, acid, infotext):
        self.echo(infotext)
        self.showroute(acid)
        return True

    def getviewlatlon(self): # Return current viewing area in lat, lon
        return self.lat0, self.lat1, self.lon0, self.lon1  
    
    def drawradbg(self): # redraw radar background
        self.redrawradbg = True
        return
        
    def feature(self,sw,arg=""):
        # Switch/toggle/cycle radar screen features e.g. from SWRAD command        
        # Coastlines
        if sw == "GEO":
            self.swgeo = not self.swgeo
        
        
        # FIR boundaries
        elif sw == "FIR":
            self.swfir = not self.swfir

        # Airport: 0 = None, 1 = Large, 2= All
        elif sw == "APT":
            self.apsw = (self.apsw + 1) % 3
            if not (arg== ""):
                self.apsw = int(cmdargs[2])
            self.navsel = []

        # Waypoint: 0 = None, 1 = VOR, 2 = also WPT, 3 = Also terminal area wpts
        elif sw == "VOR" or sw == "WPT" or sw == "WP" or sw == "NAV":
            self.wpsw = (self.wpsw + 1) % 4
            if not (arg== ""):
                self.wpsw = int(arg)
            self.navsel = []
        
        # Satellite image background on/off
        elif sw == "SAT":
            self.swsat = not self.swsat

        elif sw[:4] == "ADSB":
            self.swAdsbCoverage = not self.swAdsbCoverage

        # Traffic labels: cycle nr of lines 0,1,2,3
        elif sw[:3] == "LAB":  # Nr lines in label
            self.swlabel = (self.swlabel + 1) % 4
            if not (arg == ""):
                self.swlabel = int(arg)

        else:
            self.redrawradbg = False
            return False # switch not found

        self.redrawradbg = True
        return True # Success

    def show_file_dialog(self):
        return opendialog()
        
    def symbol(self):
        print "Hello"
        self.swsep = not self.swsep
        return True
Example #8
0
class Console:
    """ 
    Console (aka EditWin) class definition : Edit window & console class

    Methods:
        echo(msg)         : Print a message
        insert(message)   : insert characters in current edit line
        backspace()       : process backspace
        getline()         : return current edit line
        enter()           : enter, end of edit line
        scroll()          : scroll up one line
        update()          : redraw update bitmap of edit window

    Created by  : Jacco M. Hoekstra (TU Delft)
    """
    def __init__(self, win, nch, nlin, winx, winy):
        # Was Helvetica,14
        self.fontedit = Fastfont(win, 'Courier New', 14, white, False,
                                 False)  # name, size, bold,italic

        # Edit window: 6 line of 64 chars
        self.content = []
        self.nch = nch  # number of chars per line
        self.nlin = nlin  # number of lines in windows
        self.winx = winx  # x-coordinate in pixels of left side
        self.winy = winy - self.nlin * self.fontedit.linedy  # y-coordinate in pixels of top
        self.msg = []  # Messages in edit window

        for i in range(self.nlin):
            line = self.nch * [' ']
            self.content.append(line)
        self.content0 = self.content

        self.xcursor = 0
        self.xedit = 0
        # self.printeditwin('Testing 1,2,3')
        self.bmpdy = self.nlin * self.fontedit.linedy
        self.bmpdx = self.nch * self.fontedit.linedy * 10 / 17 + 2  # Guess max aspect ratio
        self.bmp = pg.Surface([self.bmpdx, self.bmpdy], pg.SRCALPHA, 32)

        self.bmp.fill(darkblue)
        self.rect = pg.Rect(self.winx, self.winy, self.bmpdx, self.bmpdy)
        self.redraw = True

        return

    def echo(self, msg):
        """print a message to console window"""
        if self.xedit == self.xcursor:
            self.insert(msg)
            j = self.xcursor / self.nch
            self.xcursor = (j + 1) * self.nch
            self.xedit = self.xcursor

            # Check for End of window
            if self.xedit >= (self.nch - 1) * (self.nlin - 1):
                del self.content[0]
                self.content.append(self.nch * [' '])
                self.xcursor = j * self.nch
                self.xedit = self.xcursor
        else:
            self.msg.append(msg)  # buffer
        return

    def insert(self, message):
        i = self.xcursor % self.nch
        j = self.xcursor / self.nch
        for ich in range(len(message)):
            self.content[j][i] = message[ich]
            i = i + 1
            # Check for end-of line
            if i >= self.nch:
                i = 0
                j = j + 1
                # Check for end-of edit window
                if j >= self.nlin:
                    self.scroll()
                    j = j - 1
        self.xcursor = j * self.nch + i
        self.redraw = True
        return

    def backspace(self):
        if self.xcursor > self.xedit:
            self.xcursor = self.xcursor - 1
        self.redraw = True
        i = self.xcursor % self.nch
        j = self.xcursor / self.nch
        self.content[j][i] = " "
        return

    def getline(self):  # enter was pressed
        line = ""
        for idx in range(self.xedit, self.xcursor + 1):
            i = idx % self.nch
            j = idx / self.nch
            line = line + self.content[j][i]
        return line

    def enter(self):
        j = self.xcursor / self.nch
        self.xcursor = (j + 1) * self.nch
        self.xedit = self.xcursor

        # End of window
        if self.xedit >= (self.nch - 1) * (self.nlin - 1):
            del self.content[0]
            self.content.append(self.nch * [' '])
            self.xcursor = j * self.nch
            self.xedit = self.xcursor

        # Print buffered messages
        self.redraw = True
        while len(self.msg) > 0:
            self.echo(
                self.msg[0])  # No endless recursion becasue xedit==xcursor
            del self.msg[0]
        return

    def scroll(self):
        """Scroll window"""
        del self.content[0]
        self.content.append(self.nch * [' '])
        self.xcursor = self.xcursor - self.nch
        self.xedit = self.xedit - self.nch

    def update(self):
        """Update: Draw a new frame"""
        # Draw edit window
        if self.redraw:
            self.bmp.fill(darkgrey)

            for j in range(self.nlin):
                for i in range(self.nch):
                    if True or self.content[j][i] != self.content0[j][i]:
                        x = i * self.fontedit.linedy * 10 / 17 + 1
                        y = j * self.fontedit.linedy + self.fontedit.linedy / 6
                        self.fontedit.printat(self.bmp, x, y,
                                              self.content[j][i])
                        self.content0[j][i] = self.content[j][i]
            # Draw cursor
            i = self.xcursor % self.nch
            j = self.xcursor / self.nch
            x = i * self.fontedit.linedy * 10 / 17
            y = j * self.fontedit.linedy + self.fontedit.linedy / 6
            self.fontedit.printat(self.bmp, x, y, "_")
            self.bmp.set_alpha(127)
            self.redraw = False

        return