def setup(self):
        self.application = QtWidgets.QApplication(sys.argv)

        # Create an initital flight track.
        initial_waypoints = [
            ft.Waypoint(flightlevel=0, location="EDMO",
                        comments="take off OP"),
            ft.Waypoint(48.10, 10.27, 200),
            ft.Waypoint(52.32, 09.21, 200),
            ft.Waypoint(52.55, 09.99, 200),
            ft.Waypoint(flightlevel=0,
                        location="Hamburg",
                        comments="landing HH")
        ]

        waypoints_model = ft.WaypointsTableModel("")
        waypoints_model.insertRows(0,
                                   rows=len(initial_waypoints),
                                   waypoints=initial_waypoints)

        self.window = tv.MSSTableViewWindow(model=waypoints_model)
        self.window.show()

        QtWidgets.QApplication.processEvents()
        QtTest.QTest.qWaitForWindowExposed(self.window)
        QtWidgets.QApplication.processEvents()
Beispiel #2
0
    def setup(self):
        self.application = QtWidgets.QApplication(sys.argv)
        self.port = PORTS.pop()
        self.tempdir = tempfile.mkdtemp()
        if not os.path.exists(self.tempdir):
            os.mkdir(self.tempdir)
        self.thread = multiprocessing.Process(target=application.run,
                                              args=("127.0.0.1", self.port))
        self.thread.start()

        initial_waypoints = [
            ft.Waypoint(40., 25., 0),
            ft.Waypoint(60., -10., 0),
            ft.Waypoint(40., 10, 0)
        ]
        waypoints_model = ft.WaypointsTableModel("")
        waypoints_model.insertRows(0,
                                   rows=len(initial_waypoints),
                                   waypoints=initial_waypoints)
        self.window = tv.MSSLinearViewWindow(model=waypoints_model)
        self.window.show()
        QtWidgets.QApplication.processEvents()
        QtTest.QTest.qWait(2000)
        QtTest.QTest.qWaitForWindowExposed(self.window)
        QtWidgets.QApplication.processEvents()
        self.window.cbTools.currentIndexChanged.emit(1)
        QtWidgets.QApplication.processEvents()
        self.wms_control = self.window.docks[0].widget()
        self.wms_control.multilayers.cbWMS_URL.setEditText("")
Beispiel #3
0
 def _setup(self, widget_type):
     self.port = PORTS.pop()
     self.application = QtWidgets.QApplication(sys.argv)
     if widget_type == "hsec":
         self.view = HSecViewMockup()
     else:
         self.view = VSecViewMockup()
     self.tempdir = tempfile.mkdtemp()
     if not os.path.exists(self.tempdir):
         os.mkdir(self.tempdir)
     QtTest.QTest.qWait(3000)
     self.thread = multiprocessing.Process(
         target=application.run,
         args=("127.0.0.1", self.port))
     self.thread.start()
     if widget_type == "hsec":
         self.window = wc.HSecWMSControlWidget(view=self.view, wms_cache=self.tempdir)
     else:
         initial_waypoints = [ft.Waypoint(40., 25., 0), ft.Waypoint(60., -10., 0), ft.Waypoint(40., 10, 0)]
         waypoints_model = ft.WaypointsTableModel("")
         waypoints_model.insertRows(0, rows=len(initial_waypoints), waypoints=initial_waypoints)
         self.window = wc.VSecWMSControlWidget(
             view=self.view, wms_cache=self.tempdir, waypoints_model=waypoints_model)
     self.window.show()
     QtWidgets.QApplication.processEvents()
     QtTest.QTest.qWait(2000)
     QtTest.QTest.qWaitForWindowExposed(self.window)
     QtTest.QTest.mouseClick(self.window.cbCacheEnabled, QtCore.Qt.LeftButton)
     QtWidgets.QApplication.processEvents()
