feat/vtk-3d-view #7
|
|
@ -9,6 +9,8 @@
|
||||||
#include <vtkPolyDataMapper.h>
|
#include <vtkPolyDataMapper.h>
|
||||||
#include <vtkStructuredGrid.h>
|
#include <vtkStructuredGrid.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
@ -47,6 +49,10 @@ vtkSmartPointer<vtkActor> buildCurtain(const geopro::core::Grid& g,
|
||||||
sc->SetName("v");
|
sc->SetName("v");
|
||||||
sc->SetNumberOfTuples(static_cast<vtkIdType>(nx) * ny);
|
sc->SetNumberOfTuples(static_cast<vtkIdType>(nx) * ny);
|
||||||
|
|
||||||
|
// 无数据格(v 为 null → Grid 存 NaN,反演不规则区大量如此)记录待消隐:NaN 标量喂给
|
||||||
|
// vtkBandedPolyDataContourFilter 的裁剪运算会崩(0xc0000005)。消隐后这些格不入表面/色带,
|
||||||
|
// 既不崩、又把空洞正确显示为透明。标量同时填 0(有限值)以防任何读取路径再触 NaN。
|
||||||
|
std::vector<vtkIdType> blanks;
|
||||||
for (int j = 0; j < ny; ++j) {
|
for (int j = 0; j < ny; ++j) {
|
||||||
for (int i = 0; i < nx; ++i) {
|
for (int i = 0; i < nx; ++i) {
|
||||||
double px, py;
|
double px, py;
|
||||||
|
|
@ -62,15 +68,35 @@ vtkSmartPointer<vtkActor> buildCurtain(const geopro::core::Grid& g,
|
||||||
const vtkIdType id = static_cast<vtkIdType>(j) * nx + i;
|
const vtkIdType id = static_cast<vtkIdType>(j) * nx + i;
|
||||||
// g.y 是深度(越大越深);VTK Z 向上 → 取负,使深部在下、浅部在上(剖面不倒置)。
|
// g.y 是深度(越大越深);VTK Z 向上 → 取负,使深部在下、浅部在上(剖面不倒置)。
|
||||||
points->SetPoint(id, px, py, -g.y[j]);
|
points->SetPoint(id, px, py, -g.y[j]);
|
||||||
sc->SetValue(id, g.valueAt(i, j));
|
const double val = g.valueAt(i, j);
|
||||||
|
if (std::isfinite(val)) {
|
||||||
|
sc->SetValue(id, val);
|
||||||
|
} else {
|
||||||
|
sc->SetValue(id, 0.0);
|
||||||
|
blanks.push_back(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sgrid->SetPoints(points);
|
sgrid->SetPoints(points);
|
||||||
sgrid->GetPointData()->SetScalars(sc);
|
sgrid->GetPointData()->SetScalars(sc);
|
||||||
|
// 消隐无数据点:vtkStructuredGrid 消隐(ghost)→ 含该点的 cell 不被 vtkDataSetSurfaceFilter 输出,
|
||||||
|
// 故 NaN 永不进入 banded contour。282/1900 有效的不规则反演区→渲染出正确的梯形帘面。
|
||||||
|
for (vtkIdType id : blanks) sgrid->BlankPoint(id);
|
||||||
|
|
||||||
// 用 colorBar 真实分段值做色带(与数据详情#18一致的清晰色带,而非连续插值的糊色)。
|
// 用 colorBar 真实分段值做色带(与数据详情#18一致的清晰色带,而非连续插值的糊色)。
|
||||||
const std::vector<double> stops = cs.stopValues();
|
// 清洗等值线值:vtkBandedPolyDataContourFilter 要求值严格升序且有限——真实色阶可能含重复值
|
||||||
|
// (addStop 排序不去重)或非有限值,未清洗会在 Update() 时崩(0xc0000005)。去非有限 + 去重保序。
|
||||||
|
std::vector<double> stops;
|
||||||
|
{
|
||||||
|
std::vector<double> raw = cs.stopValues();
|
||||||
|
raw.erase(std::remove_if(raw.begin(), raw.end(),
|
||||||
|
[](double v) { return !std::isfinite(v); }),
|
||||||
|
raw.end());
|
||||||
|
std::sort(raw.begin(), raw.end());
|
||||||
|
raw.erase(std::unique(raw.begin(), raw.end()), raw.end());
|
||||||
|
stops = std::move(raw);
|
||||||
|
}
|
||||||
double vmin, vmax;
|
double vmin, vmax;
|
||||||
if (stops.size() >= 2) { vmin = stops.front(); vmax = stops.back(); }
|
if (stops.size() >= 2) { vmin = stops.front(); vmax = stops.back(); }
|
||||||
else {
|
else {
|
||||||
|
|
@ -85,7 +111,7 @@ vtkSmartPointer<vtkActor> buildCurtain(const geopro::core::Grid& g,
|
||||||
|
|
||||||
auto lut = buildLut(cs, vmin, vmax, kLutLevels);
|
auto lut = buildLut(cs, vmin, vmax, kLutLevels);
|
||||||
|
|
||||||
// structuredGrid → 表面 polydata → banded contour(分段色带)
|
// structuredGrid → 表面 polydata(消隐格已剔除) → banded contour(分段色带,色带#18)。
|
||||||
vtkNew<vtkDataSetSurfaceFilter> surf;
|
vtkNew<vtkDataSetSurfaceFilter> surf;
|
||||||
surf->SetInputData(sgrid);
|
surf->SetInputData(sgrid);
|
||||||
vtkNew<vtkBandedPolyDataContourFilter> banded;
|
vtkNew<vtkBandedPolyDataContourFilter> banded;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue