예제 #1
0
    def bounding_box(self, settings):
        """
        Return the bounding box of the canvas area used by this component.

        :param settings:
            A dictionary of settings required by the renderer.
        :return:
         Dictionary with the elements 'x_min', 'x_max', 'y_min' and 'y_max' set
        """

        latitude = abs(settings['latitude'])

        bounding_box = {'x_min': 0, 'x_max': 0, 'y_min': 0, 'y_max': 0}

        # Trace around horizon, keeping track of minimum and maximum coordinates
        alt_edge = -12

        # At latitudes very close to the equator, the point -12 degrees below the horizon is below dec -90!
        if abs(latitude) < 15:
            alt_edge = -9

        path = [
            transform(alt=alt_edge, az=az, latitude=latitude)
            for az in arange(0, 360.5, 1)
        ]

        for p in path:
            r_b = radius(dec=p[1] / unit_deg, latitude=latitude)
            p = pos(r_b, p[0])
            bounding_box['x_min'] = min(bounding_box['x_min'], p['x'])
            bounding_box['x_max'] = max(bounding_box['x_max'], p['x'])
            bounding_box['y_min'] = min(bounding_box['y_min'], p['y'])
            bounding_box['y_max'] = max(bounding_box['y_max'], p['y'])

        return bounding_box
예제 #2
0
        def make_gluing_label(azimuth):
            pp = transform(alt=0, az=azimuth - 0.01, latitude=latitude)
            r = radius(dec=pp[1] / unit_deg, latitude=latitude)
            p = pos(r, pp[0])

            pp2 = transform(alt=0, az=azimuth + 0.01, latitude=latitude)
            r2 = radius(dec=pp2[1] / unit_deg, latitude=latitude)
            p2 = pos(r2, pp2[0])

            p3 = [p2[i] - p[i] for i in ('x', 'y')]
            tr = -unit_rev / 4 - atan2(p3[0], p3[1])

            context.text(text=text[language]["glue_here"],
                         x=p['x'],
                         y=p['y'],
                         h_align=0,
                         v_align=1,
                         gap=unit_mm,
                         rotation=tr)
예제 #3
0
        def cardinal(dir, ang):
            pp = transform(alt=0, az=ang - 0.01, latitude=latitude)
            r = radius(dec=pp[1] / unit_deg, latitude=latitude)
            p = pos(r, pp[0])

            pp2 = transform(alt=0, az=ang + 0.01, latitude=latitude)
            r2 = radius(dec=pp2[1] / unit_deg, latitude=latitude)
            p2 = pos(r=r2, t=pp2[0])

            p3 = [p2[i] - p[i] for i in ('x', 'y')]
            tr = -unit_rev / 4 - atan2(p3[0], p3[1])

            context.text(text=dir,
                         x=x0[0] + p['x'],
                         y=-x0[1] + p['y'],
                         h_align=0,
                         v_align=1,
                         gap=unit_mm,
                         rotation=tr)
예제 #4
0
    def do_rendering(self, settings, context):
        """
        This method is required to actually render this item.

        :param settings:
            A dictionary of settings required by the renderer.
        :param context:
            A GraphicsContext object to use for drawing
        :return:
            None
        """

        latitude = abs(settings['latitude'])
        language = settings['language']

        context.set_font_size(0.9)

        # Set altitude of outer edge of alt-az grid, including margin for gluing instructions
        alt_edge = -10
        azimuth_step = 1

        # At latitudes very close to the equator, the point -12 degrees below the horizon is below dec -90!
        if abs(latitude) < 15:
            alt_edge = -8
            azimuth_step = 0.2

        # Draw horizon (altitude 0), and line to cut around edge of window (altitude alt_edge)
        for alt in (alt_edge, 0):
            # Draw a line, segment by segment, taking small steps in azimuth
            path = [
                transform(alt=alt, az=az, latitude=latitude)
                for az in arange(0, 360.5, azimuth_step)
            ]

            # Project line from RA, Dec into planispheric coordinates
            context.begin_path()
            for i, p in enumerate(path):
                r_b = radius(dec=p[1] / unit_deg, latitude=latitude)
                if i == 0:
                    context.move_to(**pos(r_b, p[0]))
                else:
                    context.line_to(**pos(r_b, p[0]))
            context.stroke()

            if alt == alt_edge:
                # Draw the central hole in the middle of the viewing window
                context.begin_sub_path()
                context.circle(centre_x=0,
                               centre_y=0,
                               radius=central_hole_size)
                context.stroke()

                # Create clipping area, excluding central hole
                context.clip()

        # Draw lines of constant altitude
        context.begin_path()
        for alt in range(10, 85, 10):
            path = [
                transform(alt=alt, az=az, latitude=latitude)
                for az in arange(0, 360.5, 1)
            ]
            for i, p in enumerate(path):
                r_b = radius(dec=p[1] / unit_deg, latitude=latitude)
                if i == 0:
                    context.move_to(**pos(r_b, p[0]))
                else:
                    context.line_to(**pos(r_b, p[0]))
        context.stroke(color=(0.5, 0.5, 0.5, 1))

        # Draw lines of constant azimuth, marking S,SSE,SE,ESE,E, etc
        context.begin_path()
        for az in arange(0, 359, 22.5):
            path = [
                transform(alt=alt, az=az, latitude=latitude)
                for alt in arange(0, 90.1, 1)
            ]
            for i, p in enumerate(path):
                r_b = radius(dec=p[1] / unit_deg, latitude=latitude)
                if i == 0:
                    context.move_to(**pos(r_b, p[0]))
                else:
                    context.line_to(**pos(r_b, p[0]))
        context.stroke(color=(0.5, 0.5, 0.5, 1))

        # Gluing labels
        def make_gluing_label(azimuth):
            pp = transform(alt=0, az=azimuth - 0.01, latitude=latitude)
            r = radius(dec=pp[1] / unit_deg, latitude=latitude)
            p = pos(r, pp[0])

            pp2 = transform(alt=0, az=azimuth + 0.01, latitude=latitude)
            r2 = radius(dec=pp2[1] / unit_deg, latitude=latitude)
            p2 = pos(r2, pp2[0])

            p3 = [p2[i] - p[i] for i in ('x', 'y')]
            tr = -unit_rev / 4 - atan2(p3[0], p3[1])

            context.text(text=text[language]["glue_here"],
                         x=p['x'],
                         y=p['y'],
                         h_align=0,
                         v_align=1,
                         gap=unit_mm,
                         rotation=tr)

        # Write the text "Glue here" at various points around the horizon
        context.set_font_style(bold=True)
        context.set_color(color=(0, 0, 0, 1))
        make_gluing_label(azimuth=0)
        make_gluing_label(azimuth=90)
        make_gluing_label(azimuth=180)
        make_gluing_label(azimuth=270)
