[工程文档] 微观电荷
为了防止开发中的大间隔导致自己看不懂逻辑,遂详细记录。
世界空间
把窗口平面放置到空间中的 \(xOy\) 平面中,视角为从上向下俯视。
一期Beta:9.13 issue:
- 物体(Object)是统一的,没有区分 Ball 这个对象
- 测试时发现
Full_Range的磁场无法正确判断是否在范围内,出现一直不进区域的问题 - 定义的场是匀强场,不能定义关于信息变换的场
- 原初题目的问题没有解决!!!(物理某个洛伦兹力自助T7)
- 由于重置背景为白色,暴力的不清屏轨迹法失效
二期目标:10.1 preview:
- 解决issue1-2, issue1-3
- \(\color{red}(重要)\)将世界初始元素改为可编辑存档式:首先由存档生成器(临时:根据文本指令生成)根据用户提供数据生成二进制存档文件,再由计算程序读取该存档文件(此处只有指令文本是人类可读的)
- 加入时间关联/条件关联「事件」(event):包括修改某个对象的值,追加/删除对象,调整屏幕缩放(按键控制&作为条件触发时间关联事件),平移屏幕摄像机(按键控制&作为条件触发时间关联事件)
- 提前加入三期中的 「运动轨迹」对象:将非固定对象等时刻记录位置采样点,和该对象关联,依次用直线连接采样点得到轨迹图像
一期代码储存
// Demo.cpp
#include <SFML/Graphics.hpp>
#include "includes.h"
#include <windows.h>
unsigned int WIDTH = 1600;
unsigned int HEIGHT = 1200;
Vec2 centre = {WIDTH / 2, HEIGHT / 2, 0.0f};
int main()
{
float delt_t = 1.0 / 60.0;
// SFML draw 部分
sf::ContextSettings Settings;
Settings.antiAliasingLevel = 8; // 抗锯齿
sf::Font font("Consolas.ttf");
sf::Text text(font);
sf::RenderWindow window(sf::VideoMode({WIDTH, HEIGHT}), "Title", sf::Style::Default, sf::State::Windowed, Settings);
window.setVerticalSyncEnabled(true); // call it once after creating the window
std :: vector <Object> objects; // 小球等物体
std :: vector <Electric_Field> E_Fields; // 匀强电场 // 挖坑:非匀强电场
std :: vector <Magnetic_Field> B_Fields; // 匀强磁场 // 挖坑:非匀强磁场
std :: vector <Gravity_Field> G_Fields; // 引力场
// 测试内容 内容在改错本已经 ISSUED
B_Fields.push_back(
{
Full_Range,
{0.0f, 0.0f, 10000.0f}
}
);
objects.push_back( // A点
{
Vec2{30, 40, 0}, true,
zero3,
zero3,
1.0f,
1e-4f
}
);
objects.push_back( // B点
{
Vec2{30, 50, 0}, false,
Vec2{(float)sqrt(k_Coulomb * 1e-8 / 10.0f), 0, 0},
zero3,
1.0f,
-1e-4f
}
);
// B理应绕着A刚好做匀速圆周运动
long long int ticks = 0;
while (window.isOpen())
{
while (const std::optional event = window.pollEvent()) // 操作检测
{
if (event -> is<sf::Event::Closed>())
{
window.close();
return 0;
}
if (sf :: Mouse :: isButtonPressed(sf :: Mouse :: Button :: Left))
{
}
}
WorldUpdate(
delt_t,
objects,
E_Fields,
B_Fields,
G_Fields
); // 物理更新
window.clear(sf::Color::White);
// 绘图
// 渲染小球
window.draw(Draw_Ball(
objects[0],
5.0f / 20,
sf::Color::Black)
);
window.draw(Draw_Ball(
objects[1],
5.0f / 20,
sf::Color::Black)
);
// UI 信息
std :: stringstream ss;
ss << "Time: ";
ss << std :: setiosflags(std :: ios::fixed) << std :: setprecision(2) << ticks * delt_t;
text.setString(ss.str());
text.setCharacterSize(24); // in pixels
text.setFillColor(sf::Color::Black);
window.draw(text);
window.display();
ticks++;
}
}
math.h
#pragma once
// 三维向量(主平面即窗口平面为 xOy)
struct Vec2
{
float x;
float y;
float z;
// 线性运算
// 加法
Vec2 operator+(const Vec2& b) const
{
return {x + b.x, y + b.y, z + b.z};
}
// 减法
Vec2 operator-(const Vec2& b) const
{
return {x - b.x, y - b.y, z - b.z};
}
// 数乘
Vec2 operator*(const float& b) const
{
return {x * b, y * b, z * b};
}
// 点乘
float operator*(const Vec2& b) const
{
return x * b.x + y * b.y + z * b.z;
}
// 叉乘
Vec2 operator^(const Vec2& b) const
{
return {y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x};
}
// 模长
float mod() const
{
return sqrt(x * x + y * y + z * z);
}
};
const Vec2 zero3 = {0.0f, 0.0f, 0.0f}; // 零向量
// 范围
struct Range
{
int type; // 类型:0为矩形 1为圆形
Vec2 minn; // 左上角
Vec2 maxn; // 右下角
Vec2 centre; // 圆心
float radius; // 半径
};
const Range Full_Range = {
0,
{-1e9f, 1e9f, 0.0f},
{1e9f, -1e9f, 0.0f},
zero3,
0.0f
};
// 该坐标点是否位于区域内
bool isInRect(Vec2 point, Range temp) // true为在区域内
{
if (temp.type == 0)
{
return (temp.minn.x <= point.x && point.x <= temp.maxn.x) && (temp.minn.y <= point.y && point.y <= temp.maxn.y);
}
if (temp.type == 1)
{
return (point - temp.centre).mod() <= temp.radius;
}
}
// physic.h
#pragma once
const float k_Coulomb = 8.9875517923e9f; // 库仑常数 N·m²/C²
// 物体
struct Object
{
Vec2 position; // 位置
bool isFixed; // 是否固定
Vec2 velocity; // 速度
Vec2 acceleration; // 加速度
float mass; // 质量
float quantity; // 电荷量
};
// 电场
struct Electric_Field
{
Range area; // 作用区域
Vec2 E; // 场强
};
// 磁场
struct Magnetic_Field
{
Range area; // 作用区域
Vec2 B; // 磁感应强度
};
// 引力场
struct Gravity_Field
{
Range area; // 作用区域
Vec2 G; // 引力加速度
};
// 点电荷间库仑力
Vec2 Coulomb_Force(const Object& a, const Object& b) // a 对 b 施加的力
{
Vec2 AB = b.position - a.position;
if (AB.mod() - 1e-5 <= 0)
{
return zero3;
}
Vec2 E = AB * (k_Coulomb * a.quantity * pow(AB * AB, -1.5f));
return E * b.quantity;
}
void WorldUpdate(
float deltaTime,
std :: vector <Object> &objects,
std :: vector <Electric_Field> &E_Fields,
std :: vector <Magnetic_Field> &B_Fields,
std :: vector <Gravity_Field> &G_Fields
)
{
// 根据更新前的状态计算力
for (auto& i : objects)
{
if (i.isFixed) // 固定物体不更新
{
i.acceleration = zero3;
i.velocity = zero3;
continue;
}
Vec2 F_Sum = zero3;
// 物体间的电荷库伦力(静电力)
Vec2 F_Coulomb = zero3;
for (auto& j : objects)
{
F_Coulomb = F_Coulomb + Coulomb_Force(j, i);
}
// 物体所受的电场力
Vec2 F_Efield = zero3;
for (auto &j : E_Fields)
{
if (isInRect(i.position, j.area))
{
F_Efield = F_Efield + j.E * i.quantity;
}
}
// 物体所受的磁场洛伦兹力
Vec2 F_Bfield = zero3;
for (auto &j : B_Fields)
{
//if (isInRect(i.position, j.area)) //! ISSUE:无法正确判断范围
{
//std :: cerr << "Updated\n";
F_Bfield = F_Bfield + (i.velocity ^ j.B) * i.quantity;
}
}
// 物体所受的引力场力
Vec2 F_Gfield = zero3;
for (auto &j : G_Fields)
{
if (isInRect(i.position, j.area))
{
F_Gfield = F_Gfield + j.G * i.mass;
}
}
F_Sum = F_Coulomb + F_Efield + F_Bfield + F_Gfield;
// 更新加速度
i.acceleration = F_Sum * (1.0f / i.mass);
}
// 更新速度
for (auto& i : objects)
{
i.velocity = i.velocity + i.acceleration * deltaTime;
}
// 更新位置
for (auto& i : objects)
{
i.position = i.position + i.velocity * deltaTime;
}
}
// drawer.h
#pragma once
const float K = 20; // 缩放比例 :世界坐标 * K = 屏幕像素坐标
extern unsigned int WIDTH;
extern unsigned int HEIGHT;
extern Vec2 centre;
inline Vec2 transform_to_screen(Vec2 world_pos)
{
return Vec2{world_pos.x * K, HEIGHT - world_pos.y * K, 0.0f};
}
inline sf::CircleShape Draw_Ball(Object A, float radius, sf:: Color color)
{
sf::CircleShape t;
t.setRadius(radius * K);
t.setPointCount(20);
Vec2 screen_pos = transform_to_screen(A.position);
t.setPosition({screen_pos.x, screen_pos.y});
t.setFillColor(color);
return t;
}
// includes.h
#pragma once
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
// New Function
#include "math.h"
#include "physic.h"
#include "drawer.h"

浙公网安备 33010602011771号