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 ce6a4b3  Add a `GridGeometry.getEnvelope(CoordinateReferenceSystem)` 
method.
ce6a4b3 is described below

commit ce6a4b37eac2ad83e2b917cdb22aff18a5adaa6b
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Jan 19 17:10:09 2022 +0100

    Add a `GridGeometry.getEnvelope(CoordinateReferenceSystem)` method.
---
 .../org/apache/sis/coverage/grid/GridGeometry.java | 49 ++++++++++++++++++++++
 .../apache/sis/coverage/grid/GridGeometryTest.java | 36 +++++++++++++++-
 .../java/org/apache/sis/geometry/Envelopes.java    | 13 +++---
 3 files changed, 91 insertions(+), 7 deletions(-)

diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
index 79ae461..84b0402 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
@@ -34,6 +34,7 @@ import org.opengis.referencing.datum.PixelInCell;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.cs.CoordinateSystem;
@@ -79,6 +80,8 @@ import org.apache.sis.io.TableAppender;
 import org.apache.sis.xml.NilObject;
 import org.apache.sis.xml.NilReason;
 
+import static org.apache.sis.referencing.CRS.findOperation;
+
 
 /**
  * Valid extent of grid coordinates together with the transform from those 
grid coordinates
@@ -883,6 +886,52 @@ public class GridGeometry implements LenientComparable, 
Serializable {
     }
 
     /**
+     * Returns the "real world" bounding box of this grid geometry transformed 
to the given CRS.
+     * This envelope is computed from the {@linkplain #getExtent() grid 
extent} if available,
+     * or from the {@linkplain #getEnvelope() envelope} otherwise.
+     *
+     * @param  crs  the desired coordinate reference system for the returned 
envelope.
+     * @return the bounding box in "real world" coordinates (never {@code 
null}).
+     * @throws IncompleteGridGeometryException if this grid geometry has no 
extent and no envelope.
+     * @throws TransformException if the envelope can not be transformed to 
the specified CRS.
+     *
+     * @since 1.2
+     */
+    public Envelope getEnvelope(final CoordinateReferenceSystem crs) throws 
TransformException {
+        ArgumentChecks.ensureNonNull("crs", crs);
+        final int   bitmask;        // CRS, EXTENT or GRID_TO_CRS
+        final short errorKey;       // Resource key for error message.
+        final CoordinateReferenceSystem sourceCRS = 
getCoordinateReferenceSystem(envelope);
+        if (Utilities.equalsIgnoreMetadata(sourceCRS, crs)) {
+            return envelope;
+        } else if (sourceCRS == null) {
+            bitmask  = CRS;
+            errorKey = Resources.Keys.UnspecifiedCRS;
+        } else if (extent == null && envelope == null) {
+            bitmask  = EXTENT;
+            errorKey = Resources.Keys.UnspecifiedGridExtent;
+        } else if (cornerToCRS == null && envelope == null) {
+            bitmask  = GRID_TO_CRS;
+            errorKey = Resources.Keys.UnspecifiedTransform;
+        } else try {
+            final CoordinateOperation op = findOperation(sourceCRS, crs, 
geographicBBox());
+            final Envelope clip = (envelope != null) ? Envelopes.transform(op, 
envelope) : null;
+            if (extent == null || cornerToCRS == null) {
+                return clip;
+            }
+            MathTransform tr = MathTransforms.concatenate(cornerToCRS, 
op.getMathTransform());
+            final GeneralEnvelope env = extent.toCRS(tr, tr, clip);
+            env.setCoordinateReferenceSystem(op.getTargetCRS());
+            env.normalize();
+            env.intersect(clip);
+            return env;
+        } catch (FactoryException e) {
+            throw new TransformException(e);
+        }
+        throw incomplete(bitmask, errorKey);
+    }
+
+    /**
      * Returns the approximate latitude and longitude coordinates of the grid.
      * The prime meridian is Greenwich, but the geodetic reference frame is 
not necessarily WGS 84.
      * This is computed from the {@linkplain #getEnvelope() envelope} if the 
coordinate reference system
diff --git 
a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
 
b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
index b5929b9..c13bac0 100644
--- 
a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
+++ 
b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridGeometryTest.java
@@ -29,6 +29,7 @@ import org.apache.sis.referencing.operation.matrix.Matrix4;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
+import org.apache.sis.referencing.operation.HardCodedConversions;
 import org.apache.sis.referencing.crs.HardCodedCRS;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.test.DependsOn;
@@ -42,7 +43,7 @@ import static org.apache.sis.test.ReferencingAssert.*;
  * Tests the {@link GridGeometry} implementation.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 1.1
+ * @version 1.2
  * @since   1.0
  * @module
  */