예제 #5
0
    def do_rendering(self, settings, context):
        """
        This method is required to actually render this item.

        :param settings:
            A dictionary of settings required by the renderer.
        :param context:
            A GraphicsContext object to use for drawing
        :return:
            None
        """

        is_southern = settings['latitude'] < 0
        latitude = abs(settings['latitude'])
        language = settings['language']

        context.set_font_size(0.9)

        a = 6 * unit_cm
        h = r_1 + fold_gap

        # Draw dotted line for folding the bottom of the planisphere
        context.begin_path()
        context.move_to(x=-r_1, y=0)
        context.line_to(x=r_1, y=0)
        context.stroke(dotted=True)

        # Draw the rectangular back and lower body of the planisphere
        context.begin_path()
        context.move_to(x=-r_1, y=a)
        context.line_to(x=-r_1, y=-a)
        context.move_to(x=r_1, y=a)
        context.line_to(x=r_1, y=-a)
        context.stroke(dotted=False)

        # Draw the curved upper part of the body of the planisphere
        theta = unit_rev / 2 - atan2(r_1, h - a)
        context.begin_path()
        context.arc(centre_x=0,
                    centre_y=-h,
                    radius=r_2,
                    arc_from=-theta - pi / 2,
                    arc_to=theta - pi / 2)
        context.move_to(x=-r_2 * sin(theta), y=-h - r_2 * cos(theta))
        context.line_to(x=-r_1, y=-a)
        context.move_to(x=r_2 * sin(theta), y=-h - r_2 * cos(theta))
        context.line_to(x=r_1, y=-a)
        context.stroke()

        # Shade the viewing window which needs to be cut out
        x0 = (0, h)
        context.begin_path()
        for i, az in enumerate(arange(0, 360.5, 1)):
            pp = transform(alt=0, az=az, latitude=latitude)
            r = radius(dec=pp[1] / unit_deg, latitude=latitude)
            p = pos(r=r, t=pp[0])
            if i == 0:
                context.move_to(x0[0] + p['x'], -x0[1] + p['y'])
            else:
                context.line_to(x0[0] + p['x'], -x0[1] + p['y'])
        context.stroke()
        context.fill(color=(0, 0, 0, 0.2))

        # Display instructions for cutting out the viewing window
        instructions = text[language]["cut_out_instructions"]
        context.set_color(color=(0, 0, 0, 1))
        context.text_wrapped(text=instructions,
                             width=4 * unit_cm,
                             justify=0,
                             x=0,
                             y=-h - r_1 * 0.35,
                             h_align=0,
                             v_align=0,
                             rotation=0)

        # Cardinal points
        def cardinal(dir, ang):
            pp = transform(alt=0, az=ang - 0.01, latitude=latitude)
            r = radius(dec=pp[1] / unit_deg, latitude=latitude)
            p = pos(r, pp[0])

            pp2 = transform(alt=0, az=ang + 0.01, latitude=latitude)
            r2 = radius(dec=pp2[1] / unit_deg, latitude=latitude)
            p2 = pos(r=r2, t=pp2[0])

            p3 = [p2[i] - p[i] for i in ('x', 'y')]
            tr = -unit_rev / 4 - atan2(p3[0], p3[1])

            context.text(text=dir,
                         x=x0[0] + p['x'],
                         y=-x0[1] + p['y'],
                         h_align=0,
                         v_align=1,
                         gap=unit_mm,
                         rotation=tr)

        # Write the cardinal points around the horizon of the viewing window
        context.set_font_style(bold=True)

        txt = text[language]['cardinal_points']['w']
        cardinal(txt, 180 if not is_southern else 0)

        txt = text[language]['cardinal_points']['s']
        cardinal(txt, 270 if not is_southern else 90)

        txt = text[language]['cardinal_points']['e']
        cardinal(txt, 0 if not is_southern else 180)

        txt = text[language]['cardinal_points']['n']
        cardinal(txt, 90 if not is_southern else 270)

        context.set_font_style(bold=False)

        # Clock face, which lines up with the date scale on the star wheel
        theta = unit_rev / 24 * 7  # 5pm -> 7am means we cover 7 hours on either side of midnight
        dash = unit_rev / 24 / 4  # Draw fat dashes at 15 minute intervals

        # Outer edge of dashed scale
        r_3 = r_2 - 2 * unit_mm

        # Inner edge of dashed scale
        r_4 = r_2 - 3 * unit_mm

        # Radius of dashes for marking hours
        r_5 = r_2 - 4 * unit_mm

        # Radius of text marking hours
        r_6 = r_2 - 5.5 * unit_mm

        # Inner and outer curves around dashed scale
        context.begin_path()
        context.arc(centre_x=0,
                    centre_y=-h,
                    radius=r_3,
                    arc_from=-theta - pi / 2,
                    arc_to=theta - pi / 2)
        context.begin_sub_path()
        context.arc(centre_x=0,
                    centre_y=-h,
                    radius=r_4,
                    arc_from=-theta - pi / 2,
                    arc_to=theta - pi / 2)
        context.stroke()

        # Draw a fat dashed line with one dash every 15 minutes
        for i in arange(-theta, theta, 2 * dash):
            context.begin_path()
            context.arc(centre_x=0,
                        centre_y=-h,
                        radius=(r_3 + r_4) / 2,
                        arc_from=i - pi / 2,
                        arc_to=i + dash - pi / 2)
            context.stroke(line_width=(r_3 - r_4) / line_width_base)

        # Write the hours
        for hr in arange(-7, 7.1, 1):
            txt = "{:.0f}{}".format(hr if (hr > 0) else hr + 12, "AM" if
                                    (hr > 0) else "PM")
            if language == "fr":
                txt = "{:02d}h00".format(int(hr if (hr > 0) else hr + 24))
            if language == "mn":
                txt = "{:d}ц".format(int(hr if (hr > 0) else hr + 24))
            if hr == 0:
                txt = ""
            t = unit_rev / 24 * hr * (-1 if not is_southern else 1)

            # Stroke a dash and write the number of the hour
            context.begin_path()
            context.move_to(x=r_3 * sin(t), y=-h - r_3 * cos(t))
            context.line_to(x=r_5 * sin(t), y=-h - r_5 * cos(t))
            context.stroke(line_width=1)
            context.text(text=txt,
                         x=r_6 * sin(t),
                         y=-h - r_6 * cos(t),
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=t)

        # Back edge
        b = unit_cm
        t1 = atan2(h - a, r_1)
        t2 = asin(b / hypot(r_1, h - a))
        context.begin_path()
        context.move_to(x=-r_1, y=a)
        context.line_to(x=-b * sin(t1 + t2), y=h + b * cos(t1 + t2))
        context.move_to(x=r_1, y=a)
        context.line_to(x=b * sin(t1 + t2), y=h + b * cos(t1 + t2))
        context.arc(centre_x=0,
                    centre_y=h,
                    radius=b,
                    arc_from=unit_rev / 2 - (t1 + t2) - pi / 2,
                    arc_to=unit_rev / 2 + (t1 + t2) - pi / 2)
        context.stroke(line_width=1)

        # For latitudes not too close to the pole, we have enough space to fit instructions onto the planisphere
        if latitude < 56:
            # Big bold title
            context.set_font_size(3.0)
            txt = text[language]['title']
            context.set_font_style(bold=True)
            context.text(text="%s %d\u00B0%s" %
                         (txt, latitude, "N" if not is_southern else "S"),
                         x=0,
                         y=-4.8 * unit_cm,
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=0)
            context.set_font_style(bold=False)

            # First column of instructions
            context.set_font_size(2)
            context.text(text="1",
                         x=-5.0 * unit_cm,
                         y=-4.0 * unit_cm,
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=0)
            context.set_font_size(1)
            context.text_wrapped(text=text[language]['instructions_1'],
                                 x=-5.0 * unit_cm,
                                 y=-3.4 * unit_cm,
                                 width=4.5 * unit_cm,
                                 justify=-1,
                                 h_align=0,
                                 v_align=1,
                                 rotation=0)

            # Second column of instructions
            context.set_font_size(2)
            context.text(text="2",
                         x=0,
                         y=-4.0 * unit_cm,
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=0)
            context.set_font_size(1)
            context.text_wrapped(text=text[language]['instructions_2'].format(
                cardinal="north" if not is_southern else "south"),
                                 x=0,
                                 y=-3.4 * unit_cm,
                                 width=4.5 * unit_cm,
                                 justify=-1,
                                 h_align=0,
                                 v_align=1,
                                 rotation=0)

            # Third column of instructions
            context.set_font_size(2)
            context.text(text="3",
                         x=5.0 * unit_cm,
                         y=-4.0 * unit_cm,
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=0)
            context.set_font_size(1)
            context.text_wrapped(text=text[language]['instructions_3'],
                                 x=5.0 * unit_cm,
                                 y=-3.4 * unit_cm,
                                 width=4.5 * unit_cm,
                                 justify=-1,
                                 h_align=0,
                                 v_align=1,
                                 rotation=0)
        else:
            # For planispheres for use at high latitudes, we don't have much space, so don't show instructions.
            # We just display a big bold title
            context.set_font_size(3.0)
            txt = text[language]['title']
            context.set_font_style(bold=True)
            context.text(text="%s %d\u00B0%s" %
                         (txt, latitude, "N" if not is_southern else "S"),
                         x=0,
                         y=-1.8 * unit_cm,
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=0)
            context.set_font_style(bold=False)

        # Write explanatory text on the back of the planisphere
        context.set_font_size(1.1)
        context.text_wrapped(text=text[language]['instructions_4'],
                             x=0,
                             y=5.5 * unit_cm,
                             width=12 * unit_cm,
                             justify=-1,
                             h_align=0,
                             v_align=1,
                             rotation=0.5 * unit_rev)

        # Display web link and copyright text
        txt = text[language]['more_info']
        context.set_font_size(0.9)
        context.text(text=txt,
                     x=0,
                     y=-0.5 * unit_cm,
                     h_align=0,
                     v_align=0,
                     gap=0,
                     rotation=0)
        context.set_font_size(0.9)
        context.text(text=txt,
                     x=0,
                     y=0.5 * unit_cm,
                     h_align=0,
                     v_align=0,
                     gap=0,
                     rotation=pi)

        # Draw central hole
        context.begin_path()
        context.circle(centre_x=0, centre_y=h, radius=central_hole_size)
        context.stroke()
