diff --git a/src/main/java/com/gunshi/project/hsz/service/StZvarlBService.java b/src/main/java/com/gunshi/project/hsz/service/StZvarlBService.java index 6f68c87..5f979c1 100644 --- a/src/main/java/com/gunshi/project/hsz/service/StZvarlBService.java +++ b/src/main/java/com/gunshi/project/hsz/service/StZvarlBService.java @@ -2,6 +2,7 @@ package com.gunshi.project.hsz.service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.gunshi.project.hsz.mapper.StZvarlBMapper; +import com.gunshi.project.hsz.model.StZqrlB; import com.gunshi.project.hsz.model.StZvarlB; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -72,6 +73,90 @@ public class StZvarlBService extends ServiceImpl { .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } + /** + * 分段线性计算水位->库容 + * 首先需要保证 水位->库容的数据要按水位从小到大进行排列 + * @param zvarlBS + * @param rz + * @return + */ + public BigDecimal getWByZvarl(List zvarlBS, BigDecimal rz) { + // 1. 参数校验 + if (zvarlBS == null || zvarlBS.isEmpty()) { + throw new IllegalArgumentException("水位-库容关系列表不能为空"); + } + if (rz == null) { + throw new IllegalArgumentException("水位值不能为空"); + } + // 2. 检查边界情况:如果目标水位低于最低水位或高于最高水位 + BigDecimal minRz = zvarlBS.get(0).getRz(); + BigDecimal maxRz = zvarlBS.get(zvarlBS.size() - 1).getRz(); + if (rz.compareTo(minRz) < 0) { + // 低于最低水位,可以选择抛出异常或进行外推(这里选择抛出异常) + return BigDecimal.ZERO; + } + if (rz.compareTo(maxRz) > 0) { + // 高于最高水位,可以选择抛出异常或进行外推(这里选择抛出异常) + return BigDecimal.ZERO; + } + int l = 0; + int r = zvarlBS.size() -1; + //二分查找 由线性On时间复杂度降为Ologn + while (l <= r) { + int mid = l + (r-l) / 2; + BigDecimal midRz = zvarlBS.get(mid).getRz(); + int compareResult = midRz.compareTo(rz); + if(compareResult == 0 ){ + return zvarlBS.get(mid).getW(); + }else if(compareResult < 0){ + l = mid + 1; + }else{ + r = mid - 1; + } + } + + /** + * 此时 l 指向第一个大于rz的位置 + * r 指向最后一个小于rz的位置 + * 既 r为 x1 y1 + * l为 x2 y2 + */ + if(l < 0 || r >= zvarlBS.size()){ + return BigDecimal.ZERO; + } + //获取前后差值的点 + StZvarlB lowerPoint = zvarlBS.get(r); + StZvarlB upperPoint = zvarlBS.get(l); + return linearInterpolation(lowerPoint.getRz(),lowerPoint.getW(),upperPoint.getRz(),upperPoint.getW(),rz).setScale(3); + } + + + /** + * 线性插值辅助方法 + * @param x1 已知点1的水位 + * @param y1 已知点1的库容 + * @param x2 已知点2的水位 + * @param y2 已知点2的库容 + * @param x 目标水位 + * @return 目标水位对应的库容 + */ + private BigDecimal linearInterpolation(BigDecimal x1, BigDecimal y1, + BigDecimal x2, BigDecimal y2, + BigDecimal x) { + // 使用公式: y = y1 + ( (y2 - y1) / (x2 - x1) ) * (x - x1) + + // 计算斜率: (y2 - y1) / (x2 - x1) + BigDecimal slope = y2.subtract(y1) + .divide(x2.subtract(x1), 10, RoundingMode.HALF_UP); + + // 计算: slope * (x - x1) + BigDecimal xDiff = x.subtract(x1); + BigDecimal product = slope.multiply(xDiff); + + // 计算最终结果: y1 + product + return y1.add(product); + } + }