jiayuasu commented on code in PR #2831:
URL: https://github.com/apache/sedona/pull/2831#discussion_r3104407590
##########
common/src/main/java/org/apache/sedona/common/geography/Functions.java:
##########
@@ -75,14 +71,91 @@ private static S2Polygon rectToPolygon(double lngLo, double
latLo, double lngHi,
v.add(S2LatLng.fromDegrees(latHi, lngLo).toPoint());
S2Loop loop = new S2Loop(v);
- // Optional: normalize for canonical orientation (keeps the smaller-area
side)
loop.normalize();
return new S2Polygon(loop);
}
+ // ─── Level 1: JTS-only structural operations ─────────────────────────────
+
+ /** Return the number of points in a geography. */
+ public static int nPoints(Geography g) {
+ if (g == null) return 0;
+ return toJTS(g).getNumPoints();
+ }
+
+ // ─── Level 2: JTS + S2 geodesic metrics ──────────────────────────────────
+
+ /**
+ * Geometry-to-geometry geodesic distance in meters. Uses S2ClosestEdgeQuery
for true minimum
+ * distance between any two points on the geometries (not
centroid-to-centroid). Consistent with
+ * sedona-db's s2_distance implementation.
+ */
+ public static Double distance(Geography g1, Geography g2) {
+ if (g1 == null || g2 == null) return null;
+ if (g1 instanceof WKBGeography && g2 instanceof WKBGeography) {
+ WKBGeography w1 = (WKBGeography) g1;
+ WKBGeography w2 = (WKBGeography) g2;
+ // Fast path: point-to-point distance without building ShapeIndex
+ if (w1.isPoint() && w2.isPoint()) {
+ S1Angle angle = new S1Angle(w1.extractPoint(), w2.extractPoint());
+ return angle.radians() * EARTH_RADIUS_METERS;
+ }
+ // Fast path: point-to-complex uses PointTarget (avoids building
ShapeIndex for point side)
+ if (w1.isPoint()) {
+ double radians = Distance.S2_distancePointToIndex(w1.extractPoint(),
toShapeIndex(w2));
+ return radiansToMeters(radians);
+ }
+ if (w2.isPoint()) {
+ double radians = Distance.S2_distancePointToIndex(w2.extractPoint(),
toShapeIndex(w1));
+ return radiansToMeters(radians);
+ }
+ }
+ // General path via ShapeIndex
+ Distance dist = new Distance();
+ double radians = dist.S2_distance(toShapeIndex(g1), toShapeIndex(g2));
+ return radiansToMeters(radians);
+ }
+
+ // ─── Level 3: S2 spherical predicates ────────────────────────────────────
+
+ /** Spherical containment test using S2 boolean operations. */
+ public static boolean contains(Geography g1, Geography g2) {
+ if (g1 == null || g2 == null) return false;
+ // A point (dimension 0) cannot contain anything
+ if (g1.dimension() == 0) return false;
+
+ Predicates pred = new Predicates();
+ return pred.S2_contains(toShapeIndex(g1), toShapeIndex(g2), s2Options());
+ }
+
/** Return EWKT for geography object */
public static String asEWKT(Geography geography) {
return geography.toEWKT();
}
+
+ // ─── Helpers
───────────────────────────────────────────────────────────────
+
+ private static Geometry toJTS(Geography g) {
+ if (g instanceof WKBGeography) return ((WKBGeography) g).getJTSGeometry();
+ return Constructors.geogToGeometry(g);
+ }
+
+ private static ShapeIndexGeography toShapeIndex(Geography g) {
+ if (g instanceof WKBGeography) {
+ return ((WKBGeography) g).getShapeIndexGeography();
+ }
+ return new ShapeIndexGeography(g);
+ }
+
+ private static S2BooleanOperation.Options s2Options() {
+ return new S2BooleanOperation.Options();
+ }
+
+ /** Mean Earth radius in meters (WGS84 mean radius). */
+ private static final double EARTH_RADIUS_METERS = 6371008.8;
Review Comment:
There is another place in Sedona codebase (Distance Spheroid / Sphere) also
hard code the value of earth radius. can you unify them together?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]