Ejemplo n.º 1
0
 def update_route_data(self, data):
     self.route_acidx      = data.acidx
     if self.route_acidx >= 0:
         nsegments = len(data.lat)
         self.route.set_vertex_count(nsegments)
         routedata       = np.empty(2 * nsegments, dtype=np.float32)
         routedata[::2]  = data.lat
         routedata[1::2] = data.lon
         update_buffer(self.routebuf, routedata)
     else:
         self.route.set_vertex_count(0)
Ejemplo n.º 2
0
    def clearPolygons(self):
        # Clear all polys for sender node
        nact = self.nodedata[manager.sender()[0]]
        nact.polydata = np.array([], dtype=np.float32)
        nact.polynames.clear()

        # If the updated polygon buffer is also currently viewed, also send
        # updates to the gpu buffer
        if manager.sender()[0] == self.iactconn:
            update_buffer(self.allpolysbuf, nact.polydata)
            self.allpolys.set_vertex_count(len(nact.polydata) / 2)
Ejemplo n.º 3
0
    def update_route_data(self, data):
        self.route_acid = data.acid
        if data.acid != "" and len(data.wplat) > 0:
            nsegments = len(data.wplat)
            data.iactwp = min(max(0, data.iactwp), nsegments - 1)
            self.routelbl.n_instances = nsegments
            self.route.set_vertex_count(2 * nsegments)
            routedata = np.empty(4 * nsegments, dtype=np.float32)
            routedata[0:4] = [
                data.aclat, data.aclon, data.wplat[data.iactwp],
                data.wplon[data.iactwp]
            ]

            routedata[4::4] = data.wplat[:-1]
            routedata[5::4] = data.wplon[:-1]
            routedata[6::4] = data.wplat[1:]
            routedata[7::4] = data.wplon[1:]

            update_buffer(self.routebuf, routedata)
            update_buffer(self.routewplatbuf,
                          np.array(data.wplat, dtype=np.float32))
            update_buffer(self.routewplonbuf,
                          np.array(data.wplon, dtype=np.float32))
            wpname = []
            for wp in data.wpname:
                wpname += wp[:12].ljust(12)
            update_buffer(self.routelblbuf, np.array(wpname))
        else:
            self.route.set_vertex_count(0)
Ejemplo n.º 4
0
    def update_route_data(self, data):
        self.route_acid = data.acid
        if data.acid != "" and len(data.lat) > 0:
            nsegments = len(data.lat)
            data.iactwp = max(0, data.iactwp)
            self.routelbl.n_instances = nsegments
            self.route.set_vertex_count(2 * nsegments)
            routedata = np.empty(4 * nsegments, dtype=np.float32)
            routedata[0:4] = [data.aclat, data.aclon,
                data.lat[data.iactwp], data.lon[data.iactwp]]

            routedata[4::4] = data.lat[:-1]
            routedata[5::4] = data.lon[:-1]
            routedata[6::4] = data.lat[1:]
            routedata[7::4] = data.lon[1:]

            update_buffer(self.routebuf, routedata)
            update_buffer(self.routewplatbuf, np.array(data.lat, dtype=np.float32))
            update_buffer(self.routewplonbuf, np.array(data.lon, dtype=np.float32))
            wptlabels = []
            for wp in data.wptlabels:
                wptlabels += wp[:12].ljust(12)
            update_buffer(self.routelblbuf, np.array(wptlabels))
        else:
            self.route.set_vertex_count(0)
Ejemplo n.º 5
0
 def previewpoly(self, shape_type, data_in=None):
     if shape_type is None:
         self.polyprev.set_vertex_count(0)
         return
     if shape_type in ['BOX', 'AREA']:
         # For a box (an area is a box) we need to add two additional corners
         data = np.zeros(8, dtype=np.float32)
         data[0:2] = data_in[0:2]
         data[2:4] = data_in[2], data_in[1]
         data[4:6] = data_in[2:4]
         data[6:8] = data_in[0], data_in[3]
     else:
         data = data_in
     update_buffer(self.polyprevbuf, data)
     self.polyprev.set_vertex_count(len(data)/2)
