add multiple

main
Benjamin Kraft 1 year ago
parent 5c45de0785
commit 2c1d9b12c7
  1. 26
      src/MainWindow.cpp
  2. 39
      src/Pendulum.cpp
  3. 1
      src/Pendulum.h
  4. 29
      src/Simulation.cpp
  5. 11
      src/Simulation.h

@ -373,6 +373,30 @@ void MainWindow::normalizeLengths() {
void MainWindow::add() { void MainWindow::add() {
if (multiple){ if (multiple){
for (int i = 0; i < count; i++){
auto M = std::vector(masses.begin(), masses.begin() + segments);
auto L = std::vector(lengths.begin(), lengths.begin() + segments);
double angle = startingAngle;
double changeAmount = changeAmountPercentage / 100;
double progress = double(i) / count - 0.5;
QColor c = color;
switch (changeProperty) {
case Angle:
angle += progress * 360 * changeAmount;
break;
case Mass:
M[changeIndex] += progress * M[changeIndex] * changeAmount;
break;
case Length:
L[changeIndex] += progress * L[changeIndex] * changeAmount;
break;
}
if (rainbow){
auto hue = progress + 0.5;
c = QColor::fromHsvF(hue, 1, 1);
}
simulation->pendula.push_back(new Pendulum(M, L, c, angle));
}
} else { } else {
auto M = std::vector(masses.begin(), masses.begin() + segments); auto M = std::vector(masses.begin(), masses.begin() + segments);
auto L = std::vector(lengths.begin(), lengths.begin() + segments); auto L = std::vector(lengths.begin(), lengths.begin() + segments);
@ -381,7 +405,7 @@ void MainWindow::add() {
} }
void MainWindow::remove() { void MainWindow::remove() {
simulation->clearPendula();
} }
void MainWindow::resetSimulationControl() { void MainWindow::resetSimulationControl() {

@ -32,3 +32,42 @@ void Pendulum::draw(QPainter *p, double scale) const {
p->drawEllipse(QPointF(x.x, x.y), r * 2, r * 2); p->drawEllipse(QPointF(x.x, x.y), r * 2, r * 2);
} }
} }
void Pendulum::update(double h, double g) {
Vector p1(0, 0);
for (int i = 0; i < X.size(); i++){
V[i] = V[i] + Vector(0, g * h);
Vector p2 = X[i] + V[i] * h;
// solve distance constraint
double w1 = i == 0 ? 0 : 1 / M[i - 1];
double w2 = 1 / M[i];
Vector s = p1 - p2;
Vector n = s;
n.normalize();
double l = s.length();
Vector deltaP1 = n * -w1 / (w1 + w2) * (l - L[i]);
Vector deltaP2 = n * w2 / (w1 + w2) * (l - L[i]);
p1 = p1 + deltaP1;
p2 = p2 + deltaP2;
// integrate
if (i > 0){
V[i - 1] = (p1 - X[i - 1]) / h;
X[i - 1] = p1;
}
p1 = p2;
}
// integrate last segment
int i = X.size() - 1;
V[i] = (p1 - X[i]) / h;
X[i] = p1;
}

@ -12,6 +12,7 @@ public:
QColor color, double startAngle); QColor color, double startAngle);
void draw(QPainter*, double) const; void draw(QPainter*, double) const;
void update(double, double);
private: private:
std::vector<Vector> X, V; std::vector<Vector> X, V;

@ -1,12 +1,37 @@
#include "Simulation.h" #include "Simulation.h"
#include "Pendulum.h" #include "Pendulum.h"
#include <QPainter> #include <QPainter>
#include <QTimer>
Simulation::Simulation() = default; Simulation::Simulation() {
timer = new QTimer(this);
QTimer::connect(timer, &QTimer::timeout, this, &Simulation::update);
timer->setInterval(updateInterval);
timer->start();
};
void Simulation::draw(QPainter *p, int screenSize) const { void Simulation::draw(QPainter *p, int screenSize) const {
double scale = screenSize / size; double scale = screenSize * 0.95 / size;
for (const auto pendulum : pendula) for (const auto pendulum : pendula)
pendulum->draw(p, scale); pendulum->draw(p, scale);
} }
void Simulation::update() {
if (!isPlaying)
return;
double h = (timescale * updateInterval) / 1000;
h /= substeps;
for (int i = 0; i < substeps; i++)
for (const auto pendulum : pendula)
pendulum->update(h, gravity);
}
void Simulation::clearPendula() {
for (auto p : pendula)
delete p;
pendula.clear();
}

@ -1,10 +1,12 @@
#include <vector> #include <vector>
#include <cstdint> #include <cstdint>
#include <QObject>
class Pendulum; class Pendulum;
class QPainter; class QPainter;
class QTimer;
class Simulation { class Simulation : public QObject {
public: public:
explicit Simulation(); explicit Simulation();
@ -14,9 +16,16 @@ public:
double timescale; double timescale;
int substeps; int substeps;
int updateInterval = 17;
bool isPlaying = false; bool isPlaying = false;
std::vector<Pendulum *> pendula; std::vector<Pendulum *> pendula;
void clearPendula();
QTimer * timer;
void draw(QPainter*, int) const; void draw(QPainter*, int) const;
private slots:
void update();
}; };
Loading…
Cancel
Save