Skip to content

Commit be1a895

Browse files
committed
Fix behaviour of double views wrt. rounding
1 parent c5006af commit be1a895

5 files changed

Lines changed: 32 additions & 8 deletions

File tree

gui/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ add_executable(
113113
source/pre/utils/IntegerRange.hpp
114114
source/pre/utils/UserSettings.cpp
115115
source/pre/utils/UserSettings.hpp
116+
source/pre/utils/Rounding.cpp
117+
source/pre/utils/Rounding.hpp
116118
source/pre/views/ArcView.cpp
117119
source/pre/views/ArcView.hpp
118120
source/pre/views/CommentsView.cpp
@@ -224,6 +226,8 @@ add_executable(
224226
source/post/StressPlot.hpp
225227
source/pre/Main.cpp
226228
source/pre/utils/ListUtils.hpp
229+
source/pre/utils/Rounding.hpp
230+
source/pre/utils/Rounding.cpp
227231
)
228232

229233
target_compile_definitions(virtualbow-gui PRIVATE JSON_HAS_CPP_17)

gui/source/pre/utils/Rounding.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "Rounding.hpp"
2+
#include <cmath>
3+
4+
double floorToPow10(double x) {
5+
if (x <= 0) {
6+
return 0.0;
7+
}
8+
9+
return std::pow(10, std::floor(std::log10(x)));
10+
}

gui/source/pre/utils/Rounding.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#pragma once
2+
3+
// Rounds a positive number down to the nearest power of 10 (e.g. 200 -> 100, 0.06 -> 0.01)
4+
double floorToPow10(double x);

gui/source/pre/views/ArrowMassView.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ ArrowMassView::ArrowMassView(QAbstractItemModel* model, QPersistentModelIndex in
1515
selectionBox->setToolTip(Tooltips::ArrowMassDefinition);
1616
selectionBox->addItems({"Mass", "Mass per Force", "Mass per Energy"});
1717

18-
auto massEdit = new DoubleSpinBox(Quantities::mass, DoubleRange::nonNegative(1e-3));
18+
auto massEdit = new DoubleSpinBox(Quantities::mass, DoubleRange::positive(1e-3));
1919
massEdit->setToolTip(Tooltips::ArrowMassAbsolute);
2020
massEdit->setValue(1e-3);
2121

22-
auto massPerForceEdit = new DoubleSpinBox(Quantities::mass_per_force, DoubleRange::nonNegative(1e-6));
22+
auto massPerForceEdit = new DoubleSpinBox(Quantities::mass_per_force, DoubleRange::positive(1e-6));
2323
massPerForceEdit->setToolTip(Tooltips::ArrowMassPerForce);
2424
massPerForceEdit->setValue(1e-6);
2525

26-
auto massPerEnergyEdit = new DoubleSpinBox(Quantities::mass_per_energy, DoubleRange::nonNegative(1e-4));
26+
auto massPerEnergyEdit = new DoubleSpinBox(Quantities::mass_per_energy, DoubleRange::positive(1e-4));
2727
massPerEnergyEdit->setToolTip(Tooltips::ArrowMassPerEnergy);
2828
massPerEnergyEdit->setValue(1e-4);
2929

gui/source/pre/widgets/DoubleSpinBox.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "DoubleSpinBox.hpp"
22
#include "pre/utils/DoubleRange.hpp"
33
#include "pre/utils/Expressions.hpp"
4+
#include "pre/utils/Rounding.hpp"
45
#include "pre/models/units/UnitSystem.hpp"
56
#include <QLineEdit>
67
#include <cmath>
@@ -11,8 +12,7 @@ DoubleSpinBox::DoubleSpinBox(const Quantity& quantity, const DoubleRange& range,
1112
show_unit(true),
1213
quantity(quantity)
1314
{
14-
setDecimals(8); // Magic number
15-
setSingleStep(range.step);
15+
setDecimals(16); // High precision since this only applies to the internal value stored in base unit. Conversion and rounding is done in textFromValue.
1616
setMinimum(-std::numeric_limits<double>::infinity()); // Not used
1717
setMaximum(std::numeric_limits<double>::infinity()); // Not used
1818

@@ -33,9 +33,9 @@ QString DoubleSpinBox::textFromValue(double baseValue) const {
3333
// Convert value given in SI base to the selected unit
3434
double unitValue = quantity.getUnit().fromBase(baseValue);
3535

36-
// Convert value to string with fixed-point representation
36+
// Convert value to string with fixed-point representation and limited precision for display
3737
// If the result has a decimal point, remove any trailing zeros and possibly the point as well
38-
QString result = QString::number(unitValue, 'f', decimals());
38+
QString result = QString::number(unitValue, 'f', 6);
3939
if(result.indexOf('.') != -1) {
4040
while(result.endsWith('0')) {
4141
result.chop(1);
@@ -80,7 +80,7 @@ QValidator::State DoubleSpinBox::validate(QString& text, int& pos) const {
8080

8181
// Overwriting this ensures that the range validation also applies to steps made by "spinning"
8282
void DoubleSpinBox::stepBy(int steps) {
83-
double newValue = value() + singleStep() * steps;
83+
double newValue = value() + singleStep()*steps; // Compute new value by applying step
8484
if(range.contains(newValue)) {
8585
setValue(newValue);
8686
emit contentModified(); // Signal modification by user
@@ -91,4 +91,10 @@ void DoubleSpinBox::updateUnit() {
9191
// Show the selected unit as suffix
9292
// Setting the suffix also triggers a new evaluation of textFromValue
9393
setSuffix(quantity.getUnit().getSuffix());
94+
95+
// Select the step so that is has a smooth value when converted to the unit
96+
double unitStep = quantity.getUnit().fromBase(range.step); // Convert the preferred step size to the unít
97+
unitStep = floorToPow10(unitStep); // Make the unit step a smooth value by rounding down to the nearest power of 10
98+
99+
setSingleStep(quantity.getUnit().toBase(unitStep)); // Convert back to base value and apply
94100
}

0 commit comments

Comments
 (0)