#ifndef GPRDATAMODEL_H #define GPRDATAMODEL_H #include #include #include #include #include #include #include "SurveyGeometry.h" struct RadarTrace { QVector amplitudes; // 【重要】改为 short (16-bit),之前是 float double startTime = 0.0; double timeStep = 0.0; // 三维位置信息 QVector3D position; // 该道的三维空间位置 int channelNumber = 0; // 通道号 RadarTrace() = default; RadarTrace(const RadarTrace& other) : amplitudes(QVector(other.amplitudes.cbegin(), other.amplitudes.cend())) , startTime(other.startTime) , timeStep(other.timeStep) , position(other.position) , channelNumber(other.channelNumber) {} RadarTrace& operator=(const RadarTrace& other) { if (this != &other) { amplitudes = QVector(other.amplitudes.cbegin(), other.amplitudes.cend()); startTime = other.startTime; timeStep = other.timeStep; position = other.position; channelNumber = other.channelNumber; } return *this; } RadarTrace(RadarTrace&& other) noexcept : amplitudes(std::move(other.amplitudes)) , startTime(other.startTime) , timeStep(other.timeStep) , position(other.position) , channelNumber(other.channelNumber) {} RadarTrace& operator=(RadarTrace&& other) noexcept { if (this != &other) { amplitudes = std::move(other.amplitudes); startTime = other.startTime; timeStep = other.timeStep; position = other.position; channelNumber = other.channelNumber; } return *this; } }; class GPRDataModel { public: struct Header { int numTraces = 0; // LAST TRACE int samplesPerTrace = 0; // SAMPLES double timeWindowNs = 0.0; // TIMEWINDOW (ns) double distanceInc = 0.0; // DISTANCE INTERVAL (m) double antennaFreq = 0.0; // FREQUENCY (MHz) QString antennaType; // ANTENNAS QString date; // DATE QString timeStr; // TIME // 三维相关参数 int numberOfChannels = 1; // NUMBER_OF_CH QVector chXOffsets; // CH_X_OFFSETS QVector chYOffsets; // CH_Y_OFFSETS QString units; // UNITS double startPosition = 0.0; // START POSITION double stopPosition = 0.0; // STOP POSITION double waveVelocity = 0.1; // 波速,用于深度计算 double timeIntervalNs = 0.0; // TIME INTERVAL (ns),用于计算时窗 // 原始映射,用于调试或扩展 QMap rawParams; }; Header header; QVector traces; // 三维数据相关属性 int tracesPerChannel = 0; // 每个通道的道数 int channels = 0; // 实际通道数 double totalDistance = 0.0; // 总距离 // 三维数据体 - 存储为[channel][trace][sample]格式 QVector>> volumeData; // [channel][trace][sample] bool isEmpty() const { return traces.isEmpty(); } void clear() { traces.clear(); header = Header{}; tracesPerChannel = 0; channels = 0; totalDistance = 0.0; volumeData.clear(); } // 获取指定通道的道数 int getTracesPerChannel() const { if (header.numTraces <= 0) { return 0; } if (header.numberOfChannels > 0) { return header.numTraces / header.numberOfChannels; } return header.numTraces; } int getTraceIndex(int channel, int traceInChannel) const { const int nChannels = header.numberOfChannels > 0 ? header.numberOfChannels : 1; if (channel < 0 || channel >= nChannels || traceInChannel < 0 || traceInChannel >= getTracesPerChannel()) { return -1; } return traceInChannel * nChannels + channel; } // 获取指定通道和道号的数据 const RadarTrace* getTrace(int channel, int traceInChannel) const { const int index = getTraceIndex(channel, traceInChannel); if (index >= 0 && index < traces.size()) { return &traces[index]; } return nullptr; } // 计算深度(米) double calculateDepth(int sampleIndex) const { if (header.samplesPerTrace > 0) { // 使用默认波速0.1m/ns,除以2是因为往返时间 double timePerSample = header.timeWindowNs / header.samplesPerTrace; double timeNs = sampleIndex * timePerSample; return timeNs * header.waveVelocity / 2.0; // 深度 = 时间 * 波速 / 2 } return 0.0; } // 计算距离(米) double calculateDistance(int traceIndex) const { if (header.distanceInc > 0) { return traceIndex * header.distanceInc; } return 0.0; } // 构建三维数据体 void buildVolumeData() { if (traces.isEmpty()) return; int nChannels = header.numberOfChannels > 0 ? header.numberOfChannels : 1; int nTracesPerChannel = getTracesPerChannel(); int nSamples = header.samplesPerTrace; volumeData.resize(nChannels); for (int c = 0; c < nChannels; ++c) { volumeData[c].resize(nTracesPerChannel); for (int t = 0; t < nTracesPerChannel; ++t) { volumeData[c][t].resize(nSamples); } } // 填充数据 for (int i = 0; i < traces.size(); ++i) { int channel = i % nChannels; int traceInChannel = i / nChannels; if (channel < volumeData.size() && traceInChannel < volumeData[channel].size()) { for (int s = 0; s < traces[i].amplitudes.size() && s < nSamples; ++s) { volumeData[channel][traceInChannel][s] = traces[i].amplitudes[s]; } } } } // 获取三维数据点 short getVolumeValue(int channel, int trace, int sample) const { if (channel < 0 || channel >= volumeData.size() || trace < 0 || trace >= volumeData[channel].size() || sample < 0 || sample >= volumeData[channel][trace].size()) { return 0; } return volumeData[channel][trace][sample]; } // 获取全局最小最大值 void getGlobalMinMax(short& minVal, short& maxVal) const { if (volumeData.isEmpty()) { minVal = 0; maxVal = 0; return; } minVal = 32767; maxVal = -32768; for (const auto& channelData : volumeData) { for (const auto& traceData : channelData) { for (short val : traceData) { if (val < minVal) minVal = val; if (val > maxVal) maxVal = val; } } } } // 获取通道数 int getChannelCount() const { if (!volumeData.isEmpty()) return volumeData.size(); return qMax(1, header.numberOfChannels); } // 获取每通道的迹数 int getTraceCountPerChannel() const { if (!volumeData.isEmpty() && !volumeData[0].isEmpty()) return volumeData[0].size(); int nCh = qMax(1, header.numberOfChannels); return header.numTraces / nCh; } // 获取每迹的样本数 int getSampleCount() const { if (!volumeData.isEmpty() && !volumeData[0].isEmpty()) return volumeData[0][0].size(); return header.samplesPerTrace; } GPRDataModel() = default; GPRDataModel(const GPRDataModel&) = default; GPRDataModel& operator=(const GPRDataModel&) = default; GPRDataModel(GPRDataModel&&) = default; GPRDataModel& operator=(GPRDataModel&&) = default; }; struct TrajectoryEditPoint { QVector3D rawPosition; QVector3D editedPosition; bool enabled = true; bool manuallyEdited = false; bool distanceOutlier = false; bool speedOutlier = false; bool angleOutlier = false; }; struct TrajectoryEditSettings { bool distanceFilterEnabled = true; double maxSegmentDistanceM = 1.0; bool speedFilterEnabled = false; double maxSpeedMps = 5.0; double traceIntervalSec = 0.05; bool angleFilterEnabled = true; double maxTurnAngleDeg = 60.0; int interpolationMode = 0; // 0 linear, 1 spline bool preserveManualEdits = true; }; // 单条测线结构(含GPS) struct SurveyLine { QString name; // 测线编号,如 "_000", "_001" QString displayName; // 显示名称,如 "碧新路_000" QString radFilePath; // .rad 文件完整路径 GPRDataModel data; // 雷达数据 QVector gpsPositions; // 每个trace的GPS坐标 (X,Y,Z) QVector trajectoryEditPoints; // 可编辑中心线轨迹点 TrajectoryEditSettings trajectoryEditSettings; // 三维轨迹相关(新增) SurveyGeometry geometry; // 天线几何参数 QVector> channelTrajectories; // [channel][trace] 绝对坐标 bool hasGps() const { return !gpsPositions.isEmpty(); } bool hasValidTrajectories() const { return !channelTrajectories.isEmpty() && !channelTrajectories[0].isEmpty(); } bool isEmpty() const { return data.isEmpty(); } void clear() { name.clear(); displayName.clear(); radFilePath.clear(); data.clear(); gpsPositions.clear(); trajectoryEditPoints.clear(); trajectoryEditSettings = TrajectoryEditSettings{}; geometry = SurveyGeometry{}; channelTrajectories.clear(); } SurveyLine() = default; SurveyLine(const SurveyLine&) = default; SurveyLine& operator=(const SurveyLine&) = default; SurveyLine(SurveyLine&&) = default; SurveyLine& operator=(SurveyLine&&) = default; }; Q_DECLARE_METATYPE(SurveyLine) #endif // GPRDATAMODEL_H