Beispiel #1
0
def rightlegend(figure, chart_number, min_longitude, max_longitude,
                min_latitude, max_latitude):
    # Lower legend box
    p1 = figure.llcorner
    p2 = figure.llcorner + Point(LEGEND_WIDTH, LEGEND_HEIGHT)
    l = DrawingArea(p1, p2, p1, box=False)
    figure.add(l)
    l.draw_bounding_box(0.4)

    # Long/lat ranges
    l.draw_line(Line(Point(138, 1.5), Point(138, LEGEND_HEIGHT - 1.5)))

    minha = HourAngle()
    minha.from_degrees(min_longitude)
    maxha = HourAngle()
    maxha.from_degrees(max_longitude)
    longlabel = "\\condensed\\textbf{{{:02}\\raisebox{{0.35em}}{{\\footnotesize h}}{:02}\\raisebox{{0.35em}}{{\\footnotesize m}} to {:02}\\raisebox{{0.35em}}{{\\small h}}{:02}\\raisebox{{0.35em}}{{\\small m}}}}".format(
        minha.hours, minha.minutes, maxha.hours, maxha.minutes)
    l.draw_label(Label(Point(158, 6.75), longlabel, 90, "LARGE"))

    latlabel = "\\condensed\\textbf{{"
    if min_latitude >= 0:
        latlabel += "+{:02}".format(min_latitude)
    else:
        latlabel += "--{:02}".format(abs(min_latitude))
    latlabel += "\\textdegree{{}} to "
    if max_latitude >= 0:
        latlabel += "+{:02}".format(max_latitude)
    else:
        latlabel += "--{:02}".format(abs(max_latitude))
    latlabel += "\\textdegree}}"
    l.draw_label(Label(Point(158, 1), latlabel, 90, "LARGE"))

    # Constellations
    l.draw_line(Line(Point(178, 1.5), Point(178, LEGEND_HEIGHT - 1.5)))

    constellations = constellations_in_area(min_longitude,
                                            max_longitude,
                                            min_latitude,
                                            max_latitude,
                                            nsamples=10000)
    l.draw_label(
        Label(Point(187.5, 5.0),
              "\\condensed\\textbf{{{}}}".format(constellations[0].upper()),
              90, "LARGE"))
    if len(constellations) > 1:
        l.draw_label(
            Label(
                Point(187.5, 1.5), "\\condensed\\textbf{{{}}}".format(
                    ", ".join(constellations[1:4]).upper()), 90, "small"))

    # Chart number
    p1 = figure.urcorner + Point(-EDGE_MARGIN, TOP_MARGIN - 17)
    p2 = p1 + Point(2 * EDGE_MARGIN, 17)
    l = DrawingArea(p1, p2, box=False)
    figure.add(l)
    l.draw_label(
        Label(Point(EDGE_MARGIN, -1.5), "\\textbf{{{}}}".format(chart_number),
              90, "huge"))
Beispiel #2
0
def legend(figure, chart_number):
    l = DrawingArea(f.llcorner + Point(264, 0), f.urcorner,
                    f.llcorner + Point(264, 0))
    figure.add(l)
    l.draw_label(Label(Point(8, 189), "Epoch", 90, "tiny"))
    l.draw_label(Label(Point(8, 185), "\\textbf{2000.0}", 90, "normalsize"))
    l.draw_line(Line(Point(2, 183.5), Point(14, 183.5)))
    l.draw_line(Line(Point(2, 15), Point(14, 15)))
    l.draw_label(Label(Point(8, 11), "Chart number", 90, "tiny"))
    l.draw_label(
        Label(Point(8, 2), "\\textbf{{{}}}".format(chart_number), 90, "Huge"))