Beispiel #4
0
 def setup(self):
     self.application = QtWidgets.QApplication(sys.argv)
     initial_waypoints = [ft.Waypoint(40., 25., 0), ft.Waypoint(60., -10., 0), ft.Waypoint(40., 10, 0)]
     waypoints_model = ft.WaypointsTableModel("")
     waypoints_model.insertRows(
         0, rows=len(initial_waypoints), waypoints=initial_waypoints)
     self.window = tv.MSSTopViewWindow(model=waypoints_model)
     self.window.show()
     QtWidgets.QApplication.processEvents()
     QtTest.QTest.qWaitForWindowExposed(self.window)
     QtWidgets.QApplication.processEvents()
Beispiel #5
0
    def _add_hexagon(self):
        table_view = self.view.tableWayPoints
        waypoints_model = self.view.waypoints_model
        params = self._get_parameters()

        if params["radius"] < 0.01:
            QtWidgets.QMessageBox.warning(
                self, "Add hexagon", "You cannot create a hexagon with zero radius!")
            return
        points = create_hexagon(params["center_lat"], params["center_lon"], params["radius"], params["angle"])
        index = table_view.currentIndex()
        if not index.isValid():
            row = 0
            flightlevel = config_loader(dataset="new_flighttrack_flightlevel",
                                        default=mss_default.new_flighttrack_flightlevel)
        else:
            row = index.row() + 1
            flightlevel = waypoints_model.waypoint_data(row - 1).flightlevel
        waypoints = []
        for i, point in enumerate(points):
            waypoints.append(
                ft.Waypoint(lon=float(point[1]), lat=float(point[0]),
                            flightlevel=float(flightlevel), comments="Hexagon {:d}".format(i + 1)))
        waypoints_model.insertRows(row, rows=len(waypoints), waypoints=waypoints)
        index = waypoints_model.index(row, 0)
        table_view.setCurrentIndex(index)
        table_view.resizeRowsToContents()
Beispiel #6
0
    def cloneWaypoint(self):
        """
        Handler for button <btCloneWaypoint>. Adds a new waypoint
        after the currently selected waypoint, with same data.
        """
        tableView = self.tableWayPoints
        index = tableView.currentIndex()
        lon, lat = 0, 0
        if not index.isValid():
            row = 0
            flightlevel = 0
        else:

            row = index.row() + 1
            wp = self.waypoints_model.waypoint_data(row - 1)
            lon = wp.lon
            lat = wp.lat
            flightlevel = self.waypoints_model.waypoint_data(row - 1).flightlevel

        self.waypoints_model.insertRows(
            row, waypoints=[ft.Waypoint(lat=lat, lon=lon, flightlevel=flightlevel)])

        index = self.waypoints_model.index(row, 0)
        tableView = self.tableWayPoints
        tableView.setFocus()
        tableView.setCurrentIndex(index)
        # tableView.edit(index)
        tableView.resizeRowsToContents()
Beispiel #7
0
    def addWayPoint(self):
        """
        Handler for button <btAddWayPointToFlightTrack>. Adds a new waypoint
        behind the currently selected waypoint.
        """
        tableView = self.tableWayPoints
        index = tableView.currentIndex()
        lon, lat = 0, 0
        if not index.isValid():
            row = 0
            flightlevel = 0
        else:
            row = index.row() + 1
            flightlevel = self.waypoints_model.waypoint_data(row - 1).flightlevel
            if row < len(self.waypoints_model.all_waypoint_data()):
                wp_prev = self.waypoints_model.waypoint_data(row - 1)
                wp_next = self.waypoints_model.waypoint_data(row)
                gc = pyproj.Geod(ellps="WGS84")  # a=40e6, b=40e6)
                lon, lat = gc.npts(wp_prev.lon, wp_prev.lat, wp_next.lon, wp_next.lat, 3)[1]

        self.waypoints_model.insertRows(
            row, waypoints=[ft.Waypoint(lat=lat, lon=lon, flightlevel=flightlevel)])

        index = self.waypoints_model.index(row, 0)
        tableView = self.tableWayPoints
        tableView.setFocus()
        tableView.setCurrentIndex(index)
        # tableView.edit(index)
        tableView.resizeRowsToContents()
Beispiel #8
0
    def button_release_insert_callback(self, event):
        """Called whenever a mouse button is released.

        From the click event's coordinates, best_index is calculated as
        the index of a vertex whose x coordinate > clicked x coordinate.
        This is the position where the waypoint is to be inserted.

        'lat' and 'lon' are calculated as an average of each of the first waypoint
        in left and right neighbourhood of inserted waypoint.

        The coordinates are checked against "locations" defined in mss' config.

        A new waypoint with the coordinates, and name is inserted into the waypoints_model.
        """
        if not self.showverts or event.button != 1 or event.inaxes is None:
            return
        y = event.ydata
        wpm = self.waypoints_model
        flightlevel = float(pressure2flightlevel(y))
        [lat, lon], best_index = self.get_lat_lon(event)
        loc = find_location(
            lat, lon)  # skipped tolerance which uses appropriate_epsilon_km
        if loc is not None:
            (lat, lon), location = loc
        else:
            location = ""
        new_wp = ft.Waypoint(lat, lon, flightlevel, location=location)
        wpm.insertRows(best_index, rows=1, waypoints=[new_wp])
        self.redraw_figure()

        self._ind = None
Beispiel #9
0
def load_from_csv(filename):
    waypoints = []
    _dirname, _name = os.path.split(filename)
    _fs = open_fs(_dirname)
    with _fs.open(_name, "rb") as in_file:
        lines = in_file.readlines()
    if len(lines) < 4:
        raise SyntaxError("CSV file requires at least 4 lines!")
    dialect = csv.Sniffer().sniff(lines[-1].decode("utf-8"))
    csv_reader = csv.reader(lines, encoding="utf-8", dialect=dialect)
    name = next(csv_reader)[0]
    next(csv_reader)  # header
    for row in csv_reader:
        wp = ft.Waypoint()
        wp.location = row[1]
        wp.lat = float(row[2])
        wp.lon = float(row[3])
        wp.flightlevel = float(row[4])
        wp.pressure = float(row[5]) * 100.
        wp.distance_to_prev = float(row[6])
        wp.distance_total = float(row[7])
        wp.comments = row[8]
        waypoints.append(wp)
    name = os.path.basename(filename.replace(".csv", "").strip())
    return name, waypoints
Beispiel #10
0
    def _setup(self, widget_type):
        wc.WMS_SERVICE_CACHE = {}
        self.port = PORTS.pop()
        self.application = QtWidgets.QApplication(sys.argv)
        if widget_type == "hsec":
            self.view = HSecViewMockup()
        else:
            self.view = VSecViewMockup()
        self.tempdir = tempfile.mkdtemp()
        if not os.path.exists(self.tempdir):
            os.mkdir(self.tempdir)
        QtTest.QTest.qWait(3000)
        self.thread = multiprocessing.Process(target=application.run,
                                              args=("127.0.0.1", self.port))
        self.thread.start()
        if widget_type == "hsec":
            self.window = wc.HSecWMSControlWidget(view=self.view,
                                                  wms_cache=self.tempdir)
        else:
            initial_waypoints = [
                ft.Waypoint(40., 25., 0),
                ft.Waypoint(60., -10., 0),
                ft.Waypoint(40., 10, 0)
            ]
            waypoints_model = ft.WaypointsTableModel("")
            waypoints_model.insertRows(0,
                                       rows=len(initial_waypoints),
                                       waypoints=initial_waypoints)
            self.window = wc.VSecWMSControlWidget(
                view=self.view,
                wms_cache=self.tempdir,
                waypoints_model=waypoints_model)
        self.window.show()

        # Remove all previous cached URLs
        for url in self.window.multilayers.layers.copy():
            server = self.window.multilayers.listLayers.findItems(
                url, QtCore.Qt.MatchFixedString)[0]
            self.window.multilayers.delete_server(server)

        QtWidgets.QApplication.processEvents()
        QtTest.QTest.qWait(2000)
        QtTest.QTest.qWaitForWindowExposed(self.window)
        QtTest.QTest.mouseClick(self.window.cbCacheEnabled,
                                QtCore.Qt.LeftButton)
        QtWidgets.QApplication.processEvents()
Beispiel #11
0
def load_from_txt(filename):
    name = os.path.basename(filename.replace(".txt", "").strip())
    waypoints = []
    _dirname, _name = os.path.split(filename)
    _fs = open_fs(_dirname)
    with _fs.open(_name, "r") as in_file:
        pos = []
        for line in in_file:
            if line.startswith("#"):
                continue
            if line.startswith("Index"):
                pos.append(0)  # 0
                pos.append(line.find("Location"))  # 1
                pos.append(line.find("Lat (+-90)"))  # 2
                pos.append(line.find("Lon (+-180)"))  # 3
                pos.append(line.find("Flightlevel"))  # 4
                pos.append(line.find("Pressure (hPa)"))  # 5
                pos.append(line.find("Leg dist. (km)"))  # 6
                pos.append(line.find("Cum. dist. (km)"))  # 7
                pos.append(line.find("Comments"))  # 8
                continue
            if line.startswith("Track name: "):
                continue

            if len(pos) == 0:
                raise SyntaxError(
                    "TXT Import could not parse column headings.")
            if len(line) < max(pos):
                raise SyntaxError(f"TXT Import could not parse line: '{line}'")

            wp = ft.Waypoint()
            attr_names = [
                "location", "lat", "lon", "flightlevel", "pressure",
                "distance_to_prev", "distance_total", "comments"
            ]
            setattr(wp, attr_names[0], line[pos[1]:pos[2]].strip())
            setattr(wp, attr_names[7], line[pos[8]:].strip())
            for i in range(2, len(pos) - 1):
                if pos[i] >= 0:
                    if i == 5:
                        setattr(wp, attr_names[i - 1],
                                float(line[pos[i]:pos[i + 1]].strip()) * 100.)
                    else:
                        setattr(wp, attr_names[i - 1],
                                float(line[pos[i]:pos[i + 1]].strip()))
                else:
                    if i == 5:
                        logging.debug('calculate pressure from FL ' + str(
                            thermolib.flightlevel2pressure(
                                float(wp.flightlevel) * units.hft).magnitude))
                        setattr(
                            wp, attr_names[i - 1],
                            thermolib.flightlevel2pressure(
                                float(wp.flightlevel) * units.hft).magnitude)
            waypoints.append(wp)
    return name, waypoints
Beispiel #12
0
    def make_roundtrip(self):
        """
        Copies the first waypoint and inserts it at the back of the list again
        Essentially creating a roundtrip
        """
        # This case should never be True for users, but might be for developers at some point
        if not self.is_roundtrip_possible():
            return

        first_waypoint = self.waypoints_model.waypoint_data(0)

        self.waypoints_model.insertRows(self.waypoints_model.rowCount(), rows=1, waypoints=[
            ft.Waypoint(lat=first_waypoint.lat, lon=first_waypoint.lon, flightlevel=first_waypoint.flightlevel,
                        location=first_waypoint.location)])
Beispiel #13
0
    def button_release_insert_callback(self, event):
        """Called whenever a mouse button is released.

        From the click event's coordinates, best_index is calculated if it can be optimally fit
        as a prior waypoint in the path.

        A vertex with same coordinates is inserted into the path in canvas.

        The coordinates are checked against "locations" defined in mss' config.

        A new waypoint with the coordinates, and name is inserted into the waypoints_model.
        """
        if not self.showverts or event.button != 1 or event.inaxes is None:
            return

        # Get position for new vertex.
        x, y = event.xdata, event.ydata
        best_index = self.pathpatch.get_path().index_of_closest_segment(
            x, y, eps=self.appropriate_epsilon())
        logging.debug(
            "TopView insert point: clicked at (%f, %f), "
            "best index: %d", x, y, best_index)
        self.pathpatch.get_path().insert_vertex(best_index, [x, y],
                                                WaypointsPath.LINETO)

        lon, lat = self.map(x, y, inverse=True)
        loc = find_location(lat,
                            lon,
                            tolerance=self.appropriate_epsilon_km(px=15))
        if loc is not None:
            (lat, lon), location = loc
        else:
            location = ""
        wpm = self.waypoints_model
        if len(wpm.all_waypoint_data()) > 0 and 0 < best_index <= len(
                wpm.all_waypoint_data()):
            flightlevel = wpm.waypoint_data(best_index - 1).flightlevel
        elif len(wpm.all_waypoint_data()) > 0 and best_index == 0:
            flightlevel = wpm.waypoint_data(0).flightlevel
        else:
            logging.error("Cannot copy flightlevel. best_index: %s, len: %s",
                          best_index, len(wpm.all_waypoint_data()))
            flightlevel = 0
        new_wp = ft.Waypoint(lat, lon, flightlevel, location=location)
        wpm.insertRows(best_index, rows=1, waypoints=[new_wp])
        self.redraw_path()

        self._ind = None
