C++模拟牛顿力学(2D)

这篇具有很好参考价值的文章主要介绍了C++模拟牛顿力学(2D)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

如何用计算机来模拟真实世界呢?计算机最大的功能是计算,而物理学的种种公式就把现实世界中的物理规律以数学的语言描绘了出来,从而使我们可以通过计算大致模拟现实世界的物体运动。因此不难想到把物理学定律(这里用的是牛顿力学)用计算机语言描述出来,模拟现实世界。这个项目就用C++实现了此功能,为了方便,目前实现的是二维宇宙。
项目完成后,只要输入各项参数,我们就可以用它模拟现实中的运动了。下面是用该项目模拟某飞船围绕某恒星运动的过程(注意,运动轨迹并不是预设的动画,而是通过计算得出的)。
C++模拟牛顿力学(2D)

代码

完整代码如下:

namespace NewtonianPhysics
{
	using Scalar = long double;//标量
	const Scalar G = 6.67259e-11l;//万有引力常数
	namespace _2D
	{
		class Vector//矢量
		{
		public:
			static const Vector Zero;
			Scalar x;
			Scalar y;
			Vector() :x(0.l), y(0.l) {}
			Vector(Scalar inX, Scalar inY) :x(inX), y(inY) {}
			friend Vector operator+(const Vector& a, const Vector& b)
			{
				return Vector(a.x + b.x, a.y + b.y);
			}
			friend Vector operator-(const Vector& a, const Vector& b)
			{
				return Vector(a.x - b.x, a.y - b.y);
			}
			friend Vector operator*(const Vector& vec, Scalar n)
			{
				return Vector(vec.x * n, vec.y * n);
			}
			friend Vector operator*(Scalar n, const Vector& vec)
			{
				return Vector(vec.x * n, vec.y * n);
			}
			Vector operator-()const
			{
				return Vector(-x, -y);
			}
			Vector& operator*=(Scalar n)
			{
				x *= n;
				y *= n;
				return *this;
			}
			Vector& operator+=(const Vector& right)
			{
				x += right.x;
				y += right.y;
				return *this;
			}
			Vector& operator-=(const Vector& right)
			{
				x -= right.x;
				y -= right.y;
				return *this;
			}
			Scalar LengthSq() const
			{
				return (x * x + y * y);
			}
			Scalar Length() const
			{
				return (std::sqrt(LengthSq()));
			}
			void Normalize()
			{
				float length = Length();
				x /= length;
				y /= length;
			}
			static Vector Normalize(const Vector& vec)
			{
				Vector temp = vec;
				temp.Normalize();
				return temp;
			}
		};
		const Vector Vector::Zero;
		class MassPoint
		{
		public:
			Scalar m;//质量/kg
			Vector location;//当前位置
			Vector v;//速度/(m/s)
			Vector f;//受到的合力/(N)
			MassPoint(Scalar mass, Vector _location = { 0,0 }, Vector velocity = { 0,0 })
				:m(mass), location(_location), v(velocity) {}
			void Update(Scalar deltaTime)
			{
				//由F=ma得出加速度并更新速度
				v += f * (1 / m) * deltaTime;
				//由速度得出位移并更新坐标
				location += v * deltaTime;
				f = Vector::Zero;
			}
		};
		class World
		{
		public:
			std::vector<MassPoint> objects;
			void SetGravitation()//设置引力
			{
				for (size_t i = 0; i < objects.size(); ++i)
				{
					for (size_t j = i + 1; j < objects.size(); ++j)
					{
						//F=GMm/r²
						objects[i].f += _2D::Vector::Normalize(objects[j].location - objects[i].location) * 
							(G * objects[i].m * objects[j].m / (objects[i].location - objects[j].location).LengthSq());
						objects[j].f += -objects[i].f;
					}
				}
			}
			void Update(Scalar deltaTime)
			{
				for (MassPoint& m : objects)
					m.Update(deltaTime);
			}
		};
	}
}

标量和矢量