Beispiel #3
0
    def __init__(self,
                 tikz,
                 p1,
                 p2,
                 origin=None,
                 boxed=True,
                 box_linewidth=0.5):
        # Make sure the p1 is lower left and p2 is upper right
        self.p1 = Point(min(p1.x, p2.x), min(p1.y, p2.y))
        self.p2 = Point(max(p1.x, p2.x), max(p1.y, p2.y))

        if origin is None:
            self.set_origin(0.5 * (p1 + p2))
        else:
            self.set_origin(origin)

        # Calculate the picture coordinates of the corners
        self.llcorner = Point(self.minx, self.miny)
        self.lrcorner = Point(self.maxx, self.miny)
        self.urcorner = Point(self.maxx, self.maxy)
        self.ulcorner = Point(self.minx, self.maxy)

        # Construct the borders of the picture
        self.bottom_border = Line(self.llcorner, self.lrcorner)
        self.right_border = Line(self.lrcorner, self.urcorner)
        self.top_border = Line(self.urcorner, self.ulcorner)
        self.left_border = Line(self.ulcorner, self.llcorner)
        self.borderdict = {
            "left": self.left_border,
            "top": self.top_border,
            "right": self.right_border,
            "bottom": self.bottom_border,
        }

        self.clipper = Clipper(self.borderdict)

        self.boxed = boxed
        self.box_linewidth = box_linewidth

        self.width = p2.x - p1.x
        self.height = p2.y - p1.y

        self.texstring = ""
        self.pen_style = None
        # self._dotted = False
        # self._dashed = False
        self.linewidth = 0.5
        self.color = "black"
        self.opened = False
        self.closed = False

        tikz.add(self)
Beispiel #4
0
    def equatorial_meridian(self, tick_interval, frame):
        if tick_interval is not None:
            for i in range(int(360 / int(tick_interval))):
                l = i * tick_interval
                sp = SkyCoordDeg(l, 0, frame=frame).icrs
                if self.clip_at_border:
                    p = self.projection.project(sp)
                    if not self.clipper.point_inside(p):
                        continue
                else:
                    if not self.inside_coordinate_range(sp):
                        continue
                    p = self.projection.project(sp)

                v = self.projection.project(
                    SkyCoordDeg(l + 1, 0, frame=frame).icrs) - p
                v = v.rotate(90) / v.norm
                tp1 = p + 0.5 * v
                tp2 = p - 0.5 * v
                lp = p + 0.4 * v
                tick = Line(tp1, tp2)
                label = Label(
                    lp,
                    text=f"\\textit{{{l}\\textdegree}}",
                    fontsize="miniscule",
                    angle=tick.angle - 90,
                    position="below",
                    fill="white",
                )
                yield EquatorialMeridian(l, tick, label)
Beispiel #5
0
 def draw(self):
     center = 0.5 * LEGEND_WIDTH
     self.draw_label(
         Label(Point(center, 189), text="Epoch", fontsize="tiny"))
     self.draw_label(
         Label(Point(center, 185),
               text="2000.0",
               fontsize="normalsize",
               bold=True))
     self.draw_line(Line(Point(2, 183.5), Point(LEGEND_WIDTH - 2, 183.5)))
     self.draw_line(Line(Point(2, 15), Point(LEGEND_WIDTH - 2, 15)))
     self.draw_label(
         Label(Point(center, 11), text="Chart number", fontsize="tiny"))
     self.draw_label(
         Label(Point(center, 2),
               f"{self.chart_number}",
               bold=True,
               fontsize="Huge"))
Beispiel #6
0
    def __init__(
        self,
        coordinate_grid_config,
        projection,
        borderdict,
        clip_at_border,
        clipper,
        longitude_range,
        latitude_range,
        latitude_range_func=None,
    ):
        self.config = coordinate_grid_config
        self.projection = projection
        self.borderdict = borderdict
        self.clip_at_border = clip_at_border
        self.clipper = clipper

        self.min_longitude, self.max_longitude = longitude_range
        self.min_latitude, self.max_latitude = latitude_range
        self.latitude_range_func = latitude_range_func

        longlatborders = {
            "left":
            Line(
                Point(self.min_longitude, self.min_latitude),
                Point(self.min_longitude, self.max_latitude),
            ),
            "right":
            Line(
                Point(self.max_longitude, self.min_latitude),
                Point(self.max_longitude, self.max_latitude),
            ),
            "bottom":
            Line(
                Point(self.min_longitude, self.min_latitude),
                Point(self.max_longitude, self.min_latitude),
            ),
            "top":
            Line(
                Point(self.min_longitude, self.max_latitude),
                Point(self.max_longitude, self.max_latitude),
            ),
        }
        self.longlat_clipper = Clipper(longlatborders)