Ejemplo n.º 6
0
 def previewpoly(self, shape_type, data_in=None):
     if shape_type is None:
         self.polyprev.set_vertex_count(0)
         return
     if shape_type in ['BOX', 'AREA']:
         # For a box (an area is a box) we need to add two additional corners
         data = np.zeros(8, dtype=np.float32)
         data[0:2] = data_in[0:2]
         data[2:4] = data_in[2], data_in[1]
         data[4:6] = data_in[2:4]
         data[6:8] = data_in[0], data_in[3]
     else:
         data = data_in
     update_buffer(self.polyprevbuf, data)
     self.polyprev.set_vertex_count(len(data) / 2)
Ejemplo n.º 7
0
 def updatePolygon(self, name, data_in):
     self.makeCurrent()
     if name in self.polys:
         if data_in is None:
             del self.polys[name]
         else:
             update_buffer(self.polys[name].vertexbuf, data_in)
             self.polys[name].set_vertex_count(len(data_in) / 2)
     else:
         if data_in is None:
             print "Delete '" + name + "': object not found!"
         else:
             newpoly = RenderObject(gl.GL_LINE_LOOP, vertex_count=len(data_in)/2)
             newpoly.vertexbuf = newpoly.bind_attrib(ATTRIB_VERTEX, 2, data_in)
             newpoly.colorbuf  = newpoly.bind_attrib(ATTRIB_COLOR, 3, np.array(blue, dtype=np.float32), instance_divisor=1)
             self.polys[name]  = newpoly
Ejemplo n.º 8
0
    def updatePolygon(self, name, data_in):
        nact = self.nodedata[manager.sender()[0]]
        if name in nact.polynames:
            # We're either updating a polygon, or deleting it. In both cases
            # we remove the current one.
            nact.polydata = np.delete(nact.polydata, range(*nact.polynames[name]))
            del nact.polynames[name]

        if data_in is not None:
            nact.polynames[name] = (len(nact.polydata), 2*len(data_in))
            newbuf = np.empty(2 * len(data_in), dtype=np.float32)
            newbuf[0::4]   = data_in[0::2]  # lat
            newbuf[1::4]   = data_in[1::2]  # lon
            newbuf[2:-2:4] = data_in[2::2]  # lat
            newbuf[3:-3:4] = data_in[3::2]  # lon
            newbuf[-2:]    = data_in[0:2]
            nact.polydata = np.append(nact.polydata, newbuf)
            update_buffer(self.allpolysbuf, nact.polydata)
            self.allpolys.set_vertex_count(len(nact.polydata)/2)
Ejemplo n.º 9
0
    def updatePolygon(self, name, data_in):
        nact = self.nodedata[manager.sender()[0]]
        if name in nact.polynames:
            # We're either updating a polygon, or deleting it. In both cases
            # we remove the current one.
            nact.polydata = np.delete(nact.polydata,
                                      range(*nact.polynames[name]))
            del nact.polynames[name]

        if data_in is not None:
            nact.polynames[name] = (len(nact.polydata), 2 * len(data_in))
            newbuf = np.empty(2 * len(data_in), dtype=np.float32)
            newbuf[0::4] = data_in[0::2]  # lat
            newbuf[1::4] = data_in[1::2]  # lon
            newbuf[2:-2:4] = data_in[2::2]  # lat
            newbuf[3:-3:4] = data_in[3::2]  # lon
            newbuf[-2:] = data_in[0:2]
            nact.polydata = np.append(nact.polydata, newbuf)
            update_buffer(self.allpolysbuf, nact.polydata)
            self.allpolys.set_vertex_count(len(nact.polydata) / 2)
