feat/vtk-3d-view #7

Merged
gaozheng merged 301 commits from feat/vtk-3d-view into main 2026-06-27 18:43:52 +08:00
1 changed files with 30 additions and 6 deletions
Showing only changes of commit 7bdb291fb4 - Show all commits

View File

@ -5,6 +5,7 @@
#include <cmath>
#include <limits>
#include <stdexcept>
#include <vector>
#include <QString>
#include <QVector>
@ -110,15 +111,35 @@ geopro::core::BuiltI16 buildLineVolumeSurvey(const std::string& lineDir,
geom.cgcsZone = zone;
geom.centralMeridianDeg = centralMeridianDeg;
QVector<QVector3D> gpsCgcs;
gpsCgcs.reserve(static_cast<int>(track.pts.size()));
// 先把所有 GPS 点正算到 CGCS2000(double含带号),求局部原点。
// 根因(短线 007 失败)CGCS easting 含带号 ≈ 4.0e7 米,存入 QVector3D(float32)后
// 该量级 ULP ≈ 4 米——0.81 m 的东向跨度(近正北短线)被浮点量化抹平成同一个值,
// CScanGridder 里 maxX<=minX 判退 → 空网格(「深度0 网格无效」)。
// 桥接层修法(不碰 verbatim 算法):存入 float 轨迹前先平移到局部原点(floor 到整米)
// 令坐标降到 ~10² 米量级、float 亚毫米精度无损CScanGridder/TrajectoryCalculator 全程
// 只用差分/距离/IDW(对常量平移不变),输出与未平移逐位一致——只是网格 origin 也变成局部值,
// 故最后把平移量加回 built.origin 即还原真实 CGCS2000 世界米。
struct CgcsPt { double north; double east; double elev; };
std::vector<CgcsPt> cgcsPts;
cgcsPts.reserve(track.pts.size());
for (const auto& p : track.pts) {
double cx = 0.0, cy = 0.0; // cx=北(northing), cy=东(easting含带号)
CoordinateTransform::wgs84ToCgcs2000(p.lat * kDeg2Rad, p.lon * kDeg2Rad,
zone, cx, cy);
cgcsPts.push_back({cx, cy, p.elev});
}
// 局部原点 = 首点 floor 到整米(north→x 轴, east→y 轴,与 gpsPositions 约定一致)。
const double localOriginNorth = std::floor(cgcsPts.front().north);
const double localOriginEast = std::floor(cgcsPts.front().east);
QVector<QVector3D> gpsCgcs;
gpsCgcs.reserve(static_cast<int>(cgcsPts.size()));
for (const auto& q : cgcsPts) {
// SurveyLine.gpsPositions 约定 x=北, y=东, z=高(与 TrajectoryCalculator 一致)。
gpsCgcs.append(QVector3D(static_cast<float>(cx), static_cast<float>(cy),
static_cast<float>(p.elev)));
// 平移到局部原点后再转 float(保住亚米精度)。
gpsCgcs.append(QVector3D(static_cast<float>(q.north - localOriginNorth),
static_cast<float>(q.east - localOriginEast),
static_cast<float>(q.elev)));
}
SurveyLine line;
@ -171,8 +192,11 @@ geopro::core::BuiltI16 buildLineVolumeSurvey(const std::string& lineDir,
const int ny = g0.height; // 北向 northing 格数
const int nz = nzOut; // 深度
const double cellSize = g0.cellSizeM;
const double originX = g0.originX; // CGCS easting(含带号) 米
const double originY = g0.originY; // CGCS northing 米
// g0.originX/Y 为局部坐标系下的网格左下角(因 gpsPositions 已平移到局部原点)
// 加回 localOriginEast/North 还原真实 CGCS2000 世界米。
// (CScanGridder 网格 X=东=gpsPositions.y, Y=北=gpsPositions.x故 originX 配 East、originY 配 North。)
const double originX = g0.originX + localOriginEast; // CGCS easting(含带号) 米
const double originY = g0.originY + localOriginNorth; // CGCS northing 米
// 量化区间:先扫所有输出深度网格的有效值(命中 validMask)定 [vmin,vmax]。
// (CScanGridder values 为处理后幅值的 IDW 插值结果,连续浮点。)