package org.sxkj.odm.utils; import com.google.common.collect.Lists; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.gce.geotiff.GeoTiffReader; import org.geotools.geometry.jts.JTS; import org.geotools.referencing.CRS; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.jetbrains.annotations.NotNull; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.PrecisionModel; import org.opengis.geometry.DirectPosition; import org.opengis.geometry.Envelope; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; import org.sxkj.odm.entity.MyPoint; import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.Line2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * tif 文件读取工具 */ public class ParseTifUtils { /** * 获取tif四角位置 * * @return */ public static void getTifFour(String path) { try { // 读取 TIF 文件 GeoTiffReader reader = new GeoTiffReader(new File(path)); //获取文件的坐标系信息 CoordinateReferenceSystem crs = reader.getCoordinateReferenceSystem(); GridCoverage2D coverage = reader.read(null); // 获取 TIF 文件的四角坐标,并转换为经纬度坐标系 Envelope envelope = coverage.getEnvelope(); Envelope transformedEnvelope = CRS.transform(envelope, crs); double maxLon = transformedEnvelope.getMaximum(0); // 最大经度 double maxLat = transformedEnvelope.getMaximum(1); // 最大纬度 double minLon = transformedEnvelope.getMinimum(0); // 最小经度 double minLat = transformedEnvelope.getMinimum(1); // 最小纬度 DirectPosition lowerCorner = transformedEnvelope.getLowerCorner();// 左下角 DirectPosition upperCorner = transformedEnvelope.getUpperCorner();// 右上角 //获取tif 文件的宽度,高度 double width = coverage.getGridGeometry().getGridRange2D().getWidth(); double height = coverage.getGridGeometry().getGridRange2D().getHeight(); // 左上角(最小经度,最大纬度) 右下角(最大经度,最小纬度) // 输出结果 System.out.println("lowerCorner: " + lowerCorner); System.out.println("upperCorner: " + upperCorner); } catch (Exception e) { e.printStackTrace(); } } /** * 获取经纬度在当前tif文件中的地理坐标(单点) * @param path * @param longitude * @param latitude * @return */ public static Point getTifPosByLngLat(String path, Double longitude, Double latitude) { try { //类型 PrecisionModel precisionModel = new PrecisionModel(PrecisionModel.FLOATING); //84坐标 GeometryFactory geometryFactory = new GeometryFactory(precisionModel, 4326); // 读取 TIF 文件 GeoTiffReader reader = new GeoTiffReader(new File(path)); //获取文件的坐标系信息 GridCoverage2D coverage = reader.read(null); // 创建一个点对象,并定义其经纬度 Point point = geometryFactory.createPoint(new Coordinate(longitude, latitude)); // 转换坐标系统 MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, coverage.getCoordinateReferenceSystem()); // 转为地理坐标 Point reprojectedPoint = (Point) JTS.transform(point, transform); // 返回 return reprojectedPoint; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 获取经纬度在当前tif文件中的地理坐标(多点) * @param path * @param coordinateList 经纬度坐标集合 * @return */ public static List getTifPosByMoreLngLat(String path, List coordinateList) { List list = new ArrayList<>(); try { FileInputStream fileInputStream = new FileInputStream(path); //类型 PrecisionModel precisionModel = new PrecisionModel(PrecisionModel.FLOATING); //84坐标 GeometryFactory geometryFactory = new GeometryFactory(precisionModel, 4326); // 读取 TIF 文件 GeoTiffReader reader = new GeoTiffReader(fileInputStream); //获取文件的坐标系信息 GridCoverage2D coverage = reader.read(null); for (Coordinate coordinate : coordinateList) { // 创建一个点对象,并定义其经纬度 Point point = geometryFactory.createPoint(coordinate); // 转换坐标系统 MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, coverage.getCoordinateReferenceSystem()); // 转为地理坐标 Point reprojectedPoint = (Point) JTS.transform(point, transform); // 加入集合 list.add(reprojectedPoint); } // 关闭流 fileInputStream.close(); // 返回 return list; } catch (Exception e) { e.printStackTrace(); } return list; } /** * 在 tif 文件上画线 * @param tifFilePath tif 读取路径 * @param outPath 输出路径 * @param map */ public static void drawLineTif(String tifFilePath,String outPath, Map map) { try { FileInputStream fileInputStream = new FileInputStream(tifFilePath); // 读取TIF图片 BufferedImage bufferedImage = ImageIO.read(fileInputStream); // 创建Graphics2D对象 Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics(); // 设置红色,、画笔粗细 g2d.setColor(Color.RED); g2d.setStroke(new BasicStroke(3f)); // 画线 drawLine(g2d, map); // 释放图形上下文资源 g2d.dispose(); // 输出图片 File outputFile = new File(outPath); // 写入 ImageIO.write(bufferedImage, "tif", outputFile); // 关闭流 fileInputStream.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 在 tif 文件上批量画线 * @param tifFilePath tif 读取路径 * @param outPath 输出路径 * @param points */ public static void drawLineListTif(String tifFilePath,String outPath, List points) { try { FileInputStream fileInputStream = new FileInputStream(tifFilePath); // 读取TIF图片 BufferedImage bufferedImage = ImageIO.read(fileInputStream); // 创建Graphics2D对象 Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics(); // 设置红色,、画笔粗细 g2d.setColor(Color.RED); g2d.setStroke(new BasicStroke(3f)); List> maps = new ArrayList<>(); int size = points.size(); // 将点分成多个线,当前点和下一个点组成一条线,末尾和首个点组成一条线 for (int i = 0; i < points.size(); i++) { Map map = new HashMap<>(); MyPoint current = points.get(i); map.put("x1",current.getX()); map.put("y1",current.getY()); MyPoint next = (i == size - 1) ? points.get(0) : points.get(i + 1); map.put("x2",next.getX()); map.put("y2",next.getY()); maps.add(map); } for (Map map : maps) { // 画线 drawLine(g2d, map); } // 释放图形上下文资源 g2d.dispose(); // 输出图片 File outputFile = new File(outPath); // 写入 ImageIO.write(bufferedImage, "tif", outputFile); // 关闭流 fileInputStream.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 在 tif 文件上画面 * @param tifFilePath tif 读取路径 * @param outPath 输出路径 * @param points */ public static boolean drawPolygonByPoints(String tifFilePath,String outPath, List points, String suffix) { try { FileInputStream fileInputStream = new FileInputStream(tifFilePath); // 读取TIF图片 BufferedImage bufferedImage = ImageIO.read(fileInputStream); // 创建Graphics2D对象 Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics(); // 设置红色,、画笔粗细 g2d.setColor(Color.RED); g2d.setStroke(new BasicStroke(3f)); // 将点集合组装成画面的数组 Map hashMap = getStringMap(points); // 画面 drawPolygon(g2d,hashMap); // 释放图形上下文资源 g2d.dispose(); // 输出图片 File outputFile = new File(outPath); // 写入 ImageIO.write(bufferedImage, suffix, outputFile); // 关闭流 fileInputStream.close(); // 返回 return true; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 将点集合组装成画面的数组 * @param points * @return */ @NotNull private static Map getStringMap(List points) { Map hashMap = new HashMap<>(); List lngList = new ArrayList<>(); List latList = new ArrayList<>(); for (MyPoint point : points) { lngList.add((int)Math.round(point.getX().doubleValue())); latList.add((int)Math.round(point.getY().doubleValue())); } int[] lngArr = lngList.stream() .mapToInt(Integer::intValue) .toArray(); int[] latArr = latList.stream() .mapToInt(Integer::intValue) .toArray(); hashMap.put("lngs",lngArr); hashMap.put("lats",latArr); return hashMap; } /** * 画线 * @param g2D * @param map */ public static void drawLine(Graphics2D g2D, Map map) { // 打印转换后的Map Line2D.Double line = new Line2D.Double(map.get("x1"), map.get("y1"), map.get("x2"), map.get("y2")); g2D.draw(line); } /** * 画面 * @param g2D * @param map */ public static void drawPolygon(Graphics2D g2D, Map map) { // 创建一个多边形 int[] xPoints = map.get("lngs"); int[] yPoints = map.get("lats"); Polygon polygon = new Polygon(xPoints, yPoints, xPoints.length); // 画多边形 g2D.drawPolygon(polygon); } }