ifcviewer: include settings for deflection tolerances

This commit is contained in:
Dion Moult
2026-04-29 22:37:55 +10:00
parent 3607fbb762
commit 30cdffc27a
5 changed files with 82 additions and 1 deletions
+24
View File
@@ -22,6 +22,7 @@
#include <QCheckBox>
#include <QDialogButtonBox>
#include <QDoubleSpinBox>
#include <QFormLayout>
#include <QLineEdit>
#include <QShowEvent>
@@ -66,6 +67,25 @@ void SettingsWindow::setupUi() {
"time; dropping them keeps load times sane.");
form->addRow("Void Limit", void_limit_spin_);
deflection_tolerance_spin_ = new QDoubleSpinBox(this);
deflection_tolerance_spin_->setRange(0.000001, 1000.0);
deflection_tolerance_spin_->setDecimals(6);
deflection_tolerance_spin_->setSingleStep(0.001);
deflection_tolerance_spin_->setToolTip(
"Linear chord error between curved geometry and its triangulation, "
"in model length units. Smaller = smoother curves but more "
"triangles and slower load.");
form->addRow("Deflection Tolerance", deflection_tolerance_spin_);
angular_tolerance_spin_ = new QDoubleSpinBox(this);
angular_tolerance_spin_->setRange(0.000001, 3.141592);
angular_tolerance_spin_->setDecimals(6);
angular_tolerance_spin_->setSingleStep(0.05);
angular_tolerance_spin_->setToolTip(
"Maximum angle (radians) between adjacent facet normals on a "
"curved surface. Smaller = smoother shading but more triangles.");
form->addRow("Angular Tolerance", angular_tolerance_spin_);
auto* button_box = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
@@ -90,6 +110,8 @@ void SettingsWindow::syncFromSettings() {
backface_culling_check_->setChecked(AppSettings::instance().backfaceCulling());
load_data_source_check_->setChecked(AppSettings::instance().loadDataSource());
void_limit_spin_->setValue(AppSettings::instance().voidLimit());
deflection_tolerance_spin_->setValue(AppSettings::instance().deflectionTolerance());
angular_tolerance_spin_->setValue(AppSettings::instance().angularTolerance());
}
void SettingsWindow::onAccepted() {
@@ -98,5 +120,7 @@ void SettingsWindow::onAccepted() {
AppSettings::instance().setBackfaceCulling(backface_culling_check_->isChecked());
AppSettings::instance().setLoadDataSource(load_data_source_check_->isChecked());
AppSettings::instance().setVoidLimit(void_limit_spin_->value());
AppSettings::instance().setDeflectionTolerance(deflection_tolerance_spin_->value());
AppSettings::instance().setAngularTolerance(angular_tolerance_spin_->value());
accept();
}
+3
View File
@@ -23,6 +23,7 @@
#include <QDialog>
class QCheckBox;
class QDoubleSpinBox;
class QLineEdit;
class QShowEvent;
class QSpinBox;
@@ -47,6 +48,8 @@ private:
QCheckBox* backface_culling_check_ = nullptr;
QCheckBox* load_data_source_check_ = nullptr;
QSpinBox* void_limit_spin_ = nullptr;
QDoubleSpinBox* deflection_tolerance_spin_ = nullptr;
QDoubleSpinBox* angular_tolerance_spin_ = nullptr;
};
#endif
+34
View File
@@ -29,6 +29,10 @@ constexpr const char* kBackfaceCullingKey = "viewport/backface_culling";
constexpr const char* kLoadDataSourceKey = "loading/load_data_source";
constexpr const char* kVoidLimitKey = "loading/void_limit";
constexpr int kVoidLimitDefault = 30;
constexpr const char* kDeflectionToleranceKey = "loading/deflection_tolerance";
constexpr double kDeflectionToleranceDefault = 0.001;
constexpr const char* kAngularToleranceKey = "loading/angular_tolerance";
constexpr double kAngularToleranceDefault = 0.5;
}
AppSettings& AppSettings::instance() {
@@ -96,6 +100,30 @@ void AppSettings::setVoidLimit(int value) {
emit voidLimitChanged(value);
}
double AppSettings::deflectionTolerance() const {
return deflection_tolerance_;
}
void AppSettings::setDeflectionTolerance(double value) {
if (value <= 0.0) value = kDeflectionToleranceDefault;
if (deflection_tolerance_ == value) return;
deflection_tolerance_ = value;
persist();
emit deflectionToleranceChanged(value);
}
double AppSettings::angularTolerance() const {
return angular_tolerance_;
}
void AppSettings::setAngularTolerance(double value) {
if (value <= 0.0) value = kAngularToleranceDefault;
if (angular_tolerance_ == value) return;
angular_tolerance_ = value;
persist();
emit angularToleranceChanged(value);
}
void AppSettings::load() {
QSettings settings;
geometry_library_ = settings.value(kGeometryLibraryKey, kGeometryLibraryDefault).toString();
@@ -104,6 +132,10 @@ void AppSettings::load() {
load_data_source_ = settings.value(kLoadDataSourceKey, true).toBool();
void_limit_ = settings.value(kVoidLimitKey, kVoidLimitDefault).toInt();
if (void_limit_ < 0) void_limit_ = 0;
deflection_tolerance_ = settings.value(kDeflectionToleranceKey, kDeflectionToleranceDefault).toDouble();
if (deflection_tolerance_ <= 0.0) deflection_tolerance_ = kDeflectionToleranceDefault;
angular_tolerance_ = settings.value(kAngularToleranceKey, kAngularToleranceDefault).toDouble();
if (angular_tolerance_ <= 0.0) angular_tolerance_ = kAngularToleranceDefault;
}
void AppSettings::persist() {
@@ -113,4 +145,6 @@ void AppSettings::persist() {
settings.setValue(kBackfaceCullingKey, backface_culling_);
settings.setValue(kLoadDataSourceKey, load_data_source_);
settings.setValue(kVoidLimitKey, void_limit_);
settings.setValue(kDeflectionToleranceKey, deflection_tolerance_);
settings.setValue(kAngularToleranceKey, angular_tolerance_);
}
+15
View File
@@ -53,12 +53,25 @@ public:
int voidLimit() const;
void setVoidLimit(int value);
// Mesher tolerances passed straight to the IfcOpenShell iterator.
// Linear deflection bounds the chord error between a curve and its
// triangulation, in model length units; angular deflection bounds the
// angle (radians) between adjacent facet normals on a curved surface.
// Smaller values mean smoother geometry at the cost of more triangles
// and slower iteration.
double deflectionTolerance() const;
void setDeflectionTolerance(double value);
double angularTolerance() const;
void setAngularTolerance(double value);
signals:
void geometryLibraryChanged(const QString& value);
void showStatsChanged(bool value);
void backfaceCullingChanged(bool value);
void loadDataSourceChanged(bool value);
void voidLimitChanged(int value);
void deflectionToleranceChanged(double value);
void angularToleranceChanged(double value);
private:
AppSettings();
@@ -70,6 +83,8 @@ private:
bool backface_culling_ = true;
bool load_data_source_ = true;
int void_limit_ = 30;
double deflection_tolerance_ = 0.001;
double angular_tolerance_ = 0.5;
};
#endif // APPSETTINGS_H
+6 -1
View File
@@ -284,12 +284,17 @@ void GeometryStreamer::run(const std::string& path, int num_threads) {
// applied on the GPU per instance.
settings.set("use-world-coords", false);
settings.set("weld-vertices", false);
settings.set("apply-default-materials", true);
settings.set("apply-default-materials", false);
// Off by default in IfcOpenShell — makes face winding consistent within
// each shell, which we need for GL_CULL_FACE and for per-vertex normals
// to shade a solid without dark inside-out patches. Costs some iterator
// time, but results are cached in the sidecar so it's a one-shot hit.
settings.set("reorient-shells", true);
settings.set("layerset-first", true);
settings.set("mesher-linear-deflection", AppSettings::instance().deflectionTolerance());
settings.set("mesher-angular-deflection", AppSettings::instance().angularTolerance());
// Wire intersection checks is prohibitively slow on advanced breps. See bug #5999.
settings.set("no-wire-intersection-check", true);
// @todo parallel mapping on RocksDB-backed files still races somewhere
// outside the instance cache, producing inconsistent shape counts. Force