paleolimbot commented on code in PR #2051:
URL: https://github.com/apache/sedona/pull/2051#discussion_r2192520998


##########
common/src/main/java/org/apache/sedona/common/S2Geography/Accessors.java:
##########
@@ -0,0 +1,294 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sedona.common.S2Geography;
+
+import com.google.common.geometry.*;
+
+public class Accessors {
+
+  public Accessors() {}
+
+  public boolean S2_isEmpty(S2Geography s2Geography) {
+    for (int i = 0; i < s2Geography.numShapes(); i++) {
+      S2Shape shape = s2Geography.shape(i);
+      if (!shape.isEmpty()) return false;
+    }
+    return true;
+  }
+
+  public boolean S2_isCollection(PolygonGeography polygonGeography) {
+    int numOuterLoops = 0;
+    for (int i = 0; i < polygonGeography.polygon.numLoops(); i++) {
+      S2Loop loop = polygonGeography.polygon.loop(i);
+      if (loop.depth() == 0 && ++numOuterLoops > 10) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Returns true if `geog` is a “collection” (i.e. multi‐point, 
multi‐linestring, or multi‐polygon)
+   * rather than a single simple feature.
+   */
+  public boolean s2IsCollection(S2Geography geog) {
+    int dim = S2_dimension(geog);
+    if (dim == -1) {
+      return false;
+    }
+
+    switch (dim) {
+      case 0:
+        // point‐collection if more than one point
+        return S2_numPoints(geog) > 1;
+
+      case 1:
+        // multi‐linestring: more than one chain across all shapes
+        int chainCount = 0;
+        for (int i = 0, n = geog.numShapes(); i < n; ++i) {
+          S2Shape shape = geog.shape(i);
+          chainCount += shape.numChains();
+          if (chainCount > 1) {
+            return true;
+          }
+        }
+        return false;
+
+      default:
+        {
+          // polygons (or mixed): delegate to the polygon routine
+          if (geog instanceof PolygonGeography) {
+            return S2_isCollection((PolygonGeography) geog);
+          }
+          // not yet a PolygonGeography → build one, then test
+          // TODO:build
+          //        PolygonGeography built = S2Builder.buildPolygon(geog);
+          //        return isCollection(built);
+        }
+    }
+    return false;
+  }
+
+  public int S2_dimension(S2Geography s2Geography) {
+    int dimension = s2Geography.dimension();
+    if (dimension != -1) return dimension;
+
+    for (int i = 0; i < s2Geography.numShapes(); i++) {
+      S2Shape shape = s2Geography.shape(i);
+      if (shape.dimension() > dimension) dimension = shape.dimension();
+    }
+    return dimension;
+  }
+
+  public int S2_numPoints(S2Geography s2Geography) {
+    int numPoints = 0;
+    for (int i = 0; i < s2Geography.numShapes(); i++) {
+      S2Shape shape = s2Geography.shape(i);
+      switch (shape.dimension()) {
+        case 0:
+        case 2:
+          numPoints += shape.numEdges();
+          break;
+        case 1:
+          numPoints += shape.numEdges() + shape.numChains();
+          break;
+      }
+    }
+    return numPoints;
+  }
+
+  double S2_area(S2Geography geog) {
+    if (S2_dimension(geog) != 2) return 0;
+
+    switch (geog.kind) {
+      case POLYGON:
+        if (geog != null) return S2_area((PolygonGeography) geog);
+      case GEOGRAPHY_COLLECTION:
+        if (geog != null) return S2_area((GeographyCollection) geog);
+    }
+    // TODO: build
+    return 0;

Review Comment:
   The Area operation is one of the things that we absolutely need an 
`S2Polygon` instance for (i.e., not just shapes), so if somebody calls 
`s2_area()` on a (e.g.) ShapeIndexGeography the downcasts would fail. We can 
also throw here since we can ensure this doesn't happen when you implement 
st_area.



-- 
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]

Reply via email to