From 45a773850057dd90c4292d30715b4f9dfdc86740 Mon Sep 17 00:00:00 2001 From: 13693261870 <252740454@qq.com> Date: 星期一, 04 十二月 2023 13:42:20 +0800 Subject: [PATCH] 屏蔽NoData --- src/main/java/com/moon/server/service/data/RasterAnalysisService.java | 505 ++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 328 insertions(+), 177 deletions(-) diff --git a/src/main/java/com/moon/server/service/data/RasterAnalysisService.java b/src/main/java/com/moon/server/service/data/RasterAnalysisService.java index 8d3d40d..14d2d17 100644 --- a/src/main/java/com/moon/server/service/data/RasterAnalysisService.java +++ b/src/main/java/com/moon/server/service/data/RasterAnalysisService.java @@ -1,11 +1,15 @@ package com.moon.server.service.data; +import com.alibaba.fastjson.JSONObject; import com.moon.server.entity.all.StaticData; import com.moon.server.entity.data.AnalysisResultEntity; import com.moon.server.entity.data.MetaEntity; import com.moon.server.entity.data.PublishEntity; import com.moon.server.helper.GeoHelper; import com.moon.server.helper.PathHelper; +import com.moon.server.helper.StringHelper; +import com.moon.server.helper.WebHelper; +import com.moon.server.service.all.WebSocketService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.gdal.gdal.Band; @@ -14,15 +18,14 @@ import org.gdal.gdal.gdal; import org.gdal.ogr.Geometry; import org.gdal.ogr.ogr; -import org.gdal.osr.SpatialReference; -import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import org.geotools.referencing.CRS; -import sun.awt.IconInfo; import javax.annotation.Resource; import java.awt.geom.Point2D; import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.util.*; /** @@ -32,6 +35,9 @@ */ @Service public class RasterAnalysisService { + @Value("${sys.gdal_path}") + String gdalPath; + @Resource PathHelper pathHelper; @@ -39,6 +45,102 @@ PublishService publishService; private final static Log log = LogFactory.getLog(RasterAnalysisService.class); + + /** + * 娴嬭瘯 + * <p> + * POINT (26.72 -48.58) + * LINESTRING(18.44 -46.69,20.14 -45.93) + * POLYGON ((5.11 -41.64,7.68 -43.59,4.73 -43.3,5.11 -41.64)) + * POLYGON ((42.6 -40.3,49.1 -40.4,49.1 -65.7,46.3 -65.6,42.6 -40.3)) + */ + public List<AnalysisResultEntity> test(Geometry geo, Integer size) { + List<AnalysisResultEntity> rs = new ArrayList<>(); + AnalysisResultEntity entity = new AnalysisResultEntity(); + entity.setLayerName("Test"); + + openRaster(entity, "D:\\Moon\\data\\DOM\\Lunar_LRO_LOLA_ClrShade_Global_128ppd_v04_2.tif", geo, size); + rs.add(entity); + + return rs; + } + + /** + * 浣跨敤WKT鏌ヨ鍒嗘瀽锛岀粨鏋滀互娑堟伅鎺ㄩ�� + */ + public void analysisForPost(Geometry geo, Integer size, String token) { + List<PublishEntity> pubs = publishService.selectRaster(); + if (null == pubs || pubs.isEmpty()) { + return; + } + + //for (PublishEntity pub : pubs) { + pubs.parallelStream().forEach(pub -> { + try { + AnalysisResultEntity entity = new AnalysisResultEntity(token); + entity.setLayerName(pub.getName()); + entity.setUnit(pub.getUnit()); + + List<MetaEntity> metas = publishService.selectMetasByPubid(pub.getId()); + if (null == metas || metas.isEmpty()) { + setError(entity, "鎵句笉鍒板彂甯冩暟鎹�"); + postInfo(entity); + return; + } + + String filePath = getFilePath(metas); + File file = new File(filePath); + if (!file.exists() || file.isDirectory()) { + setError(entity, "婧愭暟鎹笉瀛樺湪"); + postInfo(entity); + return; + } + + openRaster(entity, filePath, geo, size); + postInfo(entity); + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + } + }); + } + + /** + * 鑾峰彇鏂囦欢璺緞 + */ + private String getFilePath(List<MetaEntity> metas) throws IOException { + String basePath = pathHelper.getConfig().getUploadPath() + File.separator; + if (metas.size() == 1) { + return basePath + metas.get(0).getPath(); + } + + String tempPath = pathHelper.getTempPath() + File.separator, guid = StringHelper.getGuid(); + String fileList = tempPath + guid + ".txt"; + FileWriter fw = new FileWriter(fileList); + for (int i = 0, c = metas.size(); i < c; i++) { + String str = (i > 0 ? "\r\n" : "") + basePath + metas.get(i).getPath(); + fw.write(str.toCharArray()); + } + fw.close(); + + String vrt = tempPath + guid + ".vrt"; + String cmd = String.format("\"%s\\gdalbuildvrt.exe\" -input_file_list \"%s\" \"%s\"", gdalPath, fileList, vrt); + WebHelper.exec(cmd); + + return vrt; + } + + /** + * 鎺ㄩ�佹秷鎭� + */ + private void postInfo(AnalysisResultEntity entity) throws IOException { + JSONObject map = new JSONObject(); + map.put("analysisForPost", entity); + + String json = JSONObject.toJSONString(map); + //System.out.println(json) + + WebSocketService.broadCastInfo(json); + } /** * 鍒嗘瀽鏂规硶 @@ -52,26 +154,30 @@ } for (PublishEntity pub : pubs) { - AnalysisResultEntity entity = new AnalysisResultEntity(); - entity.setLayerName(pub.getName()); + try { + AnalysisResultEntity entity = new AnalysisResultEntity(); + entity.setLayerName(pub.getName()); + entity.setUnit(pub.getUnit()); - List<MetaEntity> metas = publishService.selectMetasByPubid(pub.getId()); - if (null == metas || metas.isEmpty()) { - setError(entity, "鎵句笉鍒板彂甯冩暟鎹�"); - continue; + List<MetaEntity> metas = publishService.selectMetasByPubid(pub.getId()); + if (null == metas || metas.isEmpty()) { + setError(entity, "鎵句笉鍒板彂甯冩暟鎹�"); + continue; + } + + String filePath = getFilePath(metas); + File file = new File(filePath); + if (!file.exists() || file.isDirectory()) { + setError(entity, "婧愭暟鎹笉瀛樺湪"); + continue; + } + + openRaster(entity, filePath, geo, size); + rs.add(entity); + } catch (Exception ex) { + log.error(ex.getMessage(), ex); } - - String filePath = pathHelper.getConfig().getUploadPath() + File.separator + metas.get(0).getPath(); - File file = new File(filePath); - if (!file.exists() || file.isDirectory()) { - setError(entity, "婧愭暟鎹笉瀛樺湪"); - continue; - } - - openRaster(entity, filePath, geo, size); - rs.add(entity); } - return rs; } @@ -81,6 +187,7 @@ private void openRaster(AnalysisResultEntity entity, String filePath, Geometry geo, int size) { Dataset ds = null; try { + // filePath = "D:\\Moon\\data\\DOM\\test.tif" ds = gdal.Open(filePath); if (null == ds) { throw new Exception("鎵撳紑鏍呮牸鏁版嵁澶辫触"); @@ -121,97 +228,44 @@ } /** - * 鍒嗘瀽鐐� - */ - public void analysisPoint2(AnalysisResultEntity entity, Dataset ds, Geometry geo, int size) { - double x = geo.GetX(), y = geo.GetY(); - double[] transform = ds.GetGeoTransform(); - // double rotationX = transform[2]; double rotationY = transform[4] - double minX = transform[0], pixelWidth = transform[1], maxY = transform[3], pixelHeight = transform[5]; - - int bandCount = ds.getRasterCount(); - int xPixel = (int) Math.floor((x - minX) / pixelWidth); - int yPixel = (int) Math.floor((maxY - y) / Math.abs(pixelHeight)); - - List<double[]> list = new ArrayList<>(); - for (int i = 1; i <= bandCount; i++) { - double[] pixelValues = new double[size * size]; - Band band = ds.GetRasterBand(i); - band.ReadRaster(xPixel, yPixel, size, size, pixelValues); - - list.add(pixelValues); - } - - processResult(entity, list); - } - - /** * 鍒嗘瀽绾� */ public void analysisPolyline(AnalysisResultEntity entity, Dataset ds, Geometry geo, int size) { double[] transform = ds.GetGeoTransform(); - // double rotationX = transform[2]; double rotationY = transform[4] + int xSize = ds.getRasterXSize(), ySize = ds.getRasterYSize(); double minX = transform[0], pixelWidth = transform[1], maxY = transform[3], pixelHeight = transform[5]; + double len = 0; int bandCount = ds.getRasterCount(); double lineDis = getPolylineDistance(geo); double distance = lineDis / Math.max(geo.GetPointCount(), size); List<double[]> points = getPointsByDistance(geo, distance); - for (double[] xy : points) { + for (int i = 0, c = points.size(); i < c; i++) { + double[] xy = points.get(i); + if (i > 0) { + double[] p = points.get(i - 1); + len += GeoHelper.getDistance(p[0], p[1], xy[0], xy[1]); + } + int xPixel = (int) Math.floor((xy[0] - minX) / pixelWidth); int yPixel = (int) Math.floor((maxY - xy[1]) / Math.abs(pixelHeight)); + if (xPixel < 1 || xPixel > xSize || yPixel < 1 || yPixel > ySize) { + continue; + } List<Double> vals = new ArrayList<>(); - for (int i = 1; i <= bandCount; i++) { + for (int j = 1; j <= bandCount; j++) { double[] pixelValues = new double[1]; - ds.GetRasterBand(i).ReadRaster(xPixel, yPixel, 1, 1, pixelValues); - vals.add(pixelValues[0]); - } - entity.addPoint(xy[0], xy[1], vals); - } - } - - /** - * 鍒嗘瀽绾� - */ - public void analysisPolyline2(AnalysisResultEntity entity, Dataset ds, Geometry geo, int size) { - double[] transform = ds.GetGeoTransform(); - // double rotationX = transform[2]; double rotationY = transform[4] - double minX = transform[0], pixelWidth = transform[1], maxY = transform[3], pixelHeight = Math.abs(transform[5]); - - double buffer = Math.max(pixelWidth, pixelHeight) * size; - double[] env = new double[4]; - geo = geo.Buffer(buffer); - geo.GetEnvelope(env); - - int xMinPixel = (int) Math.floor((env[0] - minX) / pixelWidth); - int yMinPixel = (int) Math.floor((maxY - env[3]) / pixelHeight); - int xMaxPixel = (int) Math.floor((env[1] - minX) / pixelWidth); - int yMaxPixel = (int) Math.floor((maxY - env[2]) / pixelHeight); - - int bandCount = ds.getRasterCount(); - int xMin = Math.min(xMinPixel, xMaxPixel); - int xMax = Math.max(xMinPixel, xMaxPixel); - int yMin = Math.min(yMinPixel, yMaxPixel); - int yMax = Math.max(yMinPixel, yMaxPixel); - - List<Double> list = new ArrayList<>(); - for (int y = yMin; y <= yMax; y++) { - for (int x = xMin; x <= xMax; x++) { - Geometry point = new Geometry(ogr.wkbPoint); - point.AddPoint(minX + pixelWidth * x, maxY - pixelHeight * y); - if (geo.Intersects(point)) { - for (int i = 1; i <= bandCount; i++) { - double[] values = new double[1]; - ds.GetRasterBand(i).ReadRaster(x, y, 1, 1, values); - list.add(values[0]); - } + ds.GetRasterBand(j).ReadRaster(xPixel, yPixel, 1, 1, pixelValues); + if (!Double.isNaN(pixelValues[0])) { + vals.add(WebHelper.round(pixelValues[0], 3)); } } + if (vals.size() > 0) { + entity.addPoint(xy[0], xy[1], len, vals); + } } - - processResult(list, entity); } /** @@ -219,30 +273,70 @@ */ public void analysisPolygon(AnalysisResultEntity entity, Dataset ds, Geometry geo) { double[] transform = ds.GetGeoTransform(); - // double rotationX = transform[2]; double rotationY = transform[4] - double minX = transform[0], pixelWidth = transform[1], maxY = transform[3], pixelHeight = Math.abs(transform[5]); + int xSize = ds.getRasterXSize(), ySize = ds.getRasterYSize(); + double minX = transform[0], pixelWidth = transform[1], maxY = transform[3], pixelHeight = Math.abs(transform[5]), rotationX = transform[2], rotationY = transform[4]; double[] env = new double[4]; geo.GetEnvelope(env); + entity.addPoint(geo.Centroid().GetX(), geo.Centroid().GetY(), 0, null); - int xMinPixel = (int) Math.floor((env[0] - minX) / pixelWidth); - int yMinPixel = (int) Math.floor((maxY - env[3]) / pixelHeight); - int xMaxPixel = (int) Math.floor((env[1] - minX) / pixelWidth); - int yMaxPixel = (int) Math.floor((maxY - env[2]) / pixelHeight); - - int bandCount = ds.getRasterCount(); - int geoWidth = Math.abs(xMaxPixel - xMinPixel); - int geoHeight = Math.abs(yMaxPixel - yMinPixel); - - List<double[]> list = new ArrayList<>(); - for (int i = 1; i <= bandCount; i++) { - Band band = ds.GetRasterBand(i); - double[] pixelValues = new double[geoWidth * geoHeight]; - band.ReadRaster(xMinPixel, yMinPixel, geoWidth, geoHeight, pixelValues); - - list.add(pixelValues); + int xMinPixel = Math.max((int) Math.floor((env[0] - minX) / pixelWidth), 1); + int yMinPixel = Math.max((int) Math.floor((maxY - env[3]) / pixelHeight), 1); + int xMaxPixel = Math.min((int) Math.floor((env[1] - minX) / pixelWidth), xSize); + int yMaxPixel = Math.min((int) Math.floor((maxY - env[2]) / pixelHeight), ySize); + if (xMaxPixel < 1 || yMaxPixel < 1 || xMaxPixel - xMinPixel < 0 || yMaxPixel - yMinPixel < 0) { + setError(entity, "鏌ヨ鑼冨洿鏃犳晥"); + return; } - processResult(entity, list); + int bandCount = ds.getRasterCount(); + int width = xMaxPixel - xMinPixel; + int height = yMaxPixel - yMinPixel; + if (width * height > StaticData.I64 * StaticData.I64) { + readRasterForBlocks(entity, ds, bandCount, xMinPixel, yMinPixel, width, height); + return; + } + + for (int i = 1; i <= bandCount; i++) { + double[] pixelValues = new double[width * height]; + ds.GetRasterBand(i).ReadRaster(xMinPixel, yMinPixel, width, height, pixelValues); + setBandVals(entity, pixelValues); + } + } + + /** + * 鎸夌収鍧楄鍙栨爡鏍兼暟鎹� + */ + private void readRasterForBlocks(AnalysisResultEntity entity, Dataset ds, int bandCount, int xMinPixel, int yMinPixel, int width, int height) { + List<Integer> xList = getSamples(xMinPixel, width - 1); + List<Integer> yList = getSamples(yMinPixel, height - 1); + + double[] pixelValues = new double[1]; + for (int i = 1; i <= bandCount; i++) { + List<Double> list = new ArrayList<>(); + for (Integer x : xList) { + for (Integer y : yList) { + ds.GetRasterBand(i).ReadRaster(x, y, 1, 1, pixelValues); + if (!Double.isNaN(pixelValues[0])) { + list.add(pixelValues[0]); + } + } + } + setBandVals(entity, list); + } + } + + /** + * 鑾峰彇鎶芥牱鍒楄〃 + */ + private List<Integer> getSamples(int start, int strip) { + List<Integer> list = new ArrayList<>(); + + double avg = 1.0 * strip / (StaticData.I64 - 1); + for (int i = 0; i < StaticData.I64; i++) { + list.add(start + (int) Math.ceil(avg * i)); + } + + return list; } /** @@ -254,75 +348,34 @@ } /** - * 澶勭悊缁撴灉 + * 璁剧疆Band鍊� */ - private void processResult(AnalysisResultEntity entity, List<double[]> list) { + private void setBandVals(AnalysisResultEntity entity, double[] pixelValues) { + if (null == pixelValues || pixelValues.length == 0) { + return; + } + + List<Double> list = new ArrayList<>(); + for (double val : pixelValues) { + if (!Double.isNaN(val) && val > Integer.MIN_VALUE) { + list.add(val); + } + } + setBandVals(entity, list); + } + + /** + * 璁剧疆Band鍊� + */ + private void setBandVals(AnalysisResultEntity entity, List<Double> list) { if (null == list || list.isEmpty()) { return; } - List<Double> rs = new ArrayList<>(); - for (double[] ds : list) { - if (null != ds && ds.length > 0) { - for (double d : ds) { - rs.add(d); - } - } - } - - processResult(rs, entity); - } - - /** - * 澶勭悊缁撴灉 - */ - private void processResult(List<Double> rs, AnalysisResultEntity entity) { - if (null == rs || rs.isEmpty()) { - return; - } - - double avg = rs.stream().mapToDouble(Double::valueOf).average().getAsDouble(); - entity.setMin(Collections.min(rs)); - entity.setMax(Collections.max(rs)); - entity.setAvg(avg); - } - - public void processClippedDataByLine(String imagePath, String geometryString) { - // 娉ㄥ唽GDAL椹卞姩 - gdal.AllRegister(); - // 鎵撳紑鏍呮牸鍥惧儚鏁版嵁闆� - Dataset dataset = gdal.Open(imagePath); - if (dataset == null) { - throw new RuntimeException("Failed to open raster dataset."); - } - - Geometry geometry = Geometry.CreateFromWkt(geometryString); - - Dataset clippedDataset = clipRaster(dataset, geometry); - - int width = clippedDataset.GetRasterXSize(); - int height = clippedDataset.GetRasterYSize(); - int bandCount = clippedDataset.getRasterCount(); - - List<double[]> sum = new ArrayList<>(); - for (int bandIndex = 1; bandIndex <= bandCount; bandIndex++) { - Band band = clippedDataset.GetRasterBand(bandIndex); - - double[] pixelValues = new double[width * height]; - band.ReadRaster(0, 0, width, height, pixelValues); - - sum.add(pixelValues); - } - } - - public static Dataset clipRaster(Dataset dataset, Geometry geometry) { - Vector<String> warpOptions = new Vector<>(); - warpOptions.add("-crop_to_cutline"); - warpOptions.add("-cutline"); - warpOptions.add(geometry.ExportToWkt()); - warpOptions.add("-dstalpha"); - - return gdal.Warp("", new Dataset[]{dataset}, new WarpOptions(warpOptions)); + double min = Collections.min(list); + double max = Collections.max(list); + double avg = list.stream().mapToDouble(Double::valueOf).average().getAsDouble(); + entity.addBandVals(min, avg, max); } /** @@ -365,9 +418,107 @@ d += distance; } } - list.add(geo.GetPoint(c)); return list; } + + /** + * 鍒嗘瀽鐐� 2 + */ + public void analysisPoint2(AnalysisResultEntity entity, Dataset ds, Geometry geo, int size) { + double x = geo.GetX(), y = geo.GetY(); + double[] transform = ds.GetGeoTransform(); + // double rotationX = transform[2]; double rotationY = transform[4] + double minX = transform[0], pixelWidth = transform[1], maxY = transform[3], pixelHeight = transform[5]; + + int bandCount = ds.getRasterCount(); + int xPixel = (int) Math.floor((x - minX) / pixelWidth); + int yPixel = (int) Math.floor((maxY - y) / Math.abs(pixelHeight)); + + for (int i = 1; i <= bandCount; i++) { + double[] pixelValues = new double[size * size]; + Band band = ds.GetRasterBand(i); + band.ReadRaster(xPixel, yPixel, size, size, pixelValues); + } + } + + /** + * 鍒嗘瀽绾� 2 + */ + public void analysisPolyline2(AnalysisResultEntity entity, Dataset ds, Geometry geo, int size) { + double[] transform = ds.GetGeoTransform(); + // double rotationX = transform[2]; double rotationY = transform[4] + double minX = transform[0], pixelWidth = transform[1], maxY = transform[3], pixelHeight = Math.abs(transform[5]); + + double buffer = Math.max(pixelWidth, pixelHeight) * size; + double[] env = new double[4]; + geo = geo.Buffer(buffer); + geo.GetEnvelope(env); + + int xMinPixel = (int) Math.floor((env[0] - minX) / pixelWidth); + int yMinPixel = (int) Math.floor((maxY - env[3]) / pixelHeight); + int xMaxPixel = (int) Math.floor((env[1] - minX) / pixelWidth); + int yMaxPixel = (int) Math.floor((maxY - env[2]) / pixelHeight); + + int bandCount = ds.getRasterCount(); + int xMin = Math.min(xMinPixel, xMaxPixel); + int xMax = Math.max(xMinPixel, xMaxPixel); + int yMin = Math.min(yMinPixel, yMaxPixel); + int yMax = Math.max(yMinPixel, yMaxPixel); + + List<Double> list = new ArrayList<>(); + for (int y = yMin; y <= yMax; y++) { + for (int x = xMin; x <= xMax; x++) { + Geometry point = new Geometry(ogr.wkbPoint); + point.AddPoint(minX + pixelWidth * x, maxY - pixelHeight * y); + if (geo.Intersects(point)) { + for (int i = 1; i <= bandCount; i++) { + double[] values = new double[1]; + ds.GetRasterBand(i).ReadRaster(x, y, 1, 1, values); + list.add(values[0]); + } + } + } + } + // processResult(list, entity) + } + + private void processClippedDataByLine(String imagePath, String geometryString) { + // 娉ㄥ唽GDAL椹卞姩 + gdal.AllRegister(); + // 鎵撳紑鏍呮牸鍥惧儚鏁版嵁闆� + Dataset dataset = gdal.Open(imagePath); + if (dataset == null) { + throw new RuntimeException("Failed to open raster dataset."); + } + + Geometry geometry = Geometry.CreateFromWkt(geometryString); + + Dataset clippedDataset = clipRaster(dataset, geometry); + + int width = clippedDataset.GetRasterXSize(); + int height = clippedDataset.GetRasterYSize(); + int bandCount = clippedDataset.getRasterCount(); + + List<double[]> sum = new ArrayList<>(); + for (int bandIndex = 1; bandIndex <= bandCount; bandIndex++) { + Band band = clippedDataset.GetRasterBand(bandIndex); + + double[] pixelValues = new double[width * height]; + band.ReadRaster(0, 0, width, height, pixelValues); + + sum.add(pixelValues); + } + } + + private Dataset clipRaster(Dataset dataset, Geometry geometry) { + Vector<String> warpOptions = new Vector<>(); + warpOptions.add("-crop_to_cutline"); + warpOptions.add("-cutline"); + warpOptions.add(geometry.ExportToWkt()); + warpOptions.add("-dstalpha"); + + return gdal.Warp("", new Dataset[]{dataset}, new WarpOptions(warpOptions)); + } } -- Gitblit v1.9.3