Ejemplo n.º 10
0
    def update_lcd(self):
        # [0:courseLeftRight, 1:spd, 2:hdg, 3:alt, 4:vs]
        val = self.selValues
        chars = '%03d' % (int(val[0]) % 360)
        chars += '% 5d' % max(0, val[1])
        chars += '%03d' % (int(val[2]) % 360)
        chars += '% 5d' % min(99999, max(0, val[3]))
        chars += '     ' if val[4] == 0 else '% 5d' % min(9999, max(-9999, val[4]))
        chars += '%03d' % (int(val[0]) % 360)

        indices = []
        for c in chars:
            if c == ' ':
                indices += [0] * 6
            elif c == '-':
                indices += [1] * 6
            elif c == '.':
                indices += [2] * 6
            else:
                indices += [int(c) + 3] * 6

        update_buffer(self.lcdbuf, np.array(indices, dtype=np.float32))
Ejemplo n.º 11
0
    def update_lcd(self):
        # [0:courseLeftRight, 1:spd, 2:hdg, 3:alt, 4:vs]
        val = self.selValues
        chars = '%03d' % (int(val[0]) % 360)
        chars += '% 5d' % max(0, val[1])
        chars += '%03d' % (int(val[2]) % 360)
        chars += '% 5d' % min(99999, max(0, val[3]))
        chars += '     ' if val[4] == 0 else '% 5d' % min(
            9999, max(-9999, val[4]))
        chars += '%03d' % (int(val[0]) % 360)

        indices = []
        for c in chars:
            if c == ' ':
                indices += [0] * 6
            elif c == '-':
                indices += [1] * 6
            elif c == '.':
                indices += [2] * 6
            else:
                indices += [int(c) + 3] * 6

        update_buffer(self.lcdbuf, np.array(indices, dtype=np.float32))
Ejemplo n.º 12
0
    def update(self, simt, data):
        # Update the time scale
        t_hr  = int(floor(simt / 3600))
        t_min = int(floor(simt % 3600 / 60.0))
        tick1 = int(floor(float(t_min) / 5.0)) * 5

        for i in range(10):
            self.scaletxt_texc[36*i+2:36*i+18:3]    = 48 + ((tick1 + 5 * i) % 60)/10
            self.scaletxt_texc[36*i+20:36*i+36:3]   = 48 + ((tick1 + 5 * i) % 60)%10

        update_buffer(self.scaletxt_buf, self.scaletxt_texc)
        self.y_offset = -(simt % 300) / 300.0 * 0.275

        self.font.update_text_string(self.timelbl, '%02d:%02d' % (t_hr, t_min))

        # Update the aircraft list
        labels = ''
        ypos   = []
        colors = []
        for i in range(len(data.ids)):
            if data.sw_show[i] == 'ON' and data.etas[i]>simt:
                eath  = int(data.eats[i]) / 3600
                eatm  = int(data.eats[i] - 3600 * eath) / 60
                etah  = int(data.etas[i]) / 3600
                etam  = int(data.etas[i] - 3600 * etah) / 60
                delay = max(0, int(data.delays[i] / 60))

                labels += '%-8s B747 %-3s %02d%02d %02d%02d %-2d' % (data.ids[i], data.iafs[i], eath, eatm, etah, etam, delay)
                status = data.STAstatuses[i]
                if data.PopupLabels[i] == 'POPUP':
                    colors += red
                elif status == 'Fixed':
                    colors += white
                elif status == 'Semi-Fixed':
                    colors += forestgreen
                else:
                    colors += lightblue2

                # y-scale: 0.055 units = 1 minute
                # t_NOW is at -1.125
                ypos.append(-1.125 + float(data.stas[i] - simt) / 60.0 * 0.055)

        # Update the buffers
        update_buffer(self.aclblbuf, np.array(labels, dtype=np.string_))
        update_buffer(self.accolorbuf, np.array(colors, dtype=np.uint8))
        update_buffer(self.acposybuf, np.array(ypos, dtype=np.float32))
        self.aclbls.n_instances = len(data.ids)