예제 #6
0
    def do_rendering(self, settings, context):
        """
        This method is required to actually render this item.

        :param settings:
            A dictionary of settings required by the renderer.
        :param context:
            A GraphicsContext object to use for drawing
        :return:
            None
        """

        is_southern = settings['latitude'] < 0
        latitude = abs(settings['latitude'])
        language = settings['language']

        context.set_font_size(0.9)

        a = 6 * unit_cm
        h = r_1 + fold_gap
        context.begin_path()
        context.move_to(x=-r_1, y=0)
        context.line_to(x=r_1, y=0)
        context.stroke(dotted=True)
        context.begin_path()
        context.move_to(x=-r_1, y=a)
        context.line_to(x=-r_1, y=-a)
        context.move_to(x=r_1, y=a)
        context.line_to(x=r_1, y=-a)
        context.stroke(dotted=False)

        theta = unit_rev / 2 - atan2(r_1, h - a)
        context.begin_path()
        context.arc(centre_x=0,
                    centre_y=-h,
                    radius=r_2,
                    arc_from=-theta - pi / 2,
                    arc_to=theta - pi / 2)
        context.move_to(x=-r_2 * sin(theta), y=-h - r_2 * cos(theta))
        context.line_to(x=-r_1, y=-a)
        context.move_to(x=r_2 * sin(theta), y=-h - r_2 * cos(theta))
        context.line_to(x=r_1, y=-a)
        context.stroke()

        # Viewing window
        x0 = (0, h)
        context.begin_path()
        for i, az in enumerate(arange(0, 360.5, 1)):
            pp = transform(alt=0, az=az, latitude=latitude)
            r = radius(dec=pp[1] / unit_deg, latitude=latitude)
            p = pos(r=r, t=pp[0])
            if i == 0:
                context.move_to(x0[0] + p['x'], -x0[1] + p['y'])
            else:
                context.line_to(x0[0] + p['x'], -x0[1] + p['y'])
        context.stroke()
        context.fill(color=(0, 0, 0, 0.2))

        instructions = text[language]["cut_out_instructions"]
        context.set_color(color=(0, 0, 0, 1))
        context.text_wrapped(text=instructions[0],
                             width=6 * unit_cm,
                             justify=0,
                             x=0,
                             y=-h - r_1 * 0.4,
                             h_align=0,
                             v_align=0,
                             rotation=0)
        context.text_wrapped(text=instructions[1],
                             width=6 * unit_cm,
                             justify=0,
                             x=0,
                             y=-h - r_1 * 0.3,
                             h_align=0,
                             v_align=0,
                             rotation=0)

        # Cardinal points
        def cardinal(dir, ang):
            pp = transform(alt=0, az=ang - 0.01, latitude=latitude)
            r = radius(dec=pp[1] / unit_deg, latitude=latitude)
            p = pos(r, pp[0])

            pp2 = transform(alt=0, az=ang + 0.01, latitude=latitude)
            r2 = radius(dec=pp2[1] / unit_deg, latitude=latitude)
            p2 = pos(r=r2, t=pp2[0])

            p3 = [p2[i] - p[i] for i in ('x', 'y')]
            tr = -unit_rev / 4 - atan2(p3[0], p3[1])

            context.text(text=dir,
                         x=x0[0] + p['x'],
                         y=-x0[1] + p['y'],
                         h_align=0,
                         v_align=1,
                         gap=unit_mm,
                         rotation=tr)

        context.set_font_style(bold=True)

        txt = text[language]['cardinal_points']['w']
        cardinal(txt, 180 if not is_southern else 0)

        txt = text[language]['cardinal_points']['s']
        cardinal(txt, 270 if not is_southern else 90)

        txt = text[language]['cardinal_points']['e']
        cardinal(txt, 0 if not is_southern else 180)

        txt = text[language]['cardinal_points']['n']
        cardinal(txt, 90 if not is_southern else 270)

        context.set_font_style(bold=False)

        # Clock face
        theta = unit_rev / 24 * 7  # 5pm -> 7am
        dash = unit_rev / 24 / 4
        r_3 = r_2 - 2 * unit_mm
        r_4 = r_2 - 3 * unit_mm
        r_5 = r_2 - 4 * unit_mm
        r_6 = r_2 - 5.5 * unit_mm

        context.begin_path()
        context.arc(centre_x=0,
                    centre_y=-h,
                    radius=r_3,
                    arc_from=-theta - pi / 2,
                    arc_to=theta - pi / 2)
        context.begin_sub_path()
        context.arc(centre_x=0,
                    centre_y=-h,
                    radius=r_4,
                    arc_from=-theta - pi / 2,
                    arc_to=theta - pi / 2)
        context.stroke()

        for i in arange(-theta, theta, 2 * dash):
            context.begin_path()
            context.arc(centre_x=0,
                        centre_y=-h,
                        radius=(r_3 + r_4) / 2,
                        arc_from=i - pi / 2,
                        arc_to=i + dash - pi / 2)
            context.stroke(line_width=(r_3 - r_4) / line_width_base)

        for hr in arange(-7, 7.1, 1):
            txt = "{:.0f}{}".format(hr if (hr > 0) else hr + 12, "AM" if
                                    (hr > 0) else "PM")
            if language == "fr":
                txt = "{:02d}h00".format(int(hr if (hr > 0) else hr + 24))
            if hr == 0:
                txt = ""
            t = unit_rev / 24 * hr * (-1 if not is_southern else 1)

            context.begin_path()
            context.move_to(x=r_3 * sin(t), y=-h - r_3 * cos(t))
            context.line_to(x=r_5 * sin(t), y=-h - r_5 * cos(t))
            context.stroke(line_width=1)
            context.text(text=txt,
                         x=r_6 * sin(t),
                         y=-h - r_6 * cos(t),
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=t)

        # Back edge
        b = unit_cm
        t1 = atan2(h - a, r_1)
        t2 = asin(b / hypot(r_1, h - a))
        context.begin_path()
        context.move_to(x=-r_1, y=a)
        context.line_to(x=-b * sin(t1 + t2), y=h + b * cos(t1 + t2))
        context.move_to(x=r_1, y=a)
        context.line_to(x=b * sin(t1 + t2), y=h + b * cos(t1 + t2))
        context.arc(centre_x=0,
                    centre_y=h,
                    radius=b,
                    arc_from=unit_rev / 2 - (t1 + t2) - pi / 2,
                    arc_to=unit_rev / 2 + (t1 + t2) - pi / 2)
        context.stroke(line_width=1)

        # Title
        if latitude < 56:
            context.set_font_size(3.0)
            txt = text[language]['title']
            context.set_font_style(bold=True)
            context.text(text="%s %d\u00B0%s" %
                         (txt, latitude, "N" if not is_southern else "S"),
                         x=0,
                         y=-4.8 * unit_cm,
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=0)
            context.set_font_style(bold=False)

            context.set_font_size(1.6)
            context.text(text="1",
                         x=-5.0 * unit_cm,
                         y=-4.0 * unit_cm,
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=0)
            context.set_font_size(0.85)
            context.text_wrapped(text=text[language]['instructions_1'],
                                 x=-5.0 * unit_cm,
                                 y=-3.4 * unit_cm,
                                 width=4.5 * unit_cm,
                                 justify=-1,
                                 h_align=0,
                                 v_align=1,
                                 rotation=0)

            context.set_font_size(1.6)
            context.text(text="2",
                         x=0,
                         y=-4.0 * unit_cm,
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=0)
            context.set_font_size(0.85)
            context.text_wrapped(text=text[language]['instructions_2'].format(
                cardinal="north" if not is_southern else "south"),
                                 x=0,
                                 y=-3.4 * unit_cm,
                                 width=4.5 * unit_cm,
                                 justify=-1,
                                 h_align=0,
                                 v_align=1,
                                 rotation=0)

            context.set_font_size(1.6)
            context.text(text="3",
                         x=5.0 * unit_cm,
                         y=-4.0 * unit_cm,
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=0)
            context.set_font_size(0.85)
            context.text_wrapped(text=text[language]['instructions_3'],
                                 x=5.0 * unit_cm,
                                 y=-3.4 * unit_cm,
                                 width=4.5 * unit_cm,
                                 justify=-1,
                                 h_align=0,
                                 v_align=1,
                                 rotation=0)
        else:
            context.set_font_size(3.0)
            txt = text[language]['title']
            context.set_font_style(bold=True)
            context.text(text="%s %d\u00B0%s" %
                         (txt, latitude, "N" if not is_southern else "S"),
                         x=0,
                         y=-1.8 * unit_cm,
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=0)
            context.set_font_style(bold=False)

        context.set_font_size(0.9)
        context.text_wrapped(text=text[language]['instructions_4'],
                             x=0,
                             y=5.5 * unit_cm,
                             width=12 * unit_cm,
                             justify=-1,
                             h_align=0,
                             v_align=1,
                             rotation=0.5 * unit_rev)

        txt = text[language]['more_info']
        context.set_font_size(0.8)
        context.text(text=txt,
                     x=0,
                     y=-0.5 * unit_cm,
                     h_align=0,
                     v_align=0,
                     gap=0,
                     rotation=0)
        context.set_font_size(0.8)
        context.text(text=txt,
                     x=0,
                     y=0.5 * unit_cm,
                     h_align=0,
                     v_align=0,
                     gap=0,
                     rotation=pi)

        # Draw central hole
        context.begin_path()
        context.circle(centre_x=0, centre_y=h, radius=central_hole_size)
        context.stroke()
