feat/vtk-3d-view #7
|
|
@ -253,6 +253,14 @@ void VtkSceneView::setAxes(geopro::controller::AxesMode mode, geopro::controller
|
|||
axesFontSize_ = fontSize;
|
||||
}
|
||||
|
||||
void VtkSceneView::setAxesRanges(const geopro::controller::AxisRangeCfg& x,
|
||||
const geopro::controller::AxisRangeCfg& y,
|
||||
const geopro::controller::AxisRangeCfg& z) {
|
||||
axisX_ = x;
|
||||
axisY_ = y;
|
||||
axisZ_ = z;
|
||||
}
|
||||
|
||||
void VtkSceneView::applyCameraView(geopro::controller::ViewDir dir) {
|
||||
geopro::render::applyView(scene_.renderer(), toRenderViewDir(dir)); // 设朝向(内部 ResetCamera 含底图)
|
||||
double bounds[6];
|
||||
|
|
@ -296,6 +304,12 @@ void VtkSceneView::rebuildAxes() {
|
|||
opts.unit = toRenderUnit(axesUnit_);
|
||||
opts.fontSize = axesFontSize_;
|
||||
opts.frame = frame_.get();
|
||||
auto toDisp = [](const geopro::controller::AxisRangeCfg& c) {
|
||||
return geopro::render::AxisDisplay{c.visible, c.customRange, c.min, c.max};
|
||||
};
|
||||
opts.x = toDisp(axisX_);
|
||||
opts.y = toDisp(axisY_);
|
||||
opts.z = toDisp(axisZ_);
|
||||
auto axes = geopro::render::buildAxes(bounds, opts, scene_.renderer());
|
||||
if (axes) {
|
||||
scene_.addViewProp(axes);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ public:
|
|||
void setSelectedAnomaly(const std::string& anomalyId) override;
|
||||
void setAxes(geopro::controller::AxesMode mode, geopro::controller::AxesUnit unit,
|
||||
int fontSize) override;
|
||||
void setAxesRanges(const geopro::controller::AxisRangeCfg& x,
|
||||
const geopro::controller::AxisRangeCfg& y,
|
||||
const geopro::controller::AxisRangeCfg& z) override;
|
||||
void applyCameraView(geopro::controller::ViewDir dir) override;
|
||||
void zoom(double factor) override;
|
||||
void fitView() override;
|
||||
|
|
@ -108,6 +111,7 @@ private:
|
|||
geopro::controller::AxesMode axesMode_ = geopro::controller::AxesMode::Standard;
|
||||
geopro::controller::AxesUnit axesUnit_ = geopro::controller::AxesUnit::Meter;
|
||||
int axesFontSize_ = 12;
|
||||
geopro::controller::AxisRangeCfg axisX_, axisY_, axisZ_; // per-axis 可见性 + 自定义范围
|
||||
// 当前坐标轴 prop:render 可能多次调用 rebuildAxes(rebuild 末尾 + 异步回灌),
|
||||
// 持引用以便重建前移除旧 prop,避免叠加(评审 HIGH)。
|
||||
vtkSmartPointer<vtkCubeAxesActor> currentAxes_;
|
||||
|
|
|
|||
|
|
@ -1083,12 +1083,19 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
|||
// 坐标轴设置抽屉「应用」:轴显示开关 + 放大系数(=垂直夸张,下发控制器+底图);范围/单位待控制器 API。
|
||||
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*/,
|
||||
geopro::app::AxisRange z, int unitIdx,
|
||||
double scale) {
|
||||
const bool anyShow = x.show || y.show || z.show;
|
||||
sceneCtrl->setAxesMode(anyShow ? geopro::controller::AxesMode::Standard
|
||||
: geopro::controller::AxesMode::None);
|
||||
if (scale > 0) {
|
||||
// 每轴:可见性=显示开关;自定义范围=面板 min/max(按当前单位),真正改刻度。
|
||||
auto cfg = [](const geopro::app::AxisRange& a) {
|
||||
return geopro::controller::AxisRangeCfg{a.show, true, a.min, a.max};
|
||||
};
|
||||
sceneCtrl->setAxesConfig(anyShow ? geopro::controller::AxesMode::Standard
|
||||
: geopro::controller::AxesMode::None,
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,13 @@ enum class AxesUnit { None, Meter, Feet, LatLon };
|
|||
// 快捷视图方向(spec §4 C7):前/后/左/右/上/下。
|
||||
enum class ViewDir { Front, Back, Left, Right, Top, Bottom };
|
||||
|
||||
// 单轴显示配置(坐标轴设置面板):是否显示该轴 + 是否用自定义刻度范围(值按当前单位)。
|
||||
struct AxisRangeCfg {
|
||||
bool visible = true;
|
||||
bool customRange = false;
|
||||
double min = 0.0, max = 0.0;
|
||||
};
|
||||
|
||||
// 三维场景视图抽象(编排层与 VTK 渲染解耦的缝):
|
||||
// VtkSceneController 只发出"清场 / 加某类图元 / 提交渲染"指令,不认 vtkActor/vtkVolume;
|
||||
// 真实实现(VtkSceneView)调 render actor + Scene;测试用 fake 记录调用断言编排。
|
||||
|
|
@ -56,6 +63,8 @@ public:
|
|||
// 坐标轴设置(P2):显示方式 + 刻度单位 + 字号。视图据当前场景包围盒重建坐标轴 prop。
|
||||
// None 模式 = 移除坐标轴;rebuild 时由控制器在 clear 后重新下发当前坐标轴设置。
|
||||
virtual void setAxes(AxesMode mode, AxesUnit unit, int fontSize) = 0;
|
||||
// per-axis 可见性 + 自定义范围(坐标轴设置面板「应用」)。默认空实现,测试 mock 无需覆盖。
|
||||
virtual void setAxesRanges(const AxisRangeCfg&, const AxisRangeCfg&, const AxisRangeCfg&) {}
|
||||
|
||||
// 快捷视图(P2):应用 6 向相机预设并提交渲染。
|
||||
virtual void applyCameraView(ViewDir dir) = 0;
|
||||
|
|
|
|||
|
|
@ -249,6 +249,16 @@ void VtkSceneController::setAxesUnit(AxesUnit unit) {
|
|||
rebuildInternal();
|
||||
}
|
||||
|
||||
void VtkSceneController::setAxesConfig(AxesMode mode, AxesUnit unit, const AxisRangeCfg& x,
|
||||
const AxisRangeCfg& y, const AxisRangeCfg& z) {
|
||||
axesMode_ = mode;
|
||||
axesUnit_ = unit;
|
||||
axisX_ = x;
|
||||
axisY_ = y;
|
||||
axisZ_ = z;
|
||||
rebuildInternal(); // 一次重建应用全部坐标轴设置
|
||||
}
|
||||
|
||||
// 快捷视图 / 缩放:仅改相机,不重建场景(无须取数/重装图元)。
|
||||
void VtkSceneController::applyView(ViewDir dir) { view_.applyCameraView(dir); }
|
||||
void VtkSceneController::zoomIn() { view_.zoom(1.2); }
|
||||
|
|
@ -277,6 +287,7 @@ void VtkSceneController::rebuildInternal() {
|
|||
view_.setVerticalExaggeration(verticalExaggeration_);
|
||||
// 坐标轴设置在 clear 后下发:render 末尾据当前场景包围盒重建坐标轴 prop。
|
||||
view_.setAxes(axesMode_, axesUnit_, kAxesFontSize);
|
||||
view_.setAxesRanges(axisX_, axisY_, axisZ_);
|
||||
fitOnArrival_ = true; // 全量重建:到场数据自动取景
|
||||
|
||||
// 坏 dsId(loadGrid/loadColorScale 抛异常)= best-effort 跳过:emit loadFailed 但不中断。
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ public slots:
|
|||
// ── P2 三维数据集栏 ──
|
||||
void setAxesMode(AxesMode mode);
|
||||
void setAxesUnit(AxesUnit unit);
|
||||
// 坐标轴设置面板「应用」:一次性下发 显示方式 + 单位 + per-axis 可见性/范围(单次重建)。
|
||||
void setAxesConfig(AxesMode mode, AxesUnit unit, const AxisRangeCfg& x, const AxisRangeCfg& y,
|
||||
const AxisRangeCfg& z);
|
||||
void applyView(ViewDir dir); // 6 向快捷视图
|
||||
void zoomIn(); // Zoom In (×1.2)
|
||||
void zoomOut(); // Zoom Out (×1/1.2)
|
||||
|
|
@ -95,6 +98,7 @@ private:
|
|||
// 坐标轴设置(P2):默认标准 + 米;字号固定 12(字体设置待 1.0 确认)。
|
||||
AxesMode axesMode_ = AxesMode::Standard;
|
||||
AxesUnit axesUnit_ = AxesUnit::Meter;
|
||||
AxisRangeCfg axisX_, axisY_, axisZ_; // 坐标轴设置面板的 per-axis 可见性 + 自定义范围
|
||||
static constexpr int kAxesFontSize = 12;
|
||||
|
||||
// 缓存(按 dsId):避免重复读盘/插值。
|
||||
|
|
|
|||
|
|
@ -77,11 +77,14 @@ vtkSmartPointer<vtkCubeAxesActor> buildAxes(const double bounds[6], const AxesOp
|
|||
ax->SetXLabelFormat("%.5f");
|
||||
ax->SetYLabelFormat("%.5f");
|
||||
} else {
|
||||
// 米 / 英尺:显示范围 = 几何范围 × 系数。
|
||||
// 米 / 英尺:显示范围 = 自定义范围(用户按当前单位输入)或几何范围 × 系数。
|
||||
const double s = unitScaleFactor(opts.unit);
|
||||
ax->SetXAxisRange(b[0] * s, b[1] * s);
|
||||
ax->SetYAxisRange(b[2] * s, b[3] * s);
|
||||
ax->SetZAxisRange(b[4] * s, b[5] * s);
|
||||
ax->SetXAxisRange(opts.x.customRange ? opts.x.min : b[0] * s,
|
||||
opts.x.customRange ? opts.x.max : b[1] * s);
|
||||
ax->SetYAxisRange(opts.y.customRange ? opts.y.min : b[2] * s,
|
||||
opts.y.customRange ? opts.y.max : b[3] * s);
|
||||
ax->SetZAxisRange(opts.z.customRange ? opts.z.min : b[4] * s,
|
||||
opts.z.customRange ? opts.z.max : b[5] * s);
|
||||
const char* u = (opts.unit == AxesUnit::Feet) ? "ft" : "m";
|
||||
ax->SetXTitle("X");
|
||||
ax->SetYTitle("Y");
|
||||
|
|
@ -91,6 +94,11 @@ vtkSmartPointer<vtkCubeAxesActor> buildAxes(const double bounds[6], const AxesOp
|
|||
ax->SetZUnits(u);
|
||||
}
|
||||
|
||||
// per-axis 显示开关(整轴:线 + 刻度 + 标签 + 标题)。
|
||||
ax->SetXAxisVisibility(opts.x.visible);
|
||||
ax->SetYAxisVisibility(opts.y.visible);
|
||||
ax->SetZAxisVisibility(opts.z.visible);
|
||||
|
||||
applyFont(ax, opts.fontSize);
|
||||
return ax;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,14 @@ enum class AxesMode { Standard, Stereo, None };
|
|||
// LatLon 经纬度 = 经 GeoLocalFrame 反算 X→经度、Y→纬度(Z 退化为米深度)。
|
||||
enum class AxesUnit { None, Meter, Feet, LatLon };
|
||||
|
||||
// 单轴显示(原型坐标轴设置):是否显示该轴 + 是否用自定义刻度范围(覆盖按单位换算的自动范围)。
|
||||
struct AxisDisplay {
|
||||
bool visible = true;
|
||||
bool customRange = false; // true=用 min/max 作刻度显示范围(值按当前单位)
|
||||
double min = 0.0;
|
||||
double max = 0.0;
|
||||
};
|
||||
|
||||
// 坐标轴构建参数。
|
||||
struct AxesOptions {
|
||||
AxesMode mode = AxesMode::Standard;
|
||||
|
|
@ -28,6 +36,7 @@ struct AxesOptions {
|
|||
int fontSize = 12; // 标题/标签字号
|
||||
// 经纬度刻度需 frame 反算;为空则 LatLon 退化为米。
|
||||
const geopro::core::GeoLocalFrame* frame = nullptr;
|
||||
AxisDisplay x, y, z; // per-axis 可见性 + 自定义范围
|
||||
};
|
||||
|
||||
// 由数据包围盒 bounds[6]={xmin,xmax,ymin,ymax,zmin,zmax} + 选项构建坐标轴 prop。
|
||||
|
|
|
|||
Loading…
Reference in New Issue