g4display
g4displayview.cc
Go to the documentation of this file.
1 #include "g4displayview.h"
2 #include "g4display_options.h"
3 #include "gutilities.h"
4 
5 using namespace g4display;
6 
7 #include <iostream>
8 #include <string>
9 
10 using namespace std;
11 using namespace gutilities;
12 
24 G4DisplayView::G4DisplayView(GOptions* gopts, std::shared_ptr<GLogger> logger, QWidget* parent) : QWidget(parent), log(logger) {
25  log->debug(CONSTRUCTOR, "G4DisplayView");
26 
27  G4Camera jcamera = getG4Camera(gopts);
28 
29  double thetaValue = getG4Number(jcamera.theta);
30  double phiValue = getG4Number(jcamera.phi);
31 
32  vector<string> toggle_button_titles;
33  toggle_button_titles.emplace_back("Hidden\nLines");
34  toggle_button_titles.emplace_back("Anti\nAliasing");
35  toggle_button_titles.emplace_back("Auxiliary\nEdges");
36  toggle_button_titles.emplace_back("Field\nLines");
37 
38 
39  buttons_set1 = new GQTToggleButtonWidget(80, 80, 20, toggle_button_titles, false, this);
40  connect(buttons_set1, &GQTToggleButtonWidget::buttonPressedIndexChanged, this, &G4DisplayView::apply_buttons_set1);
41 
42  // Camera sliders
43  cameraTheta = new QSlider(Qt::Horizontal);
44  cameraTheta->setRange(0, 180);
45  cameraTheta->setSingleStep(1);
46  cameraTheta->setValue(thetaValue);
47  auto cameraThetaLabel = new QLabel(tr("θ"));
48 
49  auto cameraThetaLayout = new QHBoxLayout;
50  cameraThetaLayout->addWidget(cameraThetaLabel);
51  cameraThetaLayout->addWidget(cameraTheta);
52 
53  cameraPhi = new QSlider(Qt::Horizontal);
54  cameraPhi->setRange(0, 360);
55  cameraPhi->setSingleStep(1);
56  cameraPhi->setValue(phiValue);
57  auto cameraPhiLabel = new QLabel(tr("ɸ"));
58 
59  auto cameraPhiLayout = new QHBoxLayout;
60  cameraPhiLayout->addWidget(cameraPhiLabel);
61  cameraPhiLayout->addWidget(cameraPhi);
62 
63  QVBoxLayout* cameraDirectionLayout = new QVBoxLayout;
64  cameraDirectionLayout->addLayout(cameraThetaLayout);
65  cameraDirectionLayout->addSpacing(12);
66  cameraDirectionLayout->addLayout(cameraPhiLayout);
67 
68  QGroupBox* cameraAnglesGroup = new QGroupBox(tr("Camera Direction"));
69  cameraAnglesGroup->setLayout(cameraDirectionLayout);
70 
71  connect(cameraTheta, &QSlider::valueChanged, this, &G4DisplayView::changeCameraDirection);
72  connect(cameraPhi, &QSlider::valueChanged, this, &G4DisplayView::changeCameraDirection);
73 
74  // Light Direction
75  lightTheta = new QSlider(Qt::Horizontal);
76  lightTheta->setRange(0, 180);
77  lightTheta->setSingleStep(1);
78  lightTheta->setValue(thetaValue);
79  auto lightThetaLabel = new QLabel(tr("θ"));
80 
81  auto lightThetaLayout = new QHBoxLayout;
82  lightThetaLayout->addWidget(lightThetaLabel);
83  lightThetaLayout->addWidget(lightTheta);
84 
85  lightPhi = new QSlider(Qt::Horizontal);
86  lightPhi->setRange(0, 360);
87  lightPhi->setSingleStep(1);
88  lightPhi->setValue(phiValue);
89  auto lightPhiLabel = new QLabel(tr("ɸ"));
90 
91  auto lightPhiLayout = new QHBoxLayout;
92  lightPhiLayout->addWidget(lightPhiLabel);
93  lightPhiLayout->addWidget(lightPhi);
94 
95  auto lightDirectionLayout = new QVBoxLayout;
96  lightDirectionLayout->addLayout(lightThetaLayout);
97  lightDirectionLayout->addSpacing(12);
98  lightDirectionLayout->addLayout(lightPhiLayout);
99 
100  QGroupBox* lightAnglesGroup = new QGroupBox(tr("Light Direction"));
101  lightAnglesGroup->setLayout(lightDirectionLayout);
102 
103  connect(lightTheta, &QSlider::valueChanged, this, &G4DisplayView::changeLightDirection);
104  connect(lightPhi, &QSlider::valueChanged, this, &G4DisplayView::changeLightDirection);
105 
106  // x slice
107  sliceXEdit = new QLineEdit(tr("0"));
108  sliceXEdit->setMaximumWidth(100);
109  sliceXActi = new QCheckBox(tr("&On"));
110  sliceXActi->setChecked(false);
111  sliceXInve = new QCheckBox(tr("&Flip"));
112  sliceXInve->setChecked(false);
113  auto sliceXLayout = new QHBoxLayout;
114  sliceXLayout->addWidget(new QLabel(tr("X: ")));
115  sliceXLayout->addWidget(sliceXEdit);
116  sliceXLayout->addStretch(1);
117  sliceXLayout->addWidget(sliceXActi);
118  sliceXLayout->addWidget(sliceXInve);
119  sliceXLayout->addStretch(1);
120 
121 
122  // y slice
123  sliceYEdit = new QLineEdit(tr("0"));
124  sliceYEdit->setMaximumWidth(100);
125  sliceYActi = new QCheckBox(tr("&On"));
126  sliceYActi->setChecked(false);
127  sliceYInve = new QCheckBox(tr("&Flip"));
128  sliceYInve->setChecked(false);
129  auto sliceYLayout = new QHBoxLayout;
130  sliceYLayout->addWidget(new QLabel(tr("Y: ")));
131  sliceYLayout->addWidget(sliceYEdit);
132  sliceYLayout->addStretch(1);
133  sliceYLayout->addWidget(sliceYActi);
134  sliceYLayout->addWidget(sliceYInve);
135  sliceYLayout->addStretch(1);
136 
137  // z slice
138  sliceZEdit = new QLineEdit(tr("0"));
139  sliceZEdit->setMaximumWidth(100);
140  sliceZActi = new QCheckBox(tr("&On"));
141  sliceZActi->setChecked(false);
142  sliceZInve = new QCheckBox(tr("&Flip"));
143  sliceZInve->setChecked(false);
144  auto sliceZLayout = new QHBoxLayout;
145  sliceZLayout->addWidget(new QLabel(tr("Z: ")));
146  sliceZLayout->addWidget(sliceZEdit);
147  sliceZLayout->addStretch(1);
148  sliceZLayout->addWidget(sliceZActi);
149  sliceZLayout->addWidget(sliceZInve);
150  sliceZLayout->addStretch(1);
151 
152  // clear sice button
153  QPushButton* clearSliceButton = new QPushButton(tr("Clear Slices"));
154  clearSliceButton->setToolTip("Clear Slice Planes");
155  clearSliceButton->setIcon(QIcon::fromTheme("edit-clear"));
156  clearSliceButton->setIconSize(QSize(16, 16)); // Adjust as necessary
157 
158  connect(clearSliceButton, &QPushButton::clicked, this, &G4DisplayView::clearSlices);
159 
160  // slice style: Intersection or Union
161  QGroupBox* sliceChoiceBox = new QGroupBox(tr("Slices Style"));
162  sliceSectn = new QRadioButton(tr("&Intersection"), sliceChoiceBox);
163  sliceUnion = new QRadioButton(tr("&Union"), sliceChoiceBox);
164  sliceSectn->setChecked(true);
165 
166  connect(sliceSectn, &QRadioButton::toggled, this, &G4DisplayView::slice);
167  connect(sliceUnion, &QRadioButton::toggled, this, &G4DisplayView::slice);
168 
169  auto sliceChoiceLayout = new QHBoxLayout;
170  sliceChoiceLayout->addWidget(sliceSectn);
171  sliceChoiceLayout->addWidget(sliceUnion);
172  sliceChoiceBox->setLayout(sliceChoiceLayout);
173 
174 
175  // slices layout
176  auto sliceLayout = new QVBoxLayout;
177  sliceLayout->addLayout(sliceXLayout);
178  sliceLayout->addLayout(sliceYLayout);
179  sliceLayout->addLayout(sliceZLayout);
180  sliceLayout->addWidget(sliceChoiceBox);
181  sliceLayout->addWidget(clearSliceButton);
182 
183 
184  // connecting widgets to slice
185  connect(sliceXEdit, &QLineEdit::returnPressed, this, &G4DisplayView::slice);
186  connect(sliceYEdit, &QLineEdit::returnPressed, this, &G4DisplayView::slice);
187  connect(sliceZEdit, &QLineEdit::returnPressed, this, &G4DisplayView::slice);
188 
189 
190 #if QT_VERSION < QT_VERSION_CHECK(6, 7, 0) // Qt ≤6.6
191  connect(sliceXActi, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
192  connect(sliceYActi, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
193  connect(sliceZActi, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
194  connect(sliceXInve, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
195  connect(sliceYInve, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
196  connect(sliceZInve, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
197 #else // Qt≥6.7
198  connect(sliceXActi, &QCheckBox::checkStateChanged, this, &G4DisplayView::slice);
199  connect(sliceYActi, &QCheckBox::checkStateChanged, this, &G4DisplayView::slice);
200  connect(sliceZActi, &QCheckBox::checkStateChanged, this, &G4DisplayView::slice);
201  connect(sliceXInve, &QCheckBox::checkStateChanged, this, &G4DisplayView::slice);
202  connect(sliceYInve, &QCheckBox::checkStateChanged, this, &G4DisplayView::slice);
203  connect(sliceZInve, &QCheckBox::checkStateChanged, this, &G4DisplayView::slice);
204 #endif
205 
206 
207  QGroupBox* fieldPrecisionBox = new QGroupBox(tr("Number of Field Points"));
208  field_npoints = new QLineEdit(QString::number(field_NPOINTS), this);
209  field_npoints->setMaximumWidth(40);
210 
211  QFont font = field_npoints->font();
212  font.setPointSize(24);
213  field_npoints->setFont(font);
214  connect(field_npoints, &QLineEdit::returnPressed, this, &G4DisplayView::field_precision_changed);
215 
216  // buttons + field line number
217  auto fieldPointsHBox = new QHBoxLayout;
218  fieldPointsHBox->addWidget(field_npoints);
219  fieldPrecisionBox->setLayout(fieldPointsHBox);
220 
221  auto buttons_field_HBox = new QHBoxLayout;
222  buttons_field_HBox->addWidget(buttons_set1);
223  buttons_field_HBox->addWidget(fieldPrecisionBox);
224  fieldPrecisionBox->setMaximumHeight(3 * buttons_set1->height());
225  fieldPrecisionBox->setMaximumWidth(140);
226 
227 
228  // All layouts together
229  auto mainLayout = new QVBoxLayout;
230  mainLayout->addLayout(buttons_field_HBox);
231  mainLayout->addWidget(cameraAnglesGroup);
232  mainLayout->addWidget(lightAnglesGroup);
233  mainLayout->addLayout(sliceLayout);
234  setLayout(mainLayout);
235 }
236 
243 void G4DisplayView::changeCameraDirection() {
244  // Construct the command using the current slider values.
245  string command = "/vis/viewer/set/viewpointThetaPhi " +
246  to_string(cameraTheta->value()) + " " +
247  to_string(cameraPhi->value());
248  // Send the command to the Geant4 UImanager.
249  G4UImanager::GetUIpointer()->ApplyCommand(command);
250 }
251 
258 void G4DisplayView::changeLightDirection() {
259  string command = "/vis/viewer/set/lightsThetaPhi " +
260  to_string(lightTheta->value()) + " " +
261  to_string(lightPhi->value());
262  G4UImanager::GetUIpointer()->ApplyCommand(command);
263 }
264 
265 
273 void G4DisplayView::slice() {
274  G4UImanager* g4uim = G4UImanager::GetUIpointer();
275  if (g4uim == nullptr) { return; }
276 
277  // can't have a mix of wireframe / solid when doing a slice.
278  // forcing all to be solid
279  // if(!solidVis) {
280  // g4uim->ApplyCommand("/vis/geometry/set/forceSolid all -1 1");
281  // }
282 
283  g4uim->ApplyCommand("/vis/viewer/clearCutawayPlanes");
284 
285  if (sliceSectn->isChecked()) { g4uim->ApplyCommand("/vis/viewer/set/cutawayMode intersection"); }
286  else if (sliceUnion->isChecked()) { g4uim->ApplyCommand("/vis/viewer/set/cutawayMode union"); }
287 
288  g4uim->ApplyCommand("/vis/viewer/clearCutawayPlanes");
289 
290  if (sliceXActi->isChecked()) {
291  string command = "/vis/viewer/addCutawayPlane " + sliceXEdit->text().toStdString() + " 0 0 mm " +
292  to_string(sliceXInve->isChecked() ? -1 : 1) + " 0 0 ";
293  cout << "X " << command << endl;
294  g4uim->ApplyCommand(command);
295  }
296 
297  if (sliceYActi->isChecked()) {
298  string command = "/vis/viewer/addCutawayPlane 0 " + sliceYEdit->text().toStdString() + " 0 mm 0 " +
299  to_string(sliceYInve->isChecked() ? -1 : 1) + " 0 ";
300  cout << "Y " << command << endl;
301  g4uim->ApplyCommand(command);
302  }
303 
304  if (sliceZActi->isChecked()) {
305  string command = "/vis/viewer/addCutawayPlane 0 0 " + sliceZEdit->text().toStdString() + " mm 0 0 " +
306  to_string(sliceZInve->isChecked() ? -1 : 1);
307  cout << "Z " << command << endl;
308  g4uim->ApplyCommand(command);
309  }
310 
311  //solidVis = true;
312 }
313 
314 
320 void G4DisplayView::clearSlices() {
321  G4UImanager::GetUIpointer()->ApplyCommand("/vis/viewer/clearCutawayPlanes");
322  sliceXActi->setChecked(false);
323 }
324 
334 void G4DisplayView::apply_buttons_set1(int index) {
335  G4UImanager* g4uim = G4UImanager::GetUIpointer();
336  if (g4uim == nullptr) { return; }
337 
338  bool button_state = buttons_set1->lastButtonState();
339 
340  if (index == 0) {
341  string command = string("/vis/viewer/set/hiddenEdge") + (button_state ? " 1" : " 0");
342  g4uim->ApplyCommand(command);
343  g4uim->ApplyCommand("/vis/viewer/flush");
344  }
345  else if (index == 1) {
346  if (button_state == 0) {
347  glDisable(GL_LINE_SMOOTH);
348  glDisable(GL_POLYGON_SMOOTH);
349  }
350  else {
351  glEnable(GL_LINE_SMOOTH);
352  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
353  glEnable(GL_POLYGON_SMOOTH);
354  glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
355  }
356  }
357  else if (index == 2) {
358  string command = string("/vis/viewer/set/auxiliaryEdge") + (button_state ? " 1" : " 0");
359  g4uim->ApplyCommand(command);
360  command = string("/vis/viewer/set/hiddenEdge") + (button_state ? " 1" : " 0");
361  g4uim->ApplyCommand(command);
362  if (buttons_set1->buttonStatus(0) != button_state) { buttons_set1->toggleButton(0); }
363  }
364  else if (index == 3) {
365  if (button_state == 0) {
366  string command = string("vis/scene/activateModel Field 0");
367  g4uim->ApplyCommand(command);
368  g4uim->ApplyCommand("/vis/scene/removeModel Field");
369  }
370  else {
371  string npoints = to_string(field_NPOINTS);
372  string command = string("/vis/scene/add/magneticField ") + npoints;
373  g4uim->ApplyCommand(command);
374  }
375  }
376 }
377 
384 void G4DisplayView::field_precision_changed() {
385  G4UImanager* g4uim = G4UImanager::GetUIpointer();
386  if (g4uim == nullptr) { return; }
387  field_NPOINTS = field_npoints->text().toInt();
388  if (buttons_set1->buttonStatus(3) == 1) {
389  string command = string("vis/scene/activateModel Field 0");
390  g4uim->ApplyCommand(command);
391  g4uim->ApplyCommand("/vis/scene/removeModel Field");
392 
393  string npoints = to_string(field_NPOINTS);
394  command = string("/vis/scene/add/magneticField ") + npoints;
395  G4UImanager::GetUIpointer()->ApplyCommand(command);
396  }
397 }
G4DisplayView(GOptions *gopts, std::shared_ptr< GLogger > logger, QWidget *parent=nullptr)
Constructs the G4DisplayView widget.
G4Camera getG4Camera(GOptions *gopts)