fix(render): 体素卡死修复 — IDW 1/d²快速路径+maxDist提前跳过, 网格粗化(2m/1m), SmartVolumeMapper CPU回退, 忙碌光标; 按钮改名'三维体素'
This commit is contained in:
parent
ebf1e0929d
commit
3bc006e271
|
|
@ -102,9 +102,9 @@ VoxelBuildResult buildVoxelFromScatters(
|
|||
using geopro::core::IdwInterpolator;
|
||||
using geopro::core::PointSet;
|
||||
|
||||
constexpr double kDxy = 1.0; // 水平步长(米)
|
||||
constexpr double kDz = 0.5; // 垂向步长(米)
|
||||
constexpr double kPower = 2.0; // IDW 幂
|
||||
constexpr double kDxy = 2.0; // 水平步长(米);粗化体素网格保证实时(~1.4万格)
|
||||
constexpr double kDz = 1.0; // 垂向步长(米)
|
||||
constexpr double kPower = 2.0; // IDW 幂(=2 走 1/d² 快速路径)
|
||||
constexpr double kMaxDist = 4.0; // 超距留空(NaN)
|
||||
|
||||
// 合并两剖面点为一组 (X=projX, Y=projY, Z=z)。
|
||||
|
|
@ -219,7 +219,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
|||
cameraGroup->addAction(act3D);
|
||||
act2D->setChecked(true); // 默认二维
|
||||
viewToolBar->addSeparator();
|
||||
auto* actVoxel = viewToolBar->addAction(QStringLiteral("dd_voxel"));
|
||||
auto* actVoxel = viewToolBar->addAction(QStringLiteral("三维体素"));
|
||||
centerLayout->addWidget(viewToolBar);
|
||||
centerLayout->addWidget(vtkWidget, 1);
|
||||
|
||||
|
|
@ -301,9 +301,11 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
|
|||
QObject::connect(actVoxel, &QAction::triggered, vtkWidget,
|
||||
[&repo, scene, rendererPtr, renderWindowPtr, cameraMode, act3D, propLabel,
|
||||
sliceWidget, voxelImage]() {
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
const auto scatters = repo.loadVoxelScatters();
|
||||
const auto cs = repo.loadColorScale("grid1");
|
||||
auto result = buildVoxelFromScatters(scatters, cs);
|
||||
QApplication::restoreOverrideCursor();
|
||||
if (!result.volume) {
|
||||
propLabel->setText(QStringLiteral("dd_voxel: 无可用散点数据"));
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -7,22 +7,28 @@ ScalarVolume IdwInterpolator::interpolate(const PointSet& pts, const GridSpec& s
|
|||
ScalarVolume vol(s.nx, s.ny, s.nz);
|
||||
const double nan = std::numeric_limits<double>::quiet_NaN();
|
||||
const size_t n = pts.v.size();
|
||||
// 局部 IDW + 性能优化:只累加 maxDist 内的点(平方距离比较,免 sqrt);
|
||||
// power==2 时权重 = 1/d²,免 sqrt 和 pow(最常见路径,约 10x 提速)。
|
||||
const double maxd2 = s.maxDist * s.maxDist;
|
||||
const bool fastPow2 = (s.power == 2.0);
|
||||
const double halfPow = s.power * 0.5; // 1/d^power = (d²)^(-power/2)
|
||||
for (int k = 0; k < s.nz; ++k)
|
||||
for (int j = 0; j < s.ny; ++j)
|
||||
for (int i = 0; i < s.nx; ++i) {
|
||||
const double gx = s.ox + i * s.dx, gy = s.oy + j * s.dy, gz = s.oz + k * s.dz;
|
||||
double wsum = 0.0, vsum = 0.0, nearest = std::numeric_limits<double>::max();
|
||||
bool hit = false; double hitVal = 0.0;
|
||||
double wsum = 0.0, vsum = 0.0;
|
||||
bool any = false, hit = false; double hitVal = 0.0;
|
||||
for (size_t p = 0; p < n; ++p) {
|
||||
const double ddx = gx - pts.x[p], ddy = gy - pts.y[p], ddz = gz - pts.z[p];
|
||||
const double d = std::sqrt(ddx * ddx + ddy * ddy + ddz * ddz);
|
||||
if (d < nearest) nearest = d;
|
||||
if (d < 1e-12) { hit = true; hitVal = pts.v[p]; break; }
|
||||
const double w = 1.0 / std::pow(d, s.power);
|
||||
const double d2 = ddx * ddx + ddy * ddy + ddz * ddz;
|
||||
if (d2 > maxd2) continue; // 超距点不参与(局部 IDW)+ 跳过昂贵的权重计算
|
||||
any = true;
|
||||
if (d2 < 1e-24) { hit = true; hitVal = pts.v[p]; break; }
|
||||
const double w = fastPow2 ? (1.0 / d2) : std::pow(d2, -halfPow);
|
||||
wsum += w; vsum += w * pts.v[p];
|
||||
}
|
||||
if (hit) vol.at(i, j, k) = hitVal;
|
||||
else if (nearest > s.maxDist || wsum == 0.0) vol.at(i, j, k) = nan;
|
||||
else if (!any || wsum == 0.0) vol.at(i, j, k) = nan; // maxDist 内无点 → blank
|
||||
else vol.at(i, j, k) = vsum / wsum;
|
||||
}
|
||||
return vol;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
#include <vtkColorTransferFunction.h>
|
||||
#include <vtkDoubleArray.h>
|
||||
#include <vtkGPUVolumeRayCastMapper.h>
|
||||
#include <vtkNew.h>
|
||||
#include <vtkSmartVolumeMapper.h>
|
||||
#include <vtkPiecewiseFunction.h>
|
||||
#include <vtkPointData.h>
|
||||
#include <vtkVolumeProperty.h>
|
||||
|
|
@ -71,7 +71,8 @@ vtkSmartPointer<vtkVolume> buildVoxel(const geopro::core::ScalarVolume& vol,
|
|||
opacity->AddPoint(vmin, 0.0);
|
||||
opacity->AddPoint(vmax, kMaxOpacity);
|
||||
|
||||
vtkNew<vtkGPUVolumeRayCastMapper> mapper;
|
||||
// SmartVolumeMapper:有 GPU 走 GPU ray cast,否则自动回退 CPU,避免无 GPU 时卡死/失败。
|
||||
vtkNew<vtkSmartVolumeMapper> mapper;
|
||||
mapper->SetInputData(img);
|
||||
|
||||
vtkNew<vtkVolumeProperty> prop;
|
||||
|
|
|
|||
Loading…
Reference in New Issue