#include #include #include #include #include #include #include #include #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif namespace NItem { // --- 基础结构 --- struct TrendParam { double angle; double ratio; double cx, cy; double weight; }; struct GridResult { int nx, ny; double xMin, xMax, yMin, yMax, step; std::vector gx, gy, zi; }; class GeoEngine { public: void initGridStrict(const std::vector& sx, const std::vector& sy, double step, GridResult& grid) { auto x_mm = std::minmax_element(sx.begin(), sx.end()); auto y_mm = std::minmax_element(sy.begin(), sy.end()); double dx = *x_mm.second - *x_mm.first; double dy = *y_mm.second - *y_mm.first; // 10% 边界扩展 grid.xMin = *x_mm.first - dx * 0.1; grid.yMin = *y_mm.first - dy * 0.1; double targetMaxX = *x_mm.second + dx * 0.1; double targetMaxY = *y_mm.second + dy * 0.1; grid.step = step; grid.nx = 0; for (double x = grid.xMin; x < targetMaxX + step - 1e-8; x += step) grid.nx++; grid.ny = 0; for (double y = grid.yMin; y < targetMaxY + step - 1e-8; y += step) grid.ny++; // 计算实际导出边界 grid.xMax = grid.xMin + (grid.nx - 1) * step; grid.yMax = grid.yMin + (grid.ny - 1) * step; size_t total = (size_t)grid.nx * grid.ny; grid.gx.assign(total, 0.0); grid.gy.assign(total, 0.0); grid.zi.assign(total, 0.0); // 生成扁平化网格:Y 为行 (从小到大),X 为列 (从小到大) for (int r = 0; r < grid.ny; ++r) { double cur_y = grid.yMin + r * step; for (int c = 0; c < grid.nx; ++c) { size_t idx = (size_t)r * grid.nx + c; grid.gx[idx] = grid.xMin + c * step; grid.gy[idx] = cur_y; } } } /** * 2. 最小曲率插值 (TPS) + 并行处理 */ void calculateSpline(const std::vector& sx, const std::vector& sy, const std::vector& sz, const std::vector& trends, int fusionMode, GridResult& grid) { int n = sx.size(); if (n == 0 || trends.empty()) return; std::vector> trendResults(trends.size()); for (size_t t_idx = 0; t_idx < trends.size(); ++t_idx) { const auto& t = trends[t_idx]; double rad = (90.0 - t.angle) * M_PI / 180.0; double cosA = std::cos(rad), sinA = std::sin(rad); std::vector tx(n), ty(n); for (int i = 0; i < n; ++i) { double dx = sx[i] - t.cx; double dy = sy[i] - t.cy; tx[i] = (dx * cosA + dy * sinA) / t.ratio; ty[i] = -dx * sinA + dy * cosA; } Eigen::MatrixXd A(n, n); Eigen::VectorXd b(n); for (int i = 0; i < n; ++i) { b(i) = sz[i]; for (int j = 0; j < n; ++j) { double r = std::sqrt(std::pow(tx[i] - tx[j], 2) + std::pow(ty[i] - ty[j], 2)); A(i, j) = (r < 1e-12) ? 0 : r * r * std::log(r); } } A.diagonal().array() += 1e-12; // 稳定性因子 Eigen::VectorXd weights = A.fullPivLu().solve(b); std::vector cur_zi(grid.gx.size()); #pragma omp parallel for schedule(dynamic) for (long long i = 0; i < (long long)grid.gx.size(); ++i) { double dx = grid.gx[i] - t.cx; double dy = grid.gy[i] - t.cy; double rx = (dx * cosA + dy * sinA) / t.ratio; double ry = -dx * sinA + dy * cosA; double val = 0; for (int j = 0; j < n; ++j) { double r = std::sqrt(std::pow(rx - tx[j], 2) + std::pow(ry - ty[j], 2)); val += weights(j) * ((r < 1e-12) ? 0 : r * r * std::log(r)); } cur_zi[i] = val; } trendResults[t_idx] = cur_zi; } grid.zi.assign(grid.gx.size(), 0.0); #pragma omp parallel for schedule(static) for (long long i = 0; i < (long long)grid.gx.size(); ++i) { if (fusionMode == 1) { double maxVal = -1e18; for (const auto& res : trendResults) if (res[i] > maxVal) maxVal = res[i]; grid.zi[i] = maxVal; } else { double sumV = 0, sumW = 0; for (size_t t = 0; t < trends.size(); ++t) { sumV += trendResults[t][i] * trends[t].weight; sumW += trends[t].weight; } grid.zi[i] = (sumW > 1e-12) ? sumV / sumW : 0; } } } /** * 3. 导出 GRD (标准 DSAA) * 修复点:输出 yMin yMax,确保步长为正值 (+20) */ void exportToGRD(const std::string& filename, const GridResult& grid) { std::ofstream f(filename); if (!f.is_open()) return; auto mm = std::minmax_element(grid.zi.begin(), grid.zi.end()); f << "DSAA\n"; f << grid.nx << " " << grid.ny << "\n"; f << std::fixed << std::setprecision(6) << grid.xMin << " " << grid.xMax << "\n"; f << grid.yMin << " " << grid.yMax << "\n"; // 修改为 yMin yMax f << std::scientific << std::setprecision(6) << *mm.first << " " << *mm.second << "\n"; // 按 Surfer 10个数值一行的标准写入 for (size_t i = 0; i < grid.zi.size(); ++i) { f << grid.zi[i]; if ((i + 1) % 10 == 0 || (i + 1) == grid.zi.size()) f << "\n"; else f << " "; } } }; bool loadSandstoneCSV(const std::string& fname, std::vector& x, std::vector& y, std::vector& z) { std::ifstream f(fname); if (!f.is_open()) return false; std::string line; std::getline(f, line); while (std::getline(f, line)) { if (line.empty()) continue; std::stringstream ss(line); std::string item; std::vector row; while (std::getline(ss, item, ',')) row.push_back(item); if (row.size() >= 4) { try { x.push_back(std::stod(row[1])); y.push_back(std::stod(row[2])); z.push_back(std::stod(row[3])); } catch (...) { continue; } } } return !x.empty(); } } // //int main() { // GeoEngine engine; // GridResult grid; // std::vector sx, sy, sz; // // // 1. 读取数据 // if (!loadSandstoneCSV("G:/Desktop/333.csv", sx, sy, sz)) return -1; // // // 2. 初始化网格 (步长 20) // engine.initGridStrict(sx, sy, 20.0, grid); // // // 3. 确定旋转中心 (与 Python fixed 版对齐) // auto x_mm = std::minmax_element(sx.begin(), sx.end()); // auto y_mm = std::minmax_element(sy.begin(), sy.end()); // double midX = (*x_mm.first + *x_mm.second) / 2.0; // double midY = (*y_mm.first + *y_mm.second) / 2.0; // // // 4. 计算与导出 // TrendParam p1 = { 0.0, 0.0, midX, midY, 1.0 }; // engine.calculateSpline(sx, sy, sz, { p1 }, 0, grid); // engine.exportToGRD("G:/Desktop/result_cpp_fixed.grd", grid); //}