@@ -127,6 +127,32 @@ public static double distance(Line line) {
127
127
return distance (line .startPoint (), line .endPoint ());
128
128
}
129
129
130
+ /**
131
+ * Get the distance in meters between two points in degrees using the
132
+ * Haversine formula
133
+ *
134
+ * @param point1
135
+ * point 1
136
+ * @param point2
137
+ * point 2
138
+ * @return distance in meters
139
+ * @since 2.2.2
140
+ */
141
+ public static double distanceHaversine (Point point1 , Point point2 ) {
142
+ double lat1 = point1 .getY ();
143
+ double lon1 = point1 .getX ();
144
+ double lat2 = point2 .getY ();
145
+ double lon2 = point2 .getX ();
146
+ double diffLat = degreesToRadians (lat2 - lat1 );
147
+ double diffLon = degreesToRadians (lon2 - lon1 );
148
+ double a = Math .sin (diffLat / 2 ) * Math .sin (diffLat / 2 )
149
+ + Math .cos (degreesToRadians (lat1 ))
150
+ * Math .cos (degreesToRadians (lat2 ))
151
+ * Math .sin (diffLon / 2 ) * Math .sin (diffLon / 2 );
152
+ double c = 2 * Math .atan2 (Math .sqrt (a ), Math .sqrt (1 - a ));
153
+ return GeometryConstants .EARTH_RADIUS * c ;
154
+ }
155
+
130
156
/**
131
157
* Get the bearing heading in degrees between two points in degrees
132
158
*
@@ -147,6 +173,52 @@ public static double bearing(Point point1, Point point2) {
147
173
return (radiansToDegrees (Math .atan2 (y , x )) + 360 ) % 360 ;
148
174
}
149
175
176
+ /**
177
+ * Get the geodesic midpoint in degrees between two points in degrees
178
+ *
179
+ * @param point1
180
+ * point 1
181
+ * @param point2
182
+ * point 2
183
+ * @return geodesic midpoint in degrees
184
+ * @since 2.2.2
185
+ */
186
+ public static Point geodesicMidpoint (Point point1 , Point point2 ) {
187
+ Point point1Radians = degreesToRadians (point1 );
188
+ Point point2Radians = degreesToRadians (point2 );
189
+ Point midpointRadians = geodesicMidpointRadians (point1Radians ,
190
+ point2Radians );
191
+ return radiansToDegrees (midpointRadians );
192
+ }
193
+
194
+ /**
195
+ * Get the geodesic midpoint in radians between two points in radians
196
+ *
197
+ * @param point1
198
+ * point 1
199
+ * @param point2
200
+ * point 2
201
+ * @return geodesic midpoint in radians
202
+ * @since 2.2.2
203
+ */
204
+ public static Point geodesicMidpointRadians (Point point1 , Point point2 ) {
205
+
206
+ double xDiff = point2 .getX () - point1 .getX ();
207
+ double y1 = point1 .getY ();
208
+ double y2 = point2 .getY ();
209
+ double x1 = point1 .getX ();
210
+
211
+ double bx = Math .cos (y2 ) * Math .cos (xDiff );
212
+ double by = Math .cos (y2 ) * Math .sin (xDiff );
213
+
214
+ double y = Math .atan2 (Math .sin (y1 ) + Math .sin (y2 ),
215
+ Math .sqrt ((Math .cos (y1 ) + bx ) * (Math .cos (y1 ) + bx ) + by * by ));
216
+ double x = x1 + Math .atan2 (by , Math .cos (y1 ) + bx );
217
+ Point midpoint = new Point (x , y );
218
+
219
+ return midpoint ;
220
+ }
221
+
150
222
/**
151
223
* Get the bearing heading in degrees between line end points in degrees
152
224
*
@@ -238,6 +310,34 @@ public static double radiansToDegrees(double radians) {
238
310
return radians * GeometryConstants .RADIANS_TO_DEGREES ;
239
311
}
240
312
313
+ /**
314
+ * Convert point in degrees to radians
315
+ *
316
+ * @param point
317
+ * point in degrees
318
+ * @return point in radians
319
+ * @since 2.2.2
320
+ */
321
+ public static Point degreesToRadians (Point point ) {
322
+ double x = degreesToRadians (point .getX ());
323
+ double y = degreesToRadians (point .getY ());
324
+ return new Point (x , y );
325
+ }
326
+
327
+ /**
328
+ * Convert point in radians to degrees
329
+ *
330
+ * @param point
331
+ * point in radians
332
+ * @return point in degrees
333
+ * @since 2.2.2
334
+ */
335
+ public static Point radiansToDegrees (Point point ) {
336
+ double x = radiansToDegrees (point .getX ());
337
+ double y = radiansToDegrees (point .getY ());
338
+ return new Point (x , y );
339
+ }
340
+
241
341
/**
242
342
* Get the centroid point of a 2 dimensional representation of the Geometry
243
343
* (balancing point of a 2d cutout of the geometry). Only the x and y
@@ -883,6 +983,127 @@ private static List<Point> simplifyPoints(List<Point> points,
883
983
return result ;
884
984
}
885
985
986
+ /**
987
+ * Create a geodesic path of a line string in degrees with a max distance
988
+ * between any two path points
989
+ *
990
+ * @param lineString
991
+ * line string in degrees
992
+ * @param maxDistance
993
+ * max distance allowed between path points
994
+ * @return geodesic path of points
995
+ * @since 2.2.2
996
+ */
997
+ public static List <Point > geodesicPath (LineString lineString ,
998
+ double maxDistance ) {
999
+ return geodesicPath (lineString .getPoints (), maxDistance );
1000
+ }
1001
+
1002
+ /**
1003
+ * Create a geodesic path of a points in degrees with a max distance between
1004
+ * any two path points
1005
+ *
1006
+ * @param points
1007
+ * points in degrees
1008
+ * @param maxDistance
1009
+ * max distance allowed between path points
1010
+ * @return geodesic path of points
1011
+ * @since 2.2.2
1012
+ */
1013
+ public static List <Point > geodesicPath (List <Point > points ,
1014
+ double maxDistance ) {
1015
+ List <Point > path = new ArrayList <>();
1016
+ if (!points .isEmpty ()) {
1017
+ path .add (points .get (0 ));
1018
+ for (int i = 0 ; i < points .size () - 1 ; i ++) {
1019
+ List <Point > subPath = geodesicPath (points .get (i ),
1020
+ points .get (i + 1 ), maxDistance );
1021
+ path .addAll (subPath .subList (1 , subPath .size ()));
1022
+ }
1023
+ }
1024
+ return path ;
1025
+ }
1026
+
1027
+ /**
1028
+ * Create a geodesic path between the two points in degrees with a max
1029
+ * distance between any two path points
1030
+ *
1031
+ * @param point1
1032
+ * point 1
1033
+ * @param point2
1034
+ * point 2
1035
+ * @param maxDistance
1036
+ * max distance allowed between path points
1037
+ * @return geodesic path of points
1038
+ * @since 2.2.2
1039
+ */
1040
+ public static List <Point > geodesicPath (Point point1 , Point point2 ,
1041
+ double maxDistance ) {
1042
+ List <Point > path = new ArrayList <>();
1043
+ path .add (point1 );
1044
+ geodesicPath (point1 , point2 , maxDistance , path );
1045
+ path .add (point2 );
1046
+ return path ;
1047
+ }
1048
+
1049
+ /**
1050
+ * Populate a geodesic path between the two points in degrees with a max
1051
+ * distance between any two path points
1052
+ *
1053
+ * @param point1
1054
+ * point 1
1055
+ * @param point2
1056
+ * point 2
1057
+ * @param maxDistance
1058
+ * max distance allowed between path points
1059
+ * @param path
1060
+ * geodesic path of points
1061
+ */
1062
+ private static void geodesicPath (Point point1 , Point point2 ,
1063
+ double maxDistance , List <Point > path ) {
1064
+ double distance = distanceHaversine (point1 , point2 );
1065
+ if (distance > maxDistance ) {
1066
+ Point midpoint = geodesicMidpoint (point1 , point2 );
1067
+ geodesicPath (point1 , midpoint , maxDistance , path );
1068
+ path .add (midpoint );
1069
+ geodesicPath (midpoint , point2 , maxDistance , path );
1070
+ }
1071
+ }
1072
+
1073
+ /**
1074
+ * Expand the vertical bounds of a geometry envelope in degrees by including
1075
+ * geodesic bounds
1076
+ *
1077
+ * @param envelope
1078
+ * geometry envelope in degrees
1079
+ * @return geodesic expanded geometry envelope in degrees
1080
+ * @since 2.2.2
1081
+ */
1082
+ public static GeometryEnvelope geodesicEnvelope (GeometryEnvelope envelope ) {
1083
+ GeometryEnvelope geodesic = envelope .copy ();
1084
+ if (envelope .getMinY () < 0 ) {
1085
+ Point left = envelope .getBottomLeft ();
1086
+ Point right = envelope .getBottomRight ();
1087
+ Point midpoint = geodesicMidpoint (left , right );
1088
+ double y = midpoint .getY ();
1089
+ if (y < geodesic .getMinY ()) {
1090
+ geodesic .setMinY (y );
1091
+ }
1092
+
1093
+ }
1094
+ if (envelope .getMaxY () > 0 ) {
1095
+ Point left = envelope .getTopLeft ();
1096
+ Point right = envelope .getTopRight ();
1097
+ Point midpoint = geodesicMidpoint (left , right );
1098
+ double y = midpoint .getY ();
1099
+ if (y > geodesic .getMaxY ()) {
1100
+ geodesic .setMaxY (y );
1101
+ }
1102
+
1103
+ }
1104
+ return geodesic ;
1105
+ }
1106
+
886
1107
/**
887
1108
* Calculate the perpendicular distance between the point and the line
888
1109
* represented by the start and end points. Points should be in a meters
0 commit comments