package com.se.simu.service; import cn.hutool.core.io.FileUtil; import cn.hutool.json.JSONUtil; import com.se.simu.config.PropertiesConfig; import com.se.simu.domain.po.DataPo; import com.se.simu.domain.po.PondingPo; import com.se.simu.domain.po.SimuPo; import com.se.simu.domain.vo.*; import com.se.simu.helper.GdalHelper; import com.se.simu.helper.StringHelper; import lombok.extern.slf4j.Slf4j; import org.gdal.gdal.Dataset; import org.gdal.gdal.gdal; import org.gdal.gdalconst.gdalconst; import org.gdal.ogr.*; import org.gdal.osr.SpatialReference; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.io.File; import java.io.FileInputStream; import java.util.List; import java.util.stream.Collectors; @Slf4j @Service @SuppressWarnings("ALL") public class WaterService { @Resource PropertiesConfig config; public byte[] getson(String serviceName, String json) { try { String filePath = config.getOutPath() + File.separator + serviceName + File.separator + json; File dat = new File(filePath); if (!dat.exists()) { return null; } byte[] bytes = new byte[(int) dat.length()]; FileInputStream fs = new FileInputStream(filePath); fs.read(bytes); fs.close(); return bytes; } catch (Exception ex) { log.error(ex.getMessage(), ex); return null; } } public String getTerraMap(String serviceName, Integer width, Integer height) { return config.getOutPath() + File.separator + serviceName + File.separator + "terrain" + File.separator + width + "_" + height + ".png"; } public String getWaterMap(String serviceName, Integer width, Integer height, Long timestamp) { return config.getOutPath() + File.separator + serviceName + File.separator + "waters" + File.separator + timestamp + File.separator + width + "_" + height + ".png"; } public String getFlowMap(String serviceName, Integer width, Integer height, Long timestamp) { return config.getOutPath() + File.separator + serviceName + File.separator + "flows" + File.separator + timestamp + File.separator + width + "_" + height + ".png"; } public Double getWaterHeight(SimuPo simu, double x, double y, Long timestamp) { String filePath = config.getOutPath() + File.separator + simu.getServiceName() + File.separator + "waters" + File.separator + timestamp + File.separator + "water.tif"; if (!FileUtil.exist(filePath)) return null; Dataset ds = null; try { ds = gdal.Open(filePath, gdalconst.GA_ReadOnly); if (null == ds || ds.getRasterCount() < 1) { return null; } if (null == ds.GetSpatialRef()) { ds.SetSpatialRef(getSpatialRef(simu)); } double[] gt = ds.GetGeoTransform(); double[] xy = GdalHelper.fromWgs84(ds.GetSpatialRef(), x, y); int[] XY = coordinates2ColRow(gt, xy[0], xy[1]); if (XY[0] < 0 || XY[1] < 0 || XY[0] > ds.getRasterXSize() || XY[1] > ds.getRasterYSize()) { return null; } double[] vals = new double[1]; ds.GetRasterBand(1).ReadRaster(XY[0], XY[1], 1, 1, vals); return isValid(vals[0]) ? vals[0] : null; } catch (Exception ex) { log.error(ex.getMessage(), ex); return null; } finally { if (null != ds) ds.delete(); } } private SpatialReference getSpatialRef(SimuPo simu) { DataPo data = JSONUtil.toBean(simu.getData(), DataPo.class); return data.getSpatialReference(); } public int[] coordinates2ColRow(double[] gt, double x, double y) { //Double col = Math.floor(((y - gt[3]) * gt[1] - (x - gt[0]) * gt[4]) / (gt[5] * gt[1] - gt[2] * gt[4])); Double col = Math.floor((y * gt[1] - x * gt[4] + gt[0] * gt[4] - gt[3] * gt[1]) / (gt[5] * gt[1] - gt[2] * gt[4])); Double row = Math.floor((x - gt[0] - col * gt[2]) / gt[1]); return new int[]{row.intValue(), col.intValue()}; } public static boolean isValid(double val) { return !Double.isNaN(val) && val > Integer.MIN_VALUE; } public Double getWaterArea(SimuPo simu, double x, double y, Long timestamp) { List list = readWaterJson(simu.getServiceName(), timestamp); if (CollectionUtils.isEmpty(list)) return null; //DataPo data = JSONUtil.toBean(simu.getData(), DataPo.class); //SpatialReference sr = GdalHelper.createSpatialReference(data.getEpsg()); Geometry p = new Geometry(ogr.wkbPoint); p.AddPoint_2D(x, y); p.AssignSpatialReference(GdalHelper.SR4326); for (PondingPo po : list) { if (StringHelper.isEmpty(po.getPolygon())) continue; Geometry polygon = Geometry.CreateFromWkt(po.getPolygon()); polygon.AssignSpatialReference(GdalHelper.SR4326); if (polygon.Contains(p)) { return po.getArea(); } } return null; } private List readWaterJson(String serviceName, Long timestamp) { String filePath = config.getOutPath() + File.separator + serviceName + File.separator + "waters" + File.separator + timestamp + File.separator + "water.json"; String json = getText(filePath); if (StringHelper.isEmpty(json)) { return null; } return JSONUtil.toList(json, PondingPo.class); } public Double getWaterArea2(SimuPo simu, double x, double y, Long timestamp) { String filePath = config.getOutPath() + File.separator + simu.getServiceName() + File.separator + "waters" + File.separator + timestamp + File.separator + "water.geojson"; if (!FileUtil.exist(filePath)) return null; Driver driver = null; DataSource dataSource = null; org.gdal.ogr.Layer layer = null; try { driver = ogr.GetDriverByName("GeoJSON"); if (null == driver) return null; DataSource ds = driver.Open(filePath); if (null == ds) return null; layer = ds.GetLayer(0); double[] xy = GdalHelper.fromWgs84(layer.GetSpatialRef(), x, y); Geometry p = new Geometry(ogr.wkbPoint); p.AddPoint_2D(xy[0], xy[1]); p.AssignSpatialReference(layer.GetSpatialRef()); for (long i = 0, d = layer.GetFeatureCount(); i < d; i++) { Feature f = layer.GetFeature(i); if (f.GetGeometryRef().Intersects(p)) { /*f.GetFieldAsDouble("val"); Geometry g = f.GetGeometryRef(); GdalHelper.fromWgs84(layer.GetSpatialRef(), g); Double area= g.GetArea();*/ return f.GetGeometryRef().Area(); } } return null; } catch (Exception ex) { log.error(ex.getMessage(), ex); return null; } finally { GdalHelper.delete(layer, dataSource, driver); } } public List getBuildingDepthBySeid(String serviceName, String seid) { List list = readBuildingJson(serviceName); if (CollectionUtils.isEmpty(list)) return null; return list.parallelStream() .filter(b -> seid.equals(b.getId())) .sorted((a, b) -> a.getTimestamp().compareTo(b.getTimestamp())) .collect(Collectors.toList()); } public List getBuildingDepthByTime(String serviceName, Long timestamp) { List list = readBuildingJson(serviceName); if (CollectionUtils.isEmpty(list)) { return null; } return list.parallelStream().filter(b -> timestamp.equals(b.getTimestamp())).collect(Collectors.toList()); } private List readBuildingJson(String serviceName) { String filePath = config.getOutPath() + File.separator + serviceName + File.separator + "building.json"; String json = getText(filePath); if (StringHelper.isEmpty(json)) { return null; } return JSONUtil.toList(json, BuildingDepthVo.class); } private String getText(String filePath) { File file = new File(filePath); if (!file.exists()) { return null; } return FileUtil.readUtf8String(file); } }