From 37b433208e13232850798af50ad34e36d92dbb1f Mon Sep 17 00:00:00 2001 From: gaozheng Date: Tue, 16 Jun 2026 20:41:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(vtk):=20=E5=B8=98=E9=9D=A2=E6=B6=88?= =?UTF-8?q?=E9=9A=90=E6=97=A0=E6=95=B0=E6=8D=AE(NaN)=E6=A0=BC,=E6=A0=B9?= =?UTF-8?q?=E6=B2=BB=E7=9C=9F=E5=AE=9E=E5=8F=8D=E6=BC=94=E5=89=96=E9=9D=A2?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E5=B4=A9=E6=BA=83(0xc0000005)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 真实反演 v 矩阵大量 null→Grid 存 NaN→vtkBandedPolyDataContourFilter 裁剪运算崩(经真实API数据+崩溃栈定位)。 消隐含 NaN 的点(ghost)使其不入表面/色带滤镜+标量填0兜底;顺带清洗色带等值线值(去非有限/去重)。保留色带功能。 --- src/render/actors/CurtainActor.cpp | 32 +++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/render/actors/CurtainActor.cpp b/src/render/actors/CurtainActor.cpp index 1feb8e2..5571186 100644 --- a/src/render/actors/CurtainActor.cpp +++ b/src/render/actors/CurtainActor.cpp @@ -9,6 +9,8 @@ #include #include +#include +#include #include #include @@ -47,6 +49,10 @@ vtkSmartPointer buildCurtain(const geopro::core::Grid& g, sc->SetName("v"); sc->SetNumberOfTuples(static_cast(nx) * ny); + // 无数据格(v 为 null → Grid 存 NaN,反演不规则区大量如此)记录待消隐:NaN 标量喂给 + // vtkBandedPolyDataContourFilter 的裁剪运算会崩(0xc0000005)。消隐后这些格不入表面/色带, + // 既不崩、又把空洞正确显示为透明。标量同时填 0(有限值)以防任何读取路径再触 NaN。 + std::vector blanks; for (int j = 0; j < ny; ++j) { for (int i = 0; i < nx; ++i) { double px, py; @@ -62,15 +68,35 @@ vtkSmartPointer buildCurtain(const geopro::core::Grid& g, const vtkIdType id = static_cast(j) * nx + i; // g.y 是深度(越大越深);VTK Z 向上 → 取负,使深部在下、浅部在上(剖面不倒置)。 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->GetPointData()->SetScalars(sc); + // 消隐无数据点:vtkStructuredGrid 消隐(ghost)→ 含该点的 cell 不被 vtkDataSetSurfaceFilter 输出, + // 故 NaN 永不进入 banded contour。282/1900 有效的不规则反演区→渲染出正确的梯形帘面。 + for (vtkIdType id : blanks) sgrid->BlankPoint(id); // 用 colorBar 真实分段值做色带(与数据详情#18一致的清晰色带,而非连续插值的糊色)。 - const std::vector stops = cs.stopValues(); + // 清洗等值线值:vtkBandedPolyDataContourFilter 要求值严格升序且有限——真实色阶可能含重复值 + // (addStop 排序不去重)或非有限值,未清洗会在 Update() 时崩(0xc0000005)。去非有限 + 去重保序。 + std::vector stops; + { + std::vector 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; if (stops.size() >= 2) { vmin = stops.front(); vmax = stops.back(); } else { @@ -85,7 +111,7 @@ vtkSmartPointer buildCurtain(const geopro::core::Grid& g, auto lut = buildLut(cs, vmin, vmax, kLutLevels); - // structuredGrid → 表面 polydata → banded contour(分段色带) + // structuredGrid → 表面 polydata(消隐格已剔除) → banded contour(分段色带,色带#18)。 vtkNew surf; surf->SetInputData(sgrid); vtkNew banded;