Beispiel #14
0
    def create_new_flight_track(self, template=None, filename=None):
        """Creates a new flight track model from a template. Adds a new entry to
           the list of flight tracks. Called when the user selects the 'new/open
           flight track' menu entries.

        Arguments:
        template -- copy the specified template to the new flight track (so that
                    it is not empty).
        filename -- if not None, load the flight track in the specified file.
        """
        if template is None:
            template = []
            waypoints = config_loader(dataset="new_flighttrack_template")
            default_flightlevel = config_loader(
                dataset="new_flighttrack_flightlevel")
            for wp in waypoints:
                template.append(
                    ft.Waypoint(flightlevel=default_flightlevel, location=wp))
            if len(template) < 2:
                QtWidgets.QMessageBox.critical(
                    self, self.tr("flighttrack template"),
                    self.
                    tr("ERROR:Flighttrack template in configuration is too short. "
                       "Please add at least two valid locations."))

        if filename is not None:
            waypoints_model = ft.WaypointsTableModel(filename=filename)
        else:
            # Create a new flight track from the waypoints template.
            self.new_flight_track_counter += 1
            waypoints_model = ft.WaypointsTableModel(
                name=f"new flight track ({self.new_flight_track_counter:d})")
            # Make a copy of the template. Otherwise all new flight tracks would
            # use the same data structure in memory.
            template_copy = copy.deepcopy(template)
            waypoints_model.insertRows(0,
                                       rows=len(template_copy),
                                       waypoints=template_copy)
        # Create a new list entry for the flight track. Make the item name
        # editable.
        listitem = QFlightTrackListWidgetItem(waypoints_model,
                                              self.listFlightTracks)
        listitem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)

        self.activate_flight_track(listitem)
Beispiel #15
0
def load_from_flitestar(filename):
    waypoints = []
    _dirname, _name = os.path.split(filename)
    _fs = open_fs(_dirname)
    with _fs.open(_name, 'r') as f:
        firstline = f.readline()
        if not firstline.startswith(
                "# FliteStar/FliteMap generated flight plan."):
            raise SyntaxError("The file does not seem to be a FliteStar file!")
        for line in f:

            if line.startswith('FWP'):
                line = line.split()
                if len(line) < 10:
                    raise SyntaxError(f"Line {line} has less than 9 fields.")
                alt = round(float(line[-1]) / 100., 2)
                if line[4] == 'N':
                    NS = 1.
                elif line[4] == 'S':
                    NS = -1.
                else:
                    NS = np.nan
                lat = round((float(line[5]) + (float(line[6]) / 60.)) * NS, 3)
                if line[7] == 'E':
                    EW = 1.
                elif line[7] == 'W':
                    EW = -1.
                else:
                    EW = np.nan
                lon = round((float(line[8]) + (float(line[9]) / 60.)) * EW, 3)

                wp = ft.Waypoint()
                wp.location = line[3]
                wp.lat = float(lat)
                wp.lon = float(lon)
                wp.flightlevel = float(alt)
                wp.pressure = thermolib.flightlevel2pressure(
                    float(wp.flightlevel))
                waypoints.append(wp)

    name = os.path.basename(filename).strip('.txt')
    return name, waypoints