Example #1
0
 def test_get_distance(self):
     coordinates_distance = [
         ((50.355136, 7.566077), (50.353968, 4.577915), 212),
         ((-5.135943, -42.792442), (4.606085, 120.028077), 18130)
     ]
     for coord1, coord2, distance in coordinates_distance:
         assert int(utils.get_distance(coord1, coord2)) == distance
Example #2
0
    def appropriate_epsilon_km(self, px=5):
        """Determine an epsilon value appropriate for the current projection and
           figure size.

        The epsilon value gives the distance required in map projection
        coordinates that corresponds to approximately px Pixels in screen
        coordinates. The value can be used to find the line/point that is
        closest to a click while discarding clicks that are too far away
        from any geometry feature.
        """
        # (bounds = left, bottom, width, height)
        ax_bounds = self.ax.bbox.bounds
        diagonal = math.hypot(round(ax_bounds[2]), round(ax_bounds[3]))
        if self.map.projection in ['stere', 'lcc']:
            map_delta = np.hypot(self.map.llcrnry - self.map.urcrnry, self.map.llcrnrx - self.map.urcrnrx) / 1000.
        else:
            map_delta = get_distance((self.map.llcrnry, self.map.llcrnrx), (self.map.urcrnry, self.map.urcrnrx))
        km_per_px = map_delta / diagonal
        return km_per_px * px
Example #3
0
    def compute_solar_lines(self, bmap, wp_vertices, wp_heights, wp_times,
                            solartype):
        """
        Computes coloured overlay over the flight path that indicates
        the danger of looking into the sun with a limb sounder aboard
        the aircraft.

        Args:
            bmap: Projection of TopView
            wp_vertices: waypoints of the flight path
            wp_heights: altitude of the waypoints of flight path

        Returns: LineCollection of coloured lines according to the
                 angular distance between viewing direction and solar
                 angle
        """
        # calculate distances and times
        body, difftype = solartype

        times = [datetime_to_jsec(_wp_time) for _wp_time in wp_times]
        x, y = list(zip(*wp_vertices))
        wp_lons, wp_lats = bmap(x, y, inverse=True)

        fine_lines = [
            bmap.gcpoints2(wp_lons[i],
                           wp_lats[i],
                           wp_lons[i + 1],
                           wp_lats[i + 1],
                           map_coords=False) for i in range(len(wp_lons) - 1)
        ]
        line_heights = [
            np.linspace(wp_heights[i],
                        wp_heights[i + 1],
                        num=len(fine_lines[i][0]))
            for i in range(len(fine_lines))
        ]
        line_times = [
            np.linspace(times[i], times[i + 1], num=len(fine_lines[i][0]))
            for i in range(len(fine_lines))
        ]
        # fine_lines = list of tuples with x-list and y-list for each segment
        # lines = list of tuples with lon-list and lat-list for each segment
        heights = []
        times = []
        for i in range(len(fine_lines) - 1):
            heights.extend(line_heights[i][:-1])
            times.extend(line_times[i][:-1])
        heights.extend(line_heights[-1])
        times.extend(line_times[-1])
        solar_x = []
        solar_y = []
        for i in range(len(fine_lines) - 1):
            solar_x.extend(fine_lines[i][0][:-1])
            solar_y.extend(fine_lines[i][1][:-1])
        solar_x.extend(fine_lines[-1][0])
        solar_y.extend(fine_lines[-1][1])
        points = []
        old_wp = None
        total_distance = 0
        for i, (lon, lat) in enumerate(zip(solar_x, solar_y)):
            points.append([[lon, lat]
                           ])  # append double-list for later concatenation
            if old_wp is not None:
                wp_dist = get_distance((old_wp[0], old_wp[1]),
                                       (lat, lon)) * 1000.
                total_distance += wp_dist
            old_wp = (lat, lon)
        vals = []
        for i in range(len(points) - 1):
            p0, p1 = points[i][0], points[i + 1][0]

            sol_azi, sol_ele = self.compute_body_angle(body, times[i], p0[0],
                                                       p0[1])
            obs_azi, obs_ele = self.compute_view_angles(
                p0[0], p0[1], heights[i], p1[0], p1[1], heights[i + 1],
                self.dsbObsAngleAzimuth.value(),
                self.dsbObsAngleElevation.value())
            if sol_azi < 0:
                sol_azi += 360
            if obs_azi < 0:
                obs_azi += 360
            rating = self.calc_view_rating(obs_azi, obs_ele, sol_azi, sol_ele,
                                           heights[i], difftype)
            vals.append(rating)

        # convert lon, lat to map points
        for i in range(len(points)):
            points[i][0][0], points[i][0][1] = bmap(points[i][0][0],
                                                    points[i][0][1])
        points = np.concatenate([points[:-1], points[1:]], axis=1)
        # plot
        solar_lines = LineCollection(points,
                                     cmap=self.solar_cmap,
                                     norm=self.solar_norm,
                                     zorder=2,
                                     linewidths=3,
                                     animated=True)
        solar_lines.set_array(np.array(vals))
        return solar_lines
