feat(gpr): build-line 健壮支持任意测线 + 新增 build-all 批量建体(磁盘守护/coarse 下采样)
- 桥接 buildLineVolumeFromGpr3dv 增 coarse 参数:沿测线(道/X 轴)按步长下采样, spacing.x ×stride 保持真实世界尺度;通道/样本保留全分辨率。默认 coarse=1 全分辨率, 对现有调用与测试零影响。 - build-line 增 --coarse F;单线建体核心抽出 buildOneLine,加体维度退化守护 (短桩线 nx<2 等报因跳过不落盘),整条 try/catch 不崩。 - 新增 build-all <lineDir> --outBase <baseDir> [--levels N] [--coarse F] [--minFreeGB G]:扫 *_A<NN>.iprh 发现全部测线,逐条建到 baseDir/<line>/; 每条建前查磁盘剩余,低于阈值(默认 3G)停并报已建哪些;单条异常捕获跳过不中断批量; 末尾打印各线状态(成功/跳过+因/维度/大小)与合计占用。 - 通道/道/样本全从数据读,不写死;不破坏现有 gpr/bridge 测试(12/12 通过)。
This commit is contained in:
parent
4330e12c3e
commit
4e2bdc3b81
|
|
@ -67,7 +67,9 @@ double nowMs(std::chrono::steady_clock::time_point t0) {
|
||||||
|
|
||||||
geopro::core::BuiltI16 buildLineVolumeFromGpr3dv(const std::string& lineDir,
|
geopro::core::BuiltI16 buildLineVolumeFromGpr3dv(const std::string& lineDir,
|
||||||
const std::string& linePrefix,
|
const std::string& linePrefix,
|
||||||
BridgeMetrics* metricsOut) {
|
BridgeMetrics* metricsOut,
|
||||||
|
int coarse) {
|
||||||
|
const int stride = coarse > 1 ? coarse : 1; // 沿测线下采样步长(≥1)
|
||||||
const QString dir = QString::fromLocal8Bit(lineDir.c_str());
|
const QString dir = QString::fromLocal8Bit(lineDir.c_str());
|
||||||
const QString base = QString::fromLocal8Bit(linePrefix.c_str());
|
const QString base = QString::fromLocal8Bit(linePrefix.c_str());
|
||||||
|
|
||||||
|
|
@ -103,7 +105,9 @@ geopro::core::BuiltI16 buildLineVolumeFromGpr3dv(const std::string& lineDir,
|
||||||
std::to_string(traces) + "/" +
|
std::to_string(traces) + "/" +
|
||||||
std::to_string(samples) + ")");
|
std::to_string(samples) + ")");
|
||||||
}
|
}
|
||||||
const int nx = traces; // X=道(沿测线)
|
// 下采样后输出道数(向上取整保留末道附近):nxOut = ceil(traces/stride)。
|
||||||
|
const int nxOut = (traces + stride - 1) / stride;
|
||||||
|
const int nx = nxOut; // X=道(沿测线,已按 stride 下采样)
|
||||||
const int ny = channels; // Y=通道(横向)
|
const int ny = channels; // Y=通道(横向)
|
||||||
const int nz = samples; // Z=样本(深度)
|
const int nz = samples; // Z=样本(深度)
|
||||||
|
|
||||||
|
|
@ -135,17 +139,19 @@ geopro::core::BuiltI16 buildLineVolumeFromGpr3dv(const std::string& lineDir,
|
||||||
quant.offset = 0.5 * (vmin + vmax); // 中点 → 防溢出
|
quant.offset = 0.5 * (vmin + vmax); // 中点 → 防溢出
|
||||||
|
|
||||||
// 4) 逐 (ch,trace,sample) 填体。GPR 立方体为稠密体(每体素有值),无空洞 → 不置 kBlank。
|
// 4) 逐 (ch,trace,sample) 填体。GPR 立方体为稠密体(每体素有值),无空洞 → 不置 kBlank。
|
||||||
|
// 沿测线按 stride 下采样:输出道 to → 源道 t = to*stride。
|
||||||
geopro::core::BuiltI16 built;
|
geopro::core::BuiltI16 built;
|
||||||
built.vol = geopro::core::ScalarVolumeI16(nx, ny, nz);
|
built.vol = geopro::core::ScalarVolumeI16(nx, ny, nz);
|
||||||
for (int c = 0; c < channels; ++c) {
|
for (int c = 0; c < channels; ++c) {
|
||||||
const auto& chData = processed.volumeData[c];
|
const auto& chData = processed.volumeData[c];
|
||||||
for (int t = 0; t < traces; ++t) {
|
for (int to = 0; to < nxOut; ++to) {
|
||||||
const bool hasTrace = t < chData.size();
|
const int t = to * stride;
|
||||||
|
const bool hasTrace = t < static_cast<int>(chData.size());
|
||||||
for (int s = 0; s < samples; ++s) {
|
for (int s = 0; s < samples; ++s) {
|
||||||
short v = 0;
|
short v = 0;
|
||||||
if (hasTrace && s < chData[t].size()) v = chData[t][s];
|
if (hasTrace && s < static_cast<int>(chData[t].size())) v = chData[t][s];
|
||||||
// X=道 t、Y=通道 c、Z=样本 s。
|
// X=输出道 to、Y=通道 c、Z=样本 s。
|
||||||
built.vol.at(t, c, s) = quant.toQ(static_cast<double>(v));
|
built.vol.at(to, c, s) = quant.toQ(static_cast<double>(v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +159,9 @@ geopro::core::BuiltI16 buildLineVolumeFromGpr3dv(const std::string& lineDir,
|
||||||
|
|
||||||
// 5) 几何:origin=0,spacing 按 X=道距 / Y=通道横距 / Z=深度采样距。
|
// 5) 几何:origin=0,spacing 按 X=道距 / Y=通道横距 / Z=深度采样距。
|
||||||
const GPRDataModel::Header& h = processed.header;
|
const GPRDataModel::Header& h = processed.header;
|
||||||
const double dx = h.distanceInc > 1e-9 ? h.distanceInc : 1.0;
|
// 下采样后相邻输出道在世界中跨 stride 个原始道距 → dx ×stride 保持真实尺度。
|
||||||
|
const double dxBase = h.distanceInc > 1e-9 ? h.distanceInc : 1.0;
|
||||||
|
const double dx = dxBase * stride;
|
||||||
const double dy = channelSpacingY(h, channels);
|
const double dy = channelSpacingY(h, channels);
|
||||||
const double dz = depthSpacingZ(h);
|
const double dz = depthSpacingZ(h);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,13 @@ struct BridgeMetrics {
|
||||||
// 走 P1 链得处理后立方体 → 量化映射成 geopro BuiltI16(轴 X=道/Y=通道/Z=样本)。
|
// 走 P1 链得处理后立方体 → 量化映射成 geopro BuiltI16(轴 X=道/Y=通道/Z=样本)。
|
||||||
// lineDir/linePrefix 同 gpr3dv-smoke(如 "D:/Downloads/明星路", "明星路_001")。
|
// lineDir/linePrefix 同 gpr3dv-smoke(如 "D:/Downloads/明星路", "明星路_001")。
|
||||||
// metricsOut 非空时回填维度/量化/spacing/耗时(供 CLI 报告,不编造)。
|
// metricsOut 非空时回填维度/量化/spacing/耗时(供 CLI 报告,不编造)。
|
||||||
|
// coarse(下采样因子,≥1):沿测线(道/X 轴)每 coarse 道取 1,spacing.x ×coarse 保形;
|
||||||
|
// 通道/样本(横向/深度)保留全分辨率。coarse≤1 即全分辨率。磁盘紧张时省空间用。
|
||||||
// 失败(加载失败/立方体为空) → 抛 std::runtime_error。
|
// 失败(加载失败/立方体为空) → 抛 std::runtime_error。
|
||||||
geopro::core::BuiltI16 buildLineVolumeFromGpr3dv(const std::string& lineDir,
|
geopro::core::BuiltI16 buildLineVolumeFromGpr3dv(const std::string& lineDir,
|
||||||
const std::string& linePrefix,
|
const std::string& linePrefix,
|
||||||
BridgeMetrics* metricsOut);
|
BridgeMetrics* metricsOut,
|
||||||
|
int coarse = 1);
|
||||||
|
|
||||||
} // namespace geopro::io::gpr
|
} // namespace geopro::io::gpr
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -808,33 +809,60 @@ int cmdBuildGeo(int argc, char** argv) {
|
||||||
// volumeData[通道][道][样本],再桥接(Gpr3dvVolumeBridge)成 geopro int16 量化体
|
// volumeData[通道][道][样本],再桥接(Gpr3dvVolumeBridge)成 geopro int16 量化体
|
||||||
// (轴 X=道/Y=通道/Z=样本),落 ChunkedVolumeStore + buildPyramid。原样渲(14 格 Y
|
// (轴 X=道/Y=通道/Z=样本),落 ChunkedVolumeStore + buildPyramid。原样渲(14 格 Y
|
||||||
// 薄体),不做横向插值加密。
|
// 薄体),不做横向插值加密。
|
||||||
int cmdBuildLine(int argc, char** argv) {
|
// 磁盘剩余空间(GB):查 path 所在卷可用字节。失败(路径不存在等)→ -1(视为未知)。
|
||||||
const Args a = parseArgs(argc, argv, 2);
|
double freeSpaceGB(const std::string& path) {
|
||||||
if (a.positional.size() < 2) {
|
std::error_code ec;
|
||||||
std::cerr << "用法: gpr_poc build-line <lineDir> <linePrefix> "
|
// 用已存在的父目录查(out 目录可能还没建)。
|
||||||
"--out <storeDir> [--levels 3]\n"
|
fs::path p = fs::absolute(path, ec);
|
||||||
"例: gpr_poc build-line \"D:/Downloads/明星路\" 明星路_001 "
|
while (!p.empty() && !fs::exists(p, ec)) p = p.parent_path();
|
||||||
"--out tmp/line001_proc --levels 3\n";
|
if (p.empty()) p = fs::current_path(ec);
|
||||||
return 2;
|
const fs::space_info si = fs::space(p, ec);
|
||||||
|
if (ec) return -1.0;
|
||||||
|
return static_cast<double>(si.available) / (1024.0 * 1024.0 * 1024.0);
|
||||||
}
|
}
|
||||||
const std::string lineDir = a.positional[0];
|
|
||||||
const std::string linePrefix = a.positional[1];
|
// 单线建体结果(供 build-all 汇总,不编造)。ok=false 时 reason 给清晰原因。
|
||||||
const int levels = std::stoi(a.get("levels", "3"));
|
struct LineBuildResult {
|
||||||
const std::string out =
|
std::string prefix;
|
||||||
a.get("out", (fs::temp_directory_path() / "gpr_store_line").string());
|
bool ok = false;
|
||||||
|
std::string reason; // 失败/跳过原因
|
||||||
|
std::int64_t nx = 0, ny = 0, nz = 0;
|
||||||
|
std::int64_t dataBytes = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 单线建体核心:gpr3dv 处理链 → 桥接量化体(可 coarse 下采样) → 落盘 + 金字塔。
|
||||||
|
// 异常(加载失败/立方体空/短桩线维度退化)由调用方捕获,不在此中断批量。
|
||||||
|
LineBuildResult buildOneLine(const std::string& lineDir,
|
||||||
|
const std::string& linePrefix,
|
||||||
|
const std::string& out, int levels, int coarse) {
|
||||||
|
LineBuildResult r;
|
||||||
|
r.prefix = linePrefix;
|
||||||
|
|
||||||
std::cout << "[build-line] lineDir=" << lineDir << " linePrefix=" << linePrefix
|
std::cout << "[build-line] lineDir=" << lineDir << " linePrefix=" << linePrefix
|
||||||
<< " levels=" << levels << " out=" << out << "\n";
|
<< " levels=" << levels << " coarse=" << coarse << " out=" << out
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
// 1) gpr3dv 处理链 → 处理后立方体 → 桥接量化体。
|
// 1) gpr3dv 处理链 → 处理后立方体 → 桥接量化体(coarse 沿测线下采样)。
|
||||||
Stopwatch swBridge;
|
Stopwatch swBridge;
|
||||||
geopro::io::gpr::BridgeMetrics bm;
|
geopro::io::gpr::BridgeMetrics bm;
|
||||||
geopro::core::BuiltI16 built =
|
geopro::core::BuiltI16 built = geopro::io::gpr::buildLineVolumeFromGpr3dv(
|
||||||
geopro::io::gpr::buildLineVolumeFromGpr3dv(lineDir, linePrefix, &bm);
|
lineDir, linePrefix, &bm, coarse);
|
||||||
const double bridgeMs = swBridge.elapsedMs();
|
const double bridgeMs = swBridge.elapsedMs();
|
||||||
|
|
||||||
const std::int64_t nx = built.vol.nx(), ny = built.vol.ny(),
|
const std::int64_t nx = built.vol.nx(), ny = built.vol.ny(),
|
||||||
nz = built.vol.nz();
|
nz = built.vol.nz();
|
||||||
|
r.nx = nx;
|
||||||
|
r.ny = ny;
|
||||||
|
r.nz = nz;
|
||||||
|
// 短桩线/退化体守护:维度过小无法建有意义的金字塔/体绘制 → 报因跳过(不落盘)。
|
||||||
|
if (nx < 2 || ny < 1 || nz < 2) {
|
||||||
|
r.ok = false;
|
||||||
|
r.reason = "体维度退化(道×通道×样本=" + std::to_string(nx) + "x" +
|
||||||
|
std::to_string(ny) + "x" + std::to_string(nz) +
|
||||||
|
"),无法建可看体,跳过";
|
||||||
|
std::cerr << "[build-line] " << linePrefix << " " << r.reason << "\n";
|
||||||
|
return r;
|
||||||
|
}
|
||||||
const std::int64_t voxels = nx * ny * nz;
|
const std::int64_t voxels = nx * ny * nz;
|
||||||
const std::int64_t rawBytes = voxels * 2; // int16
|
const std::int64_t rawBytes = voxels * 2; // int16
|
||||||
|
|
||||||
|
|
@ -848,7 +876,7 @@ int cmdBuildLine(int argc, char** argv) {
|
||||||
std::cout << "[build-line] 世界 spacing dx=" << bm.dx << " dy=" << bm.dy
|
std::cout << "[build-line] 世界 spacing dx=" << bm.dx << " dy=" << bm.dy
|
||||||
<< " dz=" << bm.dz << " (m)\n";
|
<< " dz=" << bm.dz << " (m)\n";
|
||||||
|
|
||||||
// 2) 落盘 + 金字塔(道很长 45305>16384 → 需 levels≥2 使最粗层≤16384)。
|
// 2) 落盘 + 金字塔(道很长 → 需 levels≥2 使最粗层≤16384)。
|
||||||
fs::create_directories(out);
|
fs::create_directories(out);
|
||||||
Stopwatch swWrite;
|
Stopwatch swWrite;
|
||||||
geopro::data::ChunkedVolumeStore::write(out, built);
|
geopro::data::ChunkedVolumeStore::write(out, built);
|
||||||
|
|
@ -862,6 +890,7 @@ int cmdBuildLine(int argc, char** argv) {
|
||||||
const double pyrMs = swPyr.elapsedMs();
|
const double pyrMs = swPyr.elapsedMs();
|
||||||
|
|
||||||
const std::int64_t dataBytes = storeDataBytes(out);
|
const std::int64_t dataBytes = storeDataBytes(out);
|
||||||
|
r.dataBytes = dataBytes;
|
||||||
const double ratio =
|
const double ratio =
|
||||||
dataBytes > 0 ? static_cast<double>(rawBytes) / dataBytes : 0.0;
|
dataBytes > 0 ? static_cast<double>(rawBytes) / dataBytes : 0.0;
|
||||||
const double peak = Probe::peakMemMB();
|
const double peak = Probe::peakMemMB();
|
||||||
|
|
@ -887,9 +916,9 @@ int cmdBuildLine(int argc, char** argv) {
|
||||||
std::cout << "峰值内存(MB) : " << peak << "\n";
|
std::cout << "峰值内存(MB) : " << peak << "\n";
|
||||||
|
|
||||||
writeMetricLine(
|
writeMetricLine(
|
||||||
"build-line,prefix=" + linePrefix + ",nx=" + std::to_string(nx) +
|
"build-line,prefix=" + linePrefix + ",coarse=" + std::to_string(coarse) +
|
||||||
",ny=" + std::to_string(ny) + ",nz=" + std::to_string(nz) +
|
",nx=" + std::to_string(nx) + ",ny=" + std::to_string(ny) +
|
||||||
",voxels=" + std::to_string(voxels) +
|
",nz=" + std::to_string(nz) + ",voxels=" + std::to_string(voxels) +
|
||||||
",vmin=" + std::to_string(bm.vminPhys) +
|
",vmin=" + std::to_string(bm.vminPhys) +
|
||||||
",vmax=" + std::to_string(bm.vmaxPhys) +
|
",vmax=" + std::to_string(bm.vmaxPhys) +
|
||||||
",dx=" + std::to_string(bm.dx) + ",dy=" + std::to_string(bm.dy) +
|
",dx=" + std::to_string(bm.dx) + ",dy=" + std::to_string(bm.dy) +
|
||||||
|
|
@ -899,6 +928,133 @@ int cmdBuildLine(int argc, char** argv) {
|
||||||
",bridgeMs=" + std::to_string(bridgeMs) +
|
",bridgeMs=" + std::to_string(bridgeMs) +
|
||||||
",writeMs=" + std::to_string(writeMs) +
|
",writeMs=" + std::to_string(writeMs) +
|
||||||
",pyrMs=" + std::to_string(pyrMs) + ",peakMB=" + std::to_string(peak));
|
",pyrMs=" + std::to_string(pyrMs) + ",peakMB=" + std::to_string(peak));
|
||||||
|
|
||||||
|
r.ok = true;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmdBuildLine(int argc, char** argv) {
|
||||||
|
const Args a = parseArgs(argc, argv, 2);
|
||||||
|
if (a.positional.size() < 2) {
|
||||||
|
std::cerr << "用法: gpr_poc build-line <lineDir> <linePrefix> "
|
||||||
|
"--out <storeDir> [--levels 3] [--coarse F]\n"
|
||||||
|
"例: gpr_poc build-line \"D:/Downloads/明星路\" 明星路_001 "
|
||||||
|
"--out tmp/line001_proc --levels 3 --coarse 4\n";
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
const std::string lineDir = a.positional[0];
|
||||||
|
const std::string linePrefix = a.positional[1];
|
||||||
|
const int levels = std::stoi(a.get("levels", "3"));
|
||||||
|
const int coarse = std::stoi(a.get("coarse", "1"));
|
||||||
|
const std::string out =
|
||||||
|
a.get("out", (fs::temp_directory_path() / "gpr_store_line").string());
|
||||||
|
|
||||||
|
try {
|
||||||
|
const LineBuildResult r =
|
||||||
|
buildOneLine(lineDir, linePrefix, out, levels, coarse);
|
||||||
|
if (!r.ok) {
|
||||||
|
std::cerr << "[build-line] 跳过: " << r.reason << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "[build-line] 失败(" << linePrefix << "): " << e.what() << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build-all:发现目录下所有测线(_Axx 分组),逐条 build-line 到 baseDir/<lineName>/。
|
||||||
|
// 磁盘守护:每条建前查可用空间,低于阈值(默认 3GB)即停并报已建哪些。
|
||||||
|
// 短桩线/异常单条捕获并跳过(报因),不中断其余。
|
||||||
|
int cmdBuildAll(int argc, char** argv) {
|
||||||
|
const Args a = parseArgs(argc, argv, 2);
|
||||||
|
if (a.positional.empty() || !a.kv.count("outBase")) {
|
||||||
|
std::cerr << "用法: gpr_poc build-all <lineDir> --outBase <baseDir> "
|
||||||
|
"[--levels 3] [--coarse F] [--minFreeGB 3]\n"
|
||||||
|
"例: gpr_poc build-all \"D:/Downloads/明星路\" "
|
||||||
|
"--outBase tmp/lines_all --levels 3 --coarse 4\n";
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
const std::string lineDir = a.positional[0];
|
||||||
|
const std::string outBase = a.get("outBase", "");
|
||||||
|
const int levels = std::stoi(a.get("levels", "3"));
|
||||||
|
const int coarse = std::stoi(a.get("coarse", "1"));
|
||||||
|
const double minFreeGB = std::stod(a.get("minFreeGB", "3"));
|
||||||
|
|
||||||
|
// 1) 发现所有测线前缀:扫 *_<line>_A<NN>.iprh,取 "<...>_<line>" 部分(去 _A<NN>)。
|
||||||
|
std::set<std::string> prefixSet;
|
||||||
|
std::error_code ec;
|
||||||
|
for (const auto& e : fs::directory_iterator(lineDir, ec)) {
|
||||||
|
if (!e.is_regular_file()) continue;
|
||||||
|
const std::string name = e.path().filename().string();
|
||||||
|
if (e.path().extension().string() != ".iprh") continue;
|
||||||
|
// 找 "_A<NN>" 通道后缀,截断得测线前缀。
|
||||||
|
const std::size_t pos = name.rfind("_A");
|
||||||
|
if (pos == std::string::npos) continue;
|
||||||
|
std::size_t d = pos + 2;
|
||||||
|
while (d < name.size() && std::isdigit(static_cast<unsigned char>(name[d])))
|
||||||
|
++d;
|
||||||
|
if (d == pos + 2) continue; // _A 后无数字 → 非通道文件
|
||||||
|
prefixSet.insert(name.substr(0, pos));
|
||||||
|
}
|
||||||
|
if (prefixSet.empty()) {
|
||||||
|
std::cerr << "[build-all] 未在 " << lineDir << " 发现任何测线(*_A<NN>.iprh)\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::vector<std::string> prefixes(prefixSet.begin(), prefixSet.end());
|
||||||
|
std::cout << "[build-all] 发现 " << prefixes.size() << " 条测线,outBase="
|
||||||
|
<< outBase << " levels=" << levels << " coarse=" << coarse
|
||||||
|
<< " minFreeGB=" << minFreeGB << "\n";
|
||||||
|
|
||||||
|
fs::create_directories(outBase, ec);
|
||||||
|
|
||||||
|
// 2) 逐条建:磁盘守护 → buildOneLine(单条 try/catch)。
|
||||||
|
std::vector<LineBuildResult> results;
|
||||||
|
bool stoppedByDisk = false;
|
||||||
|
for (const std::string& prefix : prefixes) {
|
||||||
|
const double freeGB = freeSpaceGB(outBase);
|
||||||
|
std::cout << "\n[build-all] --- " << prefix << " --- 剩余磁盘 "
|
||||||
|
<< freeGB << " GB\n";
|
||||||
|
if (freeGB >= 0.0 && freeGB < minFreeGB) {
|
||||||
|
std::cerr << "[build-all] 磁盘守护触发: 剩余 " << freeGB << " GB < "
|
||||||
|
<< minFreeGB << " GB,停止,未建 " << prefix << " 及其后。\n";
|
||||||
|
stoppedByDisk = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const std::string out = (fs::path(outBase) / prefix).string();
|
||||||
|
LineBuildResult r;
|
||||||
|
r.prefix = prefix;
|
||||||
|
try {
|
||||||
|
r = buildOneLine(lineDir, prefix, out, levels, coarse);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
r.ok = false;
|
||||||
|
r.reason = std::string("异常: ") + e.what();
|
||||||
|
std::cerr << "[build-all] " << prefix << " 失败: " << e.what()
|
||||||
|
<< "(跳过,继续)\n";
|
||||||
|
}
|
||||||
|
results.push_back(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) 汇总。
|
||||||
|
std::cout << "\n=== build-all 汇总 ===\n";
|
||||||
|
int okCount = 0;
|
||||||
|
std::int64_t totalBytes = 0;
|
||||||
|
for (const auto& r : results) {
|
||||||
|
if (r.ok) {
|
||||||
|
++okCount;
|
||||||
|
totalBytes += r.dataBytes;
|
||||||
|
std::cout << " [OK] " << r.prefix << " 维度=" << r.nx << "x" << r.ny
|
||||||
|
<< "x" << r.nz << " data="
|
||||||
|
<< r.dataBytes / (1024.0 * 1024.0) << " MB\n";
|
||||||
|
} else {
|
||||||
|
std::cout << " [跳过] " << r.prefix << " 原因=" << r.reason << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "成功 " << okCount << "/" << prefixes.size()
|
||||||
|
<< " 条,合计 data=" << totalBytes / (1024.0 * 1024.0 * 1024.0)
|
||||||
|
<< " GB,剩余磁盘 " << freeSpaceGB(outBase) << " GB\n";
|
||||||
|
if (stoppedByDisk)
|
||||||
|
std::cout << "注意: 因磁盘守护提前停止,部分测线未建。\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4388,7 +4544,9 @@ void usage() {
|
||||||
" gpr_poc build-geo <dir> [--cellXY 0.5] [--cellZ 0.1] "
|
" gpr_poc build-geo <dir> [--cellXY 0.5] [--cellZ 0.1] "
|
||||||
"[--out <storeDir>] [--levels 4] [--maxLines N] [--curvilinear]\n"
|
"[--out <storeDir>] [--levels 4] [--maxLines N] [--curvilinear]\n"
|
||||||
" gpr_poc build-line <lineDir> <linePrefix> --out <storeDir> "
|
" gpr_poc build-line <lineDir> <linePrefix> --out <storeDir> "
|
||||||
"[--levels 3]\n"
|
"[--levels 3] [--coarse F]\n"
|
||||||
|
" gpr_poc build-all <lineDir> --outBase <baseDir> "
|
||||||
|
"[--levels 3] [--coarse F] [--minFreeGB 3]\n"
|
||||||
" gpr_poc load <storeDir>\n"
|
" gpr_poc load <storeDir>\n"
|
||||||
" gpr_poc selftest\n"
|
" gpr_poc selftest\n"
|
||||||
" gpr_poc offscreen-smoke\n"
|
" gpr_poc offscreen-smoke\n"
|
||||||
|
|
@ -4424,6 +4582,7 @@ int main(int argc, char** argv) {
|
||||||
if (cmd == "build-stream") return cmdBuildStream(argc, argv);
|
if (cmd == "build-stream") return cmdBuildStream(argc, argv);
|
||||||
if (cmd == "build-geo") return cmdBuildGeo(argc, argv);
|
if (cmd == "build-geo") return cmdBuildGeo(argc, argv);
|
||||||
if (cmd == "build-line") return cmdBuildLine(argc, argv);
|
if (cmd == "build-line") return cmdBuildLine(argc, argv);
|
||||||
|
if (cmd == "build-all") return cmdBuildAll(argc, argv);
|
||||||
if (cmd == "load") return cmdLoad(argc, argv);
|
if (cmd == "load") return cmdLoad(argc, argv);
|
||||||
if (cmd == "selftest") return cmdSelftest();
|
if (cmd == "selftest") return cmdSelftest();
|
||||||
if (cmd == "offscreen-smoke") return cmdOffscreenSmoke();
|
if (cmd == "offscreen-smoke") return cmdOffscreenSmoke();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue