|
|
@@ -1,5 +1,7 @@
|
|
|
package com.dji.sdk.cloudapi.map;
|
|
|
|
|
|
+import com.dji.sdk.common.AMap;
|
|
|
+import com.dji.sdk.common.CoordinateUtil;
|
|
|
import com.dji.sdk.exception.CloudSDKErrorEnum;
|
|
|
import com.dji.sdk.exception.CloudSDKException;
|
|
|
import io.swagger.v3.oas.annotations.media.Schema;
|
|
|
@@ -78,4 +80,171 @@ public class ElementLineStringGeometry extends ElementGeometryType {
|
|
|
public String getType() {
|
|
|
return type;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Calculates the distance between two points on Earth using the Haversine formula.
|
|
|
+ *
|
|
|
+ * @return The distance in meters.
|
|
|
+ */
|
|
|
+ public double getCalculateSegmentLength() {
|
|
|
+ List<ElementCoordinate> list = convertToList();
|
|
|
+ ElementCoordinate coord1 = list.get(0);
|
|
|
+ ElementCoordinate coord2 = list.get(1);
|
|
|
+ final double EARTH_RADIUS = 6371000; // Earth radius in meters
|
|
|
+ double lat1 = Math.toRadians(coord1.getLatitude());
|
|
|
+ double lon1 = Math.toRadians(coord1.getLongitude());
|
|
|
+ double lat2 = Math.toRadians(coord2.getLatitude());
|
|
|
+ double lon2 = Math.toRadians(coord2.getLongitude());
|
|
|
+
|
|
|
+ double dLat = lat2 - lat1;
|
|
|
+ double dLon = lon2 - lon1;
|
|
|
+
|
|
|
+ double a = Math.pow(Math.sin(dLat / 2), 2) +
|
|
|
+ Math.cos(lat1) * Math.cos(lat2) *
|
|
|
+ Math.pow(Math.sin(dLon / 2), 2);
|
|
|
+ double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
|
+
|
|
|
+ return EARTH_RADIUS * c;
|
|
|
+ }
|
|
|
+
|
|
|
+ public double calculateSegmentLength(ElementCoordinate coord1, ElementCoordinate coord2) {
|
|
|
+ final double EARTH_RADIUS = 6371000; // Earth radius in meters
|
|
|
+ double lat1 = Math.toRadians(coord1.getLatitude());
|
|
|
+ double lon1 = Math.toRadians(coord1.getLongitude());
|
|
|
+ double lat2 = Math.toRadians(coord2.getLatitude());
|
|
|
+ double lon2 = Math.toRadians(coord2.getLongitude());
|
|
|
+
|
|
|
+ double dLat = lat2 - lat1;
|
|
|
+ double dLon = lon2 - lon1;
|
|
|
+
|
|
|
+ double a = Math.pow(Math.sin(dLat / 2), 2) +
|
|
|
+ Math.cos(lat1) * Math.cos(lat2) *
|
|
|
+ Math.pow(Math.sin(dLon / 2), 2);
|
|
|
+ double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
|
+
|
|
|
+ return EARTH_RADIUS * c;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Calculates the distance between two points on Earth using Vincenty's formula.
|
|
|
+ *
|
|
|
+ * @param coord1 The first coordinate.
|
|
|
+ * @param coord2 The second coordinate.
|
|
|
+ * @return The distance in meters.
|
|
|
+ */
|
|
|
+ private double calculateSegmentLengthVincenty(ElementCoordinate coord1, ElementCoordinate coord2) {
|
|
|
+ final double EARTH_RADIUS_EQUATOR = 6378137; // Semi-major axis of the WGS84 ellipsoid
|
|
|
+ final double EARTH_RADIUS_POLE = 6356752.314245; // Semi-minor axis of the WGS84 ellipsoid
|
|
|
+ final double FLATTENING = (EARTH_RADIUS_EQUATOR - EARTH_RADIUS_POLE) / EARTH_RADIUS_EQUATOR; // Flattening factor
|
|
|
+ final double EARTH_RADIUS = (EARTH_RADIUS_EQUATOR + EARTH_RADIUS_POLE) / 2.0;
|
|
|
+
|
|
|
+ double lat1 = Math.toRadians(coord1.getLatitude());
|
|
|
+ double lon1 = Math.toRadians(coord1.getLongitude());
|
|
|
+ double lat2 = Math.toRadians(coord2.getLatitude());
|
|
|
+ double lon2 = Math.toRadians(coord2.getLongitude());
|
|
|
+
|
|
|
+ double U1 = Math.atan((1 - FLATTENING) * Math.tan(lat1));
|
|
|
+ double U2 = Math.atan((1 - FLATTENING) * Math.tan(lat2));
|
|
|
+ double L = lon2 - lon1;
|
|
|
+ double lambda = L;
|
|
|
+ double lambdaP = 0.0;
|
|
|
+ double iterLimit = 100;
|
|
|
+ double sinLambda = 0.0;
|
|
|
+ double cosLambda = 0.0;
|
|
|
+ double sinSigma = 0.0;
|
|
|
+ double cosSigma = 0.0;
|
|
|
+ double sigma = 0.0;
|
|
|
+ double sinAlpha = 0.0;
|
|
|
+ double cosSqAlpha = 0.0;
|
|
|
+ double cos2SigmaM = 0.0;
|
|
|
+ double uSquared = 0.0;
|
|
|
+ double A = 0.0;
|
|
|
+ double B = 0.0;
|
|
|
+ double deltaSigma = 0.0;
|
|
|
+ double sinU1 = Math.sin(U1);
|
|
|
+ double cosU1 = Math.cos(U1);
|
|
|
+ double sinU2 = Math.sin(U2);
|
|
|
+ double cosU2 = Math.cos(U2);
|
|
|
+
|
|
|
+ do {
|
|
|
+ sinLambda = Math.sin(lambda);
|
|
|
+ cosLambda = Math.cos(lambda);
|
|
|
+ sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) +
|
|
|
+ (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
|
|
|
+ if (sinSigma == 0.0) {
|
|
|
+ return 0.0; // coincident points
|
|
|
+ }
|
|
|
+ cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
|
|
|
+ sigma = Math.atan2(sinSigma, cosSigma);
|
|
|
+ sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
|
|
|
+ cosSqAlpha = 1 - sinAlpha * sinAlpha;
|
|
|
+ cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
|
|
|
+ if (Double.isNaN(cos2SigmaM)) {
|
|
|
+ cos2SigmaM = 0; // equatorial line: cosSqAlpha = 0 (§6)
|
|
|
+ }
|
|
|
+ uSquared = cosSqAlpha * (EARTH_RADIUS_EQUATOR * EARTH_RADIUS_EQUATOR - EARTH_RADIUS_POLE * EARTH_RADIUS_POLE) / (EARTH_RADIUS_POLE * EARTH_RADIUS_POLE);
|
|
|
+ A = 1 + uSquared / 16384 * (4096 + uSquared * (-768 + uSquared * (320 - 175 * uSquared)));
|
|
|
+ B = uSquared / 1024 * (256 + uSquared * (-128 + uSquared * (74 - 47 * uSquared)));
|
|
|
+ deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
|
|
|
+ B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
|
|
|
+ lambdaP = lambda;
|
|
|
+ lambda = L + (1 - B) * FLATTENING * sinAlpha * (sigma + deltaSigma); // Use the flattening factor here
|
|
|
+ } while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);
|
|
|
+
|
|
|
+ if (iterLimit == 0) {
|
|
|
+ return 0.0; // formula failed to converge
|
|
|
+ }
|
|
|
+
|
|
|
+ double s = EARTH_RADIUS * (sigma - deltaSigma);
|
|
|
+
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Calculates the total length of the line string.
|
|
|
+ *
|
|
|
+ * @return The total length in meters.
|
|
|
+ */
|
|
|
+ public double getCalculateTotalLength() {
|
|
|
+ double totalLength = 0.0;
|
|
|
+ List<ElementCoordinate> coordinateList = convertToList();
|
|
|
+
|
|
|
+ for (int i = 0; i < coordinateList.size() - 1; i++) {
|
|
|
+ ElementCoordinate coord1 = coordinateList.get(i);
|
|
|
+ AMap aMap = CoordinateUtil.transform(coord1.getLongitude(),coord1.getLatitude());
|
|
|
+ coord1.setLongitude(aMap.getLongitude());
|
|
|
+ coord1.setLatitude(aMap.getLatitude());
|
|
|
+
|
|
|
+ ElementCoordinate coord2 = coordinateList.get(i + 1);
|
|
|
+ aMap = CoordinateUtil.transform(coord2.getLongitude(),coord2.getLatitude());
|
|
|
+ coord2.setLongitude(aMap.getLongitude());
|
|
|
+ coord2.setLatitude(aMap.getLatitude());
|
|
|
+
|
|
|
+ totalLength += calculateSegmentLengthVincenty(coord1, coord2);
|
|
|
+ }
|
|
|
+
|
|
|
+ return totalLength;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ ElementLineStringGeometry lineStringGeometry = new ElementLineStringGeometry();
|
|
|
+ AMap aMap = CoordinateUtil.transform(121.59529228016724, 31.2771648028396);
|
|
|
+ AMap aMap2 = CoordinateUtil.transform(121.55949257988347, 31.27563389661576);
|
|
|
+ AMap aMap3 = CoordinateUtil.transform(121.55866186357967, 31.27687211836336);
|
|
|
+ Double[][] coordinates = new Double[][]{
|
|
|
+ {aMap.getLongitude(),aMap.getLatitude()},
|
|
|
+ {aMap2.getLongitude(),aMap2.getLatitude()},
|
|
|
+ {aMap3.getLongitude(),aMap3.getLatitude()}
|
|
|
+// {121.59529228016724, 31.2771648028396},
|
|
|
+// {121.55949257988347, 31.27563389661576},
|
|
|
+// {121.55866186357967, 31.27687211836336}
|
|
|
+
|
|
|
+
|
|
|
+ };
|
|
|
+ lineStringGeometry.setCoordinates(coordinates);
|
|
|
+
|
|
|
+ double totalLength = lineStringGeometry.getCalculateTotalLength();
|
|
|
+ System.out.println("The total length of the line string is: " + totalLength + " meters");
|
|
|
+ }
|
|
|
+
|
|
|
}
|