Beispiel #7
0
    def pole_markers(self, frame):
        for latitude in [-90, 90]:
            sp = SkyCoordDeg(0, latitude, frame=frame).icrs
            p = self.projection.project(sp)
            if self.config.rotate_poles:
                delta1 = (self.projection.project(
                    SkyCoordDeg(sp.ra.degree + 1, sp.dec.degree)) - p)
                delta2 = (self.projection.project(
                    SkyCoordDeg(sp.ra.degree, sp.dec.degree + 1)) - p)
            else:
                delta1 = Point(1, 0)
                delta2 = Point(0, 1)

            delta1 *= self.config.pole_marker_size / delta1.norm
            delta2 *= self.config.pole_marker_size / delta2.norm

            if self.clipper.point_inside(p):
                yield Line(p + delta1, p - delta1)
                yield Line(p + delta2, p - delta2)
Beispiel #8
0
    def map_meridian(self, longitude):
        p1 = SphericalPoint(longitude, self.min_latitude)
        p2 = SphericalPoint(longitude, self.max_latitude)
        l = self.map_line(Line(p1, p2))

        m = self.gridline_factory.meridian(longitude, l)
        m.border1 = "bottom"
        m.border2 = "top"
        m.tickangle1 = 270
        m.tickangle2 = 90
        return m
Beispiel #9
0
    def polar_tick(self):
        if not self.config.polar_tick:
            return None
        latitude = 90
        delta = Point(0, 1)
        if self.config.center_latitude < 0:
            delta = Point(0, -1)
            latitude *= -1

        p1 = self.projection.project(SkyCoordDeg(0, latitude))
        p2 = p1 + self.config.marked_ticksize * delta
        return Line(p1, p2)
Beispiel #10
0
    def map_parallel(self, latitude):
        p1 = SphericalPoint(self.min_longitude, latitude)
        p2 = SphericalPoint(self.max_longitude, latitude)
        l = self.map_line(Line(p1, p2))
        if l.p1.x > l.p2.x:
            l.p1, l.p2 = l.p2, l.p1

        p = self.gridline_factory.parallel(latitude, l)
        p.border1 = "left"
        p.border2 = "right"
        p.tickangle1 = 180
        p.tickangle2 = 0
        return p
Beispiel #11
0
    def map_meridian(self, longitude, longitude_offsets={}):
        offset = 0
        for l in sorted(longitude_offsets.keys(), reverse=True):
            if longitude % l == 0:
                offset = longitude_offsets[l]
                break

        if self.projection.reference_latitude > 0:
            p1 = SphericalPoint(longitude, self.min_latitude)
            p2 = SphericalPoint(longitude, self.max_latitude - offset)
        else:
            p1 = SphericalPoint(longitude, self.min_latitude + offset)
            p2 = SphericalPoint(longitude, self.max_latitude)

        l = self.map_line(Line(p1, p2))
        if self.bordered:
            intersections = self.line_intersect_borders(l)
            if not intersections:
                return None
            if len(intersections) == 1:
                if self.inside_maparea(l.p1):
                    p2, border2 = intersections[0]
                    p1, border1 = l.p1, None
                else:
                    p1, border1 = intersections[0]
                    p2, border2 = l.p2, None
            else:
                p1, border1 = intersections[0]
                p2, border2 = intersections[1]

            if p1.y < p2.y:
                p1, p2 = p2, p1
                border1, border2 = border2, border1

            l.p1 = p1
            l.p2 = p2
        else:
            border1 = "bottom"
            border2 = "top"

        m = self.gridline_factory.meridian(longitude, l)
        m.border1 = border1
        m.border2 = border2
        m.tickangle1 = l.angle + 180
        m.tickangle2 = l.angle
        if self.gridline_factory.rotate_meridian_labels:
            m.labelangle1 = l.angle - 90
            m.labelangle2 = l.angle - 90
        return m
Beispiel #12
0
    def tick(self, point, angle, border):
        if self.coordinate % self.config.marked_tick_interval == 0:
            ticklength = self.config.marked_ticksize
        elif self.coordinate % self.config.tick_interval == 0:
            ticklength = self.config.unmarked_ticksize
        else:
            return None

        if ticklength == 0:
            return None

        delta = self.tickdelta(angle, border)
        if delta.norm > 4:
            return None
        p1 = point
        p2 = point + ticklength * delta

        return Line(p1, p2)