首先,我们定义了标量和矢量的类型。标量就是只有大小的量,如时间、质量等,而矢量是既有大小又有方向的量,如速度、加速度。标量用内置的long double类型即可。
矢量就是数学中的向量,在这里我们用Vector类来表示。根据数学定理,任何一个矢量都可以用平面直角坐标系中的一个坐标来表示。在Vector类里面,我们用两个标量来表示横坐标和纵坐标,并且定义了矢量的加法、减法、与实数的乘法。Length函数的作用是求矢量的长度,而LengthSq则是求矢量长度的平方。因为Length函数需要开方,速度比较慢,所以能用LengthSq就尽量用LengthSq。而Normalize函数的作用则是将矢量变成方向相同、长度为1的单位矢量。

增量时间

根据主流物理学理论,时间是连续的,然而,通过计算机模拟现实世界时,我们只能“一帧一帧”地计算。例如,如果我们每一帧代表0.1s,当前物体速度为10m/s,我们只能默认在这0.1s内物体的速度保持10m/s不变,尽管实际上速度可能变化了。这有点类似于微分,然而微分可以引入无穷小量,而计算机计算每一帧的时间不可能是无穷小,所以计算出来和实际结果一定有误差。并且,每帧代表的时间越短,误差越小。
在上面的例子中,0.1s就叫做增量时间( Δ t ) \Delta t) Δt)

质点

牛顿力学的核心就是将物体抽象成质点(有质量无大小的点)进行研究。这里的MassPoint类就表示质点。在MassPoint类的成员变量中,m表示质量,v表示当前的速度,f表示受到的合力,location是当前的坐标。
Update函数根据物理定律对质点的状态进行更新,它的参数就是增量时间。在这个函数中,我们先通过牛顿第二定律求出加速度,然后乘以增量时间得出速度,再乘以时间便得出了位移。

这样,我们便实现了牛顿力学的基本功能。

World

在模拟程序中,所有在同一个“宇宙”中(即可以相互作用)的质点都被放到一个World中,这样就可以方便地管理它们了。此外,World还提供了一键计算引力的方法,利用万有引力公式计算出各个质点之间的引力。如果想忽略引力,不调用该函数即可。

实例

下面是太阳系中太阳、水星、金星、地球的运动模拟,每帧代表地球上的1天,每秒10帧。输入的数据全部是真实的,所以模拟结果和现实很相近(如地球公转一周在程序中大约37秒)。
当然,大家也可以调节这些数据,或者加入更多的元素,实现更加复杂的运动过程(例如三体运动)。

using namespace NewtonianPhysics;
using namespace _2D;
void Print(const World & w)
{
	cleardevice();
	for (const auto& p : w.objects)
	{
		setfillcolor(YELLOW);
		setlinecolor(RED);
		setlinestyle(PS_SOLID, 1);
		Scalar r = 2e11;
		auto x = (p.location.x + r) * 800 / (2 * r), y = (r - p.location.y) * 800 / (2 * r);
		fillcircle(x, y, 5);
	}
}
int main()
{
	initgraph(800, 800); 
	World w; 
	w.objects.push_back(MassPoint(1.9891e30, { 0,0 }, { 0,0 }));//太阳
	//行星均为远日点数据
	w.objects.push_back(MassPoint(3.3011e23, { 6.8817e10,0 }, { 0,3.9563e4 }));//水星
	w.objects.push_back(MassPoint(4.8675e24, { 1.082e11,0 }, { 0,3.5e4 }));//金星
	w.objects.push_back(MassPoint(5.97237e24, { 1.521e11,0 }, { 0,2.93e4 }));//地球
	while (1)
	{
		auto s = GetTickCount64();
		Print(w);
		w.SetGravitation();
		w.Update(86400);
		while (GetTickCount64() - s <= 100);
	}
	closegraph();
	return 0;
}

这一期就先讲到这里,如果喜欢别忘了点个赞!文章来源地址https://www.toymoban.com/news/detail-474464.html

到了这里,关于C++模拟牛顿力学(2D)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 计算机视觉与深度学习 | 非线性优化理论:图优化、高斯牛顿法和列文伯格-马夸尔特算法

    ===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 计算机视觉与深度学习 | SLAM国内外研究现状 计算机视觉与深度学习 | 视觉惯性SLAM的基础理论 计算机

    2024年02月08日
    浏览(53)
  • 单摆的动力学建模以及matlab仿真(牛顿法和拉格朗日方程法)

    有空再写 首先我们先确定广义坐标,并同时计算出来摆杆的转动惯量 接着列拉格朗日方程 计算动能(转动动能)  计算势能(取铰链处为零势能高度):  计算L 计算拉格朗日方程中的中间量   将上述的中间量带入拉格朗日方程,得到动力学模型: 变换一下形式:  当角

    2023年04月08日
    浏览(47)
  • 计算机图形学的革命:从2D到3D

    计算机图形学是一门研究如何在计算机屏幕上生成图像的学科。从其出现以来,计算机图形学经历了两次革命性的变革:从2D到3D,以及从矢量图形到位置 Independent Bitmap Images(Pixels)。这篇文章将深入探讨从2D到3D的革命,揭示其背后的核心概念、算法原理、数学模型以及代码实

    2024年02月19日
    浏览(42)
  • 计算机图形学基础:2D/3D坐标变换(Transformation)

    本文讲解了2D变换和3D变换式如何用矩阵表示的 如何将线性和非线性变换进行一个统一表示形式 三维物体在二维空间上的映射 表示向量添加了一维,分别表示单位距离和平移不变形的方向 旋转默认都是以(0, 0)为中心

    2023年04月08日
    浏览(45)
  • 【计算机视觉】二、图像形成——实验:2D变换编辑(Pygame)

    【计算机视觉】二、图像形成:1、向量和矩阵的基本运算:线性变换与齐次坐标   几何基元是计算机图形学中最基本的图形对象,它们是构建更复杂图形的基础单元。常见的几何基元包括: 点(Point) : 由一对或一组坐标值表示的零维对象。 线段(Line Segment) : 由两个端点确定的

    2024年03月22日
    浏览(45)
  • 从2D到3D,计算机视觉的ChatGPT何时到来?

    ChatGPT 及其改进型 GPT4通过一个单一模型解决了几乎所有与文本相关的任务,彻底改变了 NLP 领域。然而,这样的一个模型在计算机视觉方面并不存在,特别是对于3D视觉。本文首先从模型的角度简要介绍了深度学习在文本、图像和3D领域的进展。此外,本文还从数据的角度进一

    2024年02月03日
    浏览(69)
  • 如何用c++制作人生模拟器

    要制作一个人生模拟器,首先需要设计游戏的基本框架,并构思游戏的玩法,规则和内容。 然后,在C++中实现这个框架并添加游戏所需的各种类、函数和变量。其中,有几个关键的方面需要考虑: 模拟生命周期:利用C++的类和对象特性,可以创建一个Person类来描述每个角色

    2024年02月06日
    浏览(57)
  • 计算机视觉 图像形成 几何图形和变换 3D到2D投影

            现在我们知道如何表示2D和3D几何图元以及如何在空间上转换它们,我们需要指定如何将 3D图元投影到图像平面上。 我们可以使用线性3D到2D投影矩阵来做到这一点。最简单的模型是正交法,它不需要除法就可以得到最终的(不均匀的)结果。更常用的模型是透视,

    2023年04月08日
    浏览(66)
  • 计算机视觉简介(1)

    任何计算机视觉处理流程都始于成像系统,它从景物中捕获反射出来的光线,并将光信号转换成计算机可以读取和处理的图像格式 在计算机成像技术发展的早期,图像通过把胶卷或印刷图像素 化后获得;而现在图 像通常直接由数码相机获取,并存储成称为像素的有序数字

    2024年02月08日
    浏览(36)
  • 计算机存储层次及常用存储简介

    存储层次是在计算机体系结构下存储系统层次结构的排列顺序。 每一层于下一层相比 都拥有 较高的速度 和 较低延迟性 ,以及 较小的容量 (也有少量例外,如AMD早期的Duron CPU)。大部分现今的中央处理器的速度都非常的快。大部分程序工作量需要存储器存取。由于高速缓

    2024年02月12日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包