예제 #7
0
    def do_rendering(self, settings, context):
        """
        This method is required to actually render this item.

        :param settings:
            A dictionary of settings required by the renderer.
        :param context:
            A GraphicsContext object to use for drawing
        :return:
            None
        """

        is_southern = settings['latitude'] < 0
        language = settings['language']
        latitude = abs(settings['latitude'])
        theme = themes[settings['theme']]

        context.set_font_size(1.2)

        # Radius of outer edge of star chart
        r_2 = r_1 - r_gap

        # Radius of day-of-month ticks from centre of star chart
        r_3 = r_1 * 0.1 + r_2 * 0.9

        # Radius of every fifth day-of-month tick from centre of star chart
        r_4 = r_1 * 0.2 + r_2 * 0.8

        # Radius of lines between months on date scale
        r_5 = r_1

        # Radius for writing numeric labels for days of the month
        r_6 = r_1 * 0.4 + r_2 * 0.6

        # Shade background to month scale
        shading_inner_radius = r_1 * 0.55 + r_2 * 0.45
        context.begin_path()
        context.circle(centre_x=0, centre_y=0, radius=r_1)
        context.circle(centre_x=0, centre_y=0, radius=shading_inner_radius)
        context.fill(color=theme['shading'])

        # Draw the outer edge of planisphere
        context.begin_path()
        context.circle(centre_x=0, centre_y=0, radius=r_1)
        context.fill(color=theme['background'])

        # Draw the central hole in the middle of the planisphere
        context.begin_sub_path()
        context.circle(centre_x=0, centre_y=0, radius=central_hole_size)
        context.stroke(color=theme['edge'])

        # Combine these two paths to make a clipping path for drawing the star wheel
        context.clip()

        # Draw lines of constant declination at 15 degree intervals.
        for dec in arange(-80, 85, 15):
            # Convert declination into radius from the centre of the planisphere
            r = radius(dec=dec, latitude=latitude)
            if r > r_2:
                continue
            context.begin_path()
            context.circle(centre_x=0, centre_y=0, radius=r)
            context.stroke(color=theme['grid'])

        # Draw constellation stick figures
        for line in open("raw_data/constellation_stick_figures.dat", "rt"):
            line = line.strip()

            # Ignore blank lines and comment lines
            if (len(line) == 0) or (line[0] == '#'):
                continue

            # Split line into words.
            # These are the names of the constellations, and the start and end points for each stroke.
            [name, ra1, dec1, ra2, dec2] = line.split()

            # If we're making a southern hemisphere planisphere, we flip the sky upside down
            if is_southern:
                ra1 = -float(ra1)
                ra2 = -float(ra2)
                dec1 = -float(dec1)
                dec2 = -float(dec2)

            # Project RA and Dec into radius and azimuth in the planispheric projection
            r_point_1 = radius(dec=float(dec1), latitude=latitude)
            if r_point_1 > r_2:
                continue

            r_point_2 = radius(dec=float(dec2), latitude=latitude)
            if r_point_2 > r_2:
                continue

            p1 = (-r_point_1 * cos(float(ra1) * unit_deg),
                  -r_point_1 * sin(float(ra1) * unit_deg))
            p2 = (-r_point_2 * cos(float(ra2) * unit_deg),
                  -r_point_2 * sin(float(ra2) * unit_deg))

            # Impose a maximum length of 4 cm on constellation stick figures; they get quite distorted at the edge
            if hypot(p2[0] - p1[0], p2[1] - p1[1]) > 4 * unit_cm:
                continue

            # Stroke a line
            context.begin_path()
            context.move_to(x=p1[0], y=p1[1])
            context.line_to(x=p2[0], y=p2[1])
            context.stroke(color=theme['stick'], line_width=1, dotted=True)

        # Draw stars from Yale Bright Star Catalogue
        for star_descriptor in fetch_bright_star_list()['stars'].values():
            [ra, dec, mag] = star_descriptor[:3]

            # Discard stars fainter than mag 4
            if mag == "-" or float(mag) > 4.0:
                continue

            ra = float(ra)
            dec = float(dec)

            # If we're making a southern hemisphere planisphere, we flip the sky upside down
            if is_southern:
                ra *= -1
                dec *= -1

            r = radius(dec=dec, latitude=latitude)
            if r > r_2:
                continue

            # Represent each star with a small circle
            context.begin_path()
            context.circle(centre_x=-r * cos(ra * unit_deg),
                           centre_y=-r * sin(ra * unit_deg),
                           radius=0.18 * unit_mm * (5 - mag))
            context.fill(color=theme['star'])

        # Write constellation names
        context.set_font_size(0.7)
        context.set_color(theme['constellation'])

        # Open a list of the coordinates where we place the names of the constellations
        for line in open("raw_data/constellation_names.dat"):
            line = line.strip()

            # Ignore blank lines and comment lines
            if (len(line) == 0) or (line[0] == '#'):
                continue

            # Split line into words
            [name, ra, dec] = line.split()[:3]

            # Translate constellation name into the requested language, if required
            if name in text[language]['constellation_translations']:
                name = text[language]['constellation_translations'][name]

            ra = float(ra) * 360. / 24
            dec = float(dec)

            # If we're making a southern hemisphere planisphere, we flip the sky upside down
            if is_southern:
                ra = -ra
                dec = -dec

            # Render name of constellation, with _s turned into spaces
            name2 = re.sub("_", " ", name)
            r = radius(dec=dec, latitude=latitude)
            if r > r_2:
                continue
            p = (-r * cos(ra * unit_deg), -r * sin(ra * unit_deg))
            a = atan2(p[0], p[1])
            context.text(text=name2,
                         x=p[0],
                         y=p[1],
                         h_align=0,
                         v_align=0,
                         gap=0,
                         rotation=unit_rev / 2 - a)

        # Calendar ring counts clockwise in northern hemisphere; anticlockwise in southern hemisphere
        s = -1 if not is_southern else 1

        def theta2014(d):
            """
            Convert Julian Day into a rotation angle of the sky about the north celestial pole at midnight,
            relative to spring equinox.

            :param d:
                Julian day
            :return:
                Rotation angle, radians
            """
            return (d - calendar.julian_day(
                year=2014, month=3, day=20, hour=16, minute=55,
                sec=0)) / 365.25 * unit_rev

        # Write month names around the date scale
        context.set_font_size(2.3)
        context.set_color(theme['date'])
        for mn, (mlen, name) in enumerate(text[language]['months']):
            theta = s * theta2014(
                calendar.julian_day(year=2014,
                                    month=mn + 1,
                                    day=mlen // 2,
                                    hour=12,
                                    minute=0,
                                    sec=0))

            # We supply circular_text with a negative radius here, as a fudge to orientate the text with bottom-inwards
            context.circular_text(text=name,
                                  centre_x=0,
                                  centre_y=0,
                                  radius=-(r_1 * 0.65 + r_2 * 0.35),
                                  azimuth=theta / unit_deg + 180,
                                  spacing=1,
                                  size=1)

        # Draw ticks for the days of the month
        for mn, (mlen, name) in enumerate(text[language]['months']):
            # Tick marks for each day
            for d in range(1, mlen + 1):
                theta = s * theta2014(
                    calendar.julian_day(year=2014,
                                        month=mn + 1,
                                        day=d,
                                        hour=0,
                                        minute=0,
                                        sec=0))

                # Days of the month which are multiples of 5 get longer ticks
                R = r_3 if (d % 5) else r_4

                # The last day of each month is drawn as a dividing line between months
                if d == mlen:
                    R = r_5

                # Draw line
                context.begin_path()
                context.move_to(x=r_2 * cos(theta), y=-r_2 * sin(theta))
                context.line_to(x=R * cos(theta), y=-R * sin(theta))
                context.stroke(line_width=1, dotted=False)

            # Write numeric labels for the 10th, 20th and last day of each month
            for d in [10, 20, mlen]:
                theta = s * theta2014(
                    calendar.julian_day(year=2014,
                                        month=mn + 1,
                                        day=d,
                                        hour=0,
                                        minute=0,
                                        sec=0))
                context.set_font_size(1.2)

                # First digit
                theta2 = theta + 0.15 * unit_deg
                context.text(text="%d" % (d / 10),
                             x=r_6 * cos(theta2),
                             y=-r_6 * sin(theta2),
                             h_align=1,
                             v_align=0,
                             gap=0,
                             rotation=-theta + pi / 2)

                # Second digit
                theta2 = theta - 0.15 * unit_deg
                context.text(text="%d" % (d % 10),
                             x=r_6 * cos(theta2),
                             y=-r_6 * sin(theta2),
                             h_align=-1,
                             v_align=0,
                             gap=0,
                             rotation=-theta + pi / 2)

        # Draw the dividing line between the date scale and the star chart
        context.begin_path()
        context.circle(centre_x=0, centre_y=0, radius=r_2)
        context.stroke(color=theme['date'], line_width=1, dotted=False)