Beispiel #13
0
    def draw_internal_parallel_ticks(self,
                                     longitude,
                                     angle=90,
                                     labels=False,
                                     label_angle=None):
        reference_meridian = self.map_meridian(longitude)
        tickangle = reference_meridian.meridian.angle + angle
        start_latitude = self.gridline_factory.parallel_tick_interval * math.ceil(
            self.min_latitude / self.gridline_factory.parallel_tick_interval)
        for latitude in numpy.arange(
                start_latitude, self.max_latitude,
                self.gridline_factory.parallel_tick_interval):
            if latitude in [-90, 90]:
                continue
            p1 = self.projection(SphericalPoint(longitude, latitude))
            if not self.inside_maparea(p1):
                continue
            delta = Point(1, 0).rotate(tickangle)

            if latitude % self.gridline_factory.parallel_line_interval == 0:
                ticksize = 0
            elif latitude % self.gridline_factory.parallel_marked_tick_interval == 0:
                ticksize = self.gridline_factory.marked_ticksize
            else:
                ticksize = self.gridline_factory.unmarked_ticksize

            if ticksize > 0:
                p2 = p1 + ticksize * delta
                self.draw_line(
                    Line(p1, p2),
                    linewidth=self.gridline_factory.gridline_thickness)

            if labels and latitude % self.gridline_factory.parallel_line_interval == 0:
                p3 = p1 + 0.75 * delta
                text = "{}\\textdegree".format(int(abs(latitude)))
                if abs < 0:
                    text = "--" + text
                else:
                    text = "+" + text
                if label_angle is None:
                    label_angle = tickangle
                l = Label(p3, text, label_angle, "tiny", angle=0, fill="white")
                self.draw_label(l)
Beispiel #14
0
    def map_meridian(self, longitude, longitude_offsets={}):
        """Returns the exact line to draw for a meridian"""
        offset = 0
        for l in sorted(longitude_offsets.keys(), reverse=True):
            if longitude % l == 0:
                offset = longitude_offsets[l]
                break

        if self.projection.north:
            p1 = SphericalPoint(longitude,
                                self.projection.origin_latitude - offset)
        else:
            p1 = SphericalPoint(longitude,
                                self.projection.origin_latitude + offset)

        if self.projection.north:
            p2 = SphericalPoint(longitude, self.min_latitude)
        else:
            p2 = SphericalPoint(longitude, self.max_latitude)

        l = self.map_line(Line(p1, p2))
        if self.bordered:
            p2, border2 = self.line_intersect_borders(l)[0]
            l.p2 = p2
        else:
            border2 = "bottom"

        m = self.gridline_factory.meridian(longitude, l)
        m.border2 = border2

        if xor(self.projection.north, not self.projection.celestial):
            m.tickangle2 = -longitude + self.projection.reference_longitude
        else:
            m.tickangle2 = longitude - self.projection.reference_longitude

        if self.gridline_factory.rotate_meridian_labels:
            m.labelpos2 = 270
            m.labelangle2 = l.angle + 90
        else:
            pass

        return m
