diff --git a/src/app/AxesSettingsPanel.cpp b/src/app/AxesSettingsPanel.cpp index dc1a2d8..9eba26c 100644 --- a/src/app/AxesSettingsPanel.cpp +++ b/src/app/AxesSettingsPanel.cpp @@ -1,11 +1,14 @@ #include "AxesSettingsPanel.hpp" +#include + #include #include #include #include #include #include +#include #include #include "Theme.hpp" @@ -28,8 +31,12 @@ AxesSettingsPanel::AxesSettingsPanel(QWidget* parent) : QFrame(parent) { auto* title = new QLabel(QStringLiteral("坐标轴设置"), this); title->setStyleSheet(QStringLiteral("font-weight:600;font-size:15px;border:none;")); auto* close = new QPushButton(QStringLiteral("✕"), this); - close->setFlat(true); close->setFixedSize(24, 24); + close->setCursor(Qt::PointingHandCursor); + // 显式覆盖全局 QPushButton 的 padding(6px 14px)/border——否则 24×24 容不下 padding,× 被挤出不可见。 + close->setStyleSheet(QStringLiteral( + "QPushButton{border:none;background:transparent;padding:0;margin:0;font-size:16px;color:#888;}" + "QPushButton:hover{color:#2f6fed;}")); connect(close, &QPushButton::clicked, this, &AxesSettingsPanel::closed); titleRow->addWidget(title); titleRow->addStretch(1); @@ -49,15 +56,25 @@ AxesSettingsPanel::AxesSettingsPanel(QWidget* parent) : QFrame(parent) { y_ = addAxisRow(v, QStringLiteral("Y轴"), {true, -500, 500}); z_ = addAxisRow(v, QStringLiteral("Z轴"), {true, 0, 200}); - // 放大系数(=垂直夸张)。 + // 放大系数(=垂直夸张):滑块 1~10×(恢复重构前的拖动交互)。拖动实时改标签, + // 松手(sliderReleased)才发信号触发一次重建——VE 改的是几何,必须重建,但不在拖动中连续重建。 + auto* scaleRow = new QHBoxLayout(); auto* scaleLbl = new QLabel(QStringLiteral("放大系数"), this); scaleLbl->setStyleSheet(QStringLiteral("border:none;")); - v->addWidget(scaleLbl); - scale_ = new QComboBox(this); - scale_->addItems({QStringLiteral("0.1"), QStringLiteral("0.5"), QStringLiteral("1"), - QStringLiteral("2"), QStringLiteral("5")}); - scale_->setCurrentText(QStringLiteral("1")); - v->addWidget(scale_); + scaleRow->addWidget(scaleLbl); + scaleSlider_ = new QSlider(Qt::Horizontal, this); + scaleSlider_->setMinimum(1); + scaleSlider_->setMaximum(10); + scaleSlider_->setValue(1); + scaleLabel_ = new QLabel(QStringLiteral("1.0×"), this); + scaleLabel_->setStyleSheet(QStringLiteral("border:none;color:#888;min-width:36px;")); + connect(scaleSlider_, &QSlider::valueChanged, this, + [this](int v) { scaleLabel_->setText(QStringLiteral("%1.0×").arg(v)); }); + connect(scaleSlider_, &QSlider::sliderReleased, this, + [this] { emit verticalExaggerationChanged(static_cast(scaleSlider_->value())); }); + scaleRow->addWidget(scaleSlider_, 1); + scaleRow->addWidget(scaleLabel_); + v->addLayout(scaleRow); // 取消 / 应用。 auto* btns = new QHBoxLayout(); @@ -71,7 +88,7 @@ AxesSettingsPanel::AxesSettingsPanel(QWidget* parent) : QFrame(parent) { auto rd = [](const Row& r) { return AxisRange{r.show->isChecked(), r.lo->value(), r.hi->value()}; }; - emit applied(rd(x_), rd(y_), rd(z_), unit_->currentIndex(), scale_->currentText().toDouble()); + emit applied(rd(x_), rd(y_), rd(z_), unit_->currentIndex()); }); btns->addStretch(1); btns->addWidget(cancel); @@ -115,6 +132,16 @@ AxesSettingsPanel::Row AxesSettingsPanel::addAxisRow(QVBoxLayout* col, const QSt hiCol->addWidget(r.hi); range->addLayout(hiCol); col->addLayout(range); + + // 取消「显示」时禁用该轴的最小/最大值编辑(隐藏的轴改范围无意义)。 + auto* lo = r.lo; + auto* hi = r.hi; + connect(r.show, &QCheckBox::toggled, this, [lo, hi](bool on) { + lo->setEnabled(on); + hi->setEnabled(on); + }); + r.lo->setEnabled(def.show); + r.hi->setEnabled(def.show); return r; } @@ -123,12 +150,17 @@ void AxesSettingsPanel::setValues(AxisRange x, AxisRange y, AxisRange z, int uni r.show->setChecked(a.show); r.lo->setValue(a.min); r.hi->setValue(a.max); + r.lo->setEnabled(a.show); // 回灌时同步禁用态(隐藏轴 → 禁编辑) + r.hi->setEnabled(a.show); }; wr(x_, x); wr(y_, y); wr(z_, z); unit_->setCurrentIndex(unitIdx); - scale_->setCurrentText(QString::number(scale)); // 命中预设项则选中,否则保持 + const int v = std::max(1, std::min(10, static_cast(scale + 0.5))); + QSignalBlocker block(scaleSlider_); // 回灌不触发 sliderReleased + scaleSlider_->setValue(v); + scaleLabel_->setText(QStringLiteral("%1.0×").arg(v)); } } // namespace geopro::app diff --git a/src/app/AxesSettingsPanel.hpp b/src/app/AxesSettingsPanel.hpp index 9c40ba7..eed8f3d 100644 --- a/src/app/AxesSettingsPanel.hpp +++ b/src/app/AxesSettingsPanel.hpp @@ -7,6 +7,8 @@ class QCheckBox; class QComboBox; class QDoubleSpinBox; class QVBoxLayout; +class QSlider; +class QLabel; namespace geopro::app { @@ -21,7 +23,10 @@ public: void setValues(AxisRange x, AxisRange y, AxisRange z, int unitIdx, double scale); signals: - void applied(AxisRange x, AxisRange y, AxisRange z, int unitIdx, double scale); + // 「应用」:仅坐标轴(显示方式/单位/per-axis 可见性·范围);走增量重建,不重绘数据。 + void applied(AxisRange x, AxisRange y, AxisRange z, int unitIdx); + // 放大系数(=垂直夸张)滑块:拖动实时改数值标签,松手才发此信号触发一次重建。 + void verticalExaggerationChanged(double ve); void closed(); // × 或 取消 private: @@ -32,8 +37,9 @@ private: }; Row addAxisRow(QVBoxLayout* col, const QString& title, const AxisRange& def); - QComboBox* unit_ = nullptr; // 坐标轴单位:米 / 英尺 - QComboBox* scale_ = nullptr; // 放大系数:0.1 / 0.5 / 1 / 2 / 5 + QComboBox* unit_ = nullptr; // 坐标轴单位:米 / 英尺 + QSlider* scaleSlider_ = nullptr; // 放大系数(=垂直夸张)滑块 1~10× + QLabel* scaleLabel_ = nullptr; // 滑块当前值标签(如「3.0×」) Row x_, y_, z_; }; diff --git a/src/app/main.cpp b/src/app/main.cpp index f10779d..dc639d8 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -943,11 +943,11 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re // 垂直夸张:地形须与剖面用同一 VE 才对齐(都按真实高程×VE)。单一来源 kVerticalExaggeration 下发 // 控制器(上方)/底图;运行时 VE 改由坐标轴设置抽屉「应用」下发(旧三维数据集栏滑块已退役)。 basemap->setVerticalExaggeration(kVerticalExaggeration); - // 坐标轴设置抽屉「应用」:轴显示开关 + 放大系数(=垂直夸张,下发控制器+底图);范围/单位待控制器 API。 + // 坐标轴设置抽屉「应用」:仅轴显示开关 + 单位 + per-axis 范围 → 走 setAxesConfig(已改增量重建, + // 不再清场景重绘数据)。放大系数=垂直夸张改由滑块独立信号下发(见下)。 QObject::connect(axesPanel, &geopro::app::AxesSettingsPanel::applied, &window, - [axesPanel, sceneCtrl, basemap](geopro::app::AxisRange x, geopro::app::AxisRange y, - geopro::app::AxisRange z, int unitIdx, - double scale) { + [axesPanel, sceneCtrl](geopro::app::AxisRange x, geopro::app::AxisRange y, + geopro::app::AxisRange z, int unitIdx) { const bool anyShow = x.show || y.show || z.show; // 每轴:可见性=显示开关;自定义范围=面板 min/max(按当前单位),真正改刻度。 auto cfg = [](const geopro::app::AxisRange& a) { @@ -958,12 +958,15 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re unitIdx == 1 ? geopro::controller::AxesUnit::Feet : geopro::controller::AxesUnit::Meter, cfg(x), cfg(y), cfg(z)); - if (scale > 0) { // 放大系数=垂直夸张:控制器 + 底图同步 - sceneCtrl->setVerticalExaggeration(scale); - basemap->setVerticalExaggeration(scale); - } axesPanel->hide(); }); + // 放大系数滑块(=垂直夸张):松手即下发控制器 + 底图(VE 改几何须一次重建,但不在拖动中连续重建)。 + QObject::connect(axesPanel, &geopro::app::AxesSettingsPanel::verticalExaggerationChanged, &window, + [sceneCtrl, basemap](double ve) { + if (ve <= 0) return; + sceneCtrl->setVerticalExaggeration(ve); + basemap->setVerticalExaggeration(ve); + }); // ── 中央“空状态”引导浮层:未接入真实 sections 时,引导首次使用者从左侧入手。── // 透明背景 + 鼠标穿透(不挡 QVTK 交互);CenterOverlay 随视口尺寸保持居中; diff --git a/src/controller/VtkSceneController.cpp b/src/controller/VtkSceneController.cpp index b7d9109..957eab6 100644 --- a/src/controller/VtkSceneController.cpp +++ b/src/controller/VtkSceneController.cpp @@ -256,7 +256,11 @@ void VtkSceneController::setAxesConfig(AxesMode mode, AxesUnit unit, const AxisR axisX_ = x; axisY_ = y; axisZ_ = z; - rebuildInternal(); // 一次重建应用全部坐标轴设置 + // 增量:坐标轴只是 overlay prop,改单位/范围/可见性无需清场景重载数据。仅把配置下发 view 后 + // renderIncremental(rebuildAxes 重建坐标轴 prop + Render),不动数据图元、不重置相机。 + view_.setAxes(axesMode_, axesUnit_, kAxesFontSize); + view_.setAxesRanges(axisX_, axisY_, axisZ_); + view_.renderIncremental(); } // 快捷视图 / 缩放:仅改相机,不重建场景(无须取数/重装图元)。 diff --git a/src/render/actors/AxesActor.cpp b/src/render/actors/AxesActor.cpp index eedd5ce..3075b61 100644 --- a/src/render/actors/AxesActor.cpp +++ b/src/render/actors/AxesActor.cpp @@ -94,10 +94,23 @@ vtkSmartPointer buildAxes(const double bounds[6], const AxesOp ax->SetZUnits(u); } - // per-axis 显示开关(整轴:线 + 刻度 + 标签 + 标题)。 + // per-axis 显示开关。SetXAxisVisibility 只关轴线,刻度数字/标签/刻度线需单独关, + // 否则隐藏某轴后该轴的数字仍悬浮在场景里(用户实测 bug)。 ax->SetXAxisVisibility(opts.x.visible); ax->SetYAxisVisibility(opts.y.visible); ax->SetZAxisVisibility(opts.z.visible); + if (!opts.x.visible) { + ax->SetXAxisLabelVisibility(false); + ax->SetXAxisTickVisibility(false); + } + if (!opts.y.visible) { + ax->SetYAxisLabelVisibility(false); + ax->SetYAxisTickVisibility(false); + } + if (!opts.z.visible) { + ax->SetZAxisLabelVisibility(false); + ax->SetZAxisTickVisibility(false); + } applyFont(ax, opts.fontSize); return ax;