pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.summit</groupId>
<artifactId>summit-tools-gis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>summit-tools-gis</name>
<description>gis工具</description>
<properties>
<java.version>1.8</java.version>
<geotools.version>26.0</geotools.version>
<swagger.version>2.7.0</swagger.version>
<mybatisplus.version>3.3.0</mybatisplus.version>
<druid.version>1.1.16</druid.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- pg数据库驱动 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<!--<!–IDW 插值 –>-->
<dependency>
<groupId>com.wContour</groupId>
<artifactId>wContour</artifactId>
<version>2</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/wContour.jar</systemPath>
</dependency>
<!--swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- GEOTOOLS相关的依赖 -->
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-epsg-hsql</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-swing</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-geojson</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-coverage</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-metadata</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-referencing</artifactId>
<version>${geotools.version}</version>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-grid</artifactId>
<version>${geotools.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.locationtech.jts/jts-core -->
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.18.2</version>
</dependency>
<!--<dependency>-->
<!--<groupId>com.vividsolutions</groupId>-->
<!--<artifactId>jts</artifactId>-->
<!--<version>1.13</version>-->
<!--</dependency>-->
<!-- https://mvnrepository.com/artifact/wContour/wContour -->
<!--<dependency>-->
<!--<groupId>wContour</groupId>-->
<!--<artifactId>wContour</artifactId>-->
<!--<version>1.6.1</version>-->
<!--</dependency>-->
</dependencies>
<repositories>
<repository>
<id>osgeo</id>
<name>OSGeo Release Repository</name>
<url>https://repo.osgeo.org/repository/release/</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
<repository>
<id>osgeo-snapshot</id>
<name>OSGeo Snapshot Repository</name>
<url>https://repo.osgeo.org/repository/snapshot/</url>
<snapshots><enabled>true</enabled></snapshots>
<releases><enabled>false</enabled></releases>
</repository>
<repository>
<id>maven</id>
<name>maven</name>
<url>http://mvnrepository.com/</url>
<snapshots><enabled>true</enabled></snapshots>
<releases><enabled>false</enabled></releases>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
</project>
核心代码
/**
* All rights Reserved, Designed By www.summit.com.cn
*/
package com.summit.gis.modules.iso.utils;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.summit.gis.modules.iso.vo.Station;
import org.geotools.data.DataUtilities;
import org.geotools.data.FeatureSource;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.json.simple.JSONArray;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeature;
import com.alibaba.fastjson.JSONObject;
import com.summit.gis.modules.iso.enums.GeometryEnum;
import com.summit.gis.modules.iso.vo.InterpolationVO;
//import com.vividsolutions.jts.geom.Coordinate;
//import com.vividsolutions.jts.geom.Geometry;
import org.opengis.feature.simple.SimpleFeatureType;
import wContour.Contour;
import wContour.Global.PointD;
import wContour.Global.PolyLine;
import wContour.Contour;
import wContour.Global.PointD;
import wContour.Global.PolyLine;
import wContour.Interpolate;
import wContour.Contour;
import wContour.Interpolate;
import wContour.Global.Border;
import wContour.Global.PointD;
import wContour.Global.PolyLine;
import wContour.Global.Polygon;
/**
* @ClassName: IsoSurfaceUtil
* @Description: 生成等值面的工具
* @author: zhangchaojia
* @date: 2019年12月2日 上午10:13:31
*
*/
public class IsoSurfaceUtil {
private static final double UNDEF_DATA = -9999.0;
private static final double EPSILON = 0.001;
/**
*
* <p>Title: calculateIsoSurfaceByIDW</p>
*
* @param vo
* @return
* @throws IOException
*/
public static String calculateIsoSurfaceByIDW(InterpolationVO vo) throws IOException, SchemaException {
boolean validate = paramsValidate(vo);
if (validate) {
// File file = new File(vo.getBoundaryFilePath());
String geoJson;
Integer[] gridSize = vo.getGridSize();
int width = gridSize[0];
int height = gridSize[1];
double[] X = new double[width];
double[] Y = new double[height];
//------------根据geojson生成simpleFeatureCollection--
JSONObject boundary=vo.getBoundary();
FeatureJSON featureJSON=new FeatureJSON();
FeatureCollection featureCollection=featureJSON.readFeatureCollection(boundary.toString());
// 获取边界
double minX = featureCollection.getBounds().getMinX();
double minY = featureCollection.getBounds().getMinY();
double maxX = featureCollection.getBounds().getMaxX()+1;
double maxY = featureCollection.getBounds().getMaxY()+1;
// 创建网格X / Y坐标
Interpolate.CreateGridXY_Num(minX, minY, maxX, maxY, X, Y);
double[] dataInterval = vo.getDataInterval();
int nc = dataInterval.length;
//获取站点数据
List<Station> list=vo.getStationList();
double[][] data =new double[3][list.size()];
if(list.size()<3){
return null;
}
for(int i=0;i<list.size();i++){
Station station=list.get(i);
data[0][i]=station.getX();
data[1][i]=station.getY();
data[2][i]=station.getValue();
}
// IDW 插值
double[][] gridData = Interpolate.Interpolation_IDW_Neighbor(data, X, Y, dataInterval.length, UNDEF_DATA);
int[][] S1 = new int[gridData.length][gridData[0].length];
// 用未定义的数据跟踪网格数据的轮廓边界。 网格数据从左到右,从下到上。 网格数据数组:第一个尺寸为Y,第二个尺寸为X。
List<Border> borders = Contour.tracingBorders(gridData, X, Y, S1, UNDEF_DATA);
// 轮廓边界
List<PolyLine> polylineList = Contour.tracingContourLines(gridData, X, Y, nc, dataInterval, UNDEF_DATA,
borders, S1);
// 平滑曲线
polylineList = Contour.smoothLines(polylineList);
GeometryEnum type = vo.getType();
SimpleFeatureCollection contourSimpleFeatureCollection,clipSimpleFeatureCollection;
switch (type) {
case Line:
geoJson = polylineToGeoJson(polylineList);
//获取等值面要素
contourSimpleFeatureCollection=getSimpleCollectionByGeoJSON(geoJson);
// 根据边界裁剪等值面
clipSimpleFeatureCollection=clipPolylineFeatureCollection(featureCollection,contourSimpleFeatureCollection);
return SimpleCollectionToGeoJSON(clipSimpleFeatureCollection);
case Polygon:
// 根据等值线描述出等值面数据
List<Polygon> polygonList = Contour.tracingPolygons(gridData, polylineList, borders, dataInterval);
geoJson = polygonToGeoJson(polygonList);
//获取等值面要素
contourSimpleFeatureCollection=getSimpleCollectionByGeoJSON(geoJson);
// 根据边界裁剪等值面
clipSimpleFeatureCollection=clipPolygonFeatureCollection(featureCollection,contourSimpleFeatureCollection);
return SimpleCollectionToGeoJSON(clipSimpleFeatureCollection);
default:
geoJson = null;
break;
}
}
return null;
}
/**
* 通过geojson获取要素类
* @param geojsom
* @return
* @throws IOException
*/
private static SimpleFeatureCollection getSimpleCollectionByGeoJSON(String geojsom) throws IOException {
FeatureJSON featureJSON=new FeatureJSON();
FeatureCollection featureCollection=featureJSON.readFeatureCollection(geojsom);
List<SimpleFeature> list=new ArrayList<>();
FeatureIterator featureIterator=featureCollection.features();
while (featureIterator.hasNext()){
SimpleFeature feature=(SimpleFeature) featureIterator.next();
list.add(feature);
}
SimpleFeatureCollection simpleFeatureCollection=new ListFeatureCollection((SimpleFeatureType) featureCollection.getSchema(),list);
return simpleFeatureCollection;
}
/**
* 要素类转geojson
* @param simpleFeatureCollection
* @return
* @throws IOException
*/
private static String SimpleCollectionToGeoJSON(SimpleFeatureCollection simpleFeatureCollection) throws IOException {
FeatureCollection featureCollection=(FeatureCollection) simpleFeatureCollection;
FeatureJSON featureJSON=new FeatureJSON();
StringWriter writer = new StringWriter();
featureJSON.writeFeatureCollection(featureCollection,writer);
return writer.toString();
}
/**
* Contour面转geojson
* @param polygonList
* @return
*/
private static String polygonToGeoJson(List<Polygon> polygonList) {
String geo;
String geometry = "{ \"type\":\"Feature\",\"geometry\":";
String properties = ",\"properties\":{ \"hvalue\":";
String head = "{\"type\": \"FeatureCollection\"," + "\"features\":[";
String end = "]}";
if (polygonList == null || polygonList.isEmpty()) {
return null;
}
StringBuilder geoBuilder = new StringBuilder();
for (Polygon pPolygon : polygonList) {
List<Object> ptsTotal = new ArrayList<>();
List<Object> pts = new ArrayList<>();
pPolygon.OutLine.PointList.stream().map(point -> {
List<Double> pt = new ArrayList<>();
pt.add(point.X);
pt.add(point.Y);
return pt;
}).forEachOrdered(pts::add);
ptsTotal.add(pts);
if (pPolygon.HasHoles()) {
// 有孔洞的多面
pPolygon.HoleLines.stream().map(cptLine -> {
List<Object> cpts = new ArrayList<>();
cptLine.PointList.stream().map(ccptD -> {
List<Double> pt = new ArrayList<>();
pt.add(ccptD.X);
pt.add(ccptD.Y);
return pt;
}).forEachOrdered(cpts::add);
return cpts;
}).filter(cpts -> !cpts.isEmpty()).forEachOrdered(ptsTotal::add);
}
JSONObject js = new JSONObject();
js.put("type", "Polygon");
js.put("coordinates", ptsTotal);
double hv = pPolygon.HighValue;
double lv = pPolygon.LowValue;
// if (Math.abs(hv - lv) < EPSILON) {
// // 是否顺时针
// if (pPolygon.IsClockWise) {
// // 是否居中
// if (!pPolygon.IsHighCenter) {
// hv = hv + 0.1;
// lv = lv + 0.1;
// }
// } else {
// if (!pPolygon.IsHighCenter) {
// hv = hv - 0.1;
// lv = lv - 0.1;
// }
// }
// } else {
// if (!pPolygon.IsClockWise) {
// lv = lv + 0.1;
// } else {
// if (pPolygon.IsHighCenter) {
// hv = hv - 0.1;
// }
// }
//
// }
if (Math.abs(hv - lv) < EPSILON) {
if(pPolygon.IsHighCenter){
hv=hv+0.1;
lv=lv+0.1;
}else{
hv=hv-0.1;
lv=lv-0.1;
}
}else{
hv=hv-0.1;
lv=lv+0.1;
}
geoBuilder.insert(0, geometry + js.toString() + properties + hv + ", \"lvalue\":" + lv + "}}" + ",");
}
geo = geoBuilder.toString();
if (geo.contains(",")) {
geo = geo.substring(0, geo.lastIndexOf(","));
}
geo = head + geo + end;
return geo;
}
/**
*
* <p>Title: polylineToGeoJson</p>
* <p>Description: polyline 转换为GeoJSON字符串</p>
*
* @param polylineList
* @return
*/
private static String polylineToGeoJson(List<PolyLine> polylineList) {
StringBuilder geo = new StringBuilder();
String geometry = " { \"type\":\"Feature\",\"geometry\":";
String properties = ",\"properties\":{ \"value\":";
String head = "{\"type\": \"FeatureCollection\"," + "\"features\": [";
String end = " ] }";
if (polylineList.isEmpty()) {
return null;
}
for (PolyLine pPolyline : polylineList) {
List<Object> ptsTotal = new ArrayList<>();
for (PointD ptD : pPolyline.PointList) {
List<Double> pt = new ArrayList<>();
pt.add(ptD.X);
pt.add(ptD.Y);
ptsTotal.add(pt);
}
JSONObject js = new JSONObject();
js.put("type", "LineString");
js.put("coordinates", ptsTotal);
geo.insert(0, geometry + js.toString() + properties + pPolyline.Value + "} }" + ",");
}
if (geo.toString().contains(",")) {
geo = new StringBuilder(geo.substring(0, geo.lastIndexOf(",")));
}
geo = new StringBuilder(head + geo + end);
return geo.toString();
}
/**
*
* <p>Title: paramsValidate</p>
* <p> Description: 参数校验</p>
*
* @param vo
* @return
*/
private static boolean paramsValidate(InterpolationVO vo) {
return true;
}
/**
* 裁剪图形
* @param fc
* @param gs
* @return
* @throws SchemaException
*/
private static SimpleFeatureCollection clipPolygonFeatureCollection(FeatureCollection fc,
SimpleFeatureCollection gs) throws SchemaException {
SimpleFeatureCollection simpleFeatureCollection = null;
final SimpleFeatureType TYPE= DataUtilities.createType("polygons", "the_geom:MultiPolygon:srid=4326,lvalue:double,hvalue:double");
try {
List<SimpleFeature> list=new ArrayList<>();
SimpleFeatureIterator contourFeatureIterator = gs.features();
FeatureIterator dataFeatureIterator = fc.features();
while (dataFeatureIterator.hasNext()) {
SimpleFeature dataFeature =(SimpleFeature) dataFeatureIterator.next();
Geometry dataGeometry = (Geometry)dataFeature.getDefaultGeometry();
while (contourFeatureIterator.hasNext()) {
SimpleFeature contourFeature = contourFeatureIterator.next();
Geometry contourGeometry = (Geometry) contourFeature.getDefaultGeometry();
double lv = (Double) contourFeature.getProperty("lvalue")
.getValue();
double hv = (Double) contourFeature.getProperty("hvalue")
.getValue();
try{
if(dataGeometry.getGeometryType()=="MultiPolygon"){
for(int i=0;i<dataGeometry.getNumGeometries();i++){
Geometry geom=dataGeometry.getGeometryN(i);
if (geom.intersects(contourGeometry)) {
Geometry geo = geom
.intersection(contourGeometry);
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
featureBuilder.add(geo);
featureBuilder.add(lv);
featureBuilder.add(hv);
SimpleFeature feature =featureBuilder.buildFeature(null);
list.add(feature);
// }
}
}
}else {
if (dataGeometry.intersects(contourGeometry)) {
Geometry geo = dataGeometry
.intersection(contourGeometry);
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
featureBuilder.add(geo);
featureBuilder.add(lv);
featureBuilder.add(hv);
SimpleFeature feature = featureBuilder.buildFeature(null);
list.add(feature);
}
}
}catch (Exception e){
System.out.println(e.getMessage());
}finally {
continue;
}
}
}
contourFeatureIterator.close();
dataFeatureIterator.close();
simpleFeatureCollection=new ListFeatureCollection(TYPE,list);
} catch (Exception e) {
e.printStackTrace();
}
return simpleFeatureCollection;
}
/**
* 裁剪线
* @param fc
* @param gs
* @return
* @throws SchemaException
*/
private static SimpleFeatureCollection clipPolylineFeatureCollection(FeatureCollection fc,
SimpleFeatureCollection gs) throws SchemaException {
SimpleFeatureCollection simpleFeatureCollection = null;
final SimpleFeatureType TYPE= DataUtilities.createType("polygons", "the_geom:LineString:srid=4326,value:double");
try {
List<SimpleFeature> list=new ArrayList<>();
SimpleFeatureIterator contourFeatureIterator = gs.features();
FeatureIterator dataFeatureIterator = fc.features();
while (dataFeatureIterator.hasNext()) {
SimpleFeature dataFeature =(SimpleFeature) dataFeatureIterator.next();
Geometry dataGeometry = (Geometry)dataFeature.getDefaultGeometry();
while (contourFeatureIterator.hasNext()) {
SimpleFeature contourFeature = contourFeatureIterator.next();
Geometry contourGeometry = (Geometry) contourFeature.getDefaultGeometry();
double value = (Double) contourFeature.getProperty("value")
.getValue();
if (dataGeometry.intersects(contourGeometry)) {
Geometry geo = dataGeometry
.intersection(contourGeometry);
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
featureBuilder.add(geo);
featureBuilder.add(value);
SimpleFeature feature =featureBuilder.buildFeature(null);
list.add(feature);
}
}
}
contourFeatureIterator.close();
dataFeatureIterator.close();
simpleFeatureCollection=new ListFeatureCollection(TYPE,list);
} catch (Exception e) {
e.printStackTrace();
}
return simpleFeatureCollection;
}
}
! wcontour依赖包不要用maven下载的
网友评论