예제 #8
0
def get_hstat_profiles(N, r_l, r_t):
    r_core = constants.radius(r_l, r_t, N)
    rho_core = core_density(r_core)
    g_core = core_gravity(r_core, rho_core)
    p_core = core_pressure(r_core, rho_core, g_core)
    return r_core, rho_core, g_core, p_core
예제 #9
0
    def do_rendering(self, settings, context):
        """
        This method is required to actually render this item.

        :param settings:
            A dictionary of settings required by the renderer.
        :param context:
            A GraphicsContext object to use for drawing
        :return:
            None
        """

        latitude = abs(settings['latitude'])
        language = settings['language']

        context.set_font_size(0.9)

        # Draw horizon, and line to cut around edge
        for alt in (-10, 0):
            path = [
                transform(alt=alt, az=az, latitude=latitude)
                for az in arange(0, 360.5, 1)
            ]

            context.begin_path()
            for i, p in enumerate(path):
                r_b = radius(dec=p[1] / unit_deg, latitude=latitude)
                if i == 0:
                    context.move_to(**pos(r_b, p[0]))
                else:
                    context.line_to(**pos(r_b, p[0]))
            context.stroke()

            if alt == -10:
                # Create clipping area, excluding central hole
                context.begin_sub_path()
                context.circle(centre_x=0,
                               centre_y=0,
                               radius=central_hole_size)
                context.stroke()
                context.clip()

        # Draw lines of constant altitude
        context.begin_path()
        for alt in range(10, 85, 10):
            path = [
                transform(alt=alt, az=az, latitude=latitude)
                for az in arange(0, 360.5, 1)
            ]
            for i, p in enumerate(path):
                r_b = radius(dec=p[1] / unit_deg, latitude=latitude)
                if i == 0:
                    context.move_to(**pos(r_b, p[0]))
                else:
                    context.line_to(**pos(r_b, p[0]))
        context.stroke(color=(0.5, 0.5, 0.5, 1))

        # Draw lines marking S,SSE,SE,ESE,E, etc
        context.begin_path()
        for az in arange(0, 359, 22.5):
            path = [
                transform(alt=alt, az=az, latitude=latitude)
                for alt in arange(0, 90.1, 1)
            ]
            for i, p in enumerate(path):
                r_b = radius(dec=p[1] / unit_deg, latitude=latitude)
                if i == 0:
                    context.move_to(**pos(r_b, p[0]))
                else:
                    context.line_to(**pos(r_b, p[0]))
        context.stroke(color=(0.5, 0.5, 0.5, 1))

        # Gluing labels
        def make_gluing_label(azimuth):
            pp = transform(alt=0, az=azimuth - 0.01, latitude=latitude)
            r = radius(dec=pp[1] / unit_deg, latitude=latitude)
            p = pos(r, pp[0])

            pp2 = transform(alt=0, az=azimuth + 0.01, latitude=latitude)
            r2 = radius(dec=pp2[1] / unit_deg, latitude=latitude)
            p2 = pos(r2, pp2[0])

            p3 = [p2[i] - p[i] for i in ('x', 'y')]
            tr = -unit_rev / 4 - atan2(p3[0], p3[1])

            context.text(text=text[language]["glue_here"],
                         x=p['x'],
                         y=p['y'],
                         h_align=0,
                         v_align=1,
                         gap=unit_mm,
                         rotation=tr)

        context.set_font_style(bold=True)
        context.set_color(color=(0, 0, 0, 1))
        make_gluing_label(azimuth=0)
        make_gluing_label(azimuth=90)
        make_gluing_label(azimuth=180)
        make_gluing_label(azimuth=270)