Ejemplo n.º 13
0
    def event(self, event):
        if not self.initialized:
            return super(BlipDriver, self).event(event)

        self.makeCurrent()
        if event.type() in [
                QEvent.MouseMove, QEvent.MouseButtonPress,
                QEvent.MouseButtonRelease
        ]:
            px = 2.0 * (event.x()) / self.width - 1.0
            py = 10.0 * (self.height - event.y()) / self.height - 1.0

        if event.type(
        ) == QEvent.MouseButtonPress and event.button() & Qt.LeftButton:
            self.btn_pressed, _ = check_knob(px, py)
            if self.btn_pressed is not None:
                self.drag_start = event.x(), event.y()
                QTimer.singleShot(100, self.updateAPValues)

        elif event.type(
        ) == QEvent.MouseButtonRelease and event.button() & Qt.LeftButton:
            # print px, py
            self.btn_pressed = None
            col_triangles = 6 * [255, 255, 255, 180]
            update_buffer(self.updown.colorbuf,
                          np.array(col_triangles, dtype=np.uint8))
            # MCP button clicked?
            name, idx = check_btn(px, py)
            if name is not None:
                self.btn_state[idx] = not self.btn_state[idx]

            btn_color = []
            for b in self.btn_state:
                btn_color += 24 * [255] if b else 24 * [0]
            update_buffer(self.btn_leds.colorbuf,
                          np.array(btn_color, dtype=np.uint8))
        elif event.type() == QEvent.MouseMove:
            if event.buttons(
            ) & Qt.LeftButton and self.btn_pressed is not None:
                self.rate = float(self.drag_start[1] - event.y()) / self.height
                if self.rate > 1e-2:
                    col_triangles = 3 * [255, 140, 0, 255
                                         ] + 3 * [255, 255, 255, 180]
                elif self.rate < 1e-2:
                    col_triangles = 3 * [255, 255, 255, 180
                                         ] + 3 * [255, 140, 0, 255]
                else:
                    col_triangles = 6 * [255, 255, 255, 180]
                update_buffer(self.updown.colorbuf,
                              np.array(col_triangles, dtype=np.uint8))
                return True
            # Mouse-over for knobs
            name, self.updownpos = check_knob(px, py)

            # ismcp = float(self.height - event.y()) / self.height <= 0.2

        return super(BlipDriver, self).event(event)
Ejemplo n.º 14
0
    def update_route_data(self, data):
        self.route_acid = data.acid
        if data.acid != "" and len(data.wplat) > 0:
            nsegments = len(data.wplat)
            data.iactwp = min(max(0, data.iactwp), nsegments - 1)
            self.routelbl.n_instances = nsegments
            self.route.set_vertex_count(2 * nsegments)
            routedata = np.empty(4 * nsegments, dtype=np.float32)
            routedata[0:4] = [data.aclat, data.aclon,
                data.wplat[data.iactwp], data.wplon[data.iactwp]]

            routedata[4::4] = data.wplat[:-1]
            routedata[5::4] = data.wplon[:-1]
            routedata[6::4] = data.wplat[1:]
            routedata[7::4] = data.wplon[1:]

            update_buffer(self.routebuf, routedata)
            update_buffer(self.routewplatbuf, np.array(data.wplat, dtype=np.float32))
            update_buffer(self.routewplonbuf, np.array(data.wplon, dtype=np.float32))
            wpname = ''
            for wp, alt, spd in zip(data.wpname, data.wpalt, data.wpspd):
                if alt < 0. and spd < 0.:
                    txt = wp[:10].ljust(20)
                else:
                    txt = wp[:10].ljust(10)
                    if alt < 0:
                        txt += "-----/"
                    elif alt > 4500 * ft:
                        FL = int(round((alt / (100. * ft))))
                        txt += "FL%03d/" % FL
                    else:
                        txt += "%05d/" % int(round(alt / ft))

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

                wpname += txt
            update_buffer(self.routelblbuf, np.array(wpname))
        else:
            self.route.set_vertex_count(0)
