实例介绍
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Linq;
namespace InnerSolarSystemSimulation
{
public partial class InnerSolarSystemForm : Form
{
private Timer animationTimer;
private List<CelestialBody> bodies;
private Bitmap canvas;
private Graphics graphics;
private Font labelFont;
private Font smallFont;
// 放大缩放因子
private const float DistanceScale = 150.0f; // 从80增加到150,放大轨迹
private const float PlanetSizeScale = 4000.0f; // 增加行星大小
private const float MoonDistanceScale = 8.0f; // 增加月球轨道显示大小
public InnerSolarSystemForm()
{
InitializeComponent();
InitializeSolarSystem();
InitializeCanvas();
SetupTimer();
}
private void InitializeComponent()
{
this.Text = "内太阳系模拟 - 含月球轨道 (放大版)";
this.Size = new Size(1400, 1000); // 增加窗体大小
this.DoubleBuffered = true;
this.BackColor = Color.Black;
}
private void InitializeSolarSystem()
{
bodies = new List<CelestialBody>();
// 太阳109f
bodies.Add(new CelestialBody("太阳", 0, 0, 50f, 0, 0, Color.Yellow, true));
// 行星数据:名称, 半长轴(AU), 公转周期(年), 半径(地球半径), 偏心率, 颜色
// 水星
bodies.Add(new CelestialBody("水星", 0.387f, 0.241f, 0.383f, 0.2056f, 0, Color.LightGray));
// 金星
bodies.Add(new CelestialBody("金星", 0.723f, 0.615f, 0.949f, 0.0068f, 0, Color.Goldenrod));
// 地球(包含月球)
CelestialBody earth = new CelestialBody("地球", 1.000f, 1.000f, 1.000f, 0.0167f, 0, Color.DodgerBlue);
// 添加月球作为地球的卫星 - 使用更精确的月球数据
earth.AddMoon(new Moon("月球", 0.02257f, 0.0748f, 0.2727f, 0.0549f, Color.LightGray));
bodies.Add(earth);
// 火星
bodies.Add(new CelestialBody("火星", 1.524f, 1.881f, 0.532f, 0.0934f, 0, Color.OrangeRed));
labelFont = new Font("Arial", 10, FontStyle.Bold);
smallFont = new Font("Arial", 8);
}
private void InitializeCanvas()
{
canvas = new Bitmap(ClientSize.Width, ClientSize.Height);
graphics = Graphics.FromImage(canvas);
}
private void SetupTimer()
{
animationTimer = new Timer();
animationTimer.Interval = 20;
animationTimer.Tick = (s, e) =>
{
UpdatePositions();
Invalidate();
};
animationTimer.Start();
}
private void UpdatePositions()
{
foreach (var body in bodies)
{
if (!body.IsSun)
{
body.UpdatePosition(0.002); // 调整时间步长
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (canvas == null || canvas.Width != ClientSize.Width || canvas.Height != ClientSize.Height)
{
InitializeCanvas();
}
graphics.Clear(Color.Black);
DrawSolarSystem(graphics);
e.Graphics.DrawImage(canvas, 0, 0);
}
private void DrawSolarSystem(Graphics g)
{
int centerX = ClientSize.Width / 2;
int centerY = ClientSize.Height / 2;
// 绘制所有轨道
foreach (var body in bodies)
{
if (!body.IsSun)
{
DrawBodyOrbit(g, body, centerX, centerY);
}
}
// 绘制所有天体
foreach (var body in bodies)
{
DrawCelestialBody(g, body, centerX, centerY);
}
// 绘制图例
DrawLegend(g);
}
private void DrawBodyOrbit(Graphics g, CelestialBody body, int centerX, int centerY)
{
// 绘制行星轨道
float semiMajorAxis = body.SemiMajorAxis * DistanceScale;
float semiMinorAxis = semiMajorAxis * (float)Math.Sqrt(1 - body.Eccentricity * body.Eccentricity);
float focusDistance = semiMajorAxis * body.Eccentricity;
RectangleF orbitRect = new RectangleF(
centerX - semiMajorAxis focusDistance,
centerY - semiMinorAxis,
semiMajorAxis * 2,
semiMinorAxis * 2
);
using (Pen orbitPen = new Pen(Color.FromArgb(100, body.Color), 1.5f)) // 加粗轨道线
{
g.DrawEllipse(orbitPen, orbitRect);
}
// 如果天体有卫星,绘制卫星轨道
if (body.HasMoon)
{
PointF bodyPosition = body.GetPosition(centerX, centerY, DistanceScale);
float moonOrbitRadius = body.Moon.SemiMajorAxis * DistanceScale * MoonDistanceScale;
// 绘制月球椭圆轨道
float moonSemiMajorAxis = moonOrbitRadius;
float moonSemiMinorAxis = moonOrbitRadius * (float)Math.Sqrt(1 - body.Moon.Eccentricity * body.Moon.Eccentricity);
float moonFocusDistance = moonSemiMajorAxis * body.Moon.Eccentricity;
RectangleF moonOrbitRect = new RectangleF(
bodyPosition.X - moonSemiMajorAxis moonFocusDistance,
bodyPosition.Y - moonSemiMinorAxis,
moonSemiMajorAxis * 2,
moonSemiMinorAxis * 2
);
using (Pen moonOrbitPen = new Pen(Color.FromArgb(80, Color.LightBlue), 1f))
{
g.DrawEllipse(moonOrbitPen, moonOrbitRect);
}
}
}
private void DrawCelestialBody(Graphics g, CelestialBody body, int centerX, int centerY)
{
if (body.IsSun)
{
// 绘制太阳
float sunSize = Math.Max(30, body.Radius * PlanetSizeScale / 3000f);
g.FillEllipse(Brushes.Yellow, centerX - sunSize / 2, centerY - sunSize / 2, sunSize, sunSize);
g.DrawString(body.Name, labelFont, Brushes.White, centerX - 15, centerY sunSize / 2 5);
return;
}
// 绘制行星
PointF position = body.GetPosition(centerX, centerY, DistanceScale);
float size = Math.Max(5, body.Radius * PlanetSizeScale / 100f);
size = Math.Min(size, 35); // 增加最大尺寸
// 绘制行星(带光晕效果)
g.FillEllipse(new SolidBrush(body.Color), position.X - size / 2, position.Y - size / 2, size, size);
g.DrawEllipse(new Pen(Color.White, 1), position.X - size / 2, position.Y - size / 2, size, size);
// 绘制行星名称
g.DrawString(body.Name, labelFont, Brushes.White, position.X size 2, position.Y - 8);
// 绘制轨迹
DrawBodyTrail(g, body, centerX, centerY);
// 绘制卫星(如果有)
if (body.HasMoon)
{
DrawMoon(g, body, position);
}
}
private void DrawMoon(Graphics g, CelestialBody planet, PointF planetPosition)
{
PointF moonPosition = planet.Moon.GetPositionRelativeToPlanet(planetPosition, MoonDistanceScale * DistanceScale);
float moonSize = Math.Max(3, planet.Moon.Radius * PlanetSizeScale / 100f);
// 绘制月球
g.FillEllipse(new SolidBrush(planet.Moon.Color),
moonPosition.X - moonSize / 2,
moonPosition.Y - moonSize / 2,
moonSize,
moonSize);
// 在月球旁边显示名称
if (planet.Name == "地球")
{
g.DrawString(planet.Moon.Name, smallFont, Brushes.White, moonPosition.X moonSize 2, moonPosition.Y - 6);
}
// 绘制月球轨迹
DrawMoonTrail(g, planet, planetPosition);
}
private void DrawBodyTrail(Graphics g, CelestialBody body, int centerX, int centerY)
{
if (body.PositionHistory.Count < 2) return;
using (Pen trailPen = new Pen(Color.FromArgb(120, body.Color), 1.5f))
{
for (int i = 0; i < body.PositionHistory.Count - 1; i )
{
PointF p1 = body.PositionHistory[i];
PointF p2 = body.PositionHistory[i 1];
g.DrawLine(trailPen, p1, p2);
}
}
}
private void DrawMoonTrail(Graphics g, CelestialBody planet, PointF planetPosition)
{
if (planet.Moon.PositionHistory.Count < 2) return;
using (Pen trailPen = new Pen(Color.FromArgb(100, Color.Cyan), 1f))
{
for (int i = 0; i < planet.Moon.PositionHistory.Count - 1; i )
{
PointF p1 = planet.Moon.PositionHistory[i];
PointF p2 = planet.Moon.PositionHistory[i 1];
g.DrawLine(trailPen, p1, p2);
}
}
}
private void DrawLegend(Graphics g)
{
int startX = 20;
int startY = 20;
g.DrawString("内太阳系模拟 - 放大版",
new Font("Arial", 16, FontStyle.Bold),
Brushes.White, startX, startY);
g.DrawString("太阳 水星 金星 地球 月球 火星",
new Font("Arial", 10), Brushes.LightGray, startX, startY 30);
// 显示数据表格
DrawDataTable(g, startX, startY 70);
// 显示月球轨道说明
DrawMoonInfo(g, startX 400, startY 70);
}
private void DrawDataTable(Graphics g, int startX, int startY)
{
g.DrawString("天体轨道数据:", new Font("Arial", 11, FontStyle.Bold),
Brushes.White, startX, startY);
// 表头
g.DrawString("天体", new Font("Arial", 9, FontStyle.Bold), Brushes.Yellow, startX, startY 25);
g.DrawString("轨道半径(AU)", new Font("Arial", 9, FontStyle.Bold), Brushes.Yellow, startX 80, startY 25);
g.DrawString("偏心率", new Font("Arial", 9, FontStyle.Bold), Brushes.Yellow, startX 180, startY 25);
g.DrawString("公转周期", new Font("Arial", 9, FontStyle.Bold), Brushes.Yellow, startX 250, startY 25);
int row = 0;
foreach (var body in bodies)
{
if (body.IsSun) continue;
int rowY = startY 45 (row * 20);
g.DrawString(body.Name, labelFont, new SolidBrush(body.Color), startX, rowY);
g.DrawString($"{body.SemiMajorAxis:F3}", labelFont, Brushes.White, startX 80, rowY);
g.DrawString(body.Eccentricity.ToString("F4"), labelFont, Brushes.White, startX 180, rowY);
g.DrawString($"{body.OrbitalPeriod:F3} 年", labelFont, Brushes.White, startX 250, rowY);
row ;
// 显示月球数据
if (body.HasMoon)
{
int moonRowY = startY 45 (row * 20);
g.DrawString("↳ " body.Moon.Name, smallFont, new SolidBrush(body.Moon.Color), startX 20, moonRowY);
g.DrawString($"{body.Moon.SemiMajorAxis:F5}", smallFont, Brushes.LightGray, startX 80, moonRowY);
g.DrawString(body.Moon.Eccentricity.ToString("F4"), smallFont, Brushes.LightGray, startX 180, moonRowY);
g.DrawString($"{body.Moon.OrbitalPeriod:F3} 年", smallFont, Brushes.LightGray, startX 250, moonRowY);
g.DrawString($"(约{Math.Round(body.Moon.OrbitalPeriod * 365.25)} 天)", new Font("Arial", 7), Brushes.Gray, startX 320, moonRowY);
row ;
}
}
}
private void DrawMoonInfo(Graphics g, int startX, int startY)
{
string moonInfo = "月球轨道信息:\n\n"
"• 真实月球轨道数据:\n"
" - 平均距离: 384,400 km\n"
" - 相对于地球: 0.00257 AU\n"
" - 偏心率: 0.0549\n"
" - 公转周期: 27.3 天\n\n"
"• 模拟中的显示:\n"
" - 月球轨道已放大显示\n"
" - 保持正确的椭圆形状\n"
" - 相对速度正确\n\n"
"• 观察要点:\n"
" - 月球每月绕地球一圈\n"
" - 轨道是椭圆形\n"
" - 在近地点运动较快";
g.DrawString(moonInfo, new Font("Arial", 9), Brushes.LightGreen, startX, startY);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
InitializeCanvas();
Invalidate();
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
animationTimer?.Stop();
graphics?.Dispose();
canvas?.Dispose();
labelFont?.Dispose();
smallFont?.Dispose();
foreach (var body in bodies)
{
body.Dispose();
}
}
}
public class CelestialBody : IDisposable
{
public string Name { get; set; }
public float SemiMajorAxis { get; set; }
public float OrbitalPeriod { get; set; }
public float Radius { get; set; }
public float Eccentricity { get; set; }
public float Inclination { get; set; }
public Color Color { get; set; }
public bool IsSun { get; set; }
public Moon Moon { get; private set; }
public bool HasMoon => Moon != null;
private double meanAnomaly;
private List<PointF> positionHistory;
private const int maxHistoryLength = 400; // 增加轨迹长度
public CelestialBody(string name, float semiMajorAxis, float orbitalPeriod,
float radius, float eccentricity, float inclination, Color color, bool isSun = false)
{
Name = name;
SemiMajorAxis = semiMajorAxis;
OrbitalPeriod = orbitalPeriod;
Radius = radius;
Eccentricity = eccentricity;
Inclination = inclination;
Color = color;
IsSun = isSun;
meanAnomaly = new Random().NextDouble() * 2 * Math.PI;
positionHistory = new List<PointF>();
}
public void AddMoon(Moon moon)
{
Moon = moon;
}
public void UpdatePosition(double timeStep)
{
// 更新行星位置
if (!IsSun)
{
double meanMotion = 2 * Math.PI / OrbitalPeriod;
meanAnomaly = meanMotion * timeStep;
if (meanAnomaly > 2 * Math.PI)
meanAnomaly -= 2 * Math.PI;
}
// 更新月球位置(如果存在)
Moon?.UpdatePosition(timeStep);
}
public PointF GetPosition(int centerX, int centerY, float scale)
{
if (IsSun) return new PointF(centerX, centerY);
double eccentricAnomaly = SolveKeplerEquation(meanAnomaly, Eccentricity);
double xOrbit = SemiMajorAxis * (Math.Cos(eccentricAnomaly) - Eccentricity);
double yOrbit = SemiMajorAxis * Math.Sqrt(1 - Eccentricity * Eccentricity) * Math.Sin(eccentricAnomaly);
float focusOffset = SemiMajorAxis * Eccentricity * scale;
float x = centerX (float)xOrbit * scale focusOffset;
float y = centerY (float)yOrbit * scale;
PointF position = new PointF(x, y);
positionHistory.Add(position);
if (positionHistory.Count > maxHistoryLength)
{
positionHistory.RemoveAt(0);
}
return position;
}
public List<PointF> PositionHistory => positionHistory;
private double SolveKeplerEquation(double meanAnomaly, double eccentricity)
{
double eccentricAnomaly = meanAnomaly;
double delta = 1.0;
double tolerance = 1e-8; // 提高精度
int maxIterations = 100;
int iterations = 0;
while (Math.Abs(delta) > tolerance && iterations < maxIterations)
{
delta = (eccentricAnomaly - eccentricity * Math.Sin(eccentricAnomaly) - meanAnomaly) /
(1 - eccentricity * Math.Cos(eccentricAnomaly));
eccentricAnomaly -= delta;
iterations ;
}
return eccentricAnomaly;
}
public void Dispose()
{
positionHistory?.Clear();
Moon?.Dispose();
}
}
public class Moon : IDisposable
{
public string Name { get; set; }
public float SemiMajorAxis { get; set; }
public float OrbitalPeriod { get; set; }
public float Radius { get; set; }
public float Eccentricity { get; set; }
public Color Color { get; set; }
private double meanAnomaly;
private List<PointF> positionHistory;
private const int maxHistoryLength = 150;
public Moon(string name, float semiMajorAxis, float orbitalPeriod,
float radius, float eccentricity, Color color)
{
Name = name;
SemiMajorAxis = semiMajorAxis;
OrbitalPeriod = orbitalPeriod;
Radius = radius;
Eccentricity = eccentricity;
Color = color;
meanAnomaly = new Random().NextDouble() * 2 * Math.PI;
positionHistory = new List<PointF>();
}
public void UpdatePosition(double timeStep)
{
double meanMotion = 2 * Math.PI / OrbitalPeriod;
meanAnomaly = meanMotion * timeStep;
if (meanAnomaly > 2 * Math.PI)
meanAnomaly -= 2 * Math.PI;
}
public PointF GetPositionRelativeToPlanet(PointF planetPosition, float scale)
{
// 使用正确的开普勒方程计算月球位置
double eccentricAnomaly = SolveKeplerEquation(meanAnomaly, Eccentricity);
// 计算在轨道平面上的坐标
double xOrbit = SemiMajorAxis * (Math.Cos(eccentricAnomaly) - Eccentricity);
double yOrbit = SemiMajorAxis * Math.Sqrt(1 - Eccentricity * Eccentricity) * Math.Sin(eccentricAnomaly);
// 转换为屏幕坐标
float focusOffset = SemiMajorAxis * Eccentricity * scale;
float x = planetPosition.X (float)xOrbit * scale focusOffset;
float y = planetPosition.Y (float)yOrbit * scale;
PointF position = new PointF(x, y);
positionHistory.Add(position);
if (positionHistory.Count > maxHistoryLength)
{
positionHistory.RemoveAt(0);
}
return position;
}
public List<PointF> PositionHistory => positionHistory;
private double SolveKeplerEquation(double meanAnomaly, double eccentricity)
{
double eccentricAnomaly = meanAnomaly;
double delta = 1.0;
double tolerance = 1e-8;
int maxIterations = 100;
int iterations = 0;
while (Math.Abs(delta) > tolerance && iterations < maxIterations)
{
delta = (eccentricAnomaly - eccentricity * Math.Sin(eccentricAnomaly) - meanAnomaly) /
(1 - eccentricity * Math.Cos(eccentricAnomaly));
eccentricAnomaly -= delta;
iterations ;
}
return eccentricAnomaly;
}
public void Dispose()
{
positionHistory?.Clear();
}
}
}
标签: 太阳系行星运行模拟
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论