Example #4
0
    def update_distances(self, position, rows=1):
        """Update all distances in a flight track that are affected by a
           waypoint change involving <rows> waypoints starting at index
           <position>.

        Distances are computed along great circles.

        If rows=1, the distance to the previous waypoint is updated for
        waypoints <position> and <position+1>. The total flight track distance
        is updated for all waypoint following <position>.

        If rows>1, the distances to the previous waypoints are updated
        according to the number of modified waypoints.
        """
        waypoints = self.waypoints
        aircraft = self.performance_settings["aircraft"]

        def get_duration_fuel(flightlevel0, flightlevel1, distance, weight,
                              lastleg):
            if flightlevel0 == flightlevel1:
                tas, fuelflow = aircraft.get_cruise_performance(
                    flightlevel0 * 100, weight)
                duration = 3600. * distance / (
                    1.852 * tas)  # convert to s (tas is in nm/h)
                leg_fuel = duration * fuelflow / 3600.
                return duration, leg_fuel
            else:
                if flightlevel0 < flightlevel1:
                    duration0, dist0, fuel0 = aircraft.get_climb_performance(
                        flightlevel0 * 100, weight)
                    duration1, dist1, fuel1 = aircraft.get_climb_performance(
                        flightlevel1 * 100, weight)
                else:
                    duration0, dist0, fuel0 = aircraft.get_descent_performance(
                        flightlevel0 * 100, weight)
                    duration1, dist1, fuel1 = aircraft.get_descent_performance(
                        flightlevel1 * 100, weight)
                duration = (duration1 -
                            duration0) * 60  # convert from min to s
                dist = (dist1 - dist0) * 1.852  # convert from nm to km
                fuel = fuel1 - fuel0
                if lastleg:
                    duration_p, fuel_p = get_duration_fuel(
                        flightlevel0, flightlevel0, distance - dist, weight,
                        False)
                else:
                    duration_p, fuel_p = get_duration_fuel(
                        flightlevel1, flightlevel1, distance - dist, weight,
                        False)
                return duration + duration_p, fuel + fuel_p

        pos = position
        for offset in range(rows):
            pos = position + offset
            wp1 = waypoints[pos]
            # The distance to the first waypoint is zero.
            if pos == 0:
                wp1.distance_to_prev = 0.
                wp1.distance_total = 0.

                wp1.leg_time = 0  # time from previous waypoint
                wp1.cum_time = 0  # total time of flight
                wp1.utc_time = self.performance_settings[
                    "takeoff_time"].toPyDateTime()
                wp1.weight = self.performance_settings["takeoff_weight"]
                wp1.leg_fuel = 0
                wp1.rem_fuel = self.performance_settings["fuel"]
                wp1.ascent_rate = 0
            else:
                wp0 = waypoints[pos - 1]
                wp1.distance_to_prev = utils.get_distance((wp0.lat, wp0.lon),
                                                          (wp1.lat, wp1.lon))

                last = (pos - 1 == rows)
                time, fuel = get_duration_fuel(wp0.flightlevel,
                                               wp1.flightlevel,
                                               wp1.distance_to_prev,
                                               wp0.weight,
                                               lastleg=last)
                wp1.leg_time = time
                wp1.cum_time = wp0.cum_time + wp1.leg_time
                wp1.utc_time = wp0.utc_time + datetime.timedelta(
                    seconds=wp1.leg_time)
                wp1.leg_fuel = fuel
                wp1.rem_fuel = wp0.rem_fuel - wp1.leg_fuel
                wp1.weight = wp0.weight - wp1.leg_fuel
                if wp1.leg_time != 0:
                    wp1.ascent_rate = int((wp1.flightlevel - wp0.flightlevel) *
                                          100 / (wp1.leg_time / 60))
                else:
                    wp1.ascent_rate = 0
            wp1.ceiling_alt = aircraft.get_ceiling_altitude(wp1.weight)

        # Update the distance of the following waypoint as well.
        if pos < len(waypoints) - 1:
            wp2 = waypoints[pos + 1]
            wp2.distance_to_prev = utils.get_distance((wp1.lat, wp1.lon),
                                                      (wp2.lat, wp2.lon))
            if wp2.leg_time != 0:
                wp2.ascent_rate = int((wp2.flightlevel - wp1.flightlevel) *
                                      100 / (wp2.leg_time / 60))
            else:
                wp2.ascent_rate = 0

        # Update total distances of waypoint at index position and all
        # following waypoints.
        for i in range(max(min(position, 1), 1), len(waypoints)):
            wp0 = waypoints[i - 1]
            wp1 = waypoints[i]
            wp1.distance_total = wp0.distance_total + wp1.distance_to_prev
            wp1.weight = wp0.weight - wp0.leg_fuel
            last = (i + 1 == len(waypoints))
            time, fuel = get_duration_fuel(wp0.flightlevel,
                                           wp1.flightlevel,
                                           wp1.distance_to_prev,
                                           wp0.weight,
                                           lastleg=last)

            wp1.leg_time = time
            wp1.cum_time = wp0.cum_time + wp1.leg_time
            wp1.utc_time = wp0.utc_time + datetime.timedelta(
                seconds=wp1.leg_time)
            wp1.leg_fuel = fuel
            wp1.rem_fuel = wp0.rem_fuel - wp1.leg_fuel
            wp1.weight = wp0.weight - wp1.leg_fuel
            wp1.ceiling_alt = aircraft.get_ceiling_altitude(wp1.weight)

        index1 = self.createIndex(0, TIME_UTC)
        self.dataChanged.emit(index1, index1)