Esempio n. 1
0
    def getSunMoonCenter(self, p):
        # Get the center of the sun and the moon in screen pixels
        dt, sun_alt, sun_az, moon_alt, moon_az, sun_r, moon_r, sep, parallactic_angle, lat, lon = p
        sun_coords = horizontal_to_cartesian(deg(sun_alt), deg(sun_az))
        sun_x, sun_y, sun_z = scale_vector(sun_coords, SUN_EARTH_DISTANCE)
        moon_coords = horizontal_to_cartesian(deg(moon_alt), deg(moon_az))
        moon_x, moon_y, moon_z = scale_vector(moon_coords, EARTH_MOON_DISTANCE)

        self.setupProjection(sun_x, sun_y, sun_z)
        sun_center = gluProject(sun_x, sun_y, sun_z)
        moon_center = gluProject(moon_x, moon_y, moon_z)

        return sun_center, moon_center
Esempio n. 2
0
    def getSunSize(self, p):
        """Get the size of the sun in screen pixels.

        This is a hack: it renders the sun, then finds the contour
        surrounding the sun and computes the center/radius of that.
        """
        self.fbo.bind()
        self.clear_background()
        self.fbo.release()
        dt, sun_alt, sun_az, moon_alt, moon_az, sun_r, moon_r, sep, parallactic_angle, lat, lon = p
        sun_coords = horizontal_to_cartesian(deg(sun_alt), deg(sun_az))
        sun_x, sun_y, sun_z = scale_vector(sun_coords, SUN_EARTH_DISTANCE)
        self.fbo.bind()
        self.draw_sun(sun_x, sun_y, sun_z)
        glFlush()
        self.fbo.release()
        image = self.fbo.toImage()
        # Find the contours of the sun in the image
        contours = self.find_contours(image)
        # Make a poly that fits the contour
        poly = cv2.approxPolyDP(np.array(contours[0]), 3, True)
        # Find the minimum enclosing circle of the polygon
        c = cv2.minEnclosingCircle(poly)
        self.fbo.bind()
        self.clear_background()
        self.fbo.release()
        return c
Esempio n. 3
0
    def paint(self, p):
        # Get the potion and time parameters for this frame of rendering
        dt, sun_alt, sun_az, moon_alt, moon_az, sun_r, moon_r, sep, parallactic_angle, lat, lon = p
        sun_coords = horizontal_to_cartesian(deg(sun_alt), deg(sun_az))
        sun_x, sun_y, sun_z = scale_vector(sun_coords, SUN_EARTH_DISTANCE)
        moon_coords = horizontal_to_cartesian(deg(moon_alt), deg(moon_az))
        moon_x, moon_y, moon_z = scale_vector(moon_coords, EARTH_MOON_DISTANCE)
        # Set up the appropriate viewing projection
        self.setupProjection(sun_x, sun_y, sun_z)

        self.clear_background()

        # Draw the corona first as a background layer
        self.draw_corona(p)

        # Draw the sun and moon on top of the corona
        self.paintGL(sun_x, sun_y, sun_z, moon_x, moon_y, moon_z)

        image = self.fbo.toImage()

        return image
Esempio n. 4
0
    def getSunSizeProj(self, p):
        """Get the size of the sun in screen pixels.

        Warning: this function doesn't work correctly, unless the sun
        is positioned appropriately.  Use getSunSize instead.
        """
        dt, sun_alt, sun_az, moon_alt, moon_az, sun_r, moon_r, sep, parallactic_angle = p
        sun_coords = horizontal_to_cartesian(deg(sun_alt), deg(sun_az))
        sun_x, sun_y, sun_z = scale_vector(sun_coords, SUN_EARTH_DISTANCE)

        self.setupProjection(sun_x, sun_y, sun_z)
        x0 = gluProject(sun_x, sun_y, sun_z)
        x1 = gluProject(sun_x - SUN_RADIUS, sun_y, sun_z)

        # Return the distance between two suns spaced by solar radius,
        # in screen pixels
        x = abs(x1[0] - x0[0])
        return x
