Author: desruisseaux
Date: Tue Jan 28 23:07:36 2014
New Revision: 1562306
URL: http://svn.apache.org/r1562306
Log:
Port of CRS.isHorizontal, CRS.getProjectedCRS, CRS.getVerticalCRS and
CRS.getTemporalCRS methods.
Modified:
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/AxisDirections.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/AxisDirectionsTest.java
sis/ip-review/rev/33571/CRS.xhtml
Modified:
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/AxisDirections.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/AxisDirections.java?rev=1562306&r1=1562305&r2=1562306&view=diff
==============================================================================
---
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/AxisDirections.java
[UTF-8] (original)
+++
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/AxisDirections.java
[UTF-8] Tue Jan 28 23:07:36 2014
@@ -334,17 +334,16 @@ public final class AxisDirections extend
* @param direction The direction of the axis to search.
* @return The dimension of the axis using the given direction or its
opposite, or -1 if none.
*/
- public static int indexOf(final CoordinateSystem cs, final AxisDirection
direction) {
+ public static int indexOfColinear(final CoordinateSystem cs, final
AxisDirection direction) {
int fallback = -1;
if (cs != null) {
- final AxisDirection opposite = opposite(direction);
final int dimension = cs.getDimension();
for (int i=0; i<dimension; i++) {
final AxisDirection d = cs.getAxis(i).getDirection();
if (direction.equals(d)) {
return i;
}
- if (fallback < 0 && opposite != null && opposite.equals(d)) {
+ if (fallback < 0 && d.equals(opposite(direction))) {
fallback = i;
}
}
Modified:
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1562306&r1=1562305&r2=1562306&view=diff
==============================================================================
---
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
[UTF-8] (original)
+++
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
[UTF-8] Tue Jan 28 23:07:36 2014
@@ -16,19 +16,32 @@
*/
package org.apache.sis.referencing;
+import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import org.opengis.util.FactoryException;
import org.opengis.util.NoSuchIdentifierException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.opengis.referencing.cs.AxisDirection;
+import org.opengis.referencing.cs.CoordinateSystem;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.crs.CompoundCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.CRSAuthorityFactory;
+import org.opengis.referencing.crs.GeographicCRS;
+import org.opengis.referencing.crs.ProjectedCRS;
+import org.opengis.referencing.crs.TemporalCRS;
+import org.opengis.referencing.crs.VerticalCRS;
+import org.opengis.metadata.extent.GeographicBoundingBox;
import org.apache.sis.internal.util.DefinitionURI;
+import org.apache.sis.internal.referencing.AxisDirections;
import org.apache.sis.internal.referencing.ReferencingUtilities;
+import org.apache.sis.referencing.cs.DefaultVerticalCS;
+import org.apache.sis.referencing.crs.DefaultVerticalCRS;
import org.apache.sis.referencing.crs.DefaultCompoundCRS;
+import org.apache.sis.metadata.iso.extent.Extents;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.Static;
@@ -38,6 +51,25 @@ import static org.apache.sis.util.Argume
/**
* Static methods working on {@linkplain CoordinateReferenceSystem Coordinate
Reference Systems}.
+ * The methods defined in this class can be grouped in two categories:
+ *
+ * <ul>
+ * <li>Factory methods, the most notable one being {@link
#forCode(String)}.</li>
+ * <li>Methods providing information, like {@link
#isHorizontalCRS(CoordinateReferenceSystem)}.</li>
+ * </ul>
+ *
+ * {@section Note on kinds of CRS}
+ * The {@link #getSingleComponents(CoordinateReferenceSystem)} method
decomposes an arbitrary CRS into a flat
+ * list of single components. In such flat list, vertical and temporal
components can easily be identified by
+ * {@code instanceof} checks. But identifying the horizontal component is not
as easy. The list below suggests
+ * ways to classify the components:
+ *
+ * <ul>
+ * <li><code>if (crs instanceof TemporalCRS)</code> determines if the CRS is
for the temporal component.</li>
+ * <li><code>if (crs instanceof VerticalCRS)</code> determines if the CRS is
for the vertical component.</li>
+ * <li><code>if (CRS.{@linkplain #isHorizontalCRS(CoordinateReferenceSystem)
isHorizontalCRS}(crs))</code>
+ * determines if the CRS is for the horizontal component.</li>
+ * </ul>
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @since 0.3 (derived from geotk-2.1)
@@ -91,6 +123,8 @@ public final class CRS extends Static {
* @return The Coordinate Reference System for the given authority code.
* @throws NoSuchAuthorityCodeException If there is no known CRS
associated to the given code.
* @throws FactoryException if the CRS creation failed for an other reason.
+ *
+ * @category factory
*/
public static CoordinateReferenceSystem forCode(final String code)
throws NoSuchAuthorityCodeException, FactoryException
@@ -154,6 +188,163 @@ public final class CRS extends Static {
}
/**
+ * Returns the valid geographic area for the given coordinate reference
system, or {@code null} if unknown.
+ * This method explores the {@linkplain
CoordinateReferenceSystem#getDomainOfValidity() domain of validity}
+ * associated with the given CRS. If more than one geographic bounding box
is found, then they will be
+ * {@linkplain
org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox#add(GeographicBoundingBox)
+ * added} together.
+ *
+ * @param crs The coordinate reference system, or {@code null}.
+ * @return The geographic area, or {@code null} if none.
+ *
+ * @see #getEnvelope(CoordinateReferenceSystem)
+ *
+ * @category information
+ */
+ public static GeographicBoundingBox getGeographicBoundingBox(final
CoordinateReferenceSystem crs) {
+ return (crs != null) ?
Extents.getGeographicBoundingBox(crs.getDomainOfValidity()) : null;
+ }
+
+ /**
+ * Returns {@code true} if the given CRS is horizontal. The current
implementation considers a
+ * CRS as horizontal if it is two-dimensional and comply with one of the
following conditions:
+ *
+ * <ul>
+ * <li>It is an instance of {@link GeographicCRS}.</li>
+ * <li>It is an instance of {@link ProjectedCRS}.</li>
+ * </ul>
+ *
+ * @todo Future SIS implementation may extend the above condition list.
For example a radar station could
+ * use a polar coordinate system in a <code>DerivedCRS</code>
instance based on a projected CRS.
+ *
+ * In case of doubt, this method conservatively returns {@code false}.
+ *
+ * @param crs The coordinate reference system, or {@code null}.
+ * @return {@code true} if the given CRS is non-null and comply with one
of the above conditions,
+ * or {@code false} otherwise.
+ *
+ * @see #getHorizontalCRS(CoordinateReferenceSystem)
+ *
+ * @category information
+ */
+ public static boolean isHorizontalCRS(CoordinateReferenceSystem crs) {
+ if (crs instanceof GeographicCRS || crs instanceof ProjectedCRS) {
+ return crs.getCoordinateSystem().getDimension() == 2;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the first projected coordinate reference system found in a the
given CRS,
+ * or {@code null} if there is none.
+ *
+ * @param crs The coordinate reference system, or {@code null}.
+ * @return The first projected CRS, or {@code null} if none.
+ *
+ * @category information
+ */
+ public static ProjectedCRS getProjectedCRS(final CoordinateReferenceSystem
crs) {
+ if (crs instanceof ProjectedCRS) {
+ return (ProjectedCRS) crs;
+ }
+ if (crs instanceof CompoundCRS) {
+ final CompoundCRS cp = (CompoundCRS) crs;
+ for (final CoordinateReferenceSystem c : cp.getComponents()) {
+ final ProjectedCRS candidate = getProjectedCRS(c);
+ if (candidate != null) {
+ return candidate;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the first vertical coordinate reference system found in a the
given CRS,
+ * or {@code null} if there is none.
+ *
+ * {@section Height in a three-dimensional geographic CRS}
+ * In ISO 19111 model, ellipsoidal heights are indissociable from
geographic CRS because such heights
+ * without their (<var>latitude</var>, <var>longitude</var>) locations
make little sense. Consequently
+ * a standard-conformant library should return {@code null} when asked for
the {@code VerticalCRS}
+ * component of a geographic CRS. This is what {@code getVerticalCRS(…)}
does when the
+ * {@code allowEllipsoidal} argument is {@code false}.
+ *
+ * <p>However in some exceptional cases, handling ellipsoidal heights like
any other kind of heights
+ * may simplify the task. For example when computing <em>difference</em>
between heights above the
+ * same datum, the impact of ignoring locations may be smaller (but not
necessarily canceled).
+ * Orphan {@code VerticalCRS} may also be useful for information purpose
like labeling a plot axis.
+ * If the caller feels confident that ellipsoidal heights are safe for his
task, he can set the
+ * {@code allowEllipsoidal} argument to {@code true}. In such case, this
{@code getVerticalCRS(…)}
+ * method will create a temporary {@code VerticalCRS} from the first
three-dimensional {@code GeographicCRS}
+ * <em>in last resort</em>, only if it failed to find an existing {@code
VerticalCRS} instance.
+ * <strong>Note that this is not a valid CRS according ISO 19111</strong>
— use with care.</p>
+ *
+ * @param crs The coordinate reference system, or {@code null}.
+ * @param allowEllipsoidal {@code true} for allowing the creation of
orphan CRS for ellipsoidal heights.
+ * This is usually not recommended.
+ * @return The first vertical CRS, or {@code null} if none.
+ *
+ * @category information
+ */
+ public static VerticalCRS getVerticalCRS(final CoordinateReferenceSystem
crs, final boolean allowEllipsoidal) {
+ if (crs instanceof VerticalCRS) {
+ return (VerticalCRS) crs;
+ }
+ if (crs instanceof CompoundCRS) {
+ final CompoundCRS cp = (CompoundCRS) crs;
+ boolean a = false;
+ do { // Executed at most twice.
+ for (final CoordinateReferenceSystem c : cp.getComponents()) {
+ final VerticalCRS candidate = getVerticalCRS(c, a);
+ if (candidate != null) {
+ return candidate;
+ }
+ }
+ } while ((a = !a) == allowEllipsoidal);
+ }
+ if (allowEllipsoidal && crs instanceof GeographicCRS) {
+ final CoordinateSystem cs = crs.getCoordinateSystem();
+ final int i = AxisDirections.indexOfColinear(cs, AxisDirection.UP);
+ if (i >= 0) {
+ final CoordinateSystemAxis axis = cs.getAxis(i);
+ VerticalCRS c = CommonCRS.Vertical.ELLIPSOIDAL.crs();
+ if (!c.getCoordinateSystem().getAxis(0).equals(axis)) {
+ final Map<String,?> properties =
IdentifiedObjects.getProperties(c);
+ c = new DefaultVerticalCRS(properties, c.getDatum(), new
DefaultVerticalCS(properties, axis));
+ }
+ return c;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the first temporal coordinate reference system found in the
given CRS,
+ * or {@code null} if there is none.
+ *
+ * @param crs The coordinate reference system, or {@code null}.
+ * @return The first temporal CRS, or {@code null} if none.
+ *
+ * @category information
+ */
+ public static TemporalCRS getTemporalCRS(final CoordinateReferenceSystem
crs) {
+ if (crs instanceof TemporalCRS) {
+ return (TemporalCRS) crs;
+ }
+ if (crs instanceof CompoundCRS) {
+ final CompoundCRS cp = (CompoundCRS) crs;
+ for (final CoordinateReferenceSystem c : cp.getComponents()) {
+ final TemporalCRS candidate = getTemporalCRS(c);
+ if (candidate != null) {
+ return candidate;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
* Returns the ordered list of single coordinate reference systems for the
specified CRS.
* This method performs the following choices:
*
Modified:
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java?rev=1562306&r1=1562305&r2=1562306&view=diff
==============================================================================
---
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
[UTF-8] (original)
+++
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
[UTF-8] Tue Jan 28 23:07:36 2014
@@ -822,12 +822,11 @@ public enum CommonCRS {
* Height measured along the normal to the ellipsoid used in the
definition of horizontal datum.
* The unit of measurement is metres.
*
- * <p><b>This datum is not part of ISO 19111 international
standard.</b>
- * Usage of this datum is generally not recommended since ellipsoidal
heights make little sense without
+ * <p><b>Ellipsoidal height is not part of ISO 19111 international
standard.</b>
+ * Such vertical CRS is usually not recommended since ellipsoidal
heights make little sense without
* their (<var>latitude</var>, <var>longitude</var>) locations. The
ISO specification defines instead
- * three-dimensional {@code GeographicCRS} for that reason. However
Apache SIS provides this value
- * because it is sometime useful to temporarily express ellipsoidal
heights independently from other
- * ordinate values.</p>
+ * three-dimensional {@code GeographicCRS} for that reason. Users are
encouraged to avoid this orphan
+ * ellipsoidal height as much as possible.</p>
*/
ELLIPSOIDAL(false, Vocabulary.Keys.EllipsoidalHeight,
Vocabulary.Keys.Ellipsoid),
Modified:
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/AxisDirectionsTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/AxisDirectionsTest.java?rev=1562306&r1=1562305&r2=1562306&view=diff
==============================================================================
---
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/AxisDirectionsTest.java
[UTF-8] (original)
+++
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/AxisDirectionsTest.java
[UTF-8] Tue Jan 28 23:07:36 2014
@@ -312,11 +312,11 @@ public final strictfp class AxisDirectio
}
/**
- * Tests {@link AxisDirections#indexOf(CoordinateSystem, AxisDirection)}.
+ * Tests {@link AxisDirections#indexOfColinear(CoordinateSystem,
AxisDirection)}.
*/
@Test
- public void testIndexOf() {
- assertEquals(1, AxisDirections.indexOf(HardCodedCS.GEODETIC_3D,
AxisDirection.NORTH));
- assertEquals(1, AxisDirections.indexOf(HardCodedCS.GEODETIC_3D,
AxisDirection.SOUTH));
+ public void testIndexOfColinear() {
+ assertEquals(1,
AxisDirections.indexOfColinear(HardCodedCS.GEODETIC_3D, AxisDirection.NORTH));
+ assertEquals(1,
AxisDirections.indexOfColinear(HardCodedCS.GEODETIC_3D, AxisDirection.SOUTH));
}
}
Modified: sis/ip-review/rev/33571/CRS.xhtml
URL:
http://svn.apache.org/viewvc/sis/ip-review/rev/33571/CRS.xhtml?rev=1562306&r1=1562305&r2=1562306&view=diff
==============================================================================
--- sis/ip-review/rev/33571/CRS.xhtml (original)
+++ sis/ip-review/rev/33571/CRS.xhtml Tue Jan 28 23:07:36 2014
@@ -11,7 +11,7 @@
<div>
<h1>CRS changes for revisions 33570:33571</h1>
<p>This change, identified with the "<cite>fix for GEOT-2613</cite>"
commit message,
- has been rejected because it is wrong. This change was applied in the
following method:</p>
+ has been discarded. This change was applied in the following
method:</p>
<blockquote><pre>public static SingleCRS
getHorizontalCRS(CoordinateReferenceSystem crs);</pre></blockquote>