Ejemplo n.º 15
0
    def event(self, event):
        if not self.initialized:
            return super(BlipDriver, self).event(event)

        self.makeCurrent()
        if event.type() in [QEvent.MouseMove, QEvent.MouseButtonPress, QEvent.MouseButtonRelease]:
            px = 2.0 * (event.x()) / self.width - 1.0
            py = 10.0 * (self.height - event.y()) / self.height - 1.0

        if event.type() == QEvent.MouseButtonPress and event.button() & Qt.LeftButton:
            self.btn_pressed, _ = check_knob(px, py)
            if self.btn_pressed is not None:
                self.drag_start = event.x(), event.y()
                QTimer.singleShot(100, self.updateAPValues)

        elif event.type() == QEvent.MouseButtonRelease and event.button() & Qt.LeftButton:
            # print px, py
            self.btn_pressed = None
            col_triangles = 6 * [255, 255, 255, 180]
            update_buffer(self.updown.colorbuf, np.array(col_triangles, dtype=np.uint8))
            # MCP button clicked?
            name, idx = check_btn(px, py)
            if name is not None:
                self.btn_state[idx] = not self.btn_state[idx]

            btn_color = []
            for b in self.btn_state:
                btn_color += 24 * [255] if b else 24 * [0]
            update_buffer(self.btn_leds.colorbuf, np.array(btn_color, dtype=np.uint8))
        elif event.type() == QEvent.MouseMove:
            if event.buttons() & Qt.LeftButton and self.btn_pressed is not None:
                self.rate = float(self.drag_start[1] - event.y()) / self.height
                if self.rate > 1e-2:
                    col_triangles = 3 * [255, 140, 0, 255] + 3 * [255, 255, 255, 180]
                elif self.rate < 1e-2:
                    col_triangles = 3 * [255, 255, 255, 180] + 3 * [255, 140, 0, 255]
                else:
                    col_triangles = 6 * [255, 255, 255, 180]
                update_buffer(self.updown.colorbuf, np.array(col_triangles, dtype=np.uint8))
                return True
            # Mouse-over for knobs
            name, self.updownpos = check_knob(px, py)

            # ismcp = float(self.height - event.y()) / self.height <= 0.2

        return super(BlipDriver, self).event(event)
Ejemplo n.º 16
0
    def update_aircraft_data(self, data):
        self.naircraft = len(data.lat)
        if self.naircraft > 0:
            # Update data in GPU buffers
            update_buffer(self.aclatbuf, data.lat)
            update_buffer(self.aclonbuf, data.lon)
            update_buffer(self.achdgbuf, data.trk)
            update_buffer(self.acaltbuf, data.alt)
            update_buffer(self.actasbuf, data.tas)

            # CPA lines to indicate conflicts
            ncpalines = len(data.confcpalat)
            cpalines  = np.zeros(4 * ncpalines, dtype=np.float32)
            self.cpalines.set_vertex_count(2 * ncpalines)

            # Labels and colors
            rawlabel = ''
            color    = np.zeros((self.naircraft, 3), dtype=np.float32)
            for i in range(self.naircraft):
                if np.isnan(data.tas[i]):
                    print 'TAS NaN in %d: %s' % (i, data.id[i])
                    data.tas[i] = 0.0

                if np.isnan(data.alt[i]):
                    print 'ALT NaN in %d: %s' % (i, data.id[i])
                    data.alt[i] = 0.0

                rawlabel += '%-8sFL%03d   %-8d' % (data.id[i][:8], int(data.alt[i] / ft / 100), int(data.tas[i] / kts))
                confidx = data.iconf[i]
                if confidx >= 0:
                    color[i, :] = amber
                    cpalines[4 * confidx : 4 * confidx + 4] = [ data.lat[i], data.lon[i],
                                                                data.confcpalat[confidx], data.confcpalon[confidx]]
                else:
                    color[i, :] = green

            update_buffer(self.confcpabuf, cpalines)
            update_buffer(self.accolorbuf, color)
            update_buffer(self.aclblbuf, np.array(rawlabel, dtype=np.string_))

            # If there is a visible route, update the start position
            if self.route_acidx >= 0:
                update_buffer(self.routebuf, np.array([data.lat[self.route_acidx], data.lon[self.route_acidx]], dtype=np.float32))