Esempio n. 5
0
    def draw_corona(self, p):
        im_polar = np.zeros((RES_Y, RES_X, 4), np.uint8)
        dt, sun_alt, sun_az, moon_alt, moon_az, sun_r, moon_r, sep, parallactic_angle, lat, lon = p
        sun_coords = horizontal_to_cartesian(deg(sun_alt), deg(sun_az))
        sun_x, sun_y, sun_z = scale_vector(sun_coords, SUN_EARTH_DISTANCE)
        sun_center, sun_size = self.getSunSize(p)

        circle_center = (int(sun_center[0]), int(sun_center[1]))
        circle_size = int(sun_size)
        circle_color = (255, 255, 255, 255)

        # Draw coronal polar angle lines as bundles of truncated ellipses.
        # The ellipses start at the sun surface and project outward
        # towards the poles, then curve away
        # TODO(dek): better curving, especially angle-dependent curves
        for i, angle in enumerate(self.polar_coronal_angles):
            for j in self.polar_coronal_subangles[i]:
                x = int(circle_center[0] + math.cos(angle) * circle_size)
                y = int(circle_center[1] + math.sin(angle) * circle_size)
                cv2.ellipse(im_polar, (x, y),
                            (int(circle_size * 8), int(circle_size / 8.)),
                            deg(angle) + j, 0, 90, (255, 255, 255, 127))
        blur_polar = cv2.blur(im_polar, (5, 5))

        # Draw the coronal equatorial regions as polygons that get
        # skinnier as they get further from the sun's surface
        im_equitorial = np.zeros((RES_Y, RES_X, 4), np.uint8)
        for i, angle in enumerate(self.equatorial_coronal_angles):
            min_ = angle - math.radians(15)
            min_2 = angle - math.radians(5)
            max_2 = angle + math.radians(5)
            max_ = angle + math.radians(15)

            x1 = int(circle_center[0] + math.cos(min_) * circle_size)
            y1 = int(circle_center[1] + math.sin(min_) * circle_size)
            x1_2 = int((circle_center[0] + math.cos(min_) * circle_size * 2))
            y1_2 = int((circle_center[1] + math.sin(min_) * circle_size * 2))

            x2 = int((circle_center[0] + math.cos(min_2) * circle_size * 4))
            y2 = int((circle_center[1] + math.sin(min_2) * circle_size * 4))

            x3 = int((circle_center[0] + math.cos(angle) * circle_size * 6))
            y3 = int((circle_center[1] + math.sin(angle) * circle_size * 6))

            x4 = int((circle_center[0] + math.cos(max_2) * circle_size * 4))
            y4 = int((circle_center[1] + math.sin(max_2) * circle_size * 4))

            x5_2 = int((circle_center[0] + math.cos(max_) * circle_size * 2))
            y5_2 = int((circle_center[1] + math.sin(max_) * circle_size * 2))
            x5 = int(circle_center[0] + math.cos(max_) * circle_size)
            y5 = int(circle_center[1] + math.sin(max_) * circle_size)

            pts = np.array([[x1, y1], [x1_2, y1_2], [x2, y2], [x3, y3],
                            [x4, y4], [x5_2, y5_2], [x5, y5]])

            cv2.fillConvexPoly(im_equitorial, pts, (255, 255, 255, 127))

        # Blur the equatorial corona
        blur_equitorial = cv2.blur(im_equitorial, (100, 100))

        # Create a blurred sun to simulate glare
        im_corona_positive = np.zeros((RES_Y, RES_X, 4), np.uint8)
        cv2.circle(im_corona_positive, circle_center, int(circle_size * 3),
                   [255, 255, 255, 127], -1)
        blur_corona_positive = cv2.blur(
            im_corona_positive,
            (int(circle_size * 1.5), int(circle_size * 1.5)))
        blur_corona_positive = cv2.blur(
            blur_corona_positive,
            (int(circle_size * 1.25), int(circle_size * 1.25)))
        # Subtract out the center of the glare
        cv2.circle(blur_corona_positive, circle_center, circle_size,
                   [0, 0, 0, 255], -1)

        alpha = 1
        beta = 0.15
        # Combine the blurred polar corona with the glare
        result = cv2.addWeighted(blur_polar, alpha, blur_corona_positive, beta,
                                 0.0)
        # Combine that with the equitorial blur
        result2 = cv2.addWeighted(result, 1, blur_equitorial, 1, 0.0)

        # Render the solar corona to the screen
        self.fbo.bind()
        device = QtGui.QOpenGLPaintDevice(RES_X, RES_Y)
        painter = QtGui.QPainter()
        h, w, b = result2.shape
        painter.begin(device)
        # Apply parallactic rotation to the corona
        painter.translate(w / 2, h / 2)
        painter.rotate(math.degrees(parallactic_angle))
        painter.translate(-w / 2, -h / 2)
        image = QtGui.QImage(result2.data, w, h, QtGui.QImage.Format_ARGB32)
        image = image.rgbSwapped()
        rect = QtCore.QRect(0, 0, RES_X, RES_Y)
        painter.drawImage(rect, image, rect)
        painter.end()
        self.fbo.release()