Physics Simulation & Visualization Tool 0.1
A C++ physics simulation engine with real-time 3D visualization
Loading...
Searching...
No Matches
SolverDialog.cpp
Go to the documentation of this file.
1#include "SolverDialog.h"
2#include "ui/Vector3Widget.h"
3#include "ui/ScalarWidget.h"
6
7#include <QVBoxLayout>
8#include <QFormLayout>
9#include <QGroupBox>
10#include <QComboBox>
11#include <QLabel>
12#include <QDialogButtonBox>
13#include <qpushbutton.h>
14
15SolverDialog::SolverDialog(const ProblemRouter* problemRouter, Physics::PhysicsBody *body, QWidget *parent) : QDialog(parent), targetBody(body), router(problemRouter){
16 setWindowTitle("Physics Solver Configuration");
17 resize(450, 550);
18 setupUi();
19 updateUiState();
20}
21
22void SolverDialog::setupUi() {
23 QVBoxLayout* mainLayout = new QVBoxLayout(this);
24
25 QGroupBox* objGroup = new QGroupBox("1. Problem Definition");
26 QFormLayout* objLayout = new QFormLayout(objGroup);
27
28 QLabel* nameLabel = new QLabel("placeholder");
29 objLayout->addRow("Active Body:", nameLabel);
30
31 targetCombo = new QComboBox();
32 targetCombo->addItem("Initial Velocity (v0)", "v0");
33 targetCombo->addItem("Target Position (rT)", "rT");
34 targetCombo->addItem("Flight Duration (T)", "T");
35
36 objLayout->addRow("Solve For:", targetCombo);
37 mainLayout->addWidget(objGroup);
38 connect(targetCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SolverDialog::updateUiState);
39
40 QGroupBox* paramGroup = new QGroupBox("2. Known Parameters");
41 QFormLayout* formLayout = new QFormLayout(paramGroup);
42
43 auto addVector = [&](const QString& label, const QString& key) {
44 Vector3Widget* widget = new Vector3Widget();
45 vectorInputs[key] = widget;
46 formLayout->addRow(label, widget);
47 };
48
49 auto addScalar = [&](const QString& label, const QString& key, QString suffix) {
50 ScalarWidget* widget = new ScalarWidget(suffix);
51
52 if (key == "T") widget->setRange(0.001, 10000.0);
53
54 scalarInputs[key] = widget;
55 formLayout->addRow(label, widget);
56 };
57
58 formLayout->addRow(new QLabel("<b>Initial State</b>"));
59 addVector("Position (r0):", "r0");
60 addVector("Velocity (v0):", "v0");
61
62 formLayout->addRow(new QLabel("<b>Target State</b>"));
63 addVector("Position (rT):", "rT");
64 addVector("Velocity (vT):", "vT");
65
66 formLayout->addRow(new QLabel("<b>Constraints</b>"));
67 addScalar("Duration (T):", "T", " s");
68
69 mainLayout->addWidget(paramGroup);
70 mainLayout->addStretch();
71
72 QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
73 buttonBox->button(QDialogButtonBox::Ok)->setText("Solve");
74 connect(buttonBox, &QDialogButtonBox::accepted, this, &SolverDialog::onSolveClicked);
75 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
76 mainLayout->addWidget(buttonBox);
77}
78
79std::string SolverDialog::getTargetUnknown() const {
80 return targetCombo->currentData().toString().toStdString();
81}
82
83std::unordered_map<std::string, double> SolverDialog::getCollectedKnowns() const {
84 std::unordered_map<std::string, double> knowns;
85
86 // Flatten Vector3Widgets into x/y/z keys
87 for (auto it = vectorInputs.begin(); it != vectorInputs.end(); ++it) {
88 if (it.value()->isEnabled()) {
89 glm::vec3 val = it.value()->getValue();
90 std::string k = it.key().toStdString();
91 knowns[k + "_x"] = val.x;
92 knowns[k + "_y"] = val.y;
93 knowns[k + "_z"] = val.z;
94 }
95 }
96
97 // Collect Scalars
98 for (auto it = scalarInputs.begin(); it != scalarInputs.end(); ++it) {
99 if (it.value()->isEnabled()) {
100 knowns[it.key().toStdString()] = it.value()->getValue();
101 }
102 }
103
104 return knowns;
105}
106
107void SolverDialog::updateUiState() {
108 for(auto* w : vectorInputs) w->setEnabled(false);
109 for(auto* w : scalarInputs) w->setEnabled(false);
110
111 std::string unknown = getTargetUnknown();
112 auto requirements = router->getRequiredKeys(unknown);
113 if (requirements.empty()) return;
114
115 // Enable needed fields
116 for (const std::string& key : requirements[0]) {
117 QString qKey = QString::fromStdString(key);
118
119 if (scalarInputs.contains(qKey)) {
120 scalarInputs[qKey]->setEnabled(true);
121 }
122 else if (qKey.endsWith("_x")) {
123 QString base = qKey.left(qKey.length() - 2);
124 if (vectorInputs.contains(base)) {
125 vectorInputs[base]->setEnabled(true);
126 }
127 }
128 }
129}
130
131void SolverDialog::onSolveClicked() {
132 accept();
133}
std::vector< std::vector< std::string > > getRequiredKeys(const std::string &unknown) const
void setRange(double min, double max)
std::unordered_map< std::string, double > getCollectedKnowns() const
std::string getTargetUnknown() const
SolverDialog(const ProblemRouter *router, Physics::PhysicsBody *body, QWidget *parent=nullptr)