Ejemplo n.º 17
0
    def update_aircraft_data(self, data):
        self.naircraft = len(data.lat)
        if self.naircraft == 0:
            self.cpalines.set_vertex_count(0)
        else:
            # Update data in GPU buffers
            update_buffer(self.aclatbuf, np.array(data.lat, dtype=np.float32))
            update_buffer(self.aclonbuf, np.array(data.lon, dtype=np.float32))
            update_buffer(self.achdgbuf, np.array(data.trk, dtype=np.float32))
            update_buffer(self.acaltbuf, np.array(data.alt, dtype=np.float32))
            update_buffer(self.actasbuf, np.array(data.tas, dtype=np.float32))

            # CPA lines to indicate conflicts
            ncpalines = len(data.confcpalat)

            cpalines = np.zeros(4 * ncpalines, dtype=np.float32)
            self.cpalines.set_vertex_count(2 * ncpalines)

            # Labels and colors
            rawlabel = ''
            color = np.empty((self.naircraft, 3), dtype=np.uint8)
            for i in range(self.naircraft):
                if np.isnan(data.tas[i]):
                    print 'CAS NaN in %d: %s' % (i, data.id[i])
                    data.cas[i] = 0.0

                if np.isnan(data.alt[i]):
                    print 'ALT NaN in %d: %s' % (i, data.id[i])
                    data.alt[i] = 0.0

                # Make label: 3 lines of 8 characters per aircraft
                rawlabel += '%-8sFL%03d   %-8d' % (data.id[i][:8],
                                                   int(data.alt[i] / ft / 100),
                                                   int(data.cas[i] / kts))
                confindices = data.iconf[i]
                if len(confindices) > 0:
                    color[i, :] = amber
                    for confidx in confindices:
                        cpalines[4 * confidx:4 * confidx + 4] = [
                            data.lat[i], data.lon[i], data.confcpalat[confidx],
                            data.confcpalon[confidx]
                        ]
                else:
                    color[i, :] = green

            update_buffer(self.confcpabuf, cpalines)
            update_buffer(self.accolorbuf, color)
            update_buffer(self.aclblbuf, np.array(rawlabel, dtype=np.string_))

            # If there is a visible route, update the start position
            if self.route_acid != "":
                if self.route_acid in data.id:
                    idx = data.id.index(self.route_acid)
                    update_buffer(
                        self.routebuf,
                        np.array([data.lat[idx], data.lon[idx]],
                                 dtype=np.float32))
Ejemplo n.º 18
0
    def update_bird_data(self, data):
        self.nbirds = len(data.lat)
        if self.nbirds == 0:
            self.cpalines.set_vertex_count(0)
        else:

            if self.nbirds > MAX_NBIRDS:
                print "too many birdies", self.nbirds
                data.lat = data.lat[:MAX_NBIRDS]

            # Update data in GPU buffers
            update_buffer(self.birdlatbuf, np.array(data.lat,
                                                    dtype=np.float32))
            update_buffer(self.birdlonbuf, np.array(data.lon,
                                                    dtype=np.float32))
            update_buffer(self.birdhdgbuf, np.array(data.trk,
                                                    dtype=np.float32))
            update_buffer(self.birdaltbuf, np.array(data.alt,
                                                    dtype=np.float32))
            update_buffer(self.birdtasbuf, np.array(data.tas,
                                                    dtype=np.float32))

            # Labels and colors
            # rawlabel = ''
            color = np.empty((self.nbirds, 3), dtype=np.uint8)
            for i in range(self.nbirds):

                if np.isnan(data.tas[i]):
                    print 'CAS NaN in %d: %s' % (i, data.id[i])
                    data.cas[i] = 0.0

                if np.isnan(data.alt[i]):
                    print 'ALT NaN in %d: %s' % (i, data.id[i])
                    data.alt[i] = 0.0

