阅读量:0
读取netCdf的依赖
<dependency> <groupId>ucar</groupId> <artifactId>netcdfAll</artifactId> <version>5.5.3</version> <scope>system</scope> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>spi</artifactId> </exclusion> </exclusions> <systemPath>${basedir}/libs/netcdfAll-5.5.3.jar</systemPath> </dependency>
读取文件入库
import cn.iscas.eneity.*; import cn.iscas.picture.HeatPictureGenerator; import cn.iscas.util.DateAddition; import cn.iscas.util.GzipCompressUtil; import cn.iscas.util.LogUtil; import cn.iscas.util.PropertiesUtil; import com.google.common.collect.ImmutableList; import com.iscas.datasong.client.DataSongClient; import com.iscas.datasong.client.DataSongHttpClient; import com.iscas.datasong.client.domain.DataSongSearchResult; import com.iscas.datasong.lib.common.DataSongException; import com.iscas.datasong.lib.request.SearchDataRequest; import com.iscas.datasong.lib.request.search.builder.ConditionBuilder; import com.iscas.datasong.lib.request.search.condition.search.TermSearchCondition; import com.iscas.datasong.lib.util.DataSongJsonUtils; import ucar.nc2.NetcdfFile; import ucar.nc2.Variable; import java.io.IOException; import java.util.*; public static void salinitySaveDataSong(String fileName) throws IOException, DataSongException { NetcdfFile file = NetcdfFile.open(fileName); Map map = new HashMap<>(); ImmutableList<Variable> variables = file.getVariables(); for (Variable var : variables) { String varName = var.getFullName(); Object o = var.read().copyToNDJavaArray(); map.put(varName, o); } List<Salinity> salinityList = new ArrayList<>(); int[] time = (int[]) map.get("time"); float[] lev = (float[]) map.get("lev"); float[][][][] ss = (float[][][][]) map.get("ss"); float[] lat = (float[]) map.get("lat"); float[] lon = (float[]) map.get("lon"); for (int i = 0; i < time.length; i++) { for (int j = 0; j < lev.length; j++) { Salinity salinity = new Salinity(); salinity.setTime(DateAddition.addDays365(time[i])); salinity.setLev(lev[j]); salinity.setLat(Arrays.toString(lat)); salinity.setLon(Arrays.toString(lon)); salinity.setNetCdfPath(fileName); //压缩数据 String compress = GzipCompressUtil.compress(DataSongJsonUtils.toJson(ss[i][j])); salinity.setSs(compress); salinityList.add(salinity); } } DataSongClient dataSongClient = DataSongHttpClient.getInstance(dataSongIp, dataSongPort); dataSongClient.setDatabaseName(dataSongDatabase); dataSongClient.getDataService().batchSaveData(salinityList).toString(); LogUtil.debug(fileName + "入库解析完成"); }
读取入库数据
public static void salinityGeneratorPicture(String netCdfPath) throws DataSongException { DataSongClient dataSongClient = DataSongHttpClient.getInstance(dataSongIp,dataSongPort); dataSongClient.setDatabaseName(dataSongDatabase); TermSearchCondition levTermSearchCondition = ConditionBuilder.termCondition("netCdfPath", netCdfPath); SearchDataRequest searchDataRequest = new SearchDataRequest(); searchDataRequest.setSearch(levTermSearchCondition); DataSongSearchResult<Salinity> salinityDataSongSearchResult = dataSongClient.getDataService().searchData(Salinity.class, searchDataRequest); List<Salinity> items = salinityDataSongSearchResult.getItems(); String ss = ""; String lat = ""; String lon = ""; String pictureName = ""; for (Salinity salinity : items) { salinity.setSs(GzipCompressUtil.decompress(salinity.getSs())); ss = salinity.getSs(); lat = salinity.getLat(); lon = salinity.getLon(); pictureName = "salinity" + "_" + salinity.getTime() + "_" + Float.valueOf(salinity.getLev()).intValue(); float[] latitudes = DataSongJsonUtils.fromJson(lat, float[].class); float[] longitudes = DataSongJsonUtils.fromJson(lon, float[].class); double[][] values = DataSongJsonUtils.fromJson(ss, double[][].class); //画图 String pictureFile = HeatPictureGenerator.pictureGenerator(pictureName, latitudes, longitudes, values); if (pictureFile != null) { salinity.setPicturePath(pictureFile); //写入生成的图片位置 dataSongClient.getDataService().updateData(salinity); salinity.setSs(""); LogUtil.debug("记录一条"+salinity); } } }
绘制热力图
import javax.imageio.ImageIO; import cn.iscas.util.LogUtil; import cn.iscas.util.PropertiesUtil; import com.iscas.datasong.lib.common.DataSongException; import java.awt.*; import java.awt.Font; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; /** * 生成热力图(tiff,png格式) * 示例的经度、纬度和对应的值 * * @param latitudes float[] longitudes = {100.0f, 200.0f, 300.0f, 400.0f, 500.0f}; * @param longitudes float[] latitudes = {100.0f, 150.0f, 200.0f, 250.0f, 300.0f}; * @param values double[][] values = { * {0.2, 0.4, 0.6, 0.8, 1.0}, * {0.3, 0.5, 0.7, 0.9, 1.1}, * {0.4, 0.6, 0.8, 1.0, 1.2}, * {0.5, 0.7, 0.9, 1.1, 1.3}, * {0.6, 0.8, 1.0, 1.2, 1.4} * }; */ public static String pictureGenerator(String pictureName, float[] latitudes, float[] longitudes, double[][] values) { // 定义图像宽高 // int width = 1600; // int height = 1300; int messageHeight = 100; int width = 1486; int height = 910 + messageHeight; // 创建BufferedImage对象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 获取Graphics2D对象以便绘制 Graphics2D g2d = image.createGraphics(); // 设置背景颜色为白色 g2d.setColor(Color.WHITE); g2d.fillRect(0, 0, width, height); // 找到最小值和最大值 double minValue = Double.MAX_VALUE; double maxValue = Double.MIN_VALUE; for (int i = 0; i < latitudes.length; i++) { for (int j = 0; j < longitudes.length; j++) { if (values[i][j] != 1.0E35 && !Double.isNaN(values[i][j]) && !Double.isInfinite(values[i][j])) { if (values[i][j] < minValue) { minValue = values[i][j]; } if (values[i][j] > maxValue) { maxValue = values[i][j]; } } } } // 确定经度和纬度的最大最小值,用于缩放坐标 float minLongitude = Float.MAX_VALUE; float maxLongitude = Float.MIN_VALUE; float minLatitude = Float.MAX_VALUE; float maxLatitude = Float.MIN_VALUE; for (float longitude : longitudes) { if (longitude < minLongitude) minLongitude = longitude; if (longitude > maxLongitude) maxLongitude = longitude; } for (float latitude : latitudes) { if (latitude < minLatitude) minLatitude = latitude; if (latitude > maxLatitude) maxLatitude = latitude; } // 绘制数据点 for (int i = 0; i < latitudes.length; i++) { for (int j = 0; j < longitudes.length; j++) { // 缩放坐标 int x = Math.round((longitudes[j] - minLongitude) / (maxLongitude - minLongitude) * (width - 1)); // int y = Math.round((latitudes[i] - minLatitude) / (maxLatitude - minLatitude) * (height - 1)); int y = Math.round(height - messageHeight - 1 - ((latitudes[i] - minLatitude) / (maxLatitude - minLatitude) * (height - messageHeight - 1))); // 剔除无效值 if (values[i][j] == 1.0E35 || Double.isNaN(values[i][j]) || Double.isInfinite(values[i][j])) { // 使用一个默认值或跳过这个数据点 g2d.setColor(Color.GRAY); g2d.fillRect(x, y, 2, 2); } else { // 归一化处理 float value = (float) ((values[i][j] - minValue) / (maxValue - minValue)); // 根据值计算颜色 // Color color = new Color(value, 0.0f, 1.0f - value); // 从蓝到红的渐变色 // 将 value 从 [0, 1] 映射到 [0, 255] 的色调值(因为色调是 0-360 度的循环,但我们可以将其转换为 0-255 的范围) // 将 value 从 [0, 1] 映射到 [0, 240] 的色调值(因为蓝色是 240 度,红色是 0 度) float hue = (float) (240.0 - value * 240.0); // 从蓝色(240)渐变到红色(0) // 你可以设置固定的饱和度和亮度值,或者根据需要进行调整 float saturation = 1.0f; // 完全饱和 float brightness = 1.0f; // 最大亮度 // 使用 HSB 值创建颜色 Color color = Color.getHSBColor(hue / 360f, saturation, brightness); g2d.setColor(color); g2d.fillOval(x, y, 2, 2); // 绘制圆形点 } } } // 绘制颜色条 int colorbarHeight = 50; // 颜色条的高度 int colorbarY = height - colorbarHeight; // 颜色条的位置 int colorbarWidth = width - 200; // 颜色条的长度与图片宽度相同 // 计算每个像素代表的值,注意减1,避免除以0 double valuePerPixel = (maxValue - minValue) / (colorbarWidth - 1); // 绘制颜色条 g2d.setColor(Color.BLACK); // 假设背景是黑色 g2d.fillRect(0 + 80, colorbarY, colorbarWidth, colorbarHeight); for (int b = 0; b < colorbarWidth; b++) { double currentValue = minValue + b * valuePerPixel; // 计算色调值从蓝色(240)渐变到红色(0) float hueValue = 240f - (float) ((currentValue - minValue) / (maxValue - minValue) * 240); // 创建颜色 Color color = Color.getHSBColor(hueValue / 360f, 1.0f, 1.0f); // 使用240来归一化hue // 设置颜色并绘制像素块 g2d.setColor(color); g2d.fillRect(b + 80, colorbarY, 1, colorbarHeight); } // 绘制刻度线和标签 int tickSpacing = colorbarWidth / 10; // 假设我们想要5个刻度线 int tickLength = 10; int labelSpacing = tickSpacing; // 假设标签之间的间隔是刻度线间隔 String format = "%.2f"; // 设置值的格式,这里保留两位小数 for (int x = 0; x <= colorbarWidth; x += tickSpacing) { // 绘制刻度线 g2d.setColor(Color.BLACK); g2d.drawLine(x + 80, colorbarY, x + 80, colorbarY + tickLength); // 计算当前刻度对应的值 double currentValue = minValue + x * valuePerPixel; // 只在特定的间隔上绘制标签 if (x % labelSpacing == 0) { // 绘制标签 String label = String.format(format, currentValue); FontMetrics fm = g2d.getFontMetrics(); int labelX = x - fm.stringWidth(label) / 2 + 80; int labelY = colorbarY + colorbarHeight + 15; // 设置标签的y坐标 g2d.setColor(Color.BLACK); g2d.setFont(new Font("Default", Font.PLAIN, 20)); g2d.drawString(label, labelX, labelY - 30); } } // 绘制标签 g2d.setColor(Color.BLACK); g2d.drawString("Max: " + maxValue + " " + "Min: " + minValue, 10, colorbarY + colorbarHeight - 60); // 释放Graphics2D资源 g2d.dispose(); // 保存图像为TIFF或者PNG文件,修改pathName和formatName即可 try { File output = new File(picturePath + pictureName + ".tiff"); ImageIO.write(image, "TIFF", output); LogUtil.debug("PNG图像已成功保存到 " + output.getAbsolutePath()); return output.getAbsolutePath(); } catch (IOException e) { e.printStackTrace(); LogUtil.error("图片生成异常" + LogUtil.getStackTraceAsString(e)); return null; } }