diff --git a/src/io/gpr/Gpr3dvSurveyVolumeBridge.cpp b/src/io/gpr/Gpr3dvSurveyVolumeBridge.cpp index 62d9d2b..03f7803 100644 --- a/src/io/gpr/Gpr3dvSurveyVolumeBridge.cpp +++ b/src/io/gpr/Gpr3dvSurveyVolumeBridge.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -110,15 +111,35 @@ geopro::core::BuiltI16 buildLineVolumeSurvey(const std::string& lineDir, geom.cgcsZone = zone; geom.centralMeridianDeg = centralMeridianDeg; - QVector gpsCgcs; - gpsCgcs.reserve(static_cast(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 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 gpsCgcs; + gpsCgcs.reserve(static_cast(cgcsPts.size())); + for (const auto& q : cgcsPts) { // SurveyLine.gpsPositions 约定 x=北, y=东, z=高(与 TrajectoryCalculator 一致)。 - gpsCgcs.append(QVector3D(static_cast(cx), static_cast(cy), - static_cast(p.elev))); + // 平移到局部原点后再转 float(保住亚米精度)。 + gpsCgcs.append(QVector3D(static_cast(q.north - localOriginNorth), + static_cast(q.east - localOriginEast), + static_cast(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 插值结果,连续浮点。)