package org.example.test; import org.example.alpha.AlphaShape; import org.example.alpha.Vector2D; import org.gdal.gdal.Dataset; import org.gdal.gdal.Driver; import org.gdal.gdal.WarpOptions; import org.gdal.gdal.gdal; import org.gdal.gdalconst.gdalconst; import org.geotools.api.feature.simple.SimpleFeature; import org.geotools.api.feature.simple.SimpleFeatureType; import org.geotools.api.geometry.Bounds; import org.geotools.api.geometry.Position; import org.geotools.api.style.Style; import org.geotools.coverage.grid.GridCoordinates2D; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.processing.Operations; import org.geotools.feature.DefaultFeatureCollection; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.gce.geotiff.GeoTiffReader; import org.geotools.geojson.feature.FeatureJSON; import org.geotools.geojson.geom.GeometryJSON; import org.geotools.geometry.Position2D; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.map.FeatureLayer; import org.geotools.map.Layer; import org.geotools.map.MapContent; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.styling.SLD; import org.geotools.swing.JMapFrame; import org.geotools.util.factory.Hints; import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.geom.*; import org.locationtech.jts.operation.buffer.BufferOp; import org.locationtech.jts.operation.buffer.BufferParameters; import org.springframework.beans.factory.annotation.Value; import javax.media.jai.Interpolation; import javax.media.jai.InterpolationBicubic2; import java.awt.*; import java.io.File; import java.util.List; import java.util.*; public class CreateRingGridFixGeo { /** * 必须注册 */ static { gdal.AllRegister(); } public static GridCoverage2D coverage; public static String inputDemPath = "E:\\data\\CB测试\\geospatial_data_cloud\\ASTGTMV003_N30E119_dem.tif"; public static String outputDemPath = "E:\\data\\CB测试\\geospatial_data_cloud\\resample\\coverage_geo.tif"; public static double extendLen = 100; public static GeometryFactory geometryFactory = new GeometryFactory(); public static List> fillPoints; public static List> cutPoints; public static double cutAllSum = 0; public static double fillAllSum = 0; public static double meter = 2; // 间距,单位为米。 public static double range = 10;//容差 public static boolean isProjcetion = false; public static boolean isResample = true; private static SimpleFeatureType createFeatureType() { SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName("Location"); builder.setCRS(DefaultGeographicCRS.WGS84); // <- Coordinate reference system // add attributes in order builder.add("the_geom", Polygon.class); builder.length(15).add("name", String.class); // <- 15 chars width for name field builder.add("id", Integer.class); // build the type final SimpleFeatureType LOCATION = builder.buildFeatureType(); return LOCATION; } private static SimpleFeatureType createLineStringFeatureType() { SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName("Location"); builder.setCRS(DefaultGeographicCRS.WGS84); // <- Coordinate reference system // add attributes in order builder.add("the_geom", LineString.class); builder.length(15).add("name", String.class); // <- 15 chars width for name field builder.add("id", Integer.class); // build the type final SimpleFeatureType LOCATION = builder.buildFeatureType(); return LOCATION; } private static SimpleFeatureType createPointFeatureType() { SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName("Location"); builder.setCRS(DefaultGeographicCRS.WGS84); // <- Coordinate reference system // add attributes in order builder.add("the_geom", Point.class); // builder.length(15).add("name", String.class); // <- 15 chars width for name field builder.add("id", String.class); builder.add("bottomHeight", double.class); builder.add("topHeight", double.class); builder.add("elev", double.class); return builder.buildFeatureType(); } public static void main(String[] args) throws Exception{ loadDem(inputDemPath); GeometryFactory geometryFactory = new GeometryFactory(); List coords = new ArrayList(){{ // 新给的dem,自己画的 // add(new double[]{469037.331529372138903, 3348374.219233838375658 }); // add(new double[]{469256.397423173999414, 3348360.942513002082705 }); // add(new double[]{469246.439882546663284, 3348171.749241081997752 }); // add(new double[]{469014.097267908335198, 3348194.983502545859665 }); // add(new double[]{469037.331529372138903, 3348374.219233838375658}); add(new double[]{119.678274321091934, 30.254540850428963 }); add(new double[]{119.680550940139568, 30.254426658580112 }); add(new double[]{119.680452999081325, 30.252719786115247 }); add(new double[]{119.678038175380664, 30.252923459684105 }); add(new double[]{119.678274321091934, 30.254540850428963 }); }}; // 创建矩形的四个角点坐标 Coordinate[] coordinates = new Coordinate[5]; coordinates[0] = new Coordinate(coords.get(0)[0], coords.get(0)[1]); coordinates[1] = new Coordinate(coords.get(1)[0], coords.get(1)[1]); coordinates[2] = new Coordinate(coords.get(2)[0], coords.get(2)[1]); coordinates[3] = new Coordinate(coords.get(3)[0], coords.get(3)[1]); // 闭合多边形,复制第一个坐标作为最后一个坐标 coordinates[4] = new Coordinate(coords.get(0)[0], coords.get(0)[1]); // 计算设计标高,取四个角的高程平均值 // double centerHeight = getElevation(rectangle.getCentroid()); double corner1Height = getElevation( geometryFactory.createPoint(coordinates[0])); double corner2Height = getElevation( geometryFactory.createPoint(coordinates[1])); double corner3Height = getElevation( geometryFactory.createPoint(coordinates[2])); double corner4Height = getElevation( geometryFactory.createPoint(coordinates[3])); double targetHeight = (corner1Height+corner2Height+corner3Height+corner4Height)/4; // double targetHeight = 158.5; // double targetHeight = 145.7851371725257; System.out.println("初始标高:"+targetHeight); double startTime = System.currentTimeMillis(); Polygon rectangle = geometryFactory.createPolygon(coordinates); // resampleDem(rectangle); if(isResample){ // 重采样设置 BufferParameters bufferParameters = new BufferParameters(); bufferParameters.setEndCapStyle(BufferParameters.CAP_FLAT); bufferParameters.setJoinStyle(BufferParameters.JOIN_MITRE); BufferOp bufOp = new BufferOp(rectangle,bufferParameters); Polygon bufferLinePolygon = (Polygon)bufOp.getResultGeometry(isProjcetion?extendLen:meter2degree(extendLen)); double resampleStartTime = System.currentTimeMillis(); double distance = isProjcetion?meter:meter2degree(meter); reSample(bufferLinePolygon.getEnvelope(),inputDemPath,outputDemPath,distance,distance); loadDem(outputDemPath); System.out.println("重采样耗时:"+(System.currentTimeMillis()-resampleStartTime)+"毫秒"); } double allSum = calcBlanceHeight(rectangle,targetHeight); // double firstSum =0; // double step = 2;//起始步长 // double nextHeight=targetHeight; // int count = 1; // while (Math.abs(allSum)-range>0){ // // if((firstSum>0&&allSum<0)||(firstSum<0&&allSum>0)){ // // fix: 采用线性方式去计算步长 // step = step*Math.abs(allSum)/Math.abs(firstSum-allSum); // // } // nextHeight = allSum<0?nextHeight-step:nextHeight+step; // firstSum = calcBlanceHeight(rectangle,nextHeight); // count++; // System.out.println("firstSum:"+firstSum+"\t"+nextHeight); // if(Math.abs(firstSum)-range<0){ // allSum = firstSum; // break; // } // // if((firstSum>0&&allSum<0)||(firstSum<0&&allSum>0)){ // // fix: 采用线性方式去计算步长 // step = step*Math.abs(firstSum)/Math.abs(firstSum-allSum); // // } // double tmpHeight = firstSum<0?nextHeight-step:nextHeight+step; // allSum = calcBlanceHeight(rectangle,tmpHeight); // count++; // if(Math.abs(tmpHeight-nextHeight)<0.0001){ // nextHeight = tmpHeight; // break; // } // nextHeight = tmpHeight; // System.out.println("allSum:"+allSum+"\t"+nextHeight); // } // // // double radius = meter2degree(meter); // double radius = isProjcetion?meter:meter2degree(meter); // SimpleFeature cutBoundary = searchBourdary(cutPoints,radius,"挖方边界线"); // SimpleFeature fillBoundary = searchBourdary(fillPoints,radius,"填方边界线"); // FeatureJSON featureJSON = new FeatureJSON(new GeometryJSON(8)); // // System.out.println("理想标高:"+nextHeight); // System.out.println("总挖方量:"+cutAllSum); // System.out.println("总填方量:"+fillAllSum); // System.out.println("填挖方差值:"+allSum); // // System.out.println("单次耗时:"+(System.currentTimeMillis()-startTime)+"毫秒"); // // System.out.println("总填方格子数量:"+fillPoints.size()); // System.out.println("总挖方格子数量:"+cutPoints.size()); // // System.out.println("耗时:"+(System.currentTimeMillis()-startTime)); // // System.out.println("挖方边界线:"+featureJSON.toString(cutBoundary)); // System.out.println("填方边界线:"+featureJSON.toString(fillBoundary)); // 输出:理想标高、总挖方量、总填方量、填挖方差值、边界数据 } public static double calcBlanceHeight(Polygon rectangle ,double targetHeight) throws Exception{ // 创建GeometryFactory List> featuresProperties = new ArrayList<>();// 面要素属性集合 List> tPointFeaturesProperties = new ArrayList<>();// 目标平面的点集属性集合 // 清空 fillPoints = new ArrayList<>(); cutPoints = new ArrayList<>(); cutAllSum = 0; fillAllSum = 0; // 间距,单位为米。 // double meter = 2; double bottomRatio = 1.0/2; double topRatio = 1.0/1.5; // 创建多边形(矩形) Map innerPolygon = new HashMap<>(); // Polygon rectangle = geometryFactory.createPolygon(coordinates); innerPolygon.put("geom",rectangle); innerPolygon.put("name","输入的面"); innerPolygon.put("id",1); // BufferParameters bufferParameters = new BufferParameters(); // bufferParameters.setEndCapStyle(BufferParameters.CAP_FLAT); // bufferParameters.setJoinStyle(BufferParameters.JOIN_MITRE); // BufferOp bufOp = new BufferOp(rectangle,bufferParameters); // Polygon bufferLinePolygon = (Polygon)bufOp.getResultGeometry(isProjcetion?extendLen:meter2degree(extendLen)); // innerPolygon.put("geom",bufferLinePolygon.getEnvelope()); featuresProperties.add(innerPolygon); // 外接矩形打点 Map outPolygon1 = new HashMap<>(); Polygon out1 = (Polygon) rectangle.getEnvelope();//geometryFactory.createPolygon(cords4); outPolygon1.put("geom",out1); outPolygon1.put("name","输入面的外接矩形"); outPolygon1.put("id",6); featuresProperties.add(outPolygon1); Coordinate[] outCoords = out1.getCoordinates(); Coordinate[] outLine = new Coordinate[]{outCoords[0],outCoords[1]}; // 定义地图单位的距离 double distance = meter; if(!isProjcetion){ distance = meter2degree(distance); } addPartPoint(outLine,geometryFactory,distance,rectangle,tPointFeaturesProperties,targetHeight,"0"); // 扩展面打点 List>> pointRingFeaturesProperties = createRingPoint(rectangle,targetHeight,bottomRatio,topRatio,distance); // 中心点 Point centroid = rectangle.getCentroid(); // 计算网格 Map result = calcGrid(pointRingFeaturesProperties,centroid,meter); List> fillPointList = (List>)result.get("fillPointList"); List> cutPointList = (List>)result.get("cutPointList"); double fillSum = (double)result.get("fillSum"); double cutSum = (double)result.get("cutSum"); // 计算设计平面内的填挖方量 for(int i=0;i pfp = tPointFeaturesProperties.get(i); // double height = (double)pfp.get("height"); double height = (double)pfp.get("bottomHeight"); Point p = (Point)pfp.get("geom"); double elev = getElevation(p); pfp.put("elev",elev); if(elev>height){ cutPointList.add(pfp); cutSum += (elev - height)*Math.pow(meter,2); }else{ fillPointList.add(pfp); fillSum += (elev - height)*Math.pow(meter,2); } } System.out.println("总挖方量:"+cutSum); System.out.println("总填方量:"+fillSum); System.out.println("填挖方差量:"+(fillSum+cutSum)); // List> boundary = searchBourdary(cutPointList, meter2degree(meter)); // Create a map content and add our shapefile to it MapContent map = new MapContent(); map.setTitle("填挖方计算-创建网格"); // 构建添加面图层 final SimpleFeatureType TYPE =createFeatureType(); DefaultFeatureCollection featureCollection = new DefaultFeatureCollection(); SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE); featuresProperties.forEach(props->{ featureBuilder.add(props.get("geom")); featureBuilder.add(props.get("name")); featureBuilder.add(props.get("id")); SimpleFeature feature = featureBuilder.buildFeature((String.valueOf(props.get("id")))); featureCollection.add(feature); }); Style style = SLD.createSimpleStyle(featureCollection.getSchema()); Layer layer = new FeatureLayer(featureCollection, style); map.addLayer(layer); // 构建点要素图层 // List>> pointList = new ArrayList(){{ //// add(result.get("fillPointList")); // add(tPointFeaturesProperties); // }}; pointRingFeaturesProperties.add(tPointFeaturesProperties); List>> pointList = pointRingFeaturesProperties; pointList.stream().forEach(list->{ if(!list.isEmpty()){ final SimpleFeatureType PTYPE =createPointFeatureType(); DefaultFeatureCollection pointFeatureCollection = new DefaultFeatureCollection(); SimpleFeatureBuilder pointFeatureBuilder = new SimpleFeatureBuilder(PTYPE); list.forEach(props->{ pointFeatureBuilder.add(props.get("geom")); pointFeatureBuilder.add(props.get("id")); pointFeatureBuilder.add(props.get("bottomHeight")); pointFeatureBuilder.add(props.get("topHeight")); pointFeatureBuilder.add(props.get("elev")); SimpleFeature feature = pointFeatureBuilder.buildFeature((String.valueOf(props.get("id")))); pointFeatureCollection.add(feature); }); Style pointStyle = SLD.createSimpleStyle(pointFeatureCollection.getSchema()); Layer pointLlayer = new FeatureLayer(pointFeatureCollection, pointStyle); map.addLayer(pointLlayer); } }); final SimpleFeatureType PTYPE =createPointFeatureType(); DefaultFeatureCollection pointFeatureCollection = new DefaultFeatureCollection(); SimpleFeatureBuilder pointFeatureBuilder = new SimpleFeatureBuilder(PTYPE); List> list = (List>)result.get("cutPointList"); cutPointList.forEach(props->{ pointFeatureBuilder.add(props.get("geom")); pointFeatureBuilder.add(props.get("id")); pointFeatureBuilder.add(props.get("bottomHeight")); pointFeatureBuilder.add(props.get("topHeight")); SimpleFeature feature = pointFeatureBuilder.buildFeature((String.valueOf(props.get("id")))); pointFeatureCollection.add(feature); }); Style pointStyle = SLD.createSimpleStyle(pointFeatureCollection.getSchema(),Color.red); Layer pointLlayer = new FeatureLayer(pointFeatureCollection, pointStyle); map.addLayer(pointLlayer); final SimpleFeatureType FillPTYPE =createPointFeatureType(); DefaultFeatureCollection pointFillFeatureCollection = new DefaultFeatureCollection(); SimpleFeatureBuilder pointFillFeatureBuilder = new SimpleFeatureBuilder(FillPTYPE); // List> fillList = (List>)result.get("fillPointList"); fillPointList.forEach(props->{ pointFillFeatureBuilder.add(props.get("geom")); pointFillFeatureBuilder.add(props.get("id")); pointFillFeatureBuilder.add(props.get("bottomHeight")); pointFillFeatureBuilder.add(props.get("topHeight")); SimpleFeature feature = pointFillFeatureBuilder.buildFeature((String.valueOf(props.get("id")))); pointFillFeatureCollection.add(feature); }); Style pointFillStyle = SLD.createSimpleStyle(pointFillFeatureCollection.getSchema(),Color.blue); Layer pointFillLlayer = new FeatureLayer(pointFillFeatureCollection, pointFillStyle); map.addLayer(pointFillLlayer); JMapFrame.showMap(map); cutAllSum = cutSum; cutPoints = cutPointList; fillAllSum = fillSum; fillPoints = fillPointList; return fillSum + cutSum; // return 0; } // private static List> searchBourdary(List> fillPointList, double radius,String name) { // // AlphaShape alphaShape = new AlphaShape(radius); // List> result = new ArrayList<>(); // // 构建顶点集合对象 // List points = new ArrayList<>(); // fillPointList.forEach(pointMap->{ // Point p = (Point)pointMap.get("geom"); // Vector2D vector2D = new Vector2D(p.getX(), p.getY()); // // points.add(vector2D); // }); // List> lists = alphaShape.boundaryPoints(points); // lists.forEach(pointList->{ // pointList.forEach(point->{ // HashMap tmp = new HashMap<>(); // tmp.put("geom",geometryFactory.createPoint(new Coordinate(point.getX(),point.getY()))); // tmp.put("id",point.getIndex()); // tmp.put("bottomHeight",point.getBottomHeight()); // tmp.put("topHeight",point.getTopHeight()); // result.add(tmp); // }); // }); // // return result; // } /** * 返回线要素的 * @param fillPointList * @param radius * @return */ private static SimpleFeature searchBourdary(List> fillPointList, double radius,String name) { AlphaShape alphaShape = new AlphaShape(radius); // 构建顶点集合对象 List points = new ArrayList<>(); fillPointList.forEach(pointMap->{ Point p = (Point)pointMap.get("geom"); Vector2D vector2D = new Vector2D(p.getX(), p.getY()); points.add(vector2D); }); List> lists = alphaShape.boundaryPoints(points); List coordList = new ArrayList(); lists.forEach(pointList->{ pointList.forEach(point->{ coordList.add(new Coordinate(point.getX(),point.getY())); }); }); Coordinate[] CoordinateArray = coordList.stream().toArray(Coordinate[]::new); LineString lineString = geometryFactory.createLineString(CoordinateArray); // 构建添加线要素层 final SimpleFeatureType TYPE =createLineStringFeatureType(); SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE); String uuid = UUID.randomUUID().toString(); featureBuilder.add(lineString); featureBuilder.add(name); featureBuilder.add(uuid); SimpleFeature feature = featureBuilder.buildFeature(uuid); // featureCollection.add(feature); return feature; } private static Map calcGrid(List>> pointRingFeaturesProperties, Point centroid,double meter) throws Exception { List> lastRing = pointRingFeaturesProperties.get(pointRingFeaturesProperties.size()-1); // 定义地图单位的点距,创建缓冲区用的到 double length = isProjcetion?(meter/2):meter2degree(meter/2); List> fillPointList = new ArrayList<>();// 填方的点集 List> cutPointList = new ArrayList<>();// 挖方的点集 double fillSum = 0;// 填方量 double cutSum = 0;// 挖方量 for(Map featuresProperties:lastRing){ Point point = (Point)featuresProperties.get("geom"); // 创建缓存面 LineString lineString = geometryFactory.createLineString(new Coordinate[]{new Coordinate(point.getX(),point.getY()),new Coordinate(centroid.getX(),centroid.getY())}); BufferParameters bufferParameters = new BufferParameters(); bufferParameters.setEndCapStyle(BufferParameters.CAP_FLAT); bufferParameters.setJoinStyle(BufferParameters.JOIN_MITRE); BufferOp bufOp = new BufferOp(lineString,bufferParameters); Polygon bufferLinePolygon = (Polygon)bufOp.getResultGeometry(length); // 计算 boolean isGoDown = true;// 是否继续往下 boolean isGoHead = true; outer: for(int j=0;j> ringPointMap = pointRingFeaturesProperties.get(j); for (Map pointMap : ringPointMap) { Point p = (Point) pointMap.get("geom"); if (bufferLinePolygon.contains(p)) { double bottomHeight = (double) pointMap.get("bottomHeight"); double topHeight = (double) pointMap.get("topHeight"); double currHeight = getElevation(p); pointMap.put("elev",currHeight); if (currHeight > bottomHeight && currHeight < topHeight) { break outer; } if (currHeight >= topHeight && isGoHead) { isGoDown = false; if (!cutPointList.contains(pointMap)) {//去除重复点,避免重复计算 cutPointList.add(pointMap); cutSum += (currHeight - topHeight) * Math.pow(meter, 2); } } if (currHeight <= bottomHeight && isGoDown) { isGoHead = false; if (!fillPointList.contains(pointMap)) {//去除重复点,避免重复计算 fillPointList.add(pointMap); fillSum += (currHeight - bottomHeight) * Math.pow(meter, 2); } } } } } } Map result = new HashMap<>(); result.put("fillPointList",fillPointList); result.put("cutPointList",cutPointList); result.put("fillSum",fillSum); result.put("cutSum",cutSum); return result; } private static Map filterGrid(List>> pointRingFeaturesProperties,GeometryFactory geometryFactory,Point centroid,double meter,String type){ Map result = new HashMap<>(); double sum = 0; List> filterGrid = new ArrayList<>(); for(int i=0;i> ringPointList = pointRingFeaturesProperties.get(i); for(int j=0;j pfp = ringPointList.get(j); double height = (double)pfp.get("height"); Point p = (Point) pfp.get("geom"); try { double elevation = getElevation(p); // 填 if((type.equals("-1")&&height - elevation>=0)||(type.equals("1")&&height - elevation<0)){ List> centerLinePointSet = getCenterLinePoint(geometryFactory,pointRingFeaturesProperties,i,centroid,meter,p); if(centerLinePointSet.isEmpty()){ filterGrid.add(pfp); sum += Math.abs(height - elevation)*Math.pow(meter, 2); }else{ int count = 0; for(int k=0;k lineOnPoint = centerLinePointSet.get(k); double hp = (double)lineOnPoint.get("height"); Point geom = (Point) lineOnPoint.get("geom"); double ev = getElevation(geom); if(ev>hp){ count++; } } if(count==0){ filterGrid.add(pfp); sum += Math.abs(height - elevation)*Math.pow(meter, 2); } } } } catch (Exception e) { throw new RuntimeException(e); } } }; result.put("sum",Integer.valueOf(type)*sum); result.put("filterGrid",filterGrid); return result; } private static List> getCenterLinePoint( GeometryFactory geometryFactory,List>> pointFeaturesProperties,int index,Point centroid,double side,Point point){ // 创建缓存面 LineString lineString = geometryFactory.createLineString(new Coordinate[]{new Coordinate(point.getX(),point.getY()),new Coordinate(centroid.getX(),centroid.getY())}); BufferParameters bufferParameters = new BufferParameters(); bufferParameters.setEndCapStyle(BufferParameters.CAP_FLAT); bufferParameters.setJoinStyle(BufferParameters.JOIN_MITRE); BufferOp bufOp = new BufferOp(lineString,bufferParameters); double currDegree = side/2; Polygon bufferLine = (Polygon)bufOp.getResultGeometry(currDegree); List> result = new ArrayList<>(); for(int i=0;i> ring = pointFeaturesProperties.get(i); for(int j=0;j pfp = ring.get(j); Point p = (Point) pfp.get("geom"); if(bufferLine.intersects(p)){ result.add(pfp); } } } return result; } /** * 创建矩形外扩的环点 * 打点方式: 四条边顺时针按给定点距取点,再buffer点距,取矩形四条边重复之前按点距取点,直到外扩的最后一个矩形 * @param rectangle 设计平面 * @param targetHeight 设计标高 * @param bottomRatio 往下放坡的坡度比 * @param topRatio 往上放坡的坡度比 * @param side 点距,地图单位 * @return */ private static List>> createRingPoint(Polygon rectangle, double targetHeight, double bottomRatio,double topRatio, double side) { List>> ringPoint = new ArrayList<>(); // 先在输入面上打点 List> firstList = new ArrayList<>(); Coordinate[] coordinates = rectangle.getCoordinates(); Coordinate[] coordArr1 = new Coordinate[]{coordinates[0],coordinates[1]}; Coordinate[] coordArr2 = new Coordinate[]{coordinates[1],coordinates[2]}; Coordinate[] coordArr3 = new Coordinate[]{coordinates[2],coordinates[3]}; Coordinate[] coordArr4 = new Coordinate[]{coordinates[3],coordinates[0]}; firstList.addAll(addLinePoint(coordArr1,geometryFactory,side,targetHeight,targetHeight)); firstList.addAll(addLinePoint(coordArr2,geometryFactory,side,targetHeight,targetHeight)); firstList.addAll(addLinePoint(coordArr3,geometryFactory,side,targetHeight,targetHeight)); firstList.addAll(addLinePoint(coordArr4,geometryFactory,side,targetHeight,targetHeight)); ringPoint.add(firstList); // 计算高程用的点距,单位为米 double length = isProjcetion?side:degree2meter(side); for(int i=1;i> pointRingFeaturesProperties = new ArrayList<>(); double bottomHeight = targetHeight - length*bottomRatio*i; double topHeight = targetHeight + length*topRatio*i; BufferParameters bufferParameters = new BufferParameters(); bufferParameters.setEndCapStyle(BufferParameters.CAP_FLAT); bufferParameters.setJoinStyle(BufferParameters.JOIN_MITRE); BufferOp bufOp = new BufferOp(rectangle,bufferParameters); double currDegree = side*i; Geometry bg = bufOp.getResultGeometry(currDegree);// 缓冲分析的参数是地图单位的值 Coordinate[] boundCoord = bg.getBoundary().getCoordinates(); Coordinate[] boundArr1 = new Coordinate[]{boundCoord[0],boundCoord[1]}; Coordinate[] boundArr2 = new Coordinate[]{boundCoord[1],boundCoord[2]}; Coordinate[] boundArr3 = new Coordinate[]{boundCoord[2],boundCoord[3]}; Coordinate[] boundArr4 = new Coordinate[]{boundCoord[3],boundCoord[0]}; pointRingFeaturesProperties.addAll(addLinePoint(boundArr1,geometryFactory,side,bottomHeight,topHeight)); pointRingFeaturesProperties.addAll(addLinePoint(boundArr2,geometryFactory,side,bottomHeight,topHeight)); pointRingFeaturesProperties.addAll(addLinePoint(boundArr3,geometryFactory,side,bottomHeight,topHeight)); pointRingFeaturesProperties.addAll(addLinePoint(boundArr4,geometryFactory,side,bottomHeight,topHeight)); ringPoint.add(pointRingFeaturesProperties); } return ringPoint; } // 添加一个面的点集 public static List>> addPartPoint(Coordinate[] bgcoords, GeometryFactory geometryFactory, double side, Polygon p, List> pointFeaturesProperties, double outHeight, String type){ List>> gridList = new ArrayList(); // 计算外边界上的点 List> headPart = new ArrayList<>(); double t1 = (bgcoords[1].y - bgcoords[0].y)/(bgcoords[1].x-bgcoords[0].x); Coordinate startCoord = new Coordinate(bgcoords[0].x,bgcoords[0].y); Map centerPointMap = new HashMap<>(); Point center = geometryFactory.createPoint(startCoord); centerPointMap.put("geom",center); centerPointMap.put("id",UUID.randomUUID()); centerPointMap.put("bottomHeight",outHeight); centerPointMap.put("topHeight",outHeight); if(!type.equals("0")){ pointFeaturesProperties.add(centerPointMap); headPart.add(centerPointMap); } List> lastPart = addPointSet(bgcoords,geometryFactory,side,p,pointFeaturesProperties,center,outHeight,type); headPart.addAll(lastPart); gridList.add(headPart); int len = (int)Math.ceil((Math.sqrt(Math.pow(bgcoords[1].y - bgcoords[0].y,2)+Math.pow(bgcoords[1].x - bgcoords[0].x,2)))/side); //确定符号 double xx = bgcoords[1].x-bgcoords[0].x; double yy = bgcoords[1].y-bgcoords[0].y; int xSign = xx>=0?1:-1; int ySign = yy>=0?1:-1; for(int i=1;i> extHeadPart = new ArrayList<>(); Coordinate nextCoord = new Coordinate(nextX,nextY); Map nextPointMap = new HashMap<>(); Point nextPoint = geometryFactory.createPoint(nextCoord); nextPointMap.put("geom",nextPoint); nextPointMap.put("id",UUID.randomUUID()); nextPointMap.put("bottomHeight",outHeight); nextPointMap.put("topHeight",outHeight); if(type.equals("0")){ if(p.intersects(nextPoint)){ pointFeaturesProperties.add(nextPointMap); extHeadPart.add(nextPointMap); } }else{ pointFeaturesProperties.add(nextPointMap); extHeadPart.add(nextPointMap); } // 添加垂直于边界线的点阵 List> extLastPart = addPointSet(bgcoords,geometryFactory,side,p,pointFeaturesProperties,nextPoint,outHeight,type); extHeadPart.addAll(extLastPart); gridList.add(extHeadPart); } return gridList; } /** * 添加一个线的点集 * @param bgcoords 线的坐标 * @param geometryFactory * @param side 点距,地图单位 * @param bottomHeight 线所处的底部放坡高程 * @param topHeight 线做吃的顶部放坡高程 * @return 点集map数组 */ public static List> addLinePoint(Coordinate[] bgcoords, GeometryFactory geometryFactory, double side, double bottomHeight,double topHeight){ // double degree = side; // 计算外边界上的点 List> lineList = new ArrayList<>(); Coordinate startCoord = new Coordinate(bgcoords[0].x,bgcoords[0].y); Map startPointMap = new HashMap<>(); Point sp = geometryFactory.createPoint(startCoord); startPointMap.put("geom",sp); startPointMap.put("id",UUID.randomUUID().toString()); startPointMap.put("bottomHeight",bottomHeight); startPointMap.put("topHeight",topHeight); lineList.add(startPointMap); int len = (int)Math.floor((Math.sqrt(Math.pow(bgcoords[1].y - bgcoords[0].y,2)+Math.pow(bgcoords[1].x - bgcoords[0].x,2)))/side); double t1 = (bgcoords[1].y - bgcoords[0].y)/(bgcoords[1].x-bgcoords[0].x); //确定符号 double xx = bgcoords[1].x-bgcoords[0].x; double yy = bgcoords[1].y-bgcoords[0].y; int xSign = xx>=0?1:-1; int ySign = yy>=0?1:-1; // 计算坐标直接用地图单位的点距 for(int i=1;i nextPointMap = new HashMap<>(); Point nextPoint = geometryFactory.createPoint(nextCoord); nextPointMap.put("geom",nextPoint); nextPointMap.put("id",UUID.randomUUID().toString()); nextPointMap.put("bottomHeight",bottomHeight); nextPointMap.put("topHeight",topHeight); lineList.add(nextPointMap); } return lineList; } public static List> addPointSet(Coordinate[] bgcoords, GeometryFactory geometryFactory, double side, Polygon polygon, List> pointFeaturesProperties, Point startPoint, double boundHeight, String type){ List> extendPointProperties = new ArrayList<>(); double t1 = (bgcoords[1].y - bgcoords[0].y)/(bgcoords[1].x-bgcoords[0].x); //确定符号 double xx = bgcoords[1].x-bgcoords[0].x; double yy = bgcoords[1].y-bgcoords[0].y; int xSign = (xx>=0&&yy>0)||(xx<0&&yy>0)?1:-1; int ySign = (xx<0&&yy<0)||(xx<0&&yy>0)?1:-1; // 算高程要用到,地图单位到米 double length = isProjcetion?side:degree2meter(side); for(int i=1;i<3000;i++){ double x1 = xSign * Math.abs(Math.sin(Math.atan(t1)))*side*i + startPoint.getX(); double y1 = ySign * Math.abs(Math.cos(Math.atan(t1)))*side*i + startPoint.getY(); // 当垂直与坐标轴时 if(bgcoords[1].x==bgcoords[0].x){ x1 = side*i + startPoint.getX(); y1 = startPoint.getY(); } Point point = geometryFactory.createPoint(new Coordinate(x1,y1)); boolean contains = polygon.contains(point); if(contains){ Map tmpPoint = new HashMap<>(); tmpPoint.put("geom",point); tmpPoint.put("id",UUID.randomUUID()); double ph = boundHeight;//+(degree2meter(side))*i/2; if(type.equals("-1")){//下挖的高程计算 ph+=(length)*i/2; }else if(type.equals("1")){// ph-=(length)*i/1.5; } tmpPoint.put("bottomHeight",ph); tmpPoint.put("topHeight",ph); pointFeaturesProperties.add(tmpPoint); extendPointProperties.add(tmpPoint); } } return extendPointProperties; } public static void loadDem(String path) throws Exception{ File file = new File(path); // File file = new File("src\\main\\resources\\public\\data\\CSDEM.tif"); // File file = new File("E:\\data\\CB测试\\sample_N30E119.tif"); // File file = new File("E:\\data\\CB测试\\sample_N30E119.tif"); // Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER:设置经度为第一轴顺序 GeoTiffReader reader = new GeoTiffReader(file, new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE)); // GridCoverage2D coverage = reader.read(null); // //设置坐标系 // CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326"); // // 将 GridCoverage 进行重采样转换为另一个 CRS // CreateRingGridFixProjection.coverage = (GridCoverage2D) Operations.DEFAULT.resample(coverage, targetCRS); CreateRingGridFixGeo.coverage = reader.read(null); } public static double getElevation(Point p) throws Exception{ // 设置经纬度及坐标系等信息 Position position = new Position2D(p.getX(),p.getY()); GridGeometry2D gridGeometry = CreateRingGridFixGeo.coverage.getGridGeometry(); GridCoordinates2D gridPoint = gridGeometry.worldToGrid(position); double[] elevation = new double[1]; CreateRingGridFixGeo.coverage.evaluate(gridPoint,elevation); double height = elevation[0]; // 这里的高度就是查询位置的高程值 // System.out.println("---------"+height);//---------108.0 return height; } public static double meter2degree(double meter){ return meter/(Math.PI*6371004/180); } public static double degree2meter(double degree){ return degree*(Math.PI*6371004)/180; } /** * 对栅格重采样 * @param envelope 限定的矩形几何 * @param inputPath 输入的栅格路径 * @param outputPath 输出的栅格路径 * @param r1 东西方向像元大小(地图单位) * @param r2 南北方向像元大小(地图单位) */ public static void reSample(Geometry envelope,String inputPath, String outputPath, double r1, double r2) { // 打开输入栅格文件 Dataset dataset = gdal.Open(inputPath, gdalconst.GA_ReadOnly); double[] gt1 = dataset.GetGeoTransform(); Coordinate[] envCoords = envelope.getCoordinates(); double envWidth = (envCoords[2].x - envCoords[0].x); double envHeight = (envCoords[2].y - envCoords[0].y); int xSize = new Double(envWidth/ r1).intValue(); int ySize = new Double(envHeight / r2).intValue(); ySize = Math.abs(ySize); double[] gt2 = {envCoords[0].x, r1, 0.0, envCoords[0].y, 0.0, r2}; Driver driver = gdal.GetDriverByName("GTiff"); Dataset datasetWarp = driver.Create(outputPath, xSize, ySize, gdalconst.GA_Update, gdalconst.GDT_Float32); datasetWarp.SetGeoTransform(gt2); datasetWarp.SetSpatialRef(dataset.GetSpatialRef()); Vector vector = new Vector<>(); vector.add("-r"); vector.add("cubicspline");//执行三次卷积插值法重采样 WarpOptions warpOptions = new WarpOptions(vector); gdal.Warp(datasetWarp, new Dataset[]{dataset}, warpOptions); datasetWarp.FlushCache(); datasetWarp.delete(); dataset.delete(); } }