fix(render): 数据详情#18修正 — 用colorBar真实非均匀分段值做等值线级(修一片蓝)+纵向夸张; ColorScale暴露stopValues

This commit is contained in:
gaozheng 2026-06-07 23:18:52 +08:00
parent 039c04a233
commit 2d7dfe3582
4 changed files with 42 additions and 25 deletions

View File

@ -33,6 +33,13 @@ void ColorScale::addStop(double value, Rgba color) {
[](const Stop& x, const Stop& y) { return x.value < y.value; });
}
std::vector<double> ColorScale::stopValues() const {
std::vector<double> v;
v.reserve(stops_.size());
for (const auto& s : stops_) v.push_back(s.value); // stops_ 已升序
return v;
}
Rgba ColorScale::colorAt(double value) const {
if (std::isnan(value)) return nan_.value_or(Rgba{0, 0, 0, 0});
if (stops_.empty()) return Rgba{0, 0, 0, 0};

View File

@ -14,6 +14,8 @@ class ColorScale {
public:
void addStop(double value, Rgba color); // 内部保持按 value 升序
Rgba colorAt(double value) const; // 含 under/over/NaN 处理
std::vector<double> stopValues() const; // 升序分段值(供等值线用真实非均匀级)
std::size_t stopCount() const { return stops_.size(); }
void setUnder(Rgba c) { under_ = c; }
void setOver(Rgba c) { over_ = c; }
void setNan(Rgba c) { nan_ = c; }

View File

@ -50,18 +50,20 @@ GridActors buildGridContour(const geopro::core::Grid& g, const geopro::core::Col
sgrid->SetPoints(points);
sgrid->GetPointData()->SetScalars(sc);
// vmin/vmax 来自 Grid若退化==)则用数据极值兜底,避免 LUT/contour 退化。
double vmin = g.vmin, vmax = g.vmax;
// 等值线级用 colorBar 的**真实非均匀分段值**(电阻率低值密集),而非均匀分级——
// 否则数据全挤进低端、一片蓝。范围/色阶都以 colorBar 为准。
const std::vector<double> stops = cs.stopValues();
double vmin, vmax;
if (stops.size() >= 2) { vmin = stops.front(); vmax = stops.back(); }
else {
vmin = g.vmin; vmax = g.vmax;
if (vmin >= vmax) {
const auto& vals = g.values();
vmin = vals.empty() ? 0.0 : vals.front();
vmax = vmin;
for (double v : vals) {
if (v < vmin) vmin = v;
if (v > vmax) vmax = v;
}
vmin = vals.empty() ? 0.0 : vals.front(); vmax = vmin;
for (double v : vals) { if (v < vmin) vmin = v; if (v > vmax) vmax = v; }
if (vmin >= vmax) vmax = vmin + 1.0;
}
}
auto lut = buildLut(cs, vmin, vmax, kLutLevels);
@ -70,7 +72,12 @@ GridActors buildGridContour(const geopro::core::Grid& g, const geopro::core::Col
vtkNew<vtkBandedPolyDataContourFilter> banded;
banded->SetInputConnection(surf->GetOutputPort());
if (stops.size() >= 2) {
banded->SetNumberOfContours(static_cast<int>(stops.size()));
for (int i = 0; i < static_cast<int>(stops.size()); ++i) banded->SetValue(i, stops[i]);
} else {
banded->GenerateValues(kBandCount, vmin, vmax);
}
banded->GenerateContourEdgesOn();
banded->SetScalarModeToValue();

View File

@ -1,12 +1,12 @@
// 离屏渲染验证:把真实数据渲成 PNG肉眼核对方向/2D-3D 差异(不靠"进程活着"自欺)。
// 产出(D:/dev/spike_data/):
// verify_section.png —— 平面反演剖面(#18, 数据详情),应浅部在上、深部在下
// verify_curtain_top.png —— 帘面俯视(二维),应看到一条沿测线的带(像地图线)
// verify_curtain_3d.png —— 帘面透视(三维),应看到立着的彩色断面墙
// verify_section.png —— 平面反演剖面(#18, 数据详情), 浅部在上、深部在下, 纵向夸张填满
// verify_curtain_top.png —— 帘面俯视(二维)
// verify_curtain_3d.png —— 帘面透视(三维)
#include <fstream>
#include <numeric>
#include <sstream>
#include <string>
#include <numeric>
#include <vtkActor.h>
#include <vtkNew.h>
@ -15,12 +15,12 @@
#include <vtkRenderer.h>
#include <vtkWindowToImageFilter.h>
#include "parse/SampleParsers.hpp"
#include "geo/GeoLocalFrame.hpp"
#include "actors/GridContourActor.hpp"
#include "actors/CurtainActor.hpp"
#include "ColorLutBuilder.hpp"
#include "CameraPreset.hpp"
#include "ColorLutBuilder.hpp"
#include "actors/CurtainActor.hpp"
#include "actors/GridContourActor.hpp"
#include "geo/GeoLocalFrame.hpp"
#include "parse/SampleParsers.hpp"
static std::string slurp(const char* p) {
std::ifstream f(p);
@ -44,17 +44,18 @@ int main() {
core::Grid g = data::parseGrid(slurp((dir + "grid.json").c_str()));
core::ColorScale cs = data::parseColorScale(slurp((dir + "colorbar.json").c_str()));
// 1) 平面剖面 (#18) — 俯视看 XY 平面(face-on)
// 1) 平面剖面 (#18) — 俯视看 XY 平面(face-on); 纵向夸张 1.5x 填满宽面板(物探惯例)
{
auto a = render::buildGridContour(g, cs);
const double exag = 1.5;
vtkNew<vtkRenderer> ren; ren->SetBackground(1, 1, 1);
if (a.bands) ren->AddActor(a.bands);
if (a.edges) ren->AddActor(a.edges);
if (a.bands) { a.bands->SetScale(1.0, exag, 1.0); ren->AddActor(a.bands); }
if (a.edges) { a.edges->SetScale(1.0, exag, 1.0); ren->AddActor(a.edges); }
render::applyTop2D(ren);
renderToPng(ren, (dir + "verify_section.png").c_str(), 1100, 320);
renderToPng(ren, (dir + "verify_section.png").c_str(), 1100, 360);
}
// GeoLocalFrame原点取 lat/lon 均值
// GeoLocalFrame: 原点取 lat/lon 均值
double lat0 = std::accumulate(g.lat.begin(), g.lat.end(), 0.0) / (g.lat.empty() ? 1 : g.lat.size());
double lon0 = std::accumulate(g.lon.begin(), g.lon.end(), 0.0) / (g.lon.empty() ? 1 : g.lon.size());
core::GeoLocalFrame frame(lat0, lon0);