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
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
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
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
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()