geopro/src/core/algo/VolumeBuilder.cpp

72 lines
2.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "algo/VolumeBuilder.hpp"
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <limits>
#include <stdexcept>
#include "algo/IdwInterpolator.hpp"
namespace geopro::core {
namespace {
// 某轴:优先用 cell 间距;若包络 ext 过大致格数超 kMaxVolumeDim则**放大间距**使 maxDim 格跨满 ext
// (分辨率降低,但**不截断**——否则跨 TM 多剖面相距 > maxDim×cell 时,远端剖面落网格外、丢失)。
void fitAxis(double ext, double cell, double& outCell, int& outN) {
if (!(ext > 0.0) || !(cell > 0.0)) { outCell = (cell > 0.0 ? cell : 1.0); outN = 1; return; }
int n = static_cast<int>(ext / cell) + 1;
if (n <= kMaxVolumeDim) {
outCell = cell;
outN = (n < 1) ? 1 : n;
return;
}
outN = kMaxVolumeDim;
outCell = ext / static_cast<double>(kMaxVolumeDim - 1); // maxDim 格覆盖全 ext
}
} // namespace
BuiltVolume buildVolume(const PointSet& pts, double cellXY, double cellZ,
double power, double maxDist) {
if (pts.v.empty()) {
throw std::invalid_argument("buildVolume: empty point set");
}
// 1) 点集包络。
double minx = pts.x[0], maxx = pts.x[0];
double miny = pts.y[0], maxy = pts.y[0];
double minz = pts.z[0], maxz = pts.z[0];
for (std::size_t i = 1; i < pts.v.size(); ++i) {
minx = std::min(minx, pts.x[i]); maxx = std::max(maxx, pts.x[i]);
miny = std::min(miny, pts.y[i]); maxy = std::max(maxy, pts.y[i]);
minz = std::min(minz, pts.z[i]); maxz = std::max(maxz, pts.z[i]);
}
// 2) GridSpec角点对齐 = 原点取包络最小角)。间距优先用 cell包络过大时放大间距以覆盖全程
// fitAxis避免跨 TM 多剖面相距过远时远端被截断。
GridSpec spec{};
spec.ox = minx; spec.oy = miny; spec.oz = minz;
fitAxis(maxx - minx, cellXY, spec.dx, spec.nx);
fitAxis(maxy - miny, cellXY, spec.dy, spec.ny);
fitAxis(maxz - minz, cellZ, spec.dz, spec.nz);
spec.power = power;
spec.maxDist = maxDist;
// 3) IDWmaxDist 外 NaN 留空)。
const IdwInterpolator idw;
ScalarVolume vol = idw.interpolate(pts, spec);
// 4) 数据实测值域(仅有限值)。无有限值 → 退化 {0,1}。
double vmin = std::numeric_limits<double>::infinity();
double vmax = -std::numeric_limits<double>::infinity();
for (double v : vol.data()) {
if (std::isnan(v)) continue;
vmin = std::min(vmin, v); vmax = std::max(vmax, v);
}
if (!(vmin < vmax)) { vmin = 0.0; vmax = 1.0; }
return BuiltVolume{std::move(vol), spec, vmin, vmax};
}
} // namespace geopro::core