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  connect(sliceXActi, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
190  connect(sliceYActi, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
191  connect(sliceZActi, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
192 
193  connect(sliceXInve, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
194  connect(sliceYInve, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
195  connect(sliceZInve, &QCheckBox::stateChanged, this, &G4DisplayView::slice);
196 
197 
198  QGroupBox* fieldPrecisionBox = new QGroupBox(tr("Number of Field Points"));
199  field_npoints = new QLineEdit(QString::number(field_NPOINTS), this);
200  field_npoints->setMaximumWidth(40);
201 
202  QFont font = field_npoints->font();
203  font.setPointSize(24);
204  field_npoints->setFont(font);
205  connect(field_npoints, &QLineEdit::returnPressed, this, &G4DisplayView::field_precision_changed);
206 
207  // buttons + field line number
208  auto fieldPointsHBox = new QHBoxLayout;
209  fieldPointsHBox->addWidget(field_npoints);
210  fieldPrecisionBox->setLayout(fieldPointsHBox);
211 
212  auto buttons_field_HBox = new QHBoxLayout;
213  buttons_field_HBox->addWidget(buttons_set1);
214  buttons_field_HBox->addWidget(fieldPrecisionBox);
215  fieldPrecisionBox->setMaximumHeight(3 * buttons_set1->height());
216  fieldPrecisionBox->setMaximumWidth(140);
217 
218 
219  // All layouts together
220  auto mainLayout = new QVBoxLayout;
221  mainLayout->addLayout(buttons_field_HBox);
222  mainLayout->addWidget(cameraAnglesGroup);
223  mainLayout->addWidget(lightAnglesGroup);
224  mainLayout->addLayout(sliceLayout);
225  setLayout(mainLayout);
226 }
227 
234 void G4DisplayView::changeCameraDirection() {
235  // Construct the command using the current slider values.
236  string command = "/vis/viewer/set/viewpointThetaPhi " +
237  to_string(cameraTheta->value()) + " " +
238  to_string(cameraPhi->value());
239  // Send the command to the Geant4 UImanager.
240  G4UImanager::GetUIpointer()->ApplyCommand(command);
241 }
242 
249 void G4DisplayView::changeLightDirection() {
250  string command = "/vis/viewer/set/lightsThetaPhi " +
251  to_string(lightTheta->value()) + " " +
252  to_string(lightPhi->value());
253  G4UImanager::GetUIpointer()->ApplyCommand(command);
254 }
255 
256 
264 void G4DisplayView::slice() {
265  G4UImanager* g4uim = G4UImanager::GetUIpointer();
266  if (g4uim == nullptr) { return; }
267 
268  // can't have a mix of wireframe / solid when doing a slice.
269  // forcing all to be solid
270  // if(!solidVis) {
271  // g4uim->ApplyCommand("/vis/geometry/set/forceSolid all -1 1");
272  // }
273 
274  g4uim->ApplyCommand("/vis/viewer/clearCutawayPlanes");
275 
276  if (sliceSectn->isChecked()) { g4uim->ApplyCommand("/vis/viewer/set/cutawayMode intersection"); }
277  else if (sliceUnion->isChecked()) { g4uim->ApplyCommand("/vis/viewer/set/cutawayMode union"); }
278 
279  g4uim->ApplyCommand("/vis/viewer/clearCutawayPlanes");
280 
281  if (sliceXActi->isChecked()) {
282  string command = "/vis/viewer/addCutawayPlane " + sliceXEdit->text().toStdString() + " 0 0 mm " +
283  to_string(sliceXInve->isChecked() ? -1 : 1) + " 0 0 ";
284  cout << "X " << command << endl;
285  g4uim->ApplyCommand(command);
286  }
287 
288  if (sliceYActi->isChecked()) {
289  string command = "/vis/viewer/addCutawayPlane 0 " + sliceYEdit->text().toStdString() + " 0 mm 0 " +
290  to_string(sliceYInve->isChecked() ? -1 : 1) + " 0 ";
291  cout << "Y " << command << endl;
292  g4uim->ApplyCommand(command);
293  }
294 
295  if (sliceZActi->isChecked()) {
296  string command = "/vis/viewer/addCutawayPlane 0 0 " + sliceZEdit->text().toStdString() + " mm 0 0 " +
297  to_string(sliceZInve->isChecked() ? -1 : 1);
298  cout << "Z " << command << endl;
299  g4uim->ApplyCommand(command);
300  }
301 
302  //solidVis = true;
303 }
304 
305 
311 void G4DisplayView::clearSlices() {
312  G4UImanager::GetUIpointer()->ApplyCommand("/vis/viewer/clearCutawayPlanes");
313  sliceXActi->setChecked(false);
314 }
315 
325 void G4DisplayView::apply_buttons_set1(int index) {
326  G4UImanager* g4uim = G4UImanager::GetUIpointer();
327  if (g4uim == nullptr) { return; }
328 
329  bool button_state = buttons_set1->lastButtonState();
330 
331  if (index == 0) {
332  string command = string("/vis/viewer/set/hiddenEdge") + (button_state ? " 1" : " 0");
333  g4uim->ApplyCommand(command);
334  g4uim->ApplyCommand("/vis/viewer/flush");
335  }
336  else if (index == 1) {
337  if (button_state == 0) {
338  glDisable(GL_LINE_SMOOTH);
339  glDisable(GL_POLYGON_SMOOTH);
340  }
341  else {
342  glEnable(GL_LINE_SMOOTH);
343  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
344  glEnable(GL_POLYGON_SMOOTH);
345  glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
346  }
347  }
348  else if (index == 2) {
349  string command = string("/vis/viewer/set/auxiliaryEdge") + (button_state ? " 1" : " 0");
350  g4uim->ApplyCommand(command);
351  command = string("/vis/viewer/set/hiddenEdge") + (button_state ? " 1" : " 0");
352  g4uim->ApplyCommand(command);
353  if (buttons_set1->buttonStatus(0) != button_state) { buttons_set1->toggleButton(0); }
354  }
355  else if (index == 3) {
356  if (button_state == 0) {
357  string command = string("vis/scene/activateModel Field 0");
358  g4uim->ApplyCommand(command);
359  g4uim->ApplyCommand("/vis/scene/removeModel Field");
360  }
361  else {
362  string npoints = to_string(field_NPOINTS);
363  string command = string("/vis/scene/add/magneticField ") + npoints;
364  g4uim->ApplyCommand(command);
365  }
366  }
367 }
368 
375 void G4DisplayView::field_precision_changed() {
376  G4UImanager* g4uim = G4UImanager::GetUIpointer();
377  if (g4uim == nullptr) { return; }
378  field_NPOINTS = field_npoints->text().toInt();
379  if (buttons_set1->buttonStatus(3) == 1) {
380  string command = string("vis/scene/activateModel Field 0");
381  g4uim->ApplyCommand(command);
382  g4uim->ApplyCommand("/vis/scene/removeModel Field");
383 
384  string npoints = to_string(field_NPOINTS);
385  command = string("/vis/scene/add/magneticField ") + npoints;
386  G4UImanager::GetUIpointer()->ApplyCommand(command);
387  }
388 }
G4DisplayView(GOptions *gopts, std::shared_ptr< GLogger >, QWidget *parent=nullptr)
Constructs the G4DisplayView widget.
G4Camera getG4Camera(GOptions *gopts)