Beispiel #15
0
    def draw_coordinate_system(self,
                               transformation,
                               linewidth=0.3,
                               dashed='dashed',
                               tickinterval=None,
                               poles=False):
        points = []
        for longitude in numpy.arange(0, 360.1, 0.251):
            p = transformation(SphericalPoint(longitude, 0))
            points.append(
                SphericalPoint(self.projection.reduce_longitude(p.longitude),
                               p.latitude))

        points_to_draw = []
        for i in range(len(points)):
            prev_p = points[i - 1]
            p = points[i]
            if i + 1 == len(points):
                next_p = points[0]
            else:
                next_p = points[i + 1]

            if self.bordered:
                prev_p = self.map_point(prev_p)
                p = self.map_point(p)
                next_p = self.map_point(next_p)

                if self.inside_maparea(prev_p) or self.inside_maparea(
                        p) or self.inside_maparea(next_p):
                    points_to_draw.append(p)
            else:
                prevpinside = self.inside_coordinate_range(prev_p)
                pinside = self.inside_coordinate_range(p)
                nextpinside = self.inside_coordinate_range(next_p)
                if prevpinside or pinside or nextpinside:
                    points_to_draw.append(self.map_point(p))

        points_to_draw = sorted(points_to_draw, key=attrgetter('x'))
        if points_to_draw:
            self.draw_polygon(points_to_draw,
                              linewidth=linewidth,
                              dashed=dashed)

        # Ticks
        if tickinterval is not None:
            for i in range(360 / int(tickinterval)):
                l = i * tickinterval
                p = transformation(SphericalPoint(l, 0))
                p.longitude = self.projection.reduce_longitude(p.longitude)
                if self.bordered:
                    p = self.map_point(p)
                    if not self.inside_maparea(p):
                        continue
                else:
                    if not self.inside_coordinate_range(p):
                        continue
                    p = self.map_point(p)

                v = self.map_point(transformation(SphericalPoint(l + 1,
                                                                 0))) - p
                v = v.rotate(90) / v.norm
                tp1 = p + 0.5 * v
                tp2 = p - 0.5 * v
                lp = p + 0.8 * v
                tick = Line(tp1, tp2)
                self.draw_line(tick, linewidth=linewidth)
                self.draw_label(
                    Label(lp,
                          "\\textit{{{}\\textdegree}}".format(l),
                          270,
                          "miniscule",
                          angle=tick.angle - 90,
                          fill="white"))

        # Poles
        if poles:
            p = transformation(SphericalPoint(0, 90))
            np = self.map_point(p)
            if self.gridline_factory.rotate_poles:
                delta1 = self.map_point(p + SphericalPoint(1, 0)) - np
                delta2 = self.map_point(p + SphericalPoint(0, 1)) - np
            else:
                delta1 = Point(1, 0)
                delta2 = Point(0, 1)

            delta1 *= self.gridline_factory.pole_marker_size / delta1.norm
            delta2 *= self.gridline_factory.pole_marker_size / delta2.norm

            if self.inside_maparea(np):
                bl1 = Line(np + 1.25 * delta1, np - 1.25 * delta1)
                l1 = Line(np + delta1, np - delta1)
                bl2 = Line(np + 1.25 * delta2, np - 1.25 * delta2)
                l2 = Line(np + delta2, np - delta2)
                self.draw_line(bl1, linewidth=3 * linewidth, color="white")
                self.draw_line(bl2, linewidth=3 * linewidth, color="white")
                self.draw_line(
                    l1, linewidth=self.gridline_factory.gridline_thickness)
                self.draw_line(
                    l2, linewidth=self.gridline_factory.gridline_thickness)

            p = transformation(SphericalPoint(0, -90))
            sp = self.map_point(p)
            if self.gridline_factory.rotate_poles:
                delta1 = self.map_point(p + SphericalPoint(1, 0)) - sp
                delta2 = self.map_point(p + SphericalPoint(0, 1)) - sp
            else:
                delta1 = Point(1, 0)
                delta2 = Point(0, 1)

            delta1 *= self.gridline_factory.pole_marker_size / delta1.norm
            delta2 *= self.gridline_factory.pole_marker_size / delta2.norm

            if self.inside_maparea(sp):
                bl1 = Line(sp + 1.25 * delta1, sp - 1.25 * delta1)
                l1 = Line(sp + delta1, sp - delta1)
                bl2 = Line(sp + 1.25 * delta2, sp - 1.25 * delta2)
                l2 = Line(sp + delta2, sp - delta2)
                self.draw_line(bl1, linewidth=3 * linewidth, color="white")
                self.draw_line(bl2, linewidth=3 * linewidth, color="white")
                self.draw_line(
                    l1, linewidth=self.gridline_factory.gridline_thickness)
                self.draw_line(
                    l2, linewidth=self.gridline_factory.gridline_thickness)
