sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: Deprecate DistanceUtils, replaced by GeodeticCalculator. Current version implements only spherical formulas, but DistanceUtils was using spherical formulas too. This commit resolves https://issues.apache.org/jira/browse/SIS-385 The use of ellipsoidal formulas instead than spherical will be a separated issue.
Date Sat, 11 May 2019 21:41:08 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 23fbd3d  Deprecate DistanceUtils, replaced by GeodeticCalculator. Current version
implements only spherical formulas, but DistanceUtils was using spherical formulas too. This
commit resolves https://issues.apache.org/jira/browse/SIS-385 The use of ellipsoidal formulas
instead than spherical will be a separated issue.
23fbd3d is described below

commit 23fbd3dcde848559bf21a071686ac6f767dd863d
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Sat May 11 23:36:32 2019 +0200

    Deprecate DistanceUtils, replaced by GeodeticCalculator. Current version implements only
spherical formulas, but DistanceUtils was using spherical formulas too.
    This commit resolves https://issues.apache.org/jira/browse/SIS-385
    The use of ellipsoidal formulas instead than spherical will be a separated issue.
---
 .../org/apache/sis/services/LocationServlet.java   | 26 ++++++----
 .../org/apache/sis/distance/DistanceUtils.java     | 12 +++--
 .../org/apache/sis/distance/LatLonPointRadius.java | 58 ++++++++++++++--------
 .../java/org/apache/sis/index/tree/QuadTree.java   | 30 +++++------
 4 files changed, 78 insertions(+), 48 deletions(-)

diff --git a/application/sis-webapp/src/main/java/org/apache/sis/services/LocationServlet.java
b/application/sis-webapp/src/main/java/org/apache/sis/services/LocationServlet.java
index b24e096..df4533d 100644
--- a/application/sis-webapp/src/main/java/org/apache/sis/services/LocationServlet.java
+++ b/application/sis-webapp/src/main/java/org/apache/sis/services/LocationServlet.java
@@ -50,15 +50,19 @@ import org.w3c.dom.NodeList;
 import org.w3c.dom.Text;
 import org.xml.sax.SAXException;
 
+import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.operation.TransformException;
+
 //SIS imports
 import org.apache.sis.geometry.DirectPosition2D;
 import org.apache.sis.geometry.Envelope2D;
-import org.apache.sis.distance.DistanceUtils;
 import org.apache.sis.index.tree.GeoRSSData;
 import org.apache.sis.index.tree.QuadTree;
 import org.apache.sis.index.tree.QuadTreeData;
 import org.apache.sis.index.tree.QuadTreeReader;
 import org.apache.sis.index.tree.QuadTreeWriter;
+import org.apache.sis.referencing.GeodeticCalculator;
+import org.apache.sis.referencing.CommonCRS;
 
 //ROME imports
 import com.sun.syndication.feed.WireFeed;
@@ -157,8 +161,7 @@ public class LocationServlet extends HttpServlet {
             depth = Integer.parseInt(depthNode.item(0).getFirstChild()
                 .getNodeValue());
           }