@@ -433,6 +434,39 @@ public final strictfp class GridGeometryTest extends 
TestCase {
     }
 
     /**
+     * Tests {@link GridGeometry#getEnvelope(CoordinateReferenceSystem)}.
+     *
+     * @throws TransformException if coordinates can not be transformed.
+     */
+    @Test
+    public void testGetEnvelope() throws TransformException {
+        GridGeometry grid = new GridGeometry(
+                new GridExtent(12, 18),
+                PixelInCell.CELL_CORNER,
+                MathTransforms.linear(new Matrix3(
+                    0.25, 0,    -2,
+                    0,   -0.25, -3,
+                    0,    0,     1)),
+                HardCodedCRS.WGS84);
+
+        Envelope envelope = grid.getEnvelope(HardCodedCRS.WGS84);
+        assertSame(envelope, grid.getEnvelope());
+        assertEnvelopeEquals(new GeneralEnvelope(
+                new double[] {-2, -7.5},
+                new double[] { 1, -3.0}), envelope, STRICT);
+
+        envelope = grid.getEnvelope(HardCodedCRS.WGS84_LATITUDE_FIRST);
+        assertEnvelopeEquals(new GeneralEnvelope(
+                new double[] {-7.5, -2},
+                new double[] {-3.0,  1}), envelope, STRICT);
+
+        envelope = grid.getEnvelope(HardCodedConversions.mercator());
+        assertEnvelopeEquals(new GeneralEnvelope(
+                new double[] {-222638.98, -831717.36},
+                new double[] { 111319.49, -331876.53}), envelope, 0.01);
+    }
+
+    /**
      * Tests {@link GridGeometry#translate(long...)}.
      */
     @Test
diff --git 
a/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java 
b/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java
index 5d318bb..9a44839 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java
@@ -48,6 +48,7 @@ import 
org.apache.sis.internal.referencing.CoordinateOperations;
 import org.apache.sis.internal.referencing.DirectPositionView;
 import org.apache.sis.internal.referencing.TemporalAccessor;
 import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
@@ -758,7 +759,7 @@ nextPoint:  for (int pointIndex = 0;;) {                // 
Break condition at th
         long isWrapAroundAxis = 0;
         final int dimension = targetCS.getDimension();
 poles:  for (int i=0; i<dimension; i++) {
-            final long dimensionBitMask = 1L << i;
+            final long dimensionBitMask = Numerics.bitmask(i);
             final CoordinateSystemAxis axis = targetCS.getAxis(i);
             if (axis == null) {                 // Should never be null, but 
check as a paranoiac safety.
                 continue;
@@ -857,7 +858,7 @@ poles:  for (int i=0; i<dimension; i++) {
         if (includedBoundsValue != 0) {
             while (isWrapAroundAxis != 0) {
                 final int wrapAroundDimension = 
Long.numberOfTrailingZeros(isWrapAroundAxis);
-                final long dimensionBitMask = 1L << wrapAroundDimension;
+                final long dimensionBitMask = 
Numerics.bitmask(wrapAroundDimension);
                 isWrapAroundAxis &= ~dimensionBitMask;              // Clear 
now the bit, for the next iteration.
                 final CoordinateSystemAxis wrapAroundAxis = 
targetCS.getAxis(wrapAroundDimension);
                 final double min = wrapAroundAxis.getMinimumValue();
@@ -937,7 +938,7 @@ poles:  for (int i=0; i<dimension; i++) {
          * the [-180 … +180]° range and the target CRS uses the [0 … 360]° 
range, or the converse. We do not wrap
          * around if the source and target axes use the same range (e.g. the 
longitude stay [-180 … +180]°) in order
          * to reduce the risk of discontinuities. If the user really wants 
unconditional wrap around, (s)he can call
-         * GeneralEnvelope.normalize().
+         * `GeneralEnvelope.normalize()`.
          */
         final Set<Integer> wrapAroundChanges;
         if (isOperationComplete && operation instanceof 
AbstractCoordinateOperation) {
@@ -958,16 +959,16 @@ poles:  for (int i=0; i<dimension; i++) {
      * that every points in a {@code LINESTRING} have the same dimension. 
However this method
      * ensures that the parenthesis are balanced, in order to catch some 
malformed WKT.
      *
-     * <p>Example:</p>
+     * <div class="note"><b>Examples:</b>
      * <ul>
      *   <li>{@code BOX(-180 -90, 180 90)} (not really a geometry, but 
understood by many software products)</li>
      *   <li>{@code POINT(6 10)}</li>
      *   <li>{@code MULTIPOLYGON(((1 1, 5 1, 1 5, 1 1),(2 2, 3 2, 3 3, 2 
2)))}</li>
      *   <li>{@code GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(3 8,7 10))}</li>
      * </ul>
+     * </div>
      *
-     * See {@link GeneralEnvelope#GeneralEnvelope(CharSequence)} for more 
information about the
-     * parsing rules.
+     * See {@link GeneralEnvelope#GeneralEnvelope(CharSequence)} for more 
information about the parsing rules.
      *
      * @param  wkt  the {@code BOX}, {@code POLYGON} or other kind of element 
to parse.
      * @return the envelope of the given geometry.

Reply via email to