1、项目需要开发绘制的一个区域与地图上提供的多个基础区域做对比,计算出两个区域之间是否覆盖,并计算覆盖的面积。因为计算区域面积花了很多时间去解决,最终还是终于解决,因此记录一下
计算覆盖区域的面积解决方案:重写计算面积的方法,因为工具计算的面积得到的数据很奇怪,例如:0.051878132302049365,肯定不对的,花了很多时间去查找资料也没有找到解决办法,网上说组要坐标转换,但是下载不了需要的jar,
最后FQ下载了,但是计算的面积也不对,但是相关的js写的计算面积是正确,然后查看了js的源码,用java转换重写了计算面积的方法
2、使用jar包:
implementation 'org.locationtech.jts:jts-core:1.18.2'
implementation 'com.github.filosganga:geogson-core:1.4.31'
implementation 'com.github.filosganga:geogson-jts:1.4.31'
3、主要代码:
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new GeometryAdapterFactory()).create();
//地图的genjson
String projectMapDetailJson = JSONUtil.toJsonStr(analysisProRequest);
// 构造转化器,以将filosganga包的同名类转化为locationtech的同名类
CodecRegistry<org.locationtech.jts.geom.Geometry, Geometry<?>> codecs = new CodecRegistry<>();
// 添加对应类型的转化器,区域类型为PolygonCodoec.
codecs.addCodec(new PolygonCodec(new GeometryFactory()));
codecs.addCodec(new MultiPolygonCodec(new GeometryFactory()));
List<Feature> projectFeatures = getFeature(projectMapDetailJson);
//项目绘制的坐标geometry
org.locationtech.jts.geom.Geometry projectCoordinateValue = codecs.fromGeometry(projectFeatures.get(0).geometry());
//地图需要对比的区域,存在躲过
for (Feature feature : jsonFileFeature) {
org.locationtech.jts.geom.Geometry geometry = codecs.fromGeometry(feature.geometry());
//测试该几何结构是否拓扑有效。
boolean isValid = geometry.isValid();
if (!isValid) {
continue;
}
org.locationtech.jts.geom.Geometry intersection = geometry.intersection(geometry);
//先根据工具计算面积,判断是否存在覆盖区域
double coverArea = projectCoordinateValue.intersection(geometry).getArea();
if (coverArea > 0) {
//重写计算面积的方法,因为工具计算的面积得到的数据很奇怪,例如:0.051878132302049365,肯定不对的,花了很多时间去查找资料也没有找到解决办法,网上说组要坐标转换,
//但是下载不了需要的jar,最后FQ下载了,但是计算的面积也不对,但是相关的js写的计算面积是正确,然后查看了js的源码,用java转换重写了计算面积的方法
double area = PolygonAreaUtil.getArea(projectCoordinateValue.intersection(geometry));
BigDecimal bigDecimal = new BigDecimal(area).setScale(3, RoundingMode.HALF_UP);
log.info(String.valueOf(area));
}
}
//用到放到
private List<Feature> getFeature(String str) {
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new GeometryAdapterFactory()).create();
FeatureCollection projectFeatureCollection = gson.fromJson(str, FeatureCollection.class);
List<Feature> features = projectFeatureCollection.features();
return features;
}
计算面积的类
import org.locationtech.jts.geom.Coordinate;
public class PolygonAreaUtil {
public static int RADIUS = 6378137;
/**
* 计算区域面积,单位平方米
* @param geometry
* @return
*/
public static double getArea(org.locationtech.jts.geom.Geometry geometry) {
Coordinate[] coords = geometry.getCoordinates();
Coordinate p1;
Coordinate p2;
Coordinate p3;
int lowerIndex, middleIndex, upperIndex, i;
double total = 0.0;
int coordsLength = geometry.getCoordinates().length;
if (coordsLength > 2) {
for (i = 0; i < coordsLength; i++) {
if (i == coordsLength - 2) {
// i = N-2
lowerIndex = coordsLength - 2;
middleIndex = coordsLength - 1;
upperIndex = 0;
} else if (i == coordsLength - 1) {
// i = N-1
lowerIndex = coordsLength - 1;
middleIndex = 0;
upperIndex = 1;
} else {
// i = 0 to N-3
lowerIndex = i;
middleIndex = i + 1;
upperIndex = i + 2;
}
p1 = coords[lowerIndex];
p2 = coords[middleIndex];
p3 = coords[upperIndex];
total += (rad(p3.getX()) - rad(p1.getX())) * Math.sin(rad(p2.getY()));
}
total = (total * RADIUS * RADIUS) / 2;
}
return total;
}
public static double rad(double num) {
return (num * Math.PI) / 180;
}
}