sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 01/02: Add a GridGeometry(GridGeometry, GridExtent) constructor, un-deprecate DefaultTemporalCRS methods working on java.util.Date and adjust javadoc.
Date Thu, 13 Dec 2018 18:02:07 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

commit 3ebb5515528b3d21631aee867efa2ae631ba86ec
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Thu Dec 13 16:45:57 2018 +0100

    Add a GridGeometry(GridGeometry, GridExtent) constructor, un-deprecate DefaultTemporalCRS
methods working on java.util.Date and adjust javadoc.
---
 .../org/apache/sis/coverage/grid/GridCoverage.java |  4 +-
 .../org/apache/sis/coverage/grid/GridGeometry.java | 75 +++++++++++++++++-----
 .../sis/referencing/crs/DefaultTemporalCRS.java    | 73 +++++++++++----------
 3 files changed, 101 insertions(+), 51 deletions(-)

diff --git a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
index d9eef03..64eaa1c 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
+++ b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
@@ -108,8 +108,8 @@ public abstract class GridCoverage {
     /**
      * Returns a two-dimensional slice of grid data as a rendered image. The given {@code
slicePoint} argument specifies
      * the coordinates of the slice in all dimensions that are not in the two-dimensional
image. For example if this grid
-     * coverage has (<var>x</var>, <var>y</var>, <var>z</var>,
<var>t</var>) dimensions and we want a rendered image of
-     * data in the (<var>x</var>, <var>y</var>) dimensions, then
the given {@code slicePoint} shall contain the
+     * coverage has (<var>x</var>, <var>y</var>, <var>z</var>,
<var>t</var>) dimensions and we want to render an image
+     * of data in the (<var>x</var>, <var>y</var>) dimensions, then
the given {@code slicePoint} shall contain the
      * (<var>z</var>, <var>t</var>) coordinates of the desired slice.
The two coordinates of the data to be shown
      * (<var>x</var> and <var>y</var> in our example) shall be excluded
from the slice point in one of the following ways:
      *
diff --git a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
index aa8a5ca..9a11914 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
+++ b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridGeometry.java
@@ -80,7 +80,7 @@ import static org.apache.sis.referencing.CRS.findOperation;
  * The first three properties should be mandatory, but are allowed to be temporarily absent
during
  * grid coverage construction. Temporarily absent properties are allowed because they may
be inferred
  * from a wider context. For example a grid geometry know nothing about {@link RenderedImage},
- * but {@code GridCoverage2D} does and may use that information for providing a missing grid
envelope.
+ * but {@code GridCoverage2D} does and may use that information for providing a missing grid
extent.
  * By default, any request for an undefined property will throw an {@link IncompleteGridGeometryException}.
  * In order to check if a property is defined, use {@link #isDefined(int)}.
  *
@@ -112,7 +112,7 @@ public class GridGeometry implements Serializable {
     public static final int ENVELOPE = 2;
 
     /**
-     * A bitmask to specify the validity of the grid envelope property.
+     * A bitmask to specify the validity of the grid extent property.
      *
      * @see #isDefined(int)
      * @see #getExtent()
@@ -210,6 +210,34 @@ public class GridGeometry implements Serializable {
         nonLinears  = other.nonLinears;
     }
 
+    /**
+     * Creates a new grid geometry with the same values than the given grid geometry except
the grid extent.
+     * This constructor can be used for creating a grid geometry over a subregion, for example
with the grid
+     * extent computed by {@link #getExtent(Envelope)}.
+     *
+     * @param other   the other grid geometry to copy.
+     * @param extent  the new extent for the grid geometry to construct, or {@code null}
if none.
+     * @throws NullPointerException if {@code extent} is {@code null} and the other grid
geometry contains no other information.
+     * @throws TransformException if the math transform can not compute the geospatial envelope
from the grid extent.
+     *
+     * @see #getExtent(Envelope)
+     */
+    public GridGeometry(final GridGeometry other, final GridExtent extent) throws TransformException
{
+        ArgumentChecks.ensureNonNull("other", other);
+        if (extent != null) {
+            ensureDimensionMatches("extent", other.getDimension(), extent.getDimension());
+        }
+        this.extent = extent;
+        gridToCRS   = other.gridToCRS;
+        cornerToCRS = other.cornerToCRS;
+        resolution  = other.resolution;
+        nonLinears  = other.nonLinears;
+        envelope    = computeEnvelope(other.gridToCRS, other.envelope != null ? other.envelope.getCoordinateReferenceSystem()
: null);
+        if (envelope == null && gridToCRS == null) {
+            ArgumentChecks.ensureNonNull("extent", extent);
+        }
+    }
+
     /*
      * Do not provide convenience constructor without PixelInCell or PixelOrientation argument.
      * Experience shows that 0.5 pixel offsets in image georeferencing is a recurrent problem.
@@ -218,7 +246,7 @@ public class GridGeometry implements Serializable {
      */
 
     /**
-     * Creates a new grid geometry from a grid envelope and a mapping from pixel coordinates
to "real world" coordinates.
+     * Creates a new grid geometry from a grid extent and a mapping from pixel coordinates
to "real world" coordinates.
      * At least one of {@code extent}, {@code gridToCRS} or {@code crs} arguments shall be
non-null.
      * If {@code gridToCRS} is non-null, then {@code anchor} shall be non-null too with one
of the following values:
      *
@@ -249,8 +277,7 @@ public class GridGeometry implements Serializable {
      * @param  crs        the coordinate reference system of the "real world" coordinates,
or {@code null} if unknown.
      * @throws NullPointerException if {@code extent}, {@code gridToCRS} and {@code crs}
arguments are all null.
      * @throws MismatchedDimensionException if the math transform and the CRS do not have
consistent dimensions.
-     * @throws TransformException if the math transform can not compute the geospatial envelope
or the resolution
-     *         from the grid envelope.
+     * @throws TransformException if the math transform can not compute the geospatial envelope
or resolution from the grid extent.
      */
     public GridGeometry(final GridExtent extent, final PixelInCell anchor, final MathTransform
gridToCRS,
             final CoordinateReferenceSystem crs) throws TransformException
@@ -268,20 +295,15 @@ public class GridGeometry implements Serializable {
         this.extent      = extent;
         this.gridToCRS   = PixelTranslation.translate(gridToCRS, anchor, PixelInCell.CELL_CENTER);
         this.cornerToCRS = PixelTranslation.translate(gridToCRS, anchor, PixelInCell.CELL_CORNER);
-        GeneralEnvelope env = null;
-        if (extent != null && cornerToCRS != null) {
-            env = extent.toCRS(cornerToCRS, gridToCRS);         // 'gridToCRS' specified
by the user, not 'this.gridToCRS'.
-            env.setCoordinateReferenceSystem(crs);
-        } else if (crs != null) {
-            env = new GeneralEnvelope(crs);
-            env.setToNaN();
-        }
-        envelope = (env != null) ? new ImmutableEnvelope(env) : null;
+        this.envelope    = computeEnvelope(gridToCRS, crs);     // 'gridToCRS' specified
by the user, not 'this.gridToCRS'.
         /*
          * If the gridToCRS transform is linear, we do not even need to check the grid extent;
          * it can be null. Otherwise (if the transform is non-linear) the extent is mandatory.
          * The easiest way to estimate a resolution is then to ask for the derivative at
some
          * arbitrary point. For this constructor, we take the grid center.
+         *
+         * Note that for this computation, it does not matter if 'gridToCRS' is the user-specified
+         * transform or the 'this.gridToCRS' field value; both should produce equivalent
results.
          */
         double[] resolution = null;
         final Matrix matrix = MathTransforms.getMatrix(gridToCRS);
@@ -297,6 +319,25 @@ public class GridGeometry implements Serializable {
     }
 
     /**
+     * Computes the envelope with the given coordinate reference system. This method is invoked
from constructors.
+     * The {@link #extent}, {@link #gridToCRS} and {@link #cornerToCRS} fields must be set
before this method is invoked.
+     *
+     * @param  specified  the transform specified by the user. This is not necessarily {@link
#gridToCRS}.
+     * @param  crs        the coordinate reference system to declare in the envelope.
+     */
+    private ImmutableEnvelope computeEnvelope(final MathTransform specified, final CoordinateReferenceSystem
crs) throws TransformException {
+        GeneralEnvelope env = null;
+        if (extent != null && cornerToCRS != null) {
+            env = extent.toCRS(cornerToCRS, specified);
+            env.setCoordinateReferenceSystem(crs);
+        } else if (crs != null) {
+            env = new GeneralEnvelope(crs);
+            env.setToNaN();
+        }
+        return (env != null) ? new ImmutableEnvelope(env) : null;
+    }
+
+    /**
      * Creates a new grid geometry from a geospatial envelope and a mapping from pixel coordinates
to "real world" coordinates.
      * At least one of {@code gridToCRS} or {@code envelope} arguments shall be non-null.
      * If {@code gridToCRS} is non-null, then {@code anchor} shall be non-null too with one
of the values documented in the
@@ -314,7 +355,7 @@ public class GridGeometry implements Serializable {
      * are implementation details and may be adjusted in any Apache SIS versions.</p>
      *
      * <p>Because of the uncertainties explained in above paragraph, this constructor
should be used only in last resort,
-     * when the grid envelope is unknown. For determinist results, developers should prefer
the
+     * when the grid extent is unknown. For determinist results, developers should prefer
the
      * {@linkplain #GridGeometry(GridExtent, PixelInCell, MathTransform, CoordinateReferenceSystem)
constructor using grid extent}
      * as much as possible. In particular, this constructor is not suitable for computing
grid geometry of tiles in a tiled image,
      * because the above-cited uncertainties may result in apparently random black lines
between tiles.</p>
@@ -330,7 +371,7 @@ public class GridGeometry implements Serializable {
      * @param  envelope   the geospatial envelope, including its coordinate reference system
if available.
      *                    There is no guarantees that the envelope actually stored in the
{@code GridGeometry}
      *                    will be equal to this specified envelope.
-     * @throws TransformException if the math transform can not compute the grid envelope
or the resolution.
+     * @throws TransformException if the math transform can not compute the grid extent or
the resolution.
      */
     @SuppressWarnings("null")
     public GridGeometry(final PixelInCell anchor, final MathTransform gridToCRS, final Envelope
envelope) throws TransformException {
@@ -519,6 +560,8 @@ public class GridGeometry implements Serializable {
      * @return a grid extent of the same dimension than the grid geometry which intersects
the given area of interest.
      * @throws IncompleteGridGeometryException if this grid geometry has no extent or no
"grid to CRS" transform.
      * @throws TransformException if an error occurred while converting the envelope coordinates
to grid coordinates.
+     *
+     * @see #GridGeometry(GridGeometry, GridExtent)
      */
     public GridExtent getExtent(final Envelope areaOfInterest) throws IncompleteGridGeometryException,
TransformException {
         ArgumentChecks.ensureNonNull("areaOfInterest", areaOfInterest);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
index ae30ab5..028758c 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
@@ -19,6 +19,8 @@ package org.apache.sis.referencing.crs;
 import java.util.Map;
 import java.util.Date;
 import java.time.Instant;
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -91,7 +93,8 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS
{
 
     /**
      * A converter from values in this CRS to values in milliseconds.
-     * Will be constructed only when first needed.
+     *
+     * @see #initializeConverter()
      */
     private transient UnitConverter toMillis;
 
@@ -160,6 +163,7 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS
{
         super(properties, cs);
         ensureNonNull("datum", datum);
         this.datum = datum;
+        initializeConverter();
     }
 
     /**
@@ -176,6 +180,7 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS
{
     protected DefaultTemporalCRS(final TemporalCRS crs) {
         super(crs);
         datum = crs.getDatum();
+        initializeConverter();
     }
 
     /**
@@ -194,6 +199,26 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS
{
     }
 
     /**
+     * Invoked on deserialization for restoring the transient fields.
+     *
+     * @param  in  the input stream from which to deserialize an attribute.
+     * @throws IOException if an I/O error occurred while reading or if the stream contains
invalid data.
+     * @throws ClassNotFoundException if the class serialized on the stream is not on the
classpath.
+     */
+    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException
{
+        in.defaultReadObject();
+        initializeConverter();
+    }
+
+    /**
+     * Initialize the fields required for {@link #toInstant(double)} and {@link #toValue(Instant)}
operations.
+     */
+    private void initializeConverter() {
+        origin   = datum.getOrigin().getTime();
+        toMillis = super.getCoordinateSystem().getAxis(0).getUnit().asType(Time.class).getConverterTo(Units.MILLISECOND);
+    }
+
+    /**
      * Returns the GeoAPI interface implemented by this class.
      * The SIS implementation returns {@code TemporalCRS.class}.
      *
@@ -210,14 +235,6 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS
{
     }
 
     /**
-     * Initialize the fields required for {@link #toInstant(double)} and {@link #toValue(Instant)}
operations.
-     */
-    private void initializeConverter() {
-        origin   = datum.getOrigin().getTime();
-        toMillis = getCoordinateSystem().getAxis(0).getUnit().asType(Time.class).getConverterTo(Units.MILLISECOND);
-    }
-
-    /**
      * Returns the datum.
      *
      * @return the datum.
@@ -260,8 +277,7 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS
{
     /**
      * Convert the given value into an instant object.
      * If the given value is {@link Double#NaN NaN} or infinite, then this method returns
{@code null}.
-     *
-     * <p>This method is the converse of {@link #toValue(Instant)}.</p>
+     * This method is the converse of {@link #toValue(Instant)}.
      *
      * @param  value  a value in this axis unit.
      * @return the value as an instant, or {@code null} if the given value is NaN or infinite.
@@ -272,39 +288,31 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS
{
         if (Double.isNaN(value) || Double.isInfinite(value)) {
             return null;
         }
-        if (toMillis == null) {
-            initializeConverter();
-        }
         return Instant.ofEpochMilli(Math.round(toMillis.convert(value)) + origin);
     }
 
     /**
      * Convert the given value into a {@link Date} object.
      * If the given value is {@link Double#NaN NaN} or infinite, then this method returns
{@code null}.
+     * This method is the converse of {@link #toValue(Date)}.
      *
-     * <p>This method is the converse of {@link #toValue(Date)}.</p>
+     * <p>This method is provided for interoperability with legacy {@code java.util.Date}
object.
+     * New code should use {@link #toInstant(double)} instead.</p>
      *
      * @param  value  a value in this axis unit.
      * @return the value as a {@linkplain Date date}, or {@code null} if the given value
is NaN or infinite.
-     *
-     * @deprecated Replaced by {@link #toInstant(double)}.
      */
-    @Deprecated
     public Date toDate(final double value) {
         if (Double.isNaN(value) || Double.isInfinite(value)) {
             return null;
         }
-        if (toMillis == null) {
-            initializeConverter();
-        }
         return new Date(Math.round(toMillis.convert(value)) + origin);
     }
 
     /**
      * Convert the given instant into a value in this axis unit.
      * If the given instant is {@code null}, then this method returns {@link Double#NaN NaN}.
-     *
-     * <p>This method is the converse of {@link #toInstant(double)}.</p>
+     * This method is the converse of {@link #toInstant(double)}.
      *
      * @param  time  the value as an instant, or {@code null}.
      * @return the value in this axis unit, or {@link Double#NaN NaN} if the given instant
is {@code null}.
@@ -315,31 +323,24 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS
{
         if (time == null) {
             return Double.NaN;
         }
-        if (toMillis == null) {
-            initializeConverter();
-        }
         return toMillis.inverse().convert(time.toEpochMilli() - origin);
     }
 
     /**
      * Convert the given {@linkplain Date date} into a value in this axis unit.
      * If the given time is {@code null}, then this method returns {@link Double#NaN NaN}.
+     * This method is the converse of {@link #toDate(double)}.
      *
-     * <p>This method is the converse of {@link #toDate(double)}.</p>
+     * <p>This method is provided for interoperability with legacy {@code java.util.Date}
object.
+     * New code should use {@link #toValue(Date)} instead.</p>
      *
      * @param  time  the value as a {@linkplain Date date}, or {@code null}.
      * @return the value in this axis unit, or {@link Double#NaN NaN} if the given time is
{@code null}.
-     *
-     * @deprecated Replaced by {@link #toValue(Instant)}.
      */
-    @Deprecated
     public double toValue(final Date time) {
         if (time == null) {
             return Double.NaN;
         }
-        if (toMillis == null) {
-            initializeConverter();
-        }
         return toMillis.inverse().convert(time.getTime() - origin);
     }
 
@@ -398,6 +399,9 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS
{
     private void setDatum(final TemporalDatum value) {
         if (datum == null) {
             datum = value;
+            if (super.getCoordinateSystem() != null) {
+                initializeConverter();
+            }
         } else {
             MetadataUtilities.propertyAlreadySet(DefaultVerticalCRS.class, "setDatum", "temporalDatum");
         }
@@ -410,5 +414,8 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS
{
      */
     private void setCoordinateSystem(final TimeCS cs) {
         setCoordinateSystem("timeCS", cs);
+        if (toMillis == null && datum != null) {
+            initializeConverter();
+        }
     }
 }


Mime
View raw message