You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

绘制月初新月:实现亮面始终朝向太阳的代码修正需求

问题描述

我制作了一个月球绘图示例,通过两个圆形叠加的方式绘制月初新月——上方圆形用于遮挡月球不可见的暗部。目前存在的问题是:实际中月球亮面的中心始终朝向太阳中心,但我无法实现这一动态调整效果。

示例场景:

  • 日落时太阳方位角为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()
关键修改说明
  1. 动态计算方向向量:通过太阳与月球的坐标差,计算出从月球指向太阳的归一化方向向量,确保方向精准;
  2. 遮挡圆位置动态调整:将遮挡圆设置在月球背离太阳的一侧,未被遮挡的区域自然就是朝向太阳的亮面;
  3. 边界处理:增加了太阳与月球位置重合时的默认方向,避免计算错误。
效果验证

修改sun_azimuth或moon_azimuth参数后,月球亮面会自动朝向太阳:

  • 当太阳方位角180°、月球方位角180°时,亮面朝向下方的太阳;
  • 当月球方位角改为150°时,亮面会朝向右下方的太阳。

内容的提问来源于stack exchange,提问作者Dr. Simcha Gershon Bohrer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 11:34:55