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;
}
}