package com.se.nsl.service;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.bc.zarr.ZarrArray;
|
import com.bc.zarr.ZarrGroup;
|
import com.se.nsl.config.PropertiesConfig;
|
import com.se.nsl.domain.po.Simu;
|
import com.se.nsl.domain.vo.SimuResult;
|
import com.se.nsl.domain.vo.SimuVo;
|
import com.se.nsl.helper.StringHelper;
|
import com.se.nsl.mapper.SimuMapper;
|
import com.se.nsl.utils.CoordinateTransformer;
|
import lombok.extern.slf4j.Slf4j;
|
import org.gdal.gdal.Band;
|
import org.gdal.gdal.Dataset;
|
import org.gdal.gdal.gdal;
|
import org.gdal.gdalconst.gdalconstConstants;
|
import org.springframework.stereotype.Service;
|
import ucar.ma2.InvalidRangeException;
|
|
import javax.annotation.Resource;
|
import java.io.File;
|
import java.io.IOException;
|
import java.time.Instant;
|
import java.time.LocalDateTime;
|
import java.time.ZoneId;
|
import java.time.format.DateTimeFormatter;
|
import java.util.Arrays;
|
import java.util.List;
|
|
@Slf4j
|
@Service
|
@SuppressWarnings("ALL")
|
public class SimuService {
|
public static final String TIF_EXTSION = ".tif";
|
@Resource
|
SimuMapper simuMapper;
|
|
@Resource
|
PropertiesConfig config;
|
|
/**
|
* 分页查询推演模拟
|
*
|
* @param pageNum 页码
|
* @param pageSize 每页数量
|
* @return 分页后的推演模拟
|
*/
|
public IPage<Simu> selectPage(SimuVo vo, int pageNum, int pageSize) {
|
QueryWrapper<Simu> wrapper = getPageWrapper(vo, pageNum, pageSize);
|
|
Page<Simu> page = new Page<>(pageNum, pageSize);
|
page.addOrder(OrderItem.desc("id"));
|
|
IPage<Simu> paged = simuMapper.selectPage(page, wrapper);
|
|
return paged;
|
}
|
|
private QueryWrapper<Simu> getPageWrapper(SimuVo vo, int pageNum, int pageSize) {
|
QueryWrapper<Simu> wrapper = new QueryWrapper<>();
|
if (null != vo.getId()) {
|
wrapper.eq("id", vo.getId());
|
}
|
if (!StringHelper.isEmpty(vo.getName())) {
|
wrapper.like("lower(name)", vo.getName().trim().toLowerCase());
|
}
|
if (!StringHelper.isEmpty(vo.getServiceName())) {
|
wrapper.like("service_name", vo.getServiceName().trim());
|
}
|
if (null != vo.getType()) {
|
wrapper.eq("type", vo.getType());
|
}
|
if (null != vo.getAreaType()) {
|
wrapper.eq("area_type", vo.getAreaType());
|
}
|
if (null != vo.getStatus()) {
|
wrapper.eq("status", vo.getStatus());
|
}
|
|
return wrapper;
|
}
|
|
/**
|
* 根据ID批量删除推演模拟
|
*
|
* @param ids 要删除的区域ID列表
|
* @return 删除成功的记录数
|
*/
|
public int deleteByIds(List<Integer> ids) {
|
return simuMapper.deleteBatchIds(ids);
|
}
|
|
/**
|
* 新增推演模拟
|
*
|
* @param Simu 推演模拟对象
|
* @return 新增成功的记录数
|
*/
|
public int insert(Simu simu) {
|
return simuMapper.insert(simu);
|
}
|
|
public int inserts(List<Simu> list) {
|
return simuMapper.inserts(list);
|
}
|
|
/**
|
* 根据ID查询
|
*
|
* @param id ID
|
* @return Simu
|
*/
|
public Simu selectById(Integer id) {
|
return simuMapper.selectById(id);
|
}
|
|
/**
|
* 修改推演模拟
|
*
|
* @param Simu 推演模拟对象
|
* @return 修改成功的记录数
|
*/
|
public int updateById(Simu simu) {
|
return simuMapper.updates(Arrays.asList(simu));
|
}
|
|
public SimuResult queryByPosition(double lon, double lat, long time, String serviceName) {
|
//transform coordiante from 4326 to 4548
|
double[] xy = CoordinateTransformer.transform(4326, 4548, lon, lat);
|
// System.out.println(String.format("转换前的坐标:x:%s,y:%s", lon, lat));
|
// System.out.println(String.format("转换后的坐标:x:%s,y:%s", xy[0], xy[1]));
|
//read from zarr
|
// return null;
|
|
//read from tif file
|
return queryByTif(xy, time, serviceName);
|
|
}
|
|
private SimuResult queryByZarr(double[] xy, long time, String serviceName) {
|
double x = xy[0];
|
double y = xy[1];
|
String prefix = formatTime(time);
|
File inPath = new File(config.getInPath());
|
File tifDir = new File(inPath, serviceName + File.separator + "depth");
|
int index = 0;
|
File[] files = tifDir.listFiles();
|
for (File file : files) {
|
String name = file.getName();
|
if (!name.endsWith(TIF_EXTSION)) continue;
|
if (name.equals(prefix + TIF_EXTSION)) {
|
break;
|
}
|
index++;
|
}
|
//TODO需要计算行列号
|
int col = 0;
|
int row = 0;
|
|
|
File zarr = new File(inPath, serviceName + File.separator + "result.zarr");
|
try {
|
ZarrGroup group = ZarrGroup.open(zarr.toPath());
|
ZarrArray depthArray = group.openArray("depth");
|
Object object = depthArray.read();
|
System.out.println(object);
|
} catch (IOException | InvalidRangeException e) {
|
throw new RuntimeException(e);
|
}
|
|
|
return null;
|
}
|
|
private SimuResult queryByTif(double[] xy, long time, String serviceName) {
|
double x = xy[0];
|
double y = xy[1];
|
File inPath = new File(config.getInPath());
|
String prefix = formatTime(time);
|
String child = serviceName + File.separator + "depth" + File.separator + prefix + TIF_EXTSION;
|
File tifFile = new File(inPath, child);
|
if (!tifFile.exists()) {
|
return null;
|
}
|
|
Dataset dataset = gdal.Open(tifFile.getAbsolutePath(), gdalconstConstants.GA_ReadOnly);
|
// 获取地理变换参数(6元素数组)
|
// [0]: 左上角X坐标, [1]: 像元宽度, [2]: X方向旋转,
|
// [3]: 左上角Y坐标, [4]: Y方向旋转, [5]: 像元高度(负值表示Y轴向下)
|
double[] geoTransform = dataset.GetGeoTransform();
|
//计算栅格行列号
|
int col = (int) ((x - geoTransform[0]) / geoTransform[1]);
|
int row = (int) ((geoTransform[3] - y) / Math.abs(geoTransform[5]));
|
int width = dataset.getRasterXSize();
|
int height = dataset.getRasterYSize();
|
if (col < 0 || col > width || row < 0 || row > height) {
|
log.warn("行列号不在tif范围内");
|
return null;
|
}
|
float depth = readPixelValue(dataset, col, row, 1);
|
float velocity = calcVelocity(dataset, col, row);
|
SimuResult result = new SimuResult();
|
result.setDepth(depth);
|
result.setVelocity(velocity);
|
return result;
|
}
|
|
private float calcVelocity(Dataset dataset, int col, int row) {
|
float x = readPixelValue(dataset, col, row, 2);
|
float y = readPixelValue(dataset, col, row, 3);
|
float velocity = 0f;
|
if (Float.isNaN(x) && Float.isNaN(y)) {
|
velocity = 0f;
|
} else if (Float.isNaN(x)) {
|
velocity = y;
|
} else if (Float.isNaN(y)) {
|
velocity = x;
|
} else {
|
velocity = (float) Math.sqrt(x * x + y * y);
|
}
|
return velocity;
|
}
|
|
private float readPixelValue(Dataset dataset, int col, int row, int bandNum) {
|
Band band = dataset.GetRasterBand(bandNum);
|
float[] values = new float[1];
|
band.ReadRaster(col, row, 1, 1, values);
|
return values[0];
|
}
|
|
private String formatTime(long time) {
|
Instant instant = Instant.ofEpochMilli(time);
|
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
return localDateTime.format(formatter);
|
}
|
|
}
|