本文實現一個簡單的物理算法:彈簧質點系統(Mass-Spring System)。這是一個經典的物理模擬算法,常用于模擬彈性物體(如布料、彈簧等)的行為。我們將使用C++來實現這個算法,并結合鏈表數據結構來管理質點和彈簧。
1. 問題描述
彈簧質點系統由多個質點和連接它們的彈簧組成。每個質點受到重力和彈簧力的作用,我們可以通過牛頓第二定律計算質點的加速度,進而更新其速度和位置。
2. 數據結構設計
- 質點(Mass):包含質量、位置、速度、加速度等屬性。
- 彈簧(Spring):連接兩個質點,包含彈簧常數、自然長度等屬性。
- 系統(System):管理所有質點和彈簧,使用鏈表存儲。
3. 算法實現
#include <iostream>
#include <vector>
#include <cmath>// 定義二維向量
struct Vector2 {double x, y;Vector2(double x = 0, double y = 0) : x(x), y(y) {}Vector2 operator+(const Vector2& other) const {return Vector2(x + other.x, y + other.y);}Vector2 operator-(const Vector2& other) const {return Vector2(x - other.x, y - other.y);}Vector2 operator*(double scalar) const {return Vector2(x * scalar, y * scalar);}double length() const {return std::sqrt(x * x + y * y);}
};// 質點類
struct Mass {double mass; // 質量Vector2 position; // 位置Vector2 velocity; // 速度Vector2 force; // 受力Mass(double m, Vector2 pos) : mass(m), position(pos), velocity(0, 0), force(0, 0) {}void applyForce(Vector2 f) {force = force + f;}void update(double dt) {Vector2 acceleration = force * (1.0 / mass); // 牛頓第二定律velocity = velocity + acceleration * dt; // 更新速度position = position + velocity * dt; // 更新位置force = Vector2(0, 0); // 重置受力}
};// 彈簧類
struct Spring {Mass* mass1; // 連接的質點1Mass* mass2; // 連接的質點2double k; // 彈簧常數double restLength; // 自然長度Spring(Mass* m1, Mass* m2, double k, double restLen): mass1(m1), mass2(m2), k(k), restLength(restLen) {}void applyForce() {Vector2 delta = mass2->position - mass1->position;double length = delta.length();double forceMagnitude = k * (length - restLength); // 胡克定律Vector2 force = delta * (forceMagnitude / length);mass1->applyForce(force);mass2->applyForce(force * -1);}
};// 系統類
struct System {std::vector<Mass*> masses; // 質點鏈表std::vector<Spring*> springs; // 彈簧鏈表void addMass(Mass* mass) {masses.push_back(mass);}void addSpring(Spring* spring) {springs.push_back(spring);}void update(double dt) {// 應用重力for (auto mass : masses) {mass->applyForce(Vector2(0, -9.8 * mass->mass)); // 重力}// 應用彈簧力for (auto spring : springs) {spring->applyForce();}// 更新質點狀態for (auto mass : masses) {mass->update(dt);}}
};int main() {// 創建系統System system;// 創建質點Mass* mass1 = new Mass(1.0, Vector2(0, 0));Mass* mass2 = new Mass(1.0, Vector2(2, 0));system.addMass(mass1);system.addMass(mass2);// 創建彈簧Spring* spring = new Spring(mass1, mass2, 10.0, 1.0);system.addSpring(spring);// 模擬double dt = 0.01; // 時間步長for (int i = 0; i < 100; i++) {system.update(dt);std::cout << "Mass1 Position: (" << mass1->position.x << ", " << mass1->position.y << ")\n";std::cout << "Mass2 Position: (" << mass2->position.x << ", " << mass2->position.y << ")\n";}// 釋放內存delete mass1;delete mass2;delete spring;return 0;
}
4. 代碼解釋
- Vector2:表示二維向量,支持加減乘等操作。
- Mass:表示質點,包含質量、位置、速度、受力等屬性,并提供更新狀態的方法。
- Spring:表示彈簧,連接兩個質點,根據胡克定律計算彈簧力并應用到質點上。
- System:管理所有質點和彈簧,提供更新系統狀態的方法。
- main函數:創建系統、質點和彈簧,并進行模擬。
5. 運行結果
程序會輸出兩個質點的位置隨時間的變化,模擬彈簧質點系統的運動。