####################no label required for the  birdies
# Make label: 3 lines of 8 characters per aircraft
#     rawlabel += '%-8sFL%03d   %-8d' % (data.id[i][:8], int(data.alt[i] / ft / 100), int(data.cas[i] / kts))
#     confindices = data.iconf[i]
#     if len(confindices) > 0:
#        color[i, :] = amber
#       for confidx in confindices:
#          cpalines[4 * confidx : 4 * confidx + 4] = [ data.lat[i], data.lon[i],
#                                                     data.confcpalat[confidx], data.confcpalon[confidx]]
#else:
#color[i, :] = blue
#color[0:] = yellow
            color[np.array(data.alt) < 200.] = orange
            color[np.array(data.alt) >= 200.] = yellow

            update_buffer(self.birdcolorbuf, color)
Ejemplo n.º 19
0
 def actnodeChanged(self, nodeid, connidx):
     self.iactconn = connidx
     nact = self.nodedata[connidx]
     if len(nact.polydata) > 0:
         update_buffer(self.allpolysbuf, nact.polydata)
     self.allpolys.set_vertex_count(len(nact.polydata) / 2)
Ejemplo n.º 20
0
 def actnodeChanged(self, nodeid, connidx):
     self.iactconn = connidx
     nact = self.nodedata[connidx]
     if len(nact.polydata) > 0:
         update_buffer(self.allpolysbuf, nact.polydata)
     self.allpolys.set_vertex_count(len(nact.polydata) / 2)
Ejemplo n.º 21
0
    def update_aircraft_data(self, data):
        self.naircraft = len(data.lat)
        if self.naircraft == 0:
            self.cpalines.set_vertex_count(0)
        else:
            # Update data in GPU buffers
            update_buffer(self.aclatbuf, np.array(data.lat, dtype=np.float32))
            update_buffer(self.aclonbuf, np.array(data.lon, dtype=np.float32))
            update_buffer(self.achdgbuf, np.array(data.trk, dtype=np.float32))
            update_buffer(self.acaltbuf, np.array(data.alt, dtype=np.float32))
            update_buffer(self.actasbuf, np.array(data.tas, dtype=np.float32))

            # CPA lines to indicate conflicts
            ncpalines = len(data.confcpalat)

            cpalines  = np.zeros(4 * ncpalines, dtype=np.float32)
            self.cpalines.set_vertex_count(2 * ncpalines)

            # Labels and colors
            rawlabel = ''
            color    = np.empty((self.naircraft, 3), dtype=np.uint8)
            for i in range(self.naircraft):
                if np.isnan(data.tas[i]):
                    print 'CAS NaN in %d: %s' % (i, data.id[i])
                    data.cas[i] = 0.0

                if np.isnan(data.alt[i]):
                    print 'ALT NaN in %d: %s' % (i, data.id[i])
                    data.alt[i] = 0.0

                # Make label: 3 lines of 8 characters per aircraft
                rawlabel += '%-8sFL%03d   %-8d' % (data.id[i][:8], int(data.alt[i] / ft / 100), int(data.cas[i] / kts))
                confindices = data.iconf[i]
                if len(confindices) > 0:
                    color[i, :] = amber
                    for confidx in confindices:
                        cpalines[4 * confidx : 4 * confidx + 4] = [ data.lat[i], data.lon[i],
                                                                    data.confcpalat[confidx], data.confcpalon[confidx]]
                else:
                    color[i, :] = green

            update_buffer(self.confcpabuf, cpalines)
            update_buffer(self.accolorbuf, color)
            update_buffer(self.aclblbuf, np.array(rawlabel, dtype=np.string_))

            # If there is a visible route, update the start position
            if self.route_acid != "":
                if self.route_acid in data.id:
                    idx = data.id.index(self.route_acid)
                    update_buffer(self.routebuf,
                                  np.array([data.lat[idx], data.lon[idx]], dtype=np.float32))