12#include <QDialogButtonBox>
13#include <qpushbutton.h>
16 setWindowTitle(
"Physics Solver Configuration");
22void SolverDialog::setupUi() {
23 QVBoxLayout* mainLayout =
new QVBoxLayout(
this);
25 QGroupBox* objGroup =
new QGroupBox(
"1. Problem Definition");
26 QFormLayout* objLayout =
new QFormLayout(objGroup);
28 QLabel* nameLabel =
new QLabel(
"placeholder");
29 objLayout->addRow(
"Active Body:", nameLabel);
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");
36 objLayout->addRow(
"Solve For:", targetCombo);
37 mainLayout->addWidget(objGroup);
38 connect(targetCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &SolverDialog::updateUiState);
40 QGroupBox* paramGroup =
new QGroupBox(
"2. Known Parameters");
41 QFormLayout* formLayout =
new QFormLayout(paramGroup);
43 auto addVector = [&](
const QString& label,
const QString& key) {
45 vectorInputs[key] = widget;
46 formLayout->addRow(label, widget);
49 auto addScalar = [&](
const QString& label,
const QString& key, QString suffix) {
52 if (key ==
"T") widget->
setRange(0.001, 10000.0);
54 scalarInputs[key] = widget;
55 formLayout->addRow(label, widget);
58 formLayout->addRow(
new QLabel(
"<b>Initial State</b>"));
59 addVector(
"Position (r0):",
"r0");
60 addVector(
"Velocity (v0):",
"v0");
62 formLayout->addRow(
new QLabel(
"<b>Target State</b>"));
63 addVector(
"Position (rT):",
"rT");
64 addVector(
"Velocity (vT):",
"vT");
66 formLayout->addRow(
new QLabel(
"<b>Constraints</b>"));
67 addScalar(
"Duration (T):",
"T",
" s");
69 mainLayout->addWidget(paramGroup);
70 mainLayout->addStretch();
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);
80 return targetCombo->currentData().toString().toStdString();
84 std::unordered_map<std::string, double> knowns;
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;
98 for (
auto it = scalarInputs.begin(); it != scalarInputs.end(); ++it) {
99 if (it.value()->isEnabled()) {
100 knowns[it.key().toStdString()] = it.value()->getValue();
107void SolverDialog::updateUiState() {
108 for(
auto* w : vectorInputs) w->setEnabled(false);
109 for(
auto* w : scalarInputs) w->setEnabled(false);
113 if (requirements.empty())
return;
116 for (
const std::string& key : requirements[0]) {
117 QString qKey = QString::fromStdString(key);
119 if (scalarInputs.contains(qKey)) {
120 scalarInputs[qKey]->setEnabled(
true);
122 else if (qKey.endsWith(
"_x")) {
123 QString base = qKey.left(qKey.length() - 2);
124 if (vectorInputs.contains(base)) {
125 vectorInputs[base]->setEnabled(
true);
131void SolverDialog::onSolveClicked() {
std::vector< std::vector< std::string > > getRequiredKeys(const std::string &unknown) const
std::unordered_map< std::string, double > getCollectedKnowns() const
std::string getTargetUnknown() const
SolverDialog(const ProblemRouter *router, Physics::PhysicsBody *body, QWidget *parent=nullptr)