add single, drawing done

main
Benjamin Kraft 1 year ago
parent 1aa7bf1713
commit 5c45de0785
  1. 41
      src/GLWidget.cpp
  2. 15
      src/GLWidget.h
  3. 18
      src/MainWindow.cpp
  4. 8
      src/MainWindow.h
  5. 35
      src/Pendulum.cpp
  6. 17
      src/Pendulum.h
  7. 9
      src/Simulation.cpp
  8. 3
      src/Simulation.h
  9. 31
      src/Vector.cpp
  10. 12
      src/Vector.h

@ -2,9 +2,48 @@
#include <QPainter>
#include <QPaintEvent>
#include <iostream>
#include <QTimer>
#include "Simulation.h"
#include <QApplication>
#include <QDialog>
GLWidget::GLWidget(Simulation * simulation) : simulation(simulation) {
startTimer(1000 / 144);
previousFrame = high_resolution_clock::now();
}
void GLWidget::paintEvent(QPaintEvent *e) {
updateFPS();
auto p = new QPainter(this);
p->fillRect(e->rect(), Qt::black);
p->setRenderHint(QPainter::Antialiasing);
p->fillRect(e->rect(), QColor(30, 30, 30));
p->translate(e->rect().center());
simulation->draw(p, std::min(width(), height()));
p->end();
}
void GLWidget::timerEvent(QTimerEvent *e) {
if (!AnyDialogOpen())
update();
}
void GLWidget::updateFPS() {
auto thisFrame = high_resolution_clock::now();
auto diff = duration_cast<milliseconds>(thisFrame - previousFrame).count();
currentFPS = 1000 / (diff == 0 ? 1 : diff);
previousFrame = thisFrame;
}
bool GLWidget::AnyDialogOpen() {
for (auto widget : QApplication::topLevelWidgets())
if (auto dialog = qobject_cast<QDialog*>(widget))
if (dialog->isVisible())
return true;
return false;
}

@ -1,7 +1,22 @@
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <chrono>
using namespace std::chrono;
class Simulation;
class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions {
public:
explicit GLWidget(Simulation *);
protected:
void paintEvent(QPaintEvent* e) override;
void timerEvent(QTimerEvent* e) override;
private:
Simulation * simulation;
time_point<system_clock> previousFrame;
int currentFPS;
void updateFPS();
static bool AnyDialogOpen();
};

@ -8,11 +8,12 @@
#include <QCheckBox>
#include <QRadioButton>
#include <QButtonGroup>
#include <QSizePolicy>
#include <iostream>
#include <QDial>
#include <iostream>
#include <QColorDialog>
#include <QCoreApplication>
#include "Pendulum.h"
MainWindow::MainWindow() {
simulation = new Simulation;
@ -27,10 +28,10 @@ MainWindow::MainWindow() {
}
void MainWindow::buildUI() {
setMinimumSize(800, 500);
setMinimumSize(1000, 400);
auto uiLyt = new QVBoxLayout;
glWidget = new GLWidget;
glWidget = new GLWidget(simulation);
auto mainLyt = new QHBoxLayout(this);
mainLyt->addLayout(uiLyt);
@ -260,13 +261,14 @@ QWidget * MainWindow::buildAddUI() {
multipleLyt->addWidget(indexSlider);
auto amountLabel = new QLabel;
auto amountSlider = new Slider<double>(amountLabel, "Change Amount: %5.3f%%", &changeAmount, [](int v){
auto amountSlider = new Slider<double>(amountLabel, "Change Amount: %5.3f%%", &changeAmountPercentage, [](int v){
return double(v) / 1000;
}, [](double v){
return int(v * 1000);
});
amountSlider->setMinimum(1);
amountSlider->setMaximum(1000);
amountSlider->setFromTarget();
amountSlider->setMinimum(1);
multipleLyt->addWidget(amountLabel);
multipleLyt->addWidget(amountSlider);
}
@ -369,7 +371,13 @@ void MainWindow::normalizeLengths() {
}
void MainWindow::add() {
if (multiple){
} else {
auto M = std::vector(masses.begin(), masses.begin() + segments);
auto L = std::vector(lengths.begin(), lengths.begin() + segments);
simulation->pendula.push_back(new Pendulum(M, L, color, startingAngle));
}
}
void MainWindow::remove() {

@ -30,11 +30,11 @@ private:
int count = 100;
Property changeProperty = Angle;
int changeIndex = 0;
double changeAmount = 0.001;
double changeAmountPercentage = 0.5;
QGridLayout * segmentGrid;
Slider<double> * gravitySlider, * timescaleSlider;
Slider<> * substepsSlider;
QGridLayout * segmentGrid {};
Slider<double> * gravitySlider = nullptr, * timescaleSlider = nullptr;
Slider<> * substepsSlider = nullptr;
public slots:

@ -1 +1,34 @@
#include "Pendulum.h"
#include "Pendulum.h"
#include <iostream>
#include <QPainter>
Pendulum::Pendulum(const std::vector<double> &M,
const std::vector<double> &L,
QColor color, double startAngle) : M(M), L(L), color(color){
startAngle *= 3.141 / 180;
Vector direction(-sin(startAngle), cos(startAngle));
Vector currentPosition(0, 0);
for (int i = 0; i < M.size(); i++){
currentPosition = currentPosition + direction * L[i];
X.push_back(currentPosition);
V.emplace_back(0, 0);
}
}
void Pendulum::draw(QPainter *p, double scale) const {
p->setPen(color);
p->setBrush(Qt::white);
Vector previousX(0, 0);
for (int i = 0; i < X.size(); i++){
Vector x = X[i] * scale;
p->drawLine(previousX.x, previousX.y, x.x, x.y);
previousX = x;
double r = sqrt(M[i] * scale / 5);
p->drawEllipse(QPointF(x.x, x.y), r * 2, r * 2);
}
}

@ -1,3 +1,20 @@
#include <vector>
#include <QVector2D>
#include <QColor>
#include "Vector.h"
class QPainter;
class Pendulum {
public:
explicit Pendulum(const std::vector<double> &M,
const std::vector<double> &L,
QColor color, double startAngle);
void draw(QPainter*, double) const;
private:
std::vector<Vector> X, V;
std::vector<double> M, L;
QColor color;
};

@ -1,3 +1,12 @@
#include "Simulation.h"
#include "Pendulum.h"
#include <QPainter>
Simulation::Simulation() = default;
void Simulation::draw(QPainter *p, int screenSize) const {
double scale = screenSize / size;
for (const auto pendulum : pendula)
pendulum->draw(p, scale);
}

@ -2,6 +2,7 @@
#include <cstdint>
class Pendulum;
class QPainter;
class Simulation {
public:
@ -16,4 +17,6 @@ public:
bool isPlaying = false;
std::vector<Pendulum *> pendula;
void draw(QPainter*, int) const;
};

@ -0,0 +1,31 @@
#include "Vector.h"
#include <cmath>
Vector::Vector(double x, double y) : x(x), y(y) {}
double Vector::length() const {
return sqrt(x * x + y * y);
}
void Vector::normalize() {
double l = length();
x /= l;
y /= l;
}
Vector operator+(Vector lhs, Vector rhs) {
return {lhs.x + rhs.x, lhs.y + rhs.y};
}
Vector operator-(Vector lhs, Vector rhs) {
return {lhs.x - rhs.x, lhs.y - rhs.y};
}
Vector operator*(Vector v, double factor){
return {v.x * factor, v.y * factor};
}
Vector operator/(Vector v, double divisor){
return {v.x / divisor, v.y / divisor};
}

@ -0,0 +1,12 @@
struct Vector {
double x, y;
Vector(double x, double y);
double length() const;
void normalize();
friend Vector operator +(Vector lhs, Vector rhs);
friend Vector operator -(Vector lhs, Vector rhs);
friend Vector operator *(Vector v, double factor);
friend Vector operator /(Vector v, double divisor);
};
Loading…
Cancel
Save