Beispiel #16
0
        m.parallel_ticks['left'] = False
        m.parallel_ticks['right'] = False
        m.parallel_ticks['bottom'] = False
        m.parallel_ticks['top'] = True
        m.rotate_parallel_labels = False

        # Draw the grid
        m.draw_meridians(origin_offsets=CONIC_MERIDIAN_OFFSETS)
        m.draw_parallels()

        # Draw the +90 degrees parallel tick
        p1 = Point(0,
                   0.5 * (MAP_URCORNER.y - MAP_LLCORNER.y - 2 * MAP_VMARGIN))
        p2 = p1 + Point(0, m.gridline_factory.marked_ticksize)
        p3 = p1 + Point(0, m.gridline_factory.label_distance)
        m.draw_line(Line(p1, p2),
                    linewidth=m.gridline_factory.gridline_thickness)
        m.draw_label(Label(p3, "+90\\textdegree", 90, "tiny"))

        with m.clip(m.clipping_path):
            m.draw_constellations(dashed=CONSTELLATION_DASH_PATTERN)
        m.draw_ecliptic(tickinterval=5, dashed=ECLIPTIC_DASH_PATTERN)
        m.draw_galactic(tickinterval=5, dashed=GALACTIC_DASH_PATTERN)

        # Legend
        legend(f, chart_number)
        f.render(os.path.join(OUTPUT_FOLDER, "{:02}.pdf".format(chart_number)),
                 open=False)

    # North conic maps
    for i in range(6):
Beispiel #17
0
 def parallel(self, latitude, min_longitude, max_longitude):
     p1 = self.project(SkyCoordDeg(min_longitude - 0.1, latitude))
     p2 = self.project(SkyCoordDeg(max_longitude + 0.1, latitude))
     return Line(p1, p2)
Beispiel #18
0
 def meridian(self, longitude, min_latitude, max_latitude):
     p1 = self.project(SkyCoordDeg(longitude, min_latitude))
     p2 = self.project(SkyCoordDeg(longitude, max_latitude))
     return Line(p1, p2)
Beispiel #19
0
    def __init__(self, p1, p2, origin=None, hmargin=0, vmargin=0, box=True):
        if origin is None:
            origin = 0.5 * (p1 + p2)
        DrawingArea.__init__(self, p1, p2, origin, box)

        # Total map
        self.map_hmargin = hmargin
        self.map_vmargin = vmargin

        # Central map area
        self.map_width = float(self.width - 2 * self.map_hmargin)
        self.map_height = float(self.height - 2 * self.map_vmargin)

        self.map_minx = self.p1.x + self.map_hmargin - self.origin.x
        self.map_maxx = self.map_minx + self.map_width
        self.map_miny = self.p1.y + self.map_vmargin - self.origin.y
        self.map_maxy = self.map_miny + self.map_height

        self.map_llcorner = Point(self.map_minx, self.map_miny)
        self.map_lrcorner = Point(self.map_maxx, self.map_miny)
        self.map_urcorner = Point(self.map_maxx, self.map_maxy)
        self.map_ulcorner = Point(self.map_minx, self.map_maxy)

        self.map_bottom_border = Line(self.map_llcorner, self.map_lrcorner)
        self.map_right_border = Line(self.map_lrcorner, self.map_urcorner)
        self.map_top_border = Line(self.map_urcorner, self.map_ulcorner)
        self.map_left_border = Line(self.map_ulcorner, self.map_llcorner)

        self.map_box = Rectangle(self.map_llcorner, self.map_urcorner)

        self.projection = UnitProjection()

        # Longitude/latitude ranges
        self.min_longitude = None
        self.max_longitude = None
        self.min_latitude = None
        self.max_latitude = None

        self.bordered = True

        # Longitude/latitude grid
        self.gridline_factory = GridLineFactory()
        self.gridline_factory.marked_ticksize = 1.0
        self.gridline_factory.unmarked_ticksize = 0.5
        self.gridline_factory.meridian_line_interval = 15  # 1 hour
        self.gridline_factory.meridian_marked_tick_interval = 5  # 20 minutes
        self.gridline_factory.meridian_tick_interval = 1.25  # 5 minutes
        self.gridline_factory.parallel_line_interval = 10
        self.gridline_factory.parallel_marked_tick_interval = 10
        self.gridline_factory.parallel_tick_interval = 1

        self.parallel_ticks = {
            'left': True,
            'right': True,
            'bottom': False,
            'top': False
        }
        self.meridian_ticks = {
            'left': False,
            'right': False,
            'bottom': True,
            'top': True
        }
Beispiel #20
0
 def map_line(self, line):
     p1 = self.map_point(line.p1)
     p2 = self.map_point(line.p2)
     return Line(p1, p2)