-          this.tree = new QuadTree(capacity, depth); // TODO make this
-          // configurable
+          this.tree = new QuadTree(capacity, depth); // TODO make this configurable
 
           NodeList urlNodes = configDoc.getElementsByTagName("url");
           for (int i = 0; i < urlNodes.getLength(); i++) {
@@ -303,15 +306,20 @@ public class LocationServlet extends HttpServlet {
         }
 
         double radiusKM = Double.parseDouble(radius);
+        final GeodeticCalculator calculator = GeodeticCalculator.create(CommonCRS.SPHERE.geographic());
+        calculator.setStartPoint(point.y, point.x);
 
-        String regionStr = "";
+        StringBuilder regionStr = new StringBuilder();
 
-        for (int i = 0; i < 360; i += 10) {
-          DirectPosition2D pt = DistanceUtils.getPointOnGreatCircle(point.y, point.x, radiusKM,
i);
-          regionStr += pt.y + "," + pt.x + ",";
+        try {
+          for (int i = 0; i <= 360; i += 10) {
+            calculator.setDirection(i, radiusKM);
+            DirectPosition pt = calculator.getEndPoint();
+            regionStr.append(pt.getOrdinate(1)).append(',').append(pt.getOrdinate(0)).append(',');
+          }
+        } catch (TransformException e) {
+          throw new ServletException(e);            // Should never happen.
         }
-        DirectPosition2D pt = DistanceUtils.getPointOnGreatCircle(point.y, point.x, radiusKM,
0);
-        regionStr += pt.y + "," + pt.x + ",";
         regions.add(regionStr.substring(0, regionStr.length() - 1));
 
         beforeTime = System.currentTimeMillis();
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/distance/DistanceUtils.java
b/core/sis-referencing/src/main/java/org/apache/sis/distance/DistanceUtils.java
index 2052010..4bd20f0 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/distance/DistanceUtils.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/distance/DistanceUtils.java
@@ -16,17 +16,15 @@
  */
 package org.apache.sis.distance;
 
-// SIS imports
 import org.apache.sis.geometry.DirectPosition2D;
 
 /**
  * Class to calculate distances on earth surface. Actual calculation code very
  * similar to Apache SIS but refractor to allow use of custom classes.
  *
- * <div class="warning"><b>Warning:</b> This class may change in a future
SIS version. Current implementation
- * performs computations on a sphere of hard-coded radius. A future implementation should
perform computations
- * on a given ellipsoid.</div>
+ * @deprecated Replaced by {@link org.apache.sis.referencing.GeodeticCalculator}.
  */
+@Deprecated
 public final class DistanceUtils {
   private DistanceUtils() {
   }
@@ -46,7 +44,10 @@ public final class DistanceUtils {
    * @param bearing
    *          the great circle bearing
    * @return a coordinate at the specified bearing
+   *
+   * @deprecated Replaced by {@link org.apache.sis.referencing.GeodeticCalculator#getEndPoint()}.
    */
+  @Deprecated
   public static DirectPosition2D getPointOnGreatCircle(double latitude, double longitude,
       double d, double bearing) {
     double angularDistance = d / EARTH_RADIUS;
@@ -82,7 +83,10 @@ public final class DistanceUtils {
    * @param longitude2
    *          longitude of second coordinate
    * @return great circle distance between specified lat/lon coordinates
+   *
+   * @deprecated Replaced by {@link org.apache.sis.referencing.GeodeticCalculator#getGeodesicDistance()}.
    */
+  @Deprecated
   public static double getHaversineDistance(double latitude1,
       double longitude1, double latitude2, double longitude2) {
     double longRadian1 = Math.toRadians(longitude1);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/distance/LatLonPointRadius.java
b/core/sis-referencing/src/main/java/org/apache/sis/distance/LatLonPointRadius.java
index e992cb7..74b0cab 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/distance/LatLonPointRadius.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/distance/LatLonPointRadius.java
@@ -24,10 +24,13 @@ import java.awt.geom.Rectangle2D;
 
 // GeoAPI import
 import org.opengis.geometry.DirectPosition;
+import org.opengis.referencing.operation.TransformException;
 
 //SIS imports
 import org.apache.sis.geometry.DirectPosition2D;
 import org.apache.sis.measure.Longitude;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.referencing.GeodeticCalculator;
 
 /**
  * Represents a 2D point associated with a radius to enable great circle
@@ -79,10 +82,18 @@ public class LatLonPointRadius {
     double bearingIncrement = 0;
     if (numberOfPoints > 0) { bearingIncrement = 360/numberOfPoints; }
 
-    for (int i = 0; i < numberOfPoints; i++)
-    {
-      points[i] = DistanceUtils.getPointOnGreatCircle(center.getOrdinate(1),
-          center.getOrdinate(0), radius, i * bearingIncrement);
+    final GeodeticCalculator calculator = GeodeticCalculator.create(CommonCRS.SPHERE.geographic());
+    calculator.setStartPoint(center.getOrdinate(1), center.getOrdinate(0));
+
+    try {
+      for (int i = 0; i < numberOfPoints; i++)
+      {
+        calculator.setDirection(i * bearingIncrement, radius);
+        DirectPosition p = calculator.getEndPoint();
+        points[i] = new DirectPosition2D(p.getOrdinate(1), p.getOrdinate(0));
+      }
+    } catch (TransformException e) {
+      throw new IllegalStateException(e);       // Should never happen.
     }
 
     points[numberOfPoints] = points[0];
@@ -103,28 +114,33 @@ public class LatLonPointRadius {
     }
     int numberOfCrossOvers = 0;
 
-    Path2D path = new Path2D.Double();
-    DirectPosition2D initPT = DistanceUtils.getPointOnGreatCircle(center.getOrdinate(1),
-        center.getOrdinate(0), radius, 0);
-    path.moveTo(initPT.x + 180.0, initPT.y + 90.0);
-
-    DirectPosition2D currPT = initPT;
+    final GeodeticCalculator calculator = GeodeticCalculator.create(CommonCRS.SPHERE.geographic());
+    calculator.setStartPoint(center.getOrdinate(1), center.getOrdinate(0));
 
-    for (int i = 1; i < 360; i++) {
-
-      DirectPosition2D pt = DistanceUtils.getPointOnGreatCircle(center.getOrdinate(1),
-          center.getOrdinate(0), radius, i);
-      path.lineTo(pt.x + 180.0, pt.y + 90.0);
-
-      if (dateLineCrossOver(Longitude.normalize(currPT.x), Longitude.normalize(pt.x))) {
-        numberOfCrossOvers++;
+    Path2D path = new Path2D.Double();
+    double initX = Double.NaN, previousX = Double.NaN;
+    try {
+      for (int i = 0; i < 360; i++) {
+        calculator.setDirection(i, radius);
+        DirectPosition pt = calculator.getEndPoint();
+        double x = pt.getOrdinate(1) + 180.0;
+        double y = pt.getOrdinate(0) + 90.0;
+        if (i == 0) {
+          initX = Longitude.normalize(x);
+          path.moveTo(x, y);
+        } else {
+          path.lineTo(x, y);
+          if (dateLineCrossOver(previousX, previousX = Longitude.normalize(x))) {
+            numberOfCrossOvers++;
+          }
+        }
       }
-      currPT = pt;
+    } catch (TransformException e) {
+      throw new IllegalStateException(e);       // Should never happen.
     }
-    if (dateLineCrossOver(Longitude.normalize(initPT.x), Longitude.normalize(currPT.x)))
{
+    if (dateLineCrossOver(previousX, initX)) {
       numberOfCrossOvers++;
     }
-
     /**
      * If the path crosses the dateline once, it's a special case, so take care
      * of it differently. It will need to include areas around the pole.
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/index/tree/QuadTree.java b/storage/sis-storage/src/main/java/org/apache/sis/index/tree/QuadTree.java
index 5cb1b53..855e8ba 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/index/tree/QuadTree.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/index/tree/QuadTree.java
@@ -16,16 +16,15 @@
  */
 package org.apache.sis.index.tree;
 
-//JDK imports
 import java.awt.geom.Rectangle2D;
 import java.util.ArrayList;
 import java.util.List;
 
-//SIS imports
 import org.apache.sis.geometry.DirectPosition2D;
 import org.apache.sis.geometry.Envelope2D;
-import org.apache.sis.distance.DistanceUtils;
 import org.apache.sis.distance.LatLonPointRadius;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.referencing.GeodeticCalculator;
 
 /**
  * Implementation of Quad Tree Index. Insertion algorithm implemented based on
@@ -48,13 +47,15 @@ public class QuadTree {
     private static final double[] xf = new double[] { -0.25, 0.25, -0.25, 0.25 };
     private static final double[] yf = new double[] { 0.25, 0.25, -0.25, -0.25 };
 
-    private QuadTreeNode root;
+    private final QuadTreeNode root;
     private int size;
     private int nodeSize;
 
     private int maxDepth;
     private int capacity;
 
+    private final GeodeticCalculator calculator;
+
     /**
      * Creates a quad tree.
      *
@@ -64,11 +65,9 @@ public class QuadTree {
      *            the maximum depth of the tree
      */
     public QuadTree(int capacity, int maxDepth) {
-        this.size = 0;
-        this.nodeSize = 0;
+        this();
         this.capacity = capacity;
         this.maxDepth = maxDepth;
-        this.root = new QuadTreeNode(NodeType.GRAY, this.nodeSize);
     }
 
     /**
@@ -76,11 +75,8 @@ public class QuadTree {
      * set the capacity and depth after quad tree construction.
      */
     public QuadTree() {
-        this.size = 0;
-        this.nodeSize = 0;
-        this.capacity = 0;
-        this.maxDepth = 0;
-        this.root = new QuadTreeNode(NodeType.GRAY, this.nodeSize);
+        root = new QuadTreeNode(NodeType.GRAY, this.nodeSize);
+        calculator = GeodeticCalculator.create(CommonCRS.SPHERE.geographic());
     }
 
     /**
@@ -351,8 +347,14 @@ public class QuadTree {
             else {
                 QuadTreeData[] data = node.getData();
                 for (int i = 0; i < node.getCount(); i++) {
-                    if (DistanceUtils.getHaversineDistance(data[i].getLatLon().y, data[i].getLatLon().x,
point.y,
-                            point.x) <= radiusKM) {
+                    DirectPosition2D latLon = data[i].getLatLon();
+                    double distance;
+                    synchronized (calculator) {
+                        calculator.setStartPoint(latLon.y, latLon.x);
+                        calculator.setEndPoint(point.y, point.x);
+                        distance = calculator.getGeodesicDistance();
+                    }
+                    if (distance <= radiusKM) {
                         matches.add(data[i]);
                     }
                 }


Mime
View raw message