예제 #10
0
    def do_rendering(self, settings, context):
        """
        This method is required to actually render this item.

        :param settings:
            A dictionary of settings required by the renderer.
        :param context:
            A GraphicsContext object to use for drawing
        :return:
            None
        """

        is_southern = settings['latitude'] < 0
        language = settings['language']
        latitude = abs(settings['latitude'])
        theme = themes[settings['theme']]

        context.set_font_size(1.2)

        r_2 = r_1 - r_gap
        r_3 = r_1 * 0.1 + r_2 * 0.9
        r_4 = r_1 * 0.2 + r_2 * 0.8
        r_5 = r_1
        r_6 = r_1 * 0.4 + r_2 * 0.6

        context.begin_path()
        context.circle(centre_x=0, centre_y=0, radius=r_1)  # Outer edge of planisphere
        context.fill(color=theme['background'])
        context.begin_sub_path()
        context.circle(centre_x=0, centre_y=0, radius=central_hole_size)  # White out central hole
        context.stroke(color=theme['edge'])
        context.clip()

        for dec in arange(-80, 85, 15):
            r = radius(dec=dec, latitude=latitude)
            if r > r_2:
                continue
            context.begin_path()
            context.circle(centre_x=0, centre_y=0, radius=r)
            context.stroke(color=theme['grid'])

        # Draw constellation stick figures
        for line in open("raw_data/constellation_stick_figures.dat", "rt"):
            line = line.strip()

            # Ignore blank lines and comment lines
            if (len(line) == 0) or (line[0] == '#'):
                continue

            # Split line into words
            [name, ra1, dec1, ra2, dec2] = line.split()

            if is_southern:
                ra1 = -float(ra1)
                ra2 = -float(ra2)
                dec1 = -float(dec1)
                dec2 = -float(dec2)

            r_point_1 = radius(dec=float(dec1), latitude=latitude)
            if r_point_1 > r_2:
                continue

            r_point_2 = radius(dec=float(dec2), latitude=latitude)
            if r_point_2 > r_2:
                continue

            p1 = (-r_point_1 * cos(float(ra1) * unit_deg), -r_point_1 * sin(float(ra1) * unit_deg))
            p2 = (-r_point_2 * cos(float(ra2) * unit_deg), -r_point_2 * sin(float(ra2) * unit_deg))

            # Impose a maximum length of 4 cm on constellation stick figures; they get quite distored at the edge
            if hypot(p2[0] - p1[0], p2[1] - p1[1]) > 4 * unit_cm:
                continue

            context.begin_path()
            context.move_to(x=p1[0], y=p1[1])
            context.line_to(x=p2[0], y=p2[1])
            context.stroke(color=theme['stick'], line_width=1, dotted=True)

        # Draw stars from Yale Bright Star Catalogue
        for star_descriptor in fetch_bright_star_list()['stars'].values():
            [ra, dec, mag] = star_descriptor[:3]

            # Discard stars fainter than mag 4
            if mag == "-" or float(mag) > 4.0:
                continue

            ra = float(ra)
            dec = float(dec)
            if is_southern:
                ra *= -1
                dec *= -1

            r = radius(dec=dec, latitude=latitude)
            if r > r_2:
                continue
            context.begin_path()
            context.circle(centre_x=-r * cos(ra * unit_deg), centre_y=-r * sin(ra * unit_deg),
                           radius=0.18 * unit_mm * (5 - mag))
            context.fill(color=theme['star'])

        # Write constellation names
        context.set_font_size(0.7)
        context.set_color(theme['constellation'])

        for line in open("raw_data/constellation_names.dat"):
            line = line.strip()

            # Ignore blank lines and comment lines
            if (len(line) == 0) or (line[0] == '#'):
                continue

            # Split line into words
            [name, ra, dec] = line.split()[:3]

            # Translate constellation name, if required
            if name in text[language]['constellation_translations']:
                name = text[language]['constellation_translations'][name]

            ra = float(ra) * 360. / 24
            dec = float(dec)

            if is_southern:
                ra = -ra
                dec = -dec

            name2 = re.sub("_", " ", name)
            r = radius(dec=dec, latitude=latitude)
            if r > r_2:
                continue
            p = (-r * cos(ra * unit_deg), -r * sin(ra * unit_deg))
            a = atan2(p[0], p[1])
            context.text(text=name2, x=p[0], y=p[1], h_align=0, v_align=0, gap=0, rotation=unit_rev / 2 - a)

        # Calendar ring counts clockwise in northern hemisphere; anticlockwise in southern hemisphere
        s = -1 if not is_southern else 1

        def theta2014(d):
            """
            Convert Julian Day into a rotation angle of the sky about the NCP at midnight, relative to spring equinox.

            :param d:
                Julian day
            :return:
                Rotation angle, radians
            """
            return (d - calendar.julian_day(year=2014, month=3, day=20, hour=16, minute=55, sec=0)) / 365.25 * unit_rev

        # Write month names
        context.set_font_size(1.8)
        context.set_color(theme['date'])
        for mn, (mlen, name) in enumerate(text[language]['months']):
            theta = s * theta2014(calendar.julian_day(year=2014, month=mn+1, day=mlen // 2, hour=12, minute=0, sec=0))

            # We supply circular_text with a negative radius here, as a fudge to orientate the text with bottom-inwards
            context.circular_text(text=name, centre_x=0, centre_y=0, radius=-(r_1 * 0.65 + r_2 * 0.35),
                                  azimuth=theta / unit_deg + 180,
                                  spacing=1, size=1)

        # Write day ticks
        for mn, (mlen, name) in enumerate(text[language]['months']):
            # Tick marks
            for d in range(1, mlen + 1):
                theta = s * theta2014(calendar.julian_day(year=2014, month=mn+1, day=d, hour=0, minute=0, sec=0))
                R = r_3 if (d % 5) else r_4  # Multiples of 5 get longer ticks
                if d == mlen:
                    R = r_5
                context.begin_path()
                context.move_to(x=r_2 * cos(theta), y=-r_2 * sin(theta))
                context.line_to(x=R * cos(theta), y=-R * sin(theta))
                context.stroke(line_width=1, dotted=False)

            # Numeric labels
            for d in [10, 20, mlen]:
                theta = s * theta2014(calendar.julian_day(year=2014, month=mn+1, day=d, hour=0, minute=0, sec=0))
                context.set_font_size(1.0)
                theta2 = theta + 0.15 * unit_deg
                context.text(text="%d" % (d / 10), x=r_6 * cos(theta2), y=-r_6 * sin(theta2),
                             h_align=1, v_align=0,
                             gap=0,
                             rotation=-theta + pi/2)
                theta2 = theta - 0.15 * unit_deg
                context.text(text="%d" % (d % 10), x=r_6 * cos(theta2), y=-r_6 * sin(theta2),
                             h_align=-1, v_align=0,
                             gap=0,
                             rotation=-theta + pi/2)

        context.begin_path()
        context.circle(centre_x=0, centre_y=0, radius=r_2)
        context.stroke(color=theme['date'], line_width=1, dotted=False)