feat(view): 剖面电极标记 ▼ + 显示电极/显示等值线 开关(对齐原型, 增量4)
- ElectrodeActor(buildElectrodes): 剖面顶边(最浅深度)各 x 列画朝下三角 ▼; 坐标与 #18 一致。 离屏 verify_section_anomaly.png 顶边电极带核对吻合; +2 单测(三角数/顶点位置/空安全)。 - 数据详情工具条加「显示电极」(默认开,网格数据模式)+「显示等值线」(默认开, gate #18 黑色等值线)。 - 全 38 测试绿; app 构建干净; 待人工登录复核。 - 增量4 剩: 数值标签 / 色阶配置 / 滤波处理(进阶/M1.5)。
This commit is contained in:
parent
a2efef8ada
commit
8466fe3a5a
|
|
@ -18,10 +18,10 @@
|
||||||
- **中央 二维地图 / 三维视图**(两个**真内容**,非相机切换):
|
- **中央 二维地图 / 三维视图**(两个**真内容**,非相机切换):
|
||||||
- 二维地图 = `MapLineActor`:测线 `lat/lon` 轨迹**红线**俯视(浅底),像地图。
|
- 二维地图 = `MapLineActor`:测线 `lat/lon` 轨迹**红线**俯视(浅底),像地图。
|
||||||
- 三维视图 = `CurtainActor`:沿测线的**竖直断面墙**(分段色带,z 纵向夸张×3,沿弯曲测线弯)。中央工具条**仅**「二维地图/三维视图」。**3D 左上「视图详情」浮层**(对齐原型,仅 3D 显示):图层勾选 **帘面 / 体素**(体素=`buildVoxelFromScatters` 两交叉测线散点经 EPSG:4547 配准 IDW,与帘面同纵向夸张;PROJ 不可用则禁用)。
|
- 三维视图 = `CurtainActor`:沿测线的**竖直断面墙**(分段色带,z 纵向夸张×3,沿弯曲测线弯)。中央工具条**仅**「二维地图/三维视图」。**3D 左上「视图详情」浮层**(对齐原型,仅 3D 显示):图层勾选 **帘面 / 体素**(体素=`buildVoxelFromScatters` 两交叉测线散点经 EPSG:4547 配准 IDW,与帘面同纵向夸张;PROJ 不可用则禁用)。
|
||||||
- **下方 数据详情**:工具条「原数据/网格数据」切换 +「显示异常」开关(对齐原型命名)。单击数据集 → 网格数据=`GridContourActor` 平面剖面(#18,colorBar 真实非均匀分段值上色,纵向夸张×1.5);原数据=`ScatterActor` 彩色方块散点(#17,x=距离/y=深度取负,用散点自带色阶);显示异常=`AnomalyActor` 在上图叠加异常 dashed 折线(同纵向夸张对齐)。
|
- **下方 数据详情**:工具条「原数据/网格数据」切换 +「显示异常/显示电极/显示等值线」开关(对齐原型)。单击数据集 → 网格数据=`GridContourActor` 平面剖面(#18,colorBar 真实非均匀分段值上色,纵向夸张×1.5);原数据=`ScatterActor` 彩色方块散点(#17);显示异常=`AnomalyActor` dashed 折线叠加;显示电极=`ElectrodeActor` 顶边 ▼ 标记;显示等值线=#18 黑色等值线显隐(同纵向夸张对齐)。
|
||||||
- **右上 异常列表**(对齐原型):单击数据集→列该数据集异常(颜色块+名称(类型)+派生「位置/深/尺寸」),勾选框显隐,与数据详情异常叠加联动(取消勾选→该异常虚线隐藏)。
|
- **右上 异常列表**(对齐原型):单击数据集→列该数据集异常(颜色块+名称(类型)+派生「位置/深/尺寸」),勾选框显隐,与数据详情异常叠加联动(取消勾选→该异常虚线隐藏)。
|
||||||
- **右下 属性**:名称/网格 nx×ny/vmin·vmax/异常数。
|
- **右下 属性**:名称/网格 nx×ny/vmin·vmax/异常数。
|
||||||
- 单元测试累计 **36 个全绿**(core/data/net/render;含 Scatter 2 + Anomaly 4 + VoxelRegister 1、修复了陈旧的 Curtain mapper 类型断言);离屏 `verify_section/map/curtain_3d/scatter/section_anomaly/voxel_top/voxel_3d.png` 均核对正确(scatter 吻合 ref_17、异常吻合 ref_18、体素 footprint 吻合 ref voxel_hslice 的两臂支撑)。
|
- 单元测试累计 **38 个全绿**(core/data/net/render;含 Scatter 2 + Anomaly 4 + VoxelRegister 1 + Electrode 2、修复了陈旧的 Curtain mapper 类型断言);离屏 `verify_section/map/curtain_3d/scatter/section_anomaly(含电极▼)/voxel_top/voxel_3d.png` 均核对正确。
|
||||||
|
|
||||||
## 2. 各 Phase 完成度
|
## 2. 各 Phase 完成度
|
||||||
|
|
||||||
|
|
@ -79,7 +79,8 @@
|
||||||
- ✅ **增量1 右上「异常列表」**(2026-06-08,`panels/AnomalyListPanel`,与数据详情显隐联动;待人工复核)。
|
- ✅ **增量1 右上「异常列表」**(2026-06-08,`panels/AnomalyListPanel`,与数据详情显隐联动;待人工复核)。
|
||||||
- ✅ **增量2 左下「数据列表」+ 对象树到 TM 层**(2026-06-08,`panels/DatasetListPanel`;树 GS→TM 复选驱动中央, DS 移出树入数据列表 tab 数据/文件, DS 单击→详情+异常+属性, 启动自动选首测线/首数据集;待人工复核)。
|
- ✅ **增量2 左下「数据列表」+ 对象树到 TM 层**(2026-06-08,`panels/DatasetListPanel`;树 GS→TM 复选驱动中央, DS 移出树入数据列表 tab 数据/文件, DS 单击→详情+异常+属性, 启动自动选首测线/首数据集;待人工复核)。
|
||||||
- ✅ **增量3 3D「视图详情」图层浮层**(2026-06-08,QFrame 浮于 QVTK 左上,仅 3D 显示;帘面/体素图层勾选;体素经此正经接入=之前移除的工具条开关的正确归宿;main() 设 PROJ_DATA;待人工复核浮层渲染+体素显隐)。
|
- ✅ **增量3 3D「视图详情」图层浮层**(2026-06-08,QFrame 浮于 QVTK 左上,仅 3D 显示;帘面/体素图层勾选;体素经此正经接入=之前移除的工具条开关的正确归宿;main() 设 PROJ_DATA;待人工复核浮层渲染+体素显隐)。
|
||||||
- ⬜ **增量4 数据详情富工具条 + 电极标记 + 数值标签**;底图影像=DEM/底图任务。
|
- 🔶 **增量4 电极标记 + 工具条**(2026-06-08,`ElectrodeActor` 顶边 ▼ PNG 核对吻合; +「显示电极/显示等值线」开关;待人工复核)。**剩**:数值标签、色阶配置/滤波处理(M1.5/进阶)。
|
||||||
|
- 渲染积木累计含 `ElectrodeActor`(顶边 ▼)。底图影像=DEM/底图任务(需 GDAL)。
|
||||||
- 架构:新面板抽到 `src/app/panels/`(暂随 app 编译,如 login/),控制 main.cpp 体量;后续可升 `src/view/` 库。
|
- 架构:新面板抽到 `src/app/panels/`(暂随 app 编译,如 login/),控制 main.cpp 体量;后续可升 `src/view/` 库。
|
||||||
|
|
||||||
## 7. 渲染验证手段(务必用)
|
## 7. 渲染验证手段(务必用)
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,10 @@
|
||||||
- **人工复核**:三维视图勾"体素"→ 出十字片体素,与帘面同系;取消则移除。
|
- **人工复核**:三维视图勾"体素"→ 出十字片体素,与帘面同系;取消则移除。
|
||||||
- 提交 `feat(view): 3D 视图详情图层浮层(测线/帘面/体素) + 体素正经接入`。
|
- 提交 `feat(view): 3D 视图详情图层浮层(测线/帘面/体素) + 体素正经接入`。
|
||||||
|
|
||||||
### 增量 4:数据详情富工具条 + 电极 + 数值标签(对齐原型中下)
|
### 增量 4:数据详情富工具条 + 电极 🔶 部分完成(2026-06-08)
|
||||||
|
> ✅ `actors/ElectrodeActor`(buildElectrodes:顶边各 x 列朝下三角 ▼,离屏 PNG 核对吻合) + 数据详情
|
||||||
|
> 「显示电极/显示等值线」开关(显示等值线 gate #18 edges actor)。+2 单测,全 38 测试绿。
|
||||||
|
> ⬜ 剩:数值标签(vtkLabeledDataMapper)、色阶配置/滤波处理(进阶/M1.5)。**原计划存档**:
|
||||||
- 工具条补 色阶配置/显示电极/显示等值线 等(按需,部分 M1 可占位)。
|
- 工具条补 色阶配置/显示电极/显示等值线 等(按需,部分 M1 可占位)。
|
||||||
- 剖面顶部电极▼标记(grid.lat/lon 或 x 轴电极位);可选数值标签。
|
- 剖面顶部电极▼标记(grid.lat/lon 或 x 轴电极位);可选数值标签。
|
||||||
- 提交 `feat(view): 数据详情电极标记 + 工具条对齐原型`。
|
- 提交 `feat(view): 数据详情电极标记 + 工具条对齐原型`。
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@
|
||||||
#include "VoxelFromScatters.hpp"
|
#include "VoxelFromScatters.hpp"
|
||||||
#include "actors/AnomalyActor.hpp"
|
#include "actors/AnomalyActor.hpp"
|
||||||
#include "actors/CurtainActor.hpp"
|
#include "actors/CurtainActor.hpp"
|
||||||
|
#include "actors/ElectrodeActor.hpp"
|
||||||
#include "actors/GridContourActor.hpp"
|
#include "actors/GridContourActor.hpp"
|
||||||
#include "actors/MapLineActor.hpp"
|
#include "actors/MapLineActor.hpp"
|
||||||
#include "actors/ScatterActor.hpp"
|
#include "actors/ScatterActor.hpp"
|
||||||
|
|
@ -270,6 +271,12 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
auto* actShowAnomaly = detailToolBar->addAction(QStringLiteral("显示异常"));
|
auto* actShowAnomaly = detailToolBar->addAction(QStringLiteral("显示异常"));
|
||||||
actShowAnomaly->setCheckable(true);
|
actShowAnomaly->setCheckable(true);
|
||||||
actShowAnomaly->setChecked(true); // 默认显示异常(对齐原型 ☑显示异常)
|
actShowAnomaly->setChecked(true); // 默认显示异常(对齐原型 ☑显示异常)
|
||||||
|
auto* actShowElectrodes = detailToolBar->addAction(QStringLiteral("显示电极"));
|
||||||
|
actShowElectrodes->setCheckable(true);
|
||||||
|
actShowElectrodes->setChecked(true); // 默认显示电极 ▼(对齐原型)
|
||||||
|
auto* actShowContour = detailToolBar->addAction(QStringLiteral("显示等值线"));
|
||||||
|
actShowContour->setCheckable(true);
|
||||||
|
actShowContour->setChecked(true); // 默认显示等值线(对齐原型)
|
||||||
detailLayout->addWidget(detailToolBar);
|
detailLayout->addWidget(detailToolBar);
|
||||||
detailLayout->addWidget(detailWidget, 1);
|
detailLayout->addWidget(detailWidget, 1);
|
||||||
|
|
||||||
|
|
@ -399,13 +406,15 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
// 当前选中数据集 id(空=未选)与详情显示模式(反演剖面/原数据);切模式或换选中都重建。
|
// 当前选中数据集 id(空=未选)与详情显示模式(反演剖面/原数据);切模式或换选中都重建。
|
||||||
auto currentDsId = std::make_shared<QString>();
|
auto currentDsId = std::make_shared<QString>();
|
||||||
auto detailMode = std::make_shared<DetailMode>(DetailMode::Section18);
|
auto detailMode = std::make_shared<DetailMode>(DetailMode::Section18);
|
||||||
auto showAnomalies = std::make_shared<bool>(true); // 默认显示异常(对齐原型)
|
auto showAnomalies = std::make_shared<bool>(true); // 默认显示异常(对齐原型)
|
||||||
|
auto showElectrodes = std::make_shared<bool>(true); // 默认显示电极 ▼
|
||||||
|
auto showContour = std::make_shared<bool>(true); // 默认显示等值线
|
||||||
auto hiddenAnoms = std::make_shared<std::set<int>>(); // 异常列表中被取消勾选(隐藏)的异常下标
|
auto hiddenAnoms = std::make_shared<std::set<int>>(); // 异常列表中被取消勾选(隐藏)的异常下标
|
||||||
|
|
||||||
// 按当前选中 DS + 详情模式重建下方数据详情(平躺俯视正交,纵向夸张填面板)。
|
// 按当前选中 DS + 详情模式重建下方数据详情(平躺俯视正交,纵向夸张填面板)。
|
||||||
// 勾选「显示异常」时在 #18/#17 上叠加异常 dashed 折线(同纵向夸张对齐)。
|
// 勾选「显示异常/电极/等值线」控制对应叠加(同纵向夸张对齐)。
|
||||||
auto rebuildDetail = [&repo, detailRendererPtr, detailRenderWindowPtr, currentDsId, detailMode,
|
auto rebuildDetail = [&repo, detailRendererPtr, detailRenderWindowPtr, currentDsId, detailMode,
|
||||||
showAnomalies, hiddenAnoms]() {
|
showAnomalies, showElectrodes, showContour, hiddenAnoms]() {
|
||||||
detailRendererPtr->RemoveAllViewProps();
|
detailRendererPtr->RemoveAllViewProps();
|
||||||
if (currentDsId->isEmpty()) { // 未选数据集:清空即可
|
if (currentDsId->isEmpty()) { // 未选数据集:清空即可
|
||||||
detailRenderWindowPtr->Render();
|
detailRenderWindowPtr->Render();
|
||||||
|
|
@ -413,7 +422,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
}
|
}
|
||||||
const std::string id = currentDsId->toStdString();
|
const std::string id = currentDsId->toStdString();
|
||||||
if (*detailMode == DetailMode::Section18) {
|
if (*detailMode == DetailMode::Section18) {
|
||||||
// 网格数据:#18 banded 等值面 + 等值线,两 actor 纵向夸张 1.5x(沿 y)。
|
// 网格数据:#18 banded 等值面(+「显示等值线」时叠黑色等值线),纵向夸张 1.5x(沿 y)。
|
||||||
const auto g = repo.loadGrid(id);
|
const auto g = repo.loadGrid(id);
|
||||||
const auto cs = repo.loadColorScale(id);
|
const auto cs = repo.loadColorScale(id);
|
||||||
const auto actors = geopro::render::buildGridContour(g, cs);
|
const auto actors = geopro::render::buildGridContour(g, cs);
|
||||||
|
|
@ -421,10 +430,18 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
actors.bands->SetScale(1.0, kDetailYScale, 1.0);
|
actors.bands->SetScale(1.0, kDetailYScale, 1.0);
|
||||||
detailRendererPtr->AddViewProp(actors.bands);
|
detailRendererPtr->AddViewProp(actors.bands);
|
||||||
}
|
}
|
||||||
if (actors.edges) {
|
if (actors.edges && *showContour) {
|
||||||
actors.edges->SetScale(1.0, kDetailYScale, 1.0);
|
actors.edges->SetScale(1.0, kDetailYScale, 1.0);
|
||||||
detailRendererPtr->AddViewProp(actors.edges);
|
detailRendererPtr->AddViewProp(actors.edges);
|
||||||
}
|
}
|
||||||
|
// 顶部电极标记 ▼(仅网格数据;同纵向夸张对齐)。
|
||||||
|
if (*showElectrodes) {
|
||||||
|
auto elec = geopro::render::buildElectrodes(g);
|
||||||
|
if (elec) {
|
||||||
|
elec->SetScale(1.0, kDetailYScale, 1.0);
|
||||||
|
detailRendererPtr->AddViewProp(elec);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 原数据:#17 彩色散点,用散点自带色阶;纵向夸张同剖面以对齐观感。
|
// 原数据:#17 彩色散点,用散点自带色阶;纵向夸张同剖面以对齐观感。
|
||||||
const auto s = repo.loadScatter(id);
|
const auto s = repo.loadScatter(id);
|
||||||
|
|
@ -510,12 +527,22 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
||||||
rebuildDetail();
|
rebuildDetail();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ──「显示异常」开关:切换异常叠加 → 重建数据详情 ──
|
// ──「显示异常 / 显示电极 / 显示等值线」开关:切换叠加 → 重建数据详情 ──
|
||||||
QObject::connect(actShowAnomaly, &QAction::toggled, detailWidget,
|
QObject::connect(actShowAnomaly, &QAction::toggled, detailWidget,
|
||||||
[showAnomalies, rebuildDetail](bool on) {
|
[showAnomalies, rebuildDetail](bool on) {
|
||||||
*showAnomalies = on;
|
*showAnomalies = on;
|
||||||
rebuildDetail();
|
rebuildDetail();
|
||||||
});
|
});
|
||||||
|
QObject::connect(actShowElectrodes, &QAction::toggled, detailWidget,
|
||||||
|
[showElectrodes, rebuildDetail](bool on) {
|
||||||
|
*showElectrodes = on;
|
||||||
|
rebuildDetail();
|
||||||
|
});
|
||||||
|
QObject::connect(actShowContour, &QAction::toggled, detailWidget,
|
||||||
|
[showContour, rebuildDetail](bool on) {
|
||||||
|
*showContour = on;
|
||||||
|
rebuildDetail();
|
||||||
|
});
|
||||||
|
|
||||||
// 「视图详情」浮层显隐:仅三维显示,置于 QVTK 左上(工具条下方)并置顶。
|
// 「视图详情」浮层显隐:仅三维显示,置于 QVTK 左上(工具条下方)并置顶。
|
||||||
auto showLayerPanel = [layerPanel, viewToolBar](bool show3D) {
|
auto showLayerPanel = [layerPanel, viewToolBar](bool show3D) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
find_package(VTK REQUIRED COMPONENTS CommonCore CommonDataModel FiltersGeometry FiltersModeling RenderingCore RenderingOpenGL2 RenderingVolumeOpenGL2 InteractionStyle InteractionWidgets)
|
find_package(VTK REQUIRED COMPONENTS CommonCore CommonDataModel FiltersGeometry FiltersModeling RenderingCore RenderingOpenGL2 RenderingVolumeOpenGL2 InteractionStyle InteractionWidgets)
|
||||||
add_library(geopro_render STATIC
|
add_library(geopro_render STATIC
|
||||||
Scene.cpp ColorLutBuilder.cpp CameraPreset.cpp VoxelFromScatters.cpp actors/GridContourActor.cpp actors/VoxelActor.cpp actors/CurtainActor.cpp actors/MapLineActor.cpp actors/ScatterActor.cpp actors/AnomalyActor.cpp)
|
Scene.cpp ColorLutBuilder.cpp CameraPreset.cpp VoxelFromScatters.cpp actors/GridContourActor.cpp actors/VoxelActor.cpp actors/CurtainActor.cpp actors/MapLineActor.cpp actors/ScatterActor.cpp actors/AnomalyActor.cpp actors/ElectrodeActor.cpp)
|
||||||
target_include_directories(geopro_render PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(geopro_render PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
target_link_libraries(geopro_render PUBLIC geopro_core ${VTK_LIBRARIES})
|
target_link_libraries(geopro_render PUBLIC geopro_core ${VTK_LIBRARIES})
|
||||||
target_compile_features(geopro_render PUBLIC cxx_std_17)
|
target_compile_features(geopro_render PUBLIC cxx_std_17)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include "actors/ElectrodeActor.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <vtkCellArray.h>
|
||||||
|
#include <vtkNew.h>
|
||||||
|
#include <vtkPoints.h>
|
||||||
|
#include <vtkPolyData.h>
|
||||||
|
#include <vtkPolyDataMapper.h>
|
||||||
|
#include <vtkProperty.h>
|
||||||
|
#include <vtkTriangle.h>
|
||||||
|
|
||||||
|
namespace geopro::render {
|
||||||
|
|
||||||
|
vtkSmartPointer<vtkActor> buildElectrodes(const geopro::core::Grid& g, double markerW,
|
||||||
|
double markerH)
|
||||||
|
{
|
||||||
|
const int nx = g.nx();
|
||||||
|
if (nx < 1 || g.x.size() < static_cast<size_t>(nx) || g.y.empty()) {
|
||||||
|
return vtkSmartPointer<vtkActor>::New();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 剖面顶边(最浅) y_screen = -min(深度);#18 用 -y 使深部在下,故最浅处 y_screen 最大。
|
||||||
|
const double minDepth = *std::min_element(g.y.begin(), g.y.end());
|
||||||
|
const double yTop = -minDepth;
|
||||||
|
|
||||||
|
vtkNew<vtkPoints> points;
|
||||||
|
vtkNew<vtkCellArray> tris;
|
||||||
|
// 每个电极一个朝下三角:顶点(apex)触剖面顶边 (x, yTop),底边在其上方 (x±w, yTop+h)。
|
||||||
|
for (int i = 0; i < nx; ++i) {
|
||||||
|
const double x = g.x[i];
|
||||||
|
const vtkIdType a = points->InsertNextPoint(x, yTop, 0.0); // apex(下)
|
||||||
|
const vtkIdType l = points->InsertNextPoint(x - markerW, yTop + markerH, 0.0);
|
||||||
|
const vtkIdType r = points->InsertNextPoint(x + markerW, yTop + markerH, 0.0);
|
||||||
|
vtkNew<vtkTriangle> t;
|
||||||
|
t->GetPointIds()->SetId(0, a);
|
||||||
|
t->GetPointIds()->SetId(1, l);
|
||||||
|
t->GetPointIds()->SetId(2, r);
|
||||||
|
tris->InsertNextCell(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkNew<vtkPolyData> poly;
|
||||||
|
poly->SetPoints(points);
|
||||||
|
poly->SetPolys(tris);
|
||||||
|
|
||||||
|
vtkNew<vtkPolyDataMapper> mapper;
|
||||||
|
mapper->SetInputData(poly);
|
||||||
|
mapper->ScalarVisibilityOff();
|
||||||
|
|
||||||
|
auto actor = vtkSmartPointer<vtkActor>::New();
|
||||||
|
actor->SetMapper(mapper);
|
||||||
|
actor->GetProperty()->SetColor(0.15, 0.15, 0.15); // 深灰 ▼
|
||||||
|
return actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace geopro::render
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
#include <vtkActor.h>
|
||||||
|
#include <vtkSmartPointer.h>
|
||||||
|
|
||||||
|
#include "model/Field.hpp"
|
||||||
|
|
||||||
|
namespace geopro::render {
|
||||||
|
|
||||||
|
// 剖面顶部电极标记(对齐原型 ▼):在剖面顶边(最浅深度)各 x 列位置画一个朝下的小三角。
|
||||||
|
// 坐标与 #18 数据详情一致:x=g.x[i]、顶边 y=-min(深度)、z=0。调用方应施加与剖面相同的
|
||||||
|
// SetScale 以对齐(三角会随之略拉伸)。markerW/markerH 为数据单位下的三角半宽/高。
|
||||||
|
// 退化网格(无 x)返回空 actor。
|
||||||
|
vtkSmartPointer<vtkActor> buildElectrodes(const geopro::core::Grid& g,
|
||||||
|
double markerW = 0.5,
|
||||||
|
double markerH = 1.4);
|
||||||
|
|
||||||
|
} // namespace geopro::render
|
||||||
|
|
@ -70,6 +70,8 @@ target_sources(geopro_tests PRIVATE render/test_curtain.cpp)
|
||||||
target_sources(geopro_tests PRIVATE render/test_scatter.cpp)
|
target_sources(geopro_tests PRIVATE render/test_scatter.cpp)
|
||||||
# Anomaly:buildAnomalies(markType 点/线/面 -> vtkActor) 几何/闭合/颜色/y取负/空跳过。
|
# Anomaly:buildAnomalies(markType 点/线/面 -> vtkActor) 几何/闭合/颜色/y取负/空跳过。
|
||||||
target_sources(geopro_tests PRIVATE render/test_anomaly.cpp)
|
target_sources(geopro_tests PRIVATE render/test_anomaly.cpp)
|
||||||
|
# Electrode:buildElectrodes(剖面顶边朝下三角 ▼) 三角数/顶点位置/空安全。
|
||||||
|
target_sources(geopro_tests PRIVATE render/test_electrode.cpp)
|
||||||
target_link_libraries(geopro_tests PRIVATE geopro_render ${VTK_LIBRARIES})
|
target_link_libraries(geopro_tests PRIVATE geopro_render ${VTK_LIBRARIES})
|
||||||
vtk_module_autoinit(TARGETS geopro_tests MODULES ${VTK_LIBRARIES})
|
vtk_module_autoinit(TARGETS geopro_tests MODULES ${VTK_LIBRARIES})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <vtkPolyData.h>
|
||||||
|
#include <vtkPolyDataMapper.h>
|
||||||
|
|
||||||
|
#include "actors/ElectrodeActor.hpp"
|
||||||
|
#include "model/Field.hpp"
|
||||||
|
|
||||||
|
using namespace geopro::core;
|
||||||
|
|
||||||
|
// buildElectrodes: nx 列 → nx 个朝下三角(各 3 点);顶点 y = -min(深度)(剖面顶边)。
|
||||||
|
TEST(Electrode, BuildsDownTrianglesAtSectionTop) {
|
||||||
|
Grid g(3, 2);
|
||||||
|
g.x = {0.0, 10.0, 20.0};
|
||||||
|
g.y = {2.0, 8.0}; // 深度;min=2 → 顶边 y_screen = -2
|
||||||
|
auto actor = geopro::render::buildElectrodes(g, /*markerW*/ 0.5, /*markerH*/ 1.0);
|
||||||
|
ASSERT_NE(actor.GetPointer(), nullptr);
|
||||||
|
|
||||||
|
auto* mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
|
||||||
|
ASSERT_NE(mapper, nullptr);
|
||||||
|
auto* poly = vtkPolyData::SafeDownCast(mapper->GetInput());
|
||||||
|
ASSERT_NE(poly, nullptr);
|
||||||
|
EXPECT_EQ(poly->GetNumberOfCells(), 3); // 3 电极 → 3 三角
|
||||||
|
EXPECT_EQ(poly->GetNumberOfPoints(), 3 * 3); // 每三角 3 点
|
||||||
|
|
||||||
|
// 第一个三角的 apex(点 0) 在 (x=0, y=-2)(顶边),底边两点在其上方 y=-1。
|
||||||
|
double apex[3];
|
||||||
|
poly->GetPoint(0, apex);
|
||||||
|
EXPECT_DOUBLE_EQ(apex[0], 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(apex[1], -2.0);
|
||||||
|
double base[3];
|
||||||
|
poly->GetPoint(1, base);
|
||||||
|
EXPECT_DOUBLE_EQ(base[1], -1.0); // -2 + markerH(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 退化网格(无 x)返回空 actor。
|
||||||
|
TEST(Electrode, EmptyGridYieldsSafeActor) {
|
||||||
|
Grid g(0, 0);
|
||||||
|
auto actor = geopro::render::buildElectrodes(g);
|
||||||
|
ASSERT_NE(actor.GetPointer(), nullptr);
|
||||||
|
EXPECT_EQ(actor->GetMapper(), nullptr);
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include "VoxelFromScatters.hpp"
|
#include "VoxelFromScatters.hpp"
|
||||||
#include "actors/AnomalyActor.hpp"
|
#include "actors/AnomalyActor.hpp"
|
||||||
#include "actors/CurtainActor.hpp"
|
#include "actors/CurtainActor.hpp"
|
||||||
|
#include "actors/ElectrodeActor.hpp"
|
||||||
#include "actors/GridContourActor.hpp"
|
#include "actors/GridContourActor.hpp"
|
||||||
#include "actors/MapLineActor.hpp"
|
#include "actors/MapLineActor.hpp"
|
||||||
#include "actors/ScatterActor.hpp"
|
#include "actors/ScatterActor.hpp"
|
||||||
|
|
@ -110,6 +111,9 @@ int main() {
|
||||||
act->SetScale(1.0, exag, 1.0);
|
act->SetScale(1.0, exag, 1.0);
|
||||||
ren->AddActor(act);
|
ren->AddActor(act);
|
||||||
}
|
}
|
||||||
|
// 顶部电极标记 ▼(同纵向夸张对齐)。
|
||||||
|
auto elec = render::buildElectrodes(g);
|
||||||
|
if (elec) { elec->SetScale(1.0, exag, 1.0); ren->AddActor(elec); }
|
||||||
render::applyTop2D(ren);
|
render::applyTop2D(ren);
|
||||||
renderToPng(ren, (dir + "verify_section_anomaly.png").c_str(), 1100, 360);
|
renderToPng(ren, (dir + "verify_section_anomaly.png").c_str(), 1100, 360);
|
||||||
std::printf("ANOMALY n=%zu\n", anomalies.size());
|
std::printf("ANOMALY n=%zu\n", anomalies.size());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue