Example #1
0
    def map_parallel(self, latitude):
        p = SphericalPoint(0, latitude)
        radius = p.distance(self.projection.parallel_circle_center)
        center = self.projection.parallel_circle_center
        c = Circle(center, radius)
        c = self.map_circle(c)

        if self.bordered:
            crossings = self.circle_intersect_borders(c)
            if crossings:
                parallels = []
                for i in range(len(crossings)):
                    a1, c1, b1 = crossings[i - 1]
                    a2, c2, b2 = crossings[i]
                    if a1 > a2:
                        a2 += 360.0
                    aavg = math.radians(0.5 * (a1 + a2))
                    pavg = c.center + Point(c.radius * math.cos(aavg),
                                            c.radius * math.sin(aavg))
                    if self.inside_maparea(pavg):
                        arc = Arc(c.center, c.radius, a1, a2)
                        p = self.gridline_factory.parallel(latitude, arc)

                        p.border1 = b1
                        p.tickangle1 = a1 + 90
                        if self.gridline_factory.rotate_parallel_labels:
                            if latitude > 0:
                                p.labelangle1 = a1 + 90
                            else:
                                p.labelangle1 = a1 - 90
                        else:
                            p.labelangle1 = 0

                        p.border2 = b2
                        p.tickangle2 = a2 + 90
                        if self.gridline_factory.rotate_parallel_labels:
                            if latitude > 0:
                                p.labelangle2 = a2 + 90
                            else:
                                p.labelangle2 = a2 - 90
                        else:
                            p.labelangle2 = 0
                        parallels.append(p)
            else:
                if self.inside_maparea(c.center):
                    p = self.gridline_factory.parallel(latitude, c)
                    parallels = [p]
                else:
                    parallels = []
        else:
            if self.projection.reference_latitude > 0:
                start_angle = self.map_meridian(
                    self.min_longitude).meridian.angle + 180
                stop_angle = self.map_meridian(
                    self.max_longitude).meridian.angle + 180
            else:
                start_angle = self.map_meridian(
                    self.max_longitude).meridian.angle
                stop_angle = self.map_meridian(
                    self.min_longitude).meridian.angle
            a = Arc(c.center, c.radius, start_angle, stop_angle)
            p = self.gridline_factory.parallel(latitude, a)

            if self.projection.reference_latitude > 0:
                p.border1 = 'right'
            else:
                p.border1 = 'left'

            p.tickangle1 = start_angle + 90

            if self.gridline_factory.rotate_parallel_labels:
                if self.projection.reference_latitude > 0:
                    p.labelangle1 = start_angle + 90
                else:
                    p.labelangle1 = start_angle - 90
            else:
                p.labelangle1 = 0

            if self.projection.reference_latitude > 0:
                p.border2 = 'left'
            else:
                p.border2 = 'right'

            p.tickangle2 = stop_angle - 90

            if self.gridline_factory.rotate_parallel_labels:
                if self.projection.reference_latitude > 0:
                    p.labelangle2 = stop_angle + 90
                else:
                    p.labelangle2 = stop_angle - 90
            else:
                p.labelangle2 = 0

            parallels = [p]

        return parallels
Example #2
0
class AzimuthalEquidistantProjection(object):
    def __init__(self,
                 north=True,
                 reference_longitude=0,
                 reference_scale=45,
                 celestial=False):
        """
        :param north: whether to plot the north pole
        :param reference_longitude: the longitude that points to the right
        :param reference_scale: degrees of latitude per unit distance
        :param celestial: longitude increases clockwise around north pole
        """

        self.origin = SphericalPoint(0, 0)
        self._north = north
        self.reference_longitude = reference_longitude
        self.reference_scale = reference_scale
        self._celestial = celestial

        if self._north:
            if self.reference_scale >= 90:
                raise ProjectionError(
                    "Invalid reference scale {} for north pole".format(
                        self.reference_scale))
            self.origin_latitude = 90
        else:
            self.reference_scale = -self.reference_scale
            if self.reference_scale <= -90:
                raise ProjectionError(
                    "Invalid reference scale {} for south pole".format(
                        self.reference_scale))
            self.origin_latitude = -90

        self.reverse_polar_direction = not xor(self._north, self._celestial)

    def __call__(self, point, inverse=False):
        if inverse:
            return self.inverse_project(point)
        return self.project(point)

    @property
    def celestial(self):
        return self._celestial

    @celestial.setter
    def celestial(self, celestial):
        self._celestial = celestial
        self.reverse_polar_direction = not xor(self._north, self._celestial)

    @property
    def north(self):
        return self._north

    @north.setter
    def north(self, north):
        self.north = north
        self.reverse_polar_direction = not xor(self._north, self._celestial)

    def project(self, spherical_point):
        rho = (self.origin_latitude - spherical_point.latitude) / float(
            self.reference_scale)
        if self.reverse_polar_direction:
            theta = -self.reduce_longitude(
                spherical_point.longitude) + 90 + self.reference_longitude
        else:
            theta = self.reduce_longitude(
                spherical_point.longitude) + 90 - self.reference_longitude
        return Point(rho * math.sin(math.radians(theta)),
                     -rho * math.cos(math.radians(theta)))

    def inverse_project(self, point):
        rho = self.origin.distance(point)
        theta = ensure_angle_range(math.degrees(math.atan2(point.y, point.x)))

        if self.reverse_polar_direction:
            longitude = ensure_angle_range(-theta + self.reference_longitude)
        else:
            longitude = ensure_angle_range(theta + self.reference_longitude)

        return SphericalPoint(
            longitude, -rho * self.reference_scale + self.origin_latitude)

    def reduce_longitude(self, longitude):
        return ensure_angle_range(longitude, self.reference_longitude)