绘制月初新月:实现亮面始终朝向太阳的代码修正需求
问题描述
我制作了一个月球绘图示例,通过两个圆形叠加的方式绘制月初新月——上方圆形用于遮挡月球不可见的暗部。目前存在的问题是:实际中月球亮面的中心始终朝向太阳中心,但我无法实现这一动态调整效果。
示例场景:
- 日落时太阳方位角为180°、高度角为0°,若月球方位角同样为180°、高度角为10°,月球亮面应朝向下方的太阳;
- 当月球方位角改为150°时,亮面应朝向右下方的太阳。
恳请协助修正代码,使修改太阳方位角时,月球亮面能自动调整,始终朝向太阳。
原示例代码:
import matplotlib.pyplot as plt import numpy as np from matplotlib.patches import Circle, Wedge # Set the coordinates for Jerusalem longitude = 35.2137 # Jerusalem's longitude latitude = 31.7683 # Jerusalem's latitude # Set the time for the observation observation_time = '19:00' # Time in HH:MM format # Set the positions of the sun and the moon sun_altitude = 0 # Sun's altitude in degrees sun_azimuth = 280 # Sun's azimuth in degrees moon_altitude = 30 # Moon's altitude in degrees moon_azimuth = 280 # Moon's azimuth in degrees #moon_azimuth = 265 # Moon's azimuth in degrees # Create a figure and axes fig, ax = plt.subplots() # Set the background color background_color = "lightblue" fig.patch.set_facecolor(background_color) ax.set_facecolor(background_color) # Set the x-axis limits to represent the western horizon ax.set_xlim(sun_azimuth-30, sun_azimuth+30) ax.set_ylim(0, 40) radius = 5 # Plot the sun and the moon sun_center = (sun_azimuth, sun_altitude) sun_circle = Circle(sun_center, radius, color='orange') ax.add_patch(sun_circle) moon_center = (moon_azimuth, moon_altitude) moon_circle = Circle(moon_center, radius, color='white') ax.add_patch(moon_circle) #moon_bright_center = (moon_azimuth-0.5, moon_altitude+0.5) # if moon_azimuth == 265 and sun_azimuth == 280 moon_bright_center = (moon_azimuth, moon_altitude+0.8) # if moon_azimuth == 280 and sun_azimuth == 280 moon_bright = Circle(moon_bright_center, radius+0.5, color=background_color) ax.add_patch(moon_bright) # Set the title and labels ax.set_title(f'Western Horizon in Jerusalem on {observation_time}') ax.set_xlabel("Azimuth") ax.set_ylabel("Altitude") plt.grid() # Set the aspect ratio to equal ax.set_aspect('equal') # Show the plot plt.show()
解决方案
核心思路是通过计算太阳与月球的相对位置向量,动态确定遮挡圆的位置,确保遮挡住月球背离太阳的暗部,让亮面始终朝向太阳。修改后的代码如下:
import matplotlib.pyplot as plt import numpy as np from matplotlib.patches import Circle, Wedge # 耶路撒冷坐标 longitude = 35.2137 latitude = 31.7683 # 观测时间 observation_time = '19:00' # 太阳与月球位置参数 sun_altitude = 0 # 太阳高度角(度) sun_azimuth = 280 # 太阳方位角(度) moon_altitude = 30 # 月球高度角(度) moon_azimuth = 265 # 月球方位角(度),可修改测试效果 # 创建画布与坐标轴 fig, ax = plt.subplots() # 设置背景色 background_color = "lightblue" fig.patch.set_facecolor(background_color) ax.set_facecolor(background_color) # 设置坐标轴范围 ax.set_xlim(sun_azimuth-30, sun_azimuth+30) ax.set_ylim(0, 40) radius = 5 # 绘制太阳 sun_center = (sun_azimuth, sun_altitude) sun_circle = Circle(sun_center, radius, color='orange') ax.add_patch(sun_circle) # 绘制月球 moon_center = (moon_azimuth, moon_altitude) moon_circle = Circle(moon_center, radius, color='white') ax.add_patch(moon_circle) # 计算太阳相对于月球的方向向量,动态确定遮挡圆位置 dx = sun_azimuth - moon_azimuth dy = sun_altitude - moon_altitude dist = np.sqrt(dx**2 + dy**2) # 避免太阳与月球位置重合时的除零错误 if dist != 0: # 归一化方向向量 nx = dx / dist ny = dy / dist else: # 默认朝向下方(太阳在地平线) nx = 0 ny = -1 # 遮挡圆偏移量(控制遮挡范围,可根据需求调整) offset = 0.8 # 遮挡圆位于月球背离太阳的一侧 moon_bright_center = (moon_center[0] - nx * offset, moon_center[1] - ny * offset) moon_bright = Circle(moon_bright_center, radius + 0.5, color=background_color) ax.add_patch(moon_bright) # 设置标题与坐标轴标签 ax.set_title(f'耶路撒冷西部地平线 {observation_time}') ax.set_xlabel("方位角") ax.set_ylabel("高度角") plt.grid() # 设置等比例坐标轴 ax.set_aspect('equal') # 显示绘图 plt.show()
关键修改说明
- 动态计算方向向量:通过太阳与月球的坐标差,计算出从月球指向太阳的归一化方向向量,确保方向精准;
- 遮挡圆位置动态调整:将遮挡圆设置在月球背离太阳的一侧,未被遮挡的区域自然就是朝向太阳的亮面;
- 边界处理:增加了太阳与月球位置重合时的默认方向,避免计算错误。
效果验证
修改sun_azimuth或moon_azimuth参数后,月球亮面会自动朝向太阳:
- 当太阳方位角180°、月球方位角180°时,亮面朝向下方的太阳;
- 当月球方位角改为150°时,亮面会朝向右下方的太阳。
内容的提问来源于stack exchange,提问作者Dr. Simcha Gershon Bohrer
相关产品推荐
相关产品推荐

