From 16c0620dd3a5d7734a0ae1d211e64062f38fbefd Mon Sep 17 00:00:00 2001 From: xy <748613696@qq.com> Date: Thu, 4 Jun 2026 18:29:24 +0800 Subject: [PATCH] =?UTF-8?q?refactor(wave):=20=E4=BC=98=E5=8C=96=E6=B3=A2?= =?UTF-8?q?=E5=BD=A2=E6=95=B0=E6=8D=AE=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除波形数据抽点窗口大小配置参数wave.sample.interval - 使用NPush参数替代固定的抽点窗口大小计算方式 - 修改图像生成方法的参数传递方式,直接传入nPush参数 - 调整波形数据抽点算法,移除MinMax抽点逻辑 - 优化数据段合并处理逻辑,简化null点插入策略 - 改进关键时间点处理,移除固定的关键时间点集合 - 调整波形数据范围计算,使用动态的nPush值代替固定毫秒值 --- .../service/impl/CsEventPOServiceImpl.java | 206 +++++------------- 1 file changed, 51 insertions(+), 155 deletions(-) diff --git a/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/impl/CsEventPOServiceImpl.java b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/impl/CsEventPOServiceImpl.java index 8cc08cb..c1bc88c 100644 --- a/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/impl/CsEventPOServiceImpl.java +++ b/cs-harmonic/cs-harmonic-boot/src/main/java/com/njcn/csharmonic/service/impl/CsEventPOServiceImpl.java @@ -126,11 +126,6 @@ public class CsEventPOServiceImpl extends ServiceImpl waveDataDetails = WaveUtil.filterWaveData(waveDataDTO); //单通道处理 if (ObjectUtils.isNotEmpty(waveDataDetails) && waveDataDetails.size() == 2) { - String instantPath = wavePicComponent.generateImageShun(waveDataDTO,waveDataDetails); + String instantPath = wavePicComponent.generateImageShun(nPush,waveDataDetails,eventDetail.getPersistTime()*1000); eventDetail.setInstantPics(instantPath); if (StrUtil.isBlank(eventDetail.getRmsPics())) { - String rmsPath = wavePicComponent.generateImageRms(waveDataDTO,waveDataDetails); + String rmsPath = wavePicComponent.generateImageRms(nPush,waveDataDetails,eventDetail.getPersistTime()*1000); eventDetail.setRmsPics(rmsPath); } } //双通道处理 else if (ObjectUtils.isNotEmpty(waveDataDetails) && waveDataDetails.size() == 4) { - String instantPath = wavePicComponent.generateInstantImageZl(waveDataDetails); + String instantPath = wavePicComponent.generateInstantImageZl(nPush,waveDataDetails,eventDetail.getPersistTime()*1000); eventDetail.setInstantPics(instantPath); if (StrUtil.isBlank(eventDetail.getRmsPics())) { - String rmsPath = wavePicComponent.generateRmsImageZl(waveDataDetails); + String rmsPath = wavePicComponent.generateRmsImageZl(nPush,waveDataDetails,eventDetail.getPersistTime()*1000); eventDetail.setRmsPics(rmsPath); } } @@ -735,24 +731,20 @@ public class CsEventPOServiceImpl extends ServiceImpl keyTimes = new HashSet<>(); - keyTimes.add(startSegBegin); // 开头-100 - keyTimes.add(0.0); // 波形开始时间点0 - keyTimes.add(persistTimeMs); // 持续时间点 - keyTimes.add(endSegBegin); // 持续时间点往前-40 - keyTimes.add(endSegEnd); // 持续时间点往后+40 + // 结束段:恢复点前后 + double endSegBegin = persistTimeMs - nPush; + double endSegEnd = persistTimeMs + nPush; List> originalWaveData = waveDataDTO.getListWaveData(); List> originalRmsData = waveDataDTO.getListRmsData(); @@ -769,152 +761,56 @@ public class CsEventPOServiceImpl extends ServiceImpl> filteredRmsData; if (isMerged) { - // 两段重叠或相邻,合并为一段连续数据 + // 两段重叠或相邻,合并为一段连续数据,不做抽点 double mergedEnd = Math.max(startSegEnd, endSegEnd); - List> segWaveData = filterByTimeRange(originalWaveData, startSegBegin, mergedEnd); - List> segRmsData = filterByTimeRange(originalRmsData, startSegBegin, mergedEnd); - - // 合并为1段:MinMax抽点 + 保留关键节点 - filteredWaveData = downsampleMinMaxWithKeyPoints(segWaveData, keyTimes, waveSampleInterval); - filteredRmsData = downsampleMinMaxWithKeyPoints(segRmsData, keyTimes, waveSampleInterval); + filteredWaveData = filterByTimeRange(originalWaveData, startSegBegin, mergedEnd); + filteredRmsData = filterByTimeRange(originalRmsData, startSegBegin, mergedEnd); } else { - // 两段分离,分别MinMax抽点 + 保留关键节点 + // 两段分离,各自按时间范围裁剪,不做抽点 List> seg1Wave = filterByTimeRange(originalWaveData, startSegBegin, startSegEnd); List> seg2Wave = filterByTimeRange(originalWaveData, endSegBegin, endSegEnd); List> seg1Rms = filterByTimeRange(originalRmsData, startSegBegin, startSegEnd); List> seg2Rms = filterByTimeRange(originalRmsData, endSegBegin, endSegEnd); - List> ds1Wave = downsampleMinMaxWithKeyPoints(seg1Wave, keyTimes, waveSampleInterval); - List> ds2Wave = downsampleMinMaxWithKeyPoints(seg2Wave, keyTimes, waveSampleInterval); - List> ds1Rms = downsampleMinMaxWithKeyPoints(seg1Rms, keyTimes, waveSampleInterval); - List> ds2Rms = downsampleMinMaxWithKeyPoints(seg2Rms, keyTimes, waveSampleInterval); - - // 两段之间补固定数量的null点,时间均匀分布 - double gapStart = getTimeValue(ds1Wave.get(ds1Wave.size() - 1)); - double gapEnd = getTimeValue(ds2Wave.get(0)); - List> gapWaveData = createNullGapData(gapStart, gapEnd, waveGapNullPoints, waveColumnCount); - List> gapRmsData = createNullGapData(gapStart, gapEnd, waveGapNullPoints, rmsColumnCount); - - // 合并:段1 + null间隔 + 段2 filteredWaveData = new ArrayList<>(); - filteredWaveData.addAll(ds1Wave); - filteredWaveData.addAll(gapWaveData); - filteredWaveData.addAll(ds2Wave); - filteredRmsData = new ArrayList<>(); - filteredRmsData.addAll(ds1Rms); - filteredRmsData.addAll(gapRmsData); - filteredRmsData.addAll(ds2Rms); - } + // 段1非空才加入 + if (!seg1Wave.isEmpty()) { + filteredWaveData.addAll(seg1Wave); + } + if (!seg1Rms.isEmpty()) { + filteredRmsData.addAll(seg1Rms); + } + // 两段都非空时才补null间隔 + boolean waveGapNeeded = !seg1Wave.isEmpty() && !seg2Wave.isEmpty(); + boolean rmsGapNeeded = !seg1Rms.isEmpty() && !seg2Rms.isEmpty(); + + if (waveGapNeeded) { + double waveGapStart = getTimeValue(seg1Wave.get(seg1Wave.size() - 1)); + double waveGapEnd = getTimeValue(seg2Wave.get(0)); + List> gapWaveData = createNullGapData(waveGapStart, waveGapEnd, waveGapNullPoints, waveColumnCount); + filteredWaveData.addAll(gapWaveData); + } + if (rmsGapNeeded) { + double rmsGapStart = getTimeValue(seg1Rms.get(seg1Rms.size() - 1)); + double rmsGapEnd = getTimeValue(seg2Rms.get(0)); + List> gapRmsData = createNullGapData(rmsGapStart, rmsGapEnd, waveGapNullPoints, rmsColumnCount); + filteredRmsData.addAll(gapRmsData); + } + + // 段2非空才加入 + if (!seg2Wave.isEmpty()) { + filteredWaveData.addAll(seg2Wave); + } + if (!seg2Rms.isEmpty()) { + filteredRmsData.addAll(seg2Rms); + } + } waveDataDTO.setListWaveData(filteredWaveData); waveDataDTO.setListRmsData(filteredRmsData); } - /** - * MinMax抽点:每N个点为一个窗口,保留窗口内峰值点、谷值点、首点及关键时间点 - * 峰值=参考列最大值的数据行,谷值=参考列最小值的数据行 - * 这样正弦波的峰谷特征得以保留,波形形状不会被破坏 - * - * @param dataList 已按时间范围筛选的数据 - * @param keyTimes 关键时间点集合(ms) - * @param sampleInterval 窗口大小(N) - */ - private List> downsampleMinMaxWithKeyPoints(List> dataList, Set keyTimes, int sampleInterval) { - if (dataList.isEmpty()) { - return dataList; - } - - // 找到关键时间点对应的数据索引 - Set keyIndices = new HashSet<>(); - for (Double keyTime : keyTimes) { - int closestIdx = findClosestIndex(dataList, keyTime); - if (closestIdx >= 0) { - keyIndices.add(closestIdx); - } - } - - List> result = new ArrayList<>(); - int size = dataList.size(); - // 使用第1列(第一个值列,通常是A相电压)作为峰谷检测参考列 - int refCol = 1; - - for (int windowStart = 0; windowStart < size; windowStart += sampleInterval) { - int windowEnd = Math.min(windowStart + sampleInterval, size); - - // 在窗口内找参考列的最大值点(峰值)和最小值点(谷值) - int maxIdx = windowStart; - int minIdx = windowStart; - float maxVal = getFloatValue(dataList.get(windowStart), refCol); - float minVal = getFloatValue(dataList.get(windowStart), refCol); - - for (int i = windowStart + 1; i < windowEnd; i++) { - float val = getFloatValue(dataList.get(i), refCol); - if (val > maxVal) { - maxVal = val; - maxIdx = i; - } - if (val < minVal) { - minVal = val; - minIdx = i; - } - } - - // 保留:窗口首点 + 峰值 + 谷值 + 窗口内的关键时间点 - Set keepSet = new HashSet<>(); - keepSet.add(windowStart); - keepSet.add(maxIdx); - keepSet.add(minIdx); - for (int i = windowStart; i < windowEnd; i++) { - if (keyIndices.contains(i)) { - keepSet.add(i); - } - } - - // 按原始顺序输出(索引顺序即时间顺序) - List sortedKeep = new ArrayList<>(keepSet); - Collections.sort(sortedKeep); - for (int idx : sortedKeep) { - result.add(dataList.get(idx)); - } - } - - return result; - } - - /** - * 安全获取Float值,null时返回0 - */ - private float getFloatValue(List data, int colIdx) { - if (colIdx >= data.size()) { - return 0f; - } - Float val = data.get(colIdx); - return val != null ? val : 0f; - } - - /** - * 找到与目标时间最接近的数据点索引 - * 仅在容差1.0ms内匹配,超出容差视为该段数据中无此关键点 - */ - private int findClosestIndex(List> dataList, double targetTime) { - int closestIdx = -1; - double minDiff = Double.MAX_VALUE; - for (int i = 0; i < dataList.size(); i++) { - double time = getTimeValue(dataList.get(i)); - double diff = Math.abs(time - targetTime); - if (diff < minDiff) { - minDiff = diff; - closestIdx = i; - } - } - // 容差1.0ms,超出则认为该段不含此关键点 - if (minDiff > 1.0) { - return -1; - } - return closestIdx; - } - private double getTimeValue(List data) { return data.get(0).doubleValue(); }