2026-10-10 19:02:17 +08:00
|
|
|
#include "CloudViewSettings.h"
|
|
|
|
|
|
|
|
|
|
#include <QColor>
|
|
|
|
|
#include <QDir>
|
|
|
|
|
#include <QSettings>
|
|
|
|
|
#include <QStandardPaths>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
QString settingsFilePath()
|
|
|
|
|
{
|
|
|
|
|
QString settingsDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
|
|
|
|
if (settingsDir.isEmpty()) {
|
|
|
|
|
settingsDir = QDir::homePath() + "/CloudView";
|
|
|
|
|
}
|
|
|
|
|
QDir().mkpath(settingsDir);
|
|
|
|
|
return QDir(settingsDir).filePath("CloudView.ini");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CloudViewSettingsData CloudViewSettings::load()
|
|
|
|
|
{
|
|
|
|
|
CloudViewSettingsData result;
|
|
|
|
|
QSettings settings(settingsFilePath(), QSettings::IniFormat);
|
|
|
|
|
|
|
|
|
|
// 模式独立于启用状态保存;缺失或非法配置默认采用“替换为全 0”。
|
|
|
|
|
const QVariant savedModeValue = settings.contains("PointCloudRange/filterMode")
|
|
|
|
|
? settings.value("PointCloudRange/filterMode")
|
|
|
|
|
: settings.value("PointCloudRange/mode",
|
|
|
|
|
static_cast<int>(PointCloudXYZRangeFilterMode::ReplaceWithZero));
|
|
|
|
|
const int savedFilterMode = savedModeValue.toInt();
|
|
|
|
|
const PointCloudXYZRangeFilterMode filterMode =
|
|
|
|
|
savedFilterMode == static_cast<int>(PointCloudXYZRangeFilterMode::Remove)
|
|
|
|
|
? PointCloudXYZRangeFilterMode::Remove
|
|
|
|
|
: PointCloudXYZRangeFilterMode::ReplaceWithZero;
|
|
|
|
|
|
|
|
|
|
const float poseAxisLength = settings.value("Display/poseAxisLength", result.poseAxisLength).toFloat();
|
|
|
|
|
if (std::isfinite(poseAxisLength) && poseAxisLength > 0.0f) {
|
|
|
|
|
result.poseAxisLength = poseAxisLength;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result.pseudoColorEnabled = settings.value("PseudoColor/enabled", result.pseudoColorEnabled).toBool();
|
|
|
|
|
const bool hasPaletteSetting = settings.contains("PseudoColor/defaultPalette");
|
|
|
|
|
result.pseudoColorDefaultPalette = hasPaletteSetting
|
|
|
|
|
? settings.value("PseudoColor/defaultPalette").toBool()
|
|
|
|
|
: result.pseudoColorDefaultPalette;
|
|
|
|
|
const float period = settings.value("PseudoColor/period", result.pseudoColorPeriod).toFloat();
|
|
|
|
|
if (std::isfinite(period) && period > 0.0f) {
|
|
|
|
|
result.pseudoColorPeriod = period;
|
|
|
|
|
}
|
|
|
|
|
const QColor startColor(settings.value("PseudoColor/startColor", "#0000ff").toString());
|
|
|
|
|
const QColor endColor(settings.value("PseudoColor/endColor", "#ff0000").toString());
|
|
|
|
|
if (startColor.isValid()) {
|
|
|
|
|
result.pseudoColorStartColor = QVector3D(startColor.redF(), startColor.greenF(), startColor.blueF());
|
|
|
|
|
}
|
|
|
|
|
if (endColor.isValid()) {
|
|
|
|
|
result.pseudoColorEndColor = QVector3D(endColor.redF(), endColor.greenF(), endColor.blueF());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!hasPaletteSetting && settings.contains("PseudoColor/period")) {
|
|
|
|
|
const QColor legacyStartColor(settings.value("PseudoColor/startColor", "#0000ff").toString());
|
|
|
|
|
const QColor legacyEndColor(settings.value("PseudoColor/endColor", "#ff0000").toString());
|
|
|
|
|
const bool legacyDefaults = qFuzzyCompare(result.pseudoColorPeriod, 100.0f) &&
|
|
|
|
|
legacyStartColor == QColor("#0000ff") &&
|
|
|
|
|
legacyEndColor == QColor("#ff0000");
|
|
|
|
|
if (legacyDefaults) {
|
|
|
|
|
// 旧版周期色环配置迁移为 Z 范围蓝→红梯度。
|
|
|
|
|
result.pseudoColorPeriod = 500.0f;
|
|
|
|
|
result.pseudoColorStartColor = QVector3D(0.0f, 0.0f, 1.0f);
|
|
|
|
|
result.pseudoColorEndColor = QVector3D(1.0f, 0.0f, 0.0f);
|
|
|
|
|
result.pseudoColorDefaultPalette = true;
|
|
|
|
|
} else {
|
|
|
|
|
// 非默认旧配置继续使用原有的自定义起止色渐变。
|
|
|
|
|
result.pseudoColorDefaultPalette = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool rangeEnabled = settings.value("PointCloudRange/enabled", false).toBool();
|
|
|
|
|
PointCloudXYZRange range;
|
|
|
|
|
range.enabled = rangeEnabled;
|
|
|
|
|
range.filterMode = filterMode;
|
|
|
|
|
if (rangeEnabled) {
|
|
|
|
|
const auto readBound = [&settings](const char* key, double fallback) {
|
|
|
|
|
bool ok = false;
|
|
|
|
|
const double value = settings.value(key).toDouble(&ok);
|
|
|
|
|
return ok && std::isfinite(value) ? value : fallback;
|
|
|
|
|
};
|
|
|
|
|
// Missing bounds retain the range object's implicit unbounded side.
|
|
|
|
|
range.minX = readBound("PointCloudRange/minX", range.minX);
|
|
|
|
|
range.maxX = readBound("PointCloudRange/maxX", range.maxX);
|
|
|
|
|
range.minY = readBound("PointCloudRange/minY", range.minY);
|
|
|
|
|
range.maxY = readBound("PointCloudRange/maxY", range.maxY);
|
|
|
|
|
range.minZ = readBound("PointCloudRange/minZ", range.minZ);
|
|
|
|
|
range.maxZ = readBound("PointCloudRange/maxZ", range.maxZ);
|
|
|
|
|
if (range.isValid()) {
|
|
|
|
|
result.pointCloudRange = range;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
result.pointCloudRange = range;
|
|
|
|
|
}
|
|
|
|
|
// Keep the mode even when a persisted enabled range is invalid and is
|
|
|
|
|
// therefore reset to the disabled default range.
|
|
|
|
|
result.pointCloudRange.filterMode = filterMode;
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CloudViewSettings::save(const CloudViewSettingsData& value)
|
|
|
|
|
{
|
|
|
|
|
QSettings settings(settingsFilePath(), QSettings::IniFormat);
|
|
|
|
|
if (std::isfinite(value.poseAxisLength) && value.poseAxisLength > 0.0f) {
|
|
|
|
|
settings.setValue("Display/poseAxisLength", value.poseAxisLength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
settings.setValue("PseudoColor/enabled", value.pseudoColorEnabled);
|
|
|
|
|
settings.setValue("PseudoColor/defaultPalette", value.pseudoColorDefaultPalette);
|
|
|
|
|
settings.setValue("PseudoColor/period", qMax(1.0f, value.pseudoColorPeriod));
|
|
|
|
|
settings.setValue("PseudoColor/startColor",
|
|
|
|
|
QColor::fromRgbF(value.pseudoColorStartColor.x(),
|
|
|
|
|
value.pseudoColorStartColor.y(),
|
|
|
|
|
value.pseudoColorStartColor.z()).name(QColor::HexRgb));
|
|
|
|
|
settings.setValue("PseudoColor/endColor",
|
|
|
|
|
QColor::fromRgbF(value.pseudoColorEndColor.x(),
|
|
|
|
|
value.pseudoColorEndColor.y(),
|
|
|
|
|
value.pseudoColorEndColor.z()).name(QColor::HexRgb));
|
|
|
|
|
|
|
|
|
|
const PointCloudXYZRange& range = value.pointCloudRange;
|
|
|
|
|
const bool saveRange = range.enabled && range.isValid();
|
|
|
|
|
settings.setValue("PointCloudRange/enabled", saveRange);
|
|
|
|
|
const int filterModeValue = range.filterMode == PointCloudXYZRangeFilterMode::Remove
|
|
|
|
|
? static_cast<int>(PointCloudXYZRangeFilterMode::Remove)
|
|
|
|
|
: static_cast<int>(PointCloudXYZRangeFilterMode::ReplaceWithZero);
|
|
|
|
|
settings.setValue("PointCloudRange/filterMode", filterModeValue);
|
|
|
|
|
settings.setValue("PointCloudRange/mode", filterModeValue);
|
|
|
|
|
if (saveRange) {
|
|
|
|
|
const auto saveBound = [&settings](const char* key, double bound) {
|
|
|
|
|
if (std::isfinite(bound)) {
|
|
|
|
|
settings.setValue(key, bound);
|
|
|
|
|
} else {
|
|
|
|
|
settings.remove(key);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
saveBound("PointCloudRange/minX", range.minX);
|
|
|
|
|
saveBound("PointCloudRange/maxX", range.maxX);
|
|
|
|
|
saveBound("PointCloudRange/minY", range.minY);
|
|
|
|
|
saveBound("PointCloudRange/maxY", range.maxY);
|
|
|
|
|
saveBound("PointCloudRange/minZ", range.minZ);
|
|
|
|
|
saveBound("PointCloudRange/maxZ", range.maxZ);
|
|
|
|
|
} else {
|
|
|
|
|
// Disabled ranges use implicit infinite bounds; do not persist infinities.
|
|
|
|
|
settings.remove("PointCloudRange/minX");
|
|
|
|
|
settings.remove("PointCloudRange/maxX");
|
|
|
|
|
settings.remove("PointCloudRange/minY");
|
|
|
|
|
settings.remove("PointCloudRange/maxY");
|
|
|
|
|
settings.remove("PointCloudRange/minZ");
|
|
|
|
|
settings.remove("PointCloudRange/maxZ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove keys from the former min/max/stop based implementation so old
|
|
|
|
|
// values cannot reappear in the user configuration file.
|
|
|
|
|
settings.remove("PseudoColor/autoRange");
|
|
|
|
|
settings.remove("PseudoColor/minZ");
|
|
|
|
|
settings.remove("PseudoColor/maxZ");
|
|
|
|
|
settings.remove("PseudoColor/divisionCount");
|
|
|
|
|
settings.remove("PseudoColor/gradient");
|
|
|
|
|
settings.remove("PseudoColor/stops");
|
|
|
|
|
|
|
|
|
|
settings.sync();
|
|
|
|
|
return settings.status() == QSettings::NoError;
|
|
|
|
|
}
|