Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -18,11 +18,13 @@ package org.apache.sis.referencing.cs; import java.util.Arrays; import javax.measure.unit.Unit; +import javax.measure.quantity.Length; import javax.measure.converter.UnitConverter; import javax.measure.converter.LinearConverter; import javax.measure.converter.ConversionException; import org.opengis.referencing.cs.AxisDirection; import org.opengis.referencing.cs.CoordinateSystem; +import org.opengis.referencing.cs.CoordinateSystemAxis; import org.opengis.referencing.operation.Matrix; import org.apache.sis.measure.Angle; import org.apache.sis.measure.ElevationAngle; @@ -49,7 +51,7 @@ import org.apache.sis.internal.jdk7.Obje * * @author Martin Desruisseaux (IRD, Geomatys) * @since 0.4 - * @version 0.6 + * @version 0.7 * @module */ public final class CoordinateSystems extends Static { @@ -306,8 +308,8 @@ public final class CoordinateSystems ext * not a matrix multiplication. The last column is processed in a special * way, since it contains the offset values. */ - final int sourceDim = matrix.getNumCol() - 1; // == sourceCS.getDimension() - final int targetDim = matrix.getNumRow() - 1; // == targetCS.getDimension() + final int sourceDim = matrix.getNumCol() - 1; // == sourceCS.getDimension() + final int targetDim = matrix.getNumRow() - 1; // == targetCS.getDimension() for (int j=0; j<targetDim; j++) { final Unit<?> targetUnit = targetCS.getAxis(j).getUnit(); for (int i=0; i<sourceDim; i++) { @@ -405,4 +407,106 @@ public final class CoordinateSystems ext } return cs; } + + /** + * Returns a coordinate system derived from the given one but with all linear units replaced by the given unit. + * Non-linear units (e.g. angular or scale units) are left unchanged. + * + * <p>This convenience method is equivalent to the following code:</p> + * {@preformat java + * return CoordinateSystems.replaceAxes(cs, new AxisFilter() { + * @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> unit) { + * return Units.isLinear(unit) ? newUnit : unit; + * } + * }); + * } + * + * @param cs The coordinate system in which to replace linear units, or {@code null}. + * @param newUnit The new linear unit. + * @return The modified coordinate system as a new instance, + * or {@code cs} if all linear units were already equal to the given one. + * + * @see Units#isLinear(Unit) + * + * @since 0.7 + */ + public static CoordinateSystem replaceLinearUnit(final CoordinateSystem cs, final Unit<Length> newUnit) { + ensureNonNull("newUnit", newUnit); + return CoordinateSystems.replaceAxes(cs, new AxisFilter() { + @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> unit) { + return Units.isLinear(unit) ? newUnit : unit; + } + + @Override + public boolean accept(CoordinateSystemAxis axis) { + return true; + } + + @Override + public AxisDirection getDirectionReplacement(CoordinateSystemAxis axis, AxisDirection direction) { + return direction; + } + + @Deprecated @Override + public AxisDirection getDirectionReplacement(AxisDirection direction) { + return direction; + } + + @Deprecated @Override + public Unit<?> getUnitReplacement(Unit<?> unit) { + return getUnitReplacement(null, unit); + } + }); + } + + /** + * Returns a coordinate system derived from the given one but with all angular units replaced by the given unit. + * Non-angular units (e.g. linear or scale units) are left unchanged. + * + * <p>This convenience method is equivalent to the following code:</p> + * {@preformat java + * return CoordinateSystems.replaceAxes(cs, new AxisFilter() { + * @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> unit) { + * return Units.isAngular(unit) ? newUnit : unit; + * } + * }); + * } + * + * @param cs The coordinate system in which to replace angular units, or {@code null}. + * @param newUnit The new angular unit. + * @return The modified coordinate system as a new instance, + * or {@code cs} if all angular units were already equal to the given one. + * + * @see Units#isAngular(Unit) + * + * @since 0.7 + */ + public static CoordinateSystem replaceAngularUnit(final CoordinateSystem cs, final Unit<javax.measure.quantity.Angle> newUnit) { + ensureNonNull("newUnit", newUnit); + return CoordinateSystems.replaceAxes(cs, new AxisFilter() { + @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> unit) { + return Units.isAngular(unit) ? newUnit : unit; + } + + @Override + public boolean accept(CoordinateSystemAxis axis) { + return true; + } + + @Override + public AxisDirection getDirectionReplacement(CoordinateSystemAxis axis, AxisDirection direction) { + return direction; + } + + @Deprecated @Override + public AxisDirection getDirectionReplacement(AxisDirection direction) { + return direction; + } + + @Deprecated @Override + public Unit<?> getUnitReplacement(Unit<?> unit) { + return getUnitReplacement(null, unit); + } + }); + } }
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -139,7 +139,7 @@ public class DefaultCompoundCS extends A ensureNonNull("components", components); components = components.clone(); for (int i=0; i<components.length; i++) { - ensureNonNullElement("components", i, components); + ensureNonNullElement("components", i, components[i]); } return components; } Copied: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java (from r1740152, sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java) URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java?p2=sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java&p1=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java&r1=1740152&r2=1740177&rev=1740177&view=diff ============================================================================== --- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -20,7 +20,6 @@ import java.util.Map; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import org.opengis.referencing.cs.CoordinateSystemAxis; -import org.opengis.referencing.cs.ParametricCS; /** @@ -53,7 +52,7 @@ import org.opengis.referencing.cs.Parame */ @XmlType(name = "ParametricCSType") @XmlRootElement(name = "ParametricCS") -public class DefaultParametricCS extends AbstractCS implements ParametricCS { +public class DefaultParametricCS extends AbstractCS { /** * Serial number for inter-operability with different versions. */ @@ -119,46 +118,16 @@ public class DefaultParametricCS extends * * <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p> * - * @param cs The coordinate system to copy. + * <div class="warning"><b>Warning:</b> in a future SIS version, the parameter type may be changed + * to {@code org.opengis.referencing.cs.ParametricCS}. This change is pending GeoAPI revision.</div> * - * @see #castOrCopy(ParametricCS) + * @param cs The coordinate system to copy. */ - protected DefaultParametricCS(final ParametricCS cs) { + protected DefaultParametricCS(final DefaultParametricCS cs) { super(cs); } /** - * Returns a SIS coordinate system implementation with the same values than the given arbitrary implementation. - * If the given object is {@code null}, then this method returns {@code null}. - * Otherwise if the given object is already a SIS implementation, then the given object is returned unchanged. - * Otherwise a new SIS implementation is created and initialized to the attribute values of the given object. - * - * @param object The object to get as a SIS implementation, or {@code null} if none. - * @return A SIS implementation containing the values of the given object (may be the - * given object itself), or {@code null} if the argument was null. - */ - public static DefaultParametricCS castOrCopy(final ParametricCS object) { - return (object == null) || (object instanceof DefaultParametricCS) - ? (DefaultParametricCS) object : new DefaultParametricCS(object); - } - - /** - * Returns the GeoAPI interface implemented by this class. - * The SIS implementation returns {@code ParametricCS.class}. - * - * <div class="note"><b>Note for implementors:</b> - * Subclasses usually do not need to override this method since GeoAPI does not define {@code ParametricCS} - * sub-interface. Overriding possibility is left mostly for implementors who wish to extend GeoAPI with - * their own set of interfaces.</div> - * - * @return {@code ParametricCS.class} or a user-defined sub-interface. - */ - @Override - public Class<? extends ParametricCS> getInterface() { - return ParametricCS.class; - } - - /** * {@inheritDoc} * * @return {@inheritDoc} Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -83,6 +83,7 @@ import org.apache.sis.internal.jdk7.Obje DefaultGeodeticDatum.class, DefaultVerticalDatum.class, DefaultTemporalDatum.class, + DefaultParametricDatum.class, DefaultEngineeringDatum.class, DefaultImageDatum.class }) Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -238,7 +238,7 @@ public class BursaWolfParameters extends * * <p><b>Maintenance note:</b> * if the above policy regarding prime meridians is modified, then some {@code createOperationStep(…)} method - * implementations in {@link org.apache.sis.referencing.operation.CoordinateOperationInference} may need to be + * implementations in {@link org.apache.sis.referencing.operation.CoordinateOperationFinder} may need to be * revisited. See especially the methods creating a transformation between a pair of {@code GeocentricCRS} or * between a pair of {@code GeographicCRS} (tip: search for {@code DefaultGeodeticDatum}).</p> * Copied: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java (from r1740152, sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java) URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java?p2=sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java&p1=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java&r1=1740152&r2=1740177&rev=1740177&view=diff ============================================================================== --- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -20,7 +20,6 @@ import java.util.Date; import java.util.Map; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import org.opengis.referencing.datum.ParametricDatum; import org.apache.sis.internal.metadata.WKTKeywords; import org.apache.sis.io.wkt.Formatter; @@ -57,7 +56,7 @@ import org.apache.sis.io.wkt.Formatter; */ @XmlType(name = "ParametricDatumType") @XmlRootElement(name = "ParametricDatum") -public class DefaultParametricDatum extends AbstractDatum implements ParametricDatum { +public class DefaultParametricDatum extends AbstractDatum { /** * Serial number for inter-operability with different versions. */ @@ -132,46 +131,16 @@ public class DefaultParametricDatum exte * * <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p> * - * @param datum The datum to copy. + * <div class="warning"><b>Warning:</b> in a future SIS version, the parameter type may be changed + * to {@code org.opengis.referencing.datum.ParametricDatum}. This change is pending GeoAPI revision.</div> * - * @see #castOrCopy(ParametricDatum) + * @param datum The datum to copy. */ - protected DefaultParametricDatum(final ParametricDatum datum) { + protected DefaultParametricDatum(final DefaultParametricDatum datum) { super(datum); } /** - * Returns a SIS datum implementation with the same values than the given arbitrary implementation. - * If the given object is {@code null}, then this method returns {@code null}. - * Otherwise if the given object is already a SIS implementation, then the given object is returned unchanged. - * Otherwise a new SIS implementation is created and initialized to the attribute values of the given object. - * - * @param object The object to get as a SIS implementation, or {@code null} if none. - * @return A SIS implementation containing the values of the given object (may be the - * given object itself), or {@code null} if the argument was null. - */ - public static DefaultParametricDatum castOrCopy(final ParametricDatum object) { - return (object == null) || (object instanceof DefaultParametricDatum) ? - (DefaultParametricDatum) object : new DefaultParametricDatum(object); - } - - /** - * Returns the GeoAPI interface implemented by this class. - * The SIS implementation returns {@code ParametricDatum.class}. - * - * <div class="note"><b>Note for implementors:</b> - * Subclasses usually do not need to override this method since GeoAPI does not define {@code TemporalDatum} - * sub-interface. Overriding possibility is left mostly for implementors who wish to extend GeoAPI with their - * own set of interfaces.</div> - * - * @return {@code ParametricDatum.class} or a user-defined sub-interface. - */ - @Override - public Class<? extends ParametricDatum> getInterface() { - return ParametricDatum.class; - } - - /** * Formats this datum as a <cite>Well Known Text</cite> {@code ParametricDatum[…]} element. * * <div class="note"><b>Compatibility note:</b> Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -26,6 +26,7 @@ import java.util.Arrays; import javax.measure.unit.SI; import javax.measure.unit.NonSI; import javax.measure.unit.Unit; +import javax.measure.quantity.Length; import org.opengis.util.FactoryException; import org.opengis.util.InternationalString; import org.opengis.metadata.citation.Citation; @@ -42,7 +43,6 @@ import org.opengis.referencing.crs.Singl import org.opengis.referencing.cs.CSFactory; import org.opengis.referencing.cs.CartesianCS; import org.opengis.referencing.cs.AxisDirection; -import org.opengis.referencing.cs.CoordinateSystemAxis; import org.opengis.referencing.datum.DatumFactory; import org.opengis.referencing.datum.EngineeringDatum; import org.apache.sis.internal.referencing.GeodeticObjectBuilder; @@ -52,7 +52,6 @@ import org.apache.sis.internal.system.Lo import org.apache.sis.internal.util.Constants; import org.apache.sis.measure.Units; import org.apache.sis.referencing.CommonCRS; -import org.apache.sis.referencing.cs.AxisFilter; import org.apache.sis.referencing.cs.CoordinateSystems; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.ArraysExt; @@ -627,36 +626,14 @@ public class CommonAuthorityFactory exte * At this point we got a coordinate system with axes in metres. * If the user asked for another unit of measurement, change the axes now. */ - final Unit<?> unit; + final Unit<Length> unit; if (isLegacy) { - unit = createUnitFromEPSG(factor); + unit = createUnitFromEPSG(factor).asType(Length.class); } else { unit = (factor != 1) ? Units.multiply(SI.METRE, factor) : SI.METRE; } if (!SI.METRE.equals(unit)) { - cs = (CartesianCS) CoordinateSystems.replaceAxes(cs, new AxisFilter() { - @Override public Unit<?> getUnitReplacement(Unit<?> ignored) { - assert SI.METRE.equals(ignored) : ignored; - return unit; - } - - @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> ignored) { - assert SI.METRE.equals(ignored) : ignored; - return unit; - } - - @Override public boolean accept(CoordinateSystemAxis axis) { - return true; - } - - @Override public AxisDirection getDirectionReplacement(AxisDirection direction) { - return direction; - } - - @Override public AxisDirection getDirectionReplacement(CoordinateSystemAxis axis, AxisDirection direction) { - return direction; - } - }); + cs = (CartesianCS) CoordinateSystems.replaceLinearUnit(cs, unit); } /* * Set the projection name, operation method and parameters. The parameters for the Transverse Mercator Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -40,6 +40,11 @@ import org.apache.sis.util.CharSequences import org.apache.sis.util.Classes; import org.apache.sis.util.Debug; +// Branch-dependent imports +import org.apache.sis.referencing.cs.DefaultParametricCS; +import org.apache.sis.referencing.crs.DefaultParametricCRS; +import org.apache.sis.referencing.datum.DefaultParametricDatum; + /** * Creates geodetic objects from codes defined by an authority. @@ -62,6 +67,7 @@ import org.apache.sis.util.Debug; * However, other methods may be overridden as well for better performances.</p> * * @author Martin Desruisseaux (IRD, Geomatys) + * @author Johann Sorel (Geomatys) * @since 0.7 * @version 0.7 * @module @@ -393,6 +399,27 @@ public abstract class GeodeticAuthorityF } /** + * Creates a 1-dimensional parametric coordinate reference system. + * + * <div class="section">Default implementation</div> + * The default implementation delegates to {@link #createCoordinateReferenceSystem(String)} and casts the result. + * If the result can not be casted, then a {@link NoSuchAuthorityCodeException} is thrown. + * + * <div class="warning"><b>Warning:</b> in a future SIS version, the return type may be changed + * to {@code org.opengis.referencing.crs.ParametricCRS}. This change is pending GeoAPI revision.</div> + * + * @param code Value allocated by authority. + * @return The coordinate reference system for the given code. + * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. + * @throws FactoryException if the object creation failed for some other reason. + * + * @see org.apache.sis.referencing.crs.DefaultParametricCRS + */ + public DefaultParametricCRS createParametricCRS(final String code) throws NoSuchAuthorityCodeException, FactoryException { + return cast(DefaultParametricCRS.class, createCoordinateReferenceSystem(code), code); + } + + /** * Creates a CRS describing the position of points through two or more independent coordinate reference systems. * * <div class="note"><b>Example:</b> @@ -610,6 +637,27 @@ public abstract class GeodeticAuthorityF } /** + * Creates a datum defining the origin of a parametric coordinate reference system. + * + * <div class="section">Default implementation</div> + * The default implementation delegates to {@link #createDatum(String)} and casts the result. + * If the result can not be casted, then a {@link NoSuchAuthorityCodeException} is thrown. + * + * <div class="warning"><b>Warning:</b> in a future SIS version, the return type may be changed + * to {@code org.opengis.referencing.datum.ParametricDatum}. This change is pending GeoAPI revision.</div> + * + * @param code Value allocated by authority. + * @return The datum for the given code. + * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. + * @throws FactoryException if the object creation failed for some other reason. + * + * @see org.apache.sis.referencing.datum.DefaultParametricDatum + */ + public DefaultParametricDatum createParametricDatum(final String code) throws NoSuchAuthorityCodeException, FactoryException { + return cast(DefaultParametricDatum.class, createDatum(code), code); + } + + /** * Creates a datum defining the origin of an engineering coordinate reference system. * An engineering datum is used in a region around that origin. * This origin can be fixed with respect to the earth or be a defined point on a moving vehicle. @@ -870,6 +918,27 @@ public abstract class GeodeticAuthorityF } /** + * Creates a 1-dimensional parametric coordinate system. + * + * <div class="section">Default implementation</div> + * The default implementation delegates to {@link #createCoordinateSystem(String)} and casts the result. + * If the result can not be casted, then a {@link NoSuchAuthorityCodeException} is thrown. + * + * <div class="warning"><b>Warning:</b> in a future SIS version, the return type may be changed + * to {@code org.opengis.referencing.cs.ParametricCS}. This change is pending GeoAPI revision.</div> + * + * @param code Value allocated by authority. + * @return The coordinate system for the given code. + * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. + * @throws FactoryException if the object creation failed for some other reason. + * + * @see org.apache.sis.referencing.cs.DefaultParametricCS + */ + public DefaultParametricCS createParametricCS(final String code) throws NoSuchAuthorityCodeException, FactoryException { + return cast(DefaultParametricCS.class, createCoordinateSystem(code), code); + } + + /** * Creates a 2- or 3-dimensional Cartesian coordinate system made of straight orthogonal axes. * All axes shall have the same linear unit of measure. * Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -189,6 +189,7 @@ import org.apache.sis.xml.XML; * * @author Martin Desruisseaux (IRD, Geomatys) * @author Guilhem Legal (Geomatys) + * @author Johann Sorel (Geomatys) * @since 0.6 * @version 0.7 * @module @@ -1036,6 +1037,103 @@ public class GeodeticObjectFactory exten } /** + * Creates a parametric coordinate reference system. + * Parametric CRS can be used for physical properties or functions that vary monotonically with height. + * A typical example is the pressure in meteorological applications. + * + * <div class="note"><b>Dependencies:</b> + * the components needed by this method can be created by the following methods: + * <ol> + * <li>{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}</li> + * <li>{@link #createParametricCS(Map, CoordinateSystemAxis)}</li> + * <li>{@link #createParametricDatum(Map)}</li> + * </ol></div> + * + * The default implementation creates a {@link DefaultParametricCRS} instance. + * + * <div class="warning"><b>Warning:</b> in a future SIS version, the parameter types may be changed to + * {@code org.opengis.referencing.datum.ParametricDatum} and {@code org.opengis.referencing.cs.ParametricCS}, + * and the return type may be changed to {@code org.opengis.referencing.crs.ParametricCRS}. + * Those change are pending GeoAPI revision.</div> + * + * @param properties Name and other properties to give to the new object. + * @param datum The parametric datum to use in created CRS. + * @param cs The parametric coordinate system for the created CRS. + * @throws FactoryException if the object creation failed. + * + * @see DefaultParametricCRS#DefaultParametricCRS(Map, DefaultParametricDatum, DefaultParametricCS) + * @see GeodeticAuthorityFactory#createParametricCRS(String) + */ + public DefaultParametricCRS createParametricCRS(final Map<String,?> properties, + final DefaultParametricDatum datum, final DefaultParametricCS cs) throws FactoryException + { + final DefaultParametricCRS crs; + try { + crs = new DefaultParametricCRS(complete(properties), datum, cs); + } catch (IllegalArgumentException exception) { + throw new InvalidGeodeticParameterException(exception); + } + return unique("createParametricCRS", crs); + } + + /** + * Creates a parametric datum. + * The default implementation creates a {@link DefaultParametricDatum} instance. + * + * <div class="warning"><b>Warning:</b> in a future SIS version, the return type may be changed + * to {@code org.opengis.referencing.datum.ParametricDatum}. This change is pending GeoAPI revision.</div> + * + * @param properties Name and other properties to give to the new object. + * @throws FactoryException if the object creation failed. + * + * @see DefaultParametricDatum#DefaultParametricDatum(Map) + * @see GeodeticAuthorityFactory#createParametricDatum(String) + */ + public DefaultParametricDatum createParametricDatum(final Map<String,?> properties) + throws FactoryException + { + final DefaultParametricDatum datum; + try { + datum = new DefaultParametricDatum(complete(properties)); + } catch (IllegalArgumentException exception) { + throw new InvalidGeodeticParameterException(exception); + } + return unique("createParametricDatum", datum); + } + + /** + * Creates a parametric coordinate system. + * This coordinate system can be used only with parametric CRS. + * + * <div class="note"><b>Dependencies:</b> + * the components needed by this method can be created by the following methods: + * <ol> + * <li>{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}</li> + * </ol></div> + * + * The default implementation creates a {@link DefaultParametricCS} instance. + * + * <div class="warning"><b>Warning:</b> in a future SIS version, the return type may be changed + * to {@code org.opengis.referencing.cs.ParametricCS}. This change is pending GeoAPI revision.</div> + * + * @param properties Name and other properties to give to the new object. + * @param axis The single axis. + * @throws FactoryException if the object creation failed. + * + * @see DefaultParametricCS#DefaultParametricCS(Map, CoordinateSystemAxis) + * @see GeodeticAuthorityFactory#createParametricCS(String) + */ + public DefaultParametricCS createParametricCS(Map<String, ?> properties, CoordinateSystemAxis axis) throws FactoryException { + final DefaultParametricCS cs; + try { + cs = new DefaultParametricCS(complete(properties), axis); + } catch (IllegalArgumentException exception) { + throw new InvalidGeodeticParameterException(exception); + } + return unique("createParametricCS", cs); + } + + /** * Creates a compound coordinate reference system from an ordered list of {@code CoordinateReferenceSystem} objects. * Apache SIS puts no restriction on the components that can be used in a compound CRS. * However for better inter-operability, users are encouraged to follow the order mandated by ISO 19162: @@ -1458,6 +1556,7 @@ public class GeodeticObjectFactory exten * @throws FactoryException if the object creation failed. * * @see XML#unmarshal(String) + * @see org.apache.sis.referencing.CRS#fromXML(String) */ @Override public CoordinateReferenceSystem createFromXML(final String xml) throws FactoryException { Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -341,7 +341,7 @@ public class IdentifiedObjectFinder { * If the set returned by {@link #find(IdentifiedObject)} contains exactly one element, * then that element is returned. Otherwise this method returns {@code null}. * - * <p>Note that this method returns {@code null} even if there is more than one element, + * <p>This method returns {@code null} if there is more than one element * because in such case we consider that there is an ambiguity.</p> * * @param object The object looked up. Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -1591,11 +1591,11 @@ public class MultiAuthoritiesFactory ext */ public void reload() { for (int type=0; type < providers.length; type++) { - Iterable<?> provider = providers[type]; + final Iterable<?> provider = providers[type]; if (provider != null) { synchronized (provider) { if (provider instanceof LazySet<?>) { - provider = ((LazySet<?>) provider).reload(); + ((LazySet<?>) provider).reload(); } if (provider instanceof ServiceLoader<?>) { ((ServiceLoader<?>) provider).reload(); Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -67,10 +67,12 @@ import org.opengis.referencing.Identifie import org.opengis.referencing.NoSuchAuthorityCodeException; import org.apache.sis.internal.metadata.ReferencingServices; import org.apache.sis.internal.metadata.TransformationAccuracy; +import org.apache.sis.internal.metadata.WKTKeywords; import org.apache.sis.internal.metadata.sql.SQLUtilities; import org.apache.sis.internal.referencing.DeprecatedCode; import org.apache.sis.internal.referencing.EPSGParameterDomain; import org.apache.sis.internal.referencing.ReferencingUtilities; +import org.apache.sis.internal.referencing.SignReversalComment; import org.apache.sis.internal.referencing.Formulas; import org.apache.sis.internal.system.Loggers; import org.apache.sis.internal.system.Semaphores; @@ -121,6 +123,8 @@ import org.apache.sis.internal.jdk7.JDK7 import org.apache.sis.internal.jdk8.JDK8; import org.apache.sis.internal.jdk7.AutoCloseable; import org.apache.sis.internal.util.StandardDateFormat; +import org.apache.sis.referencing.cs.DefaultParametricCS; +import org.apache.sis.referencing.datum.DefaultParametricDatum; /** @@ -1064,13 +1068,13 @@ addURIs: for (int i=0; ; i++) { * @param table The table on which a query has been executed. * @param name The name for the {@link IndentifiedObject} to construct. * @param code The EPSG code of the object to construct. - * @param remarks Remarks, or {@code null} if none. + * @param remarks Remarks as a {@link String} or {@link InternationalString}, or {@code null} if none. * @param deprecated {@code true} if the object to create is deprecated. * @return The name together with a set of properties. */ @SuppressWarnings("ReturnOfCollectionOrArrayField") private Map<String,Object> createProperties(final String table, String name, final Integer code, - String remarks, final boolean deprecated) throws SQLException, FactoryDataException + CharSequence remarks, final boolean deprecated) throws SQLException, FactoryDataException { /* * Search for aliases. Note that searching for the object code is not sufficient. We also need to check if the @@ -1172,8 +1176,12 @@ addURIs: for (int i=0; ; i++) { * @return The name together with a set of properties. */ private Map<String,Object> createProperties(final String table, final String name, final Integer code, - final String domainCode, String scope, String remarks, final boolean deprecated) throws SQLException, FactoryException + final String domainCode, String scope, final String remarks, final boolean deprecated) + throws SQLException, FactoryException { + if ("?".equals(scope)) { // EPSG sometime uses this value for unspecified scope. + scope = null; + } final Map<String,Object> properties = createProperties(table, name, code, remarks, deprecated); if (domainCode != null) { properties.put(Datum.DOMAIN_OF_VALIDITY_KEY, owner.createExtent(domainCode)); @@ -1537,6 +1545,15 @@ addURIs: for (int i=0; ; i++) { name, epsg, area, scope, remarks, deprecated), datum, cs); } /* ---------------------------------------------------------------------- + * PARAMETRIC CRS + * ---------------------------------------------------------------------- */ + else if (type.equalsIgnoreCase("engineering")) { + final DefaultParametricCS cs = owner.createParametricCS (getString(code, result, 8)); + final DefaultParametricDatum datum = owner.createParametricDatum(getString(code, result, 9)); + crs = ReferencingServices.getInstance().createParametricCRS(createProperties("Coordinate Reference System", + name, epsg, area, scope, remarks, deprecated), datum, cs, crsFactory); + } + /* ---------------------------------------------------------------------- * UNKNOWN CRS * ---------------------------------------------------------------------- */ else { @@ -1685,6 +1702,9 @@ addURIs: for (int i=0; ; i++) { else if (type.equalsIgnoreCase("engineering")) { datum = datumFactory.createEngineeringDatum(properties); } + else if (type.equalsIgnoreCase("parametric")) { + datum = ReferencingServices.getInstance().createParametricDatum(properties, datumFactory); + } else { throw new FactoryDataException(error().getString(Errors.Keys.UnknownType_1, type)); } @@ -2136,49 +2156,54 @@ addURIs: for (int i=0; ; i++) { final CSFactory csFactory = owner.csFactory; CoordinateSystem cs = null; { // On the JDK7 branch, this is a switch on strings. - if (type.equalsIgnoreCase("ellipsoidal")) { + if (type.equalsIgnoreCase(WKTKeywords.ellipsoidal)) { switch (dimension) { case 2: cs = csFactory.createEllipsoidalCS(properties, axes[0], axes[1]); break; case 3: cs = csFactory.createEllipsoidalCS(properties, axes[0], axes[1], axes[2]); break; } } - else if (type.equalsIgnoreCase("cartesian")) { + else if (type.equalsIgnoreCase("cartesian")) { // Need lower-case "c" switch (dimension) { case 2: cs = csFactory.createCartesianCS(properties, axes[0], axes[1]); break; case 3: cs = csFactory.createCartesianCS(properties, axes[0], axes[1], axes[2]); break; } } - else if (type.equalsIgnoreCase("spherical")) { + else if (type.equalsIgnoreCase(WKTKeywords.spherical)) { switch (dimension) { case 3: cs = csFactory.createSphericalCS(properties, axes[0], axes[1], axes[2]); break; } } - else if (type.equalsIgnoreCase("vertical") || type.equalsIgnoreCase("gravity-related")) { + else if (type.equalsIgnoreCase(WKTKeywords.vertical) || type.equalsIgnoreCase("gravity-related")) { switch (dimension) { case 1: cs = csFactory.createVerticalCS(properties, axes[0]); break; } } - else if (type.equalsIgnoreCase("time") || type.equalsIgnoreCase("temporal")) { + else if (type.equalsIgnoreCase("time") || type.equalsIgnoreCase(WKTKeywords.temporal)) { switch (dimension) { case 1: cs = csFactory.createTimeCS(properties, axes[0]); break; } } - else if (type.equalsIgnoreCase("linear")) { + else if (type.equalsIgnoreCase(WKTKeywords.parametric)) { + switch (dimension) { + case 1: cs = ReferencingServices.getInstance().createParametricCS(properties, axes[0], csFactory); break; + } + } + else if (type.equalsIgnoreCase(WKTKeywords.linear)) { switch (dimension) { case 1: cs = csFactory.createLinearCS(properties, axes[0]); break; } } - else if (type.equalsIgnoreCase("polar")) { + else if (type.equalsIgnoreCase(WKTKeywords.polar)) { switch (dimension) { case 2: cs = csFactory.createPolarCS(properties, axes[0], axes[1]); break; } } - else if (type.equalsIgnoreCase("cylindrical")) { + else if (type.equalsIgnoreCase(WKTKeywords.cylindrical)) { switch (dimension) { case 3: cs = csFactory.createCylindricalCS(properties, axes[0], axes[1], axes[2]); break; } } - else if (type.equalsIgnoreCase("affine")) { + else if (type.equalsIgnoreCase(WKTKeywords.affine)) { switch (dimension) { case 2: cs = csFactory.createAffineCS(properties, axes[0], axes[1]); break; case 3: cs = csFactory.createAffineCS(properties, axes[0], axes[1], axes[2]); break; @@ -2506,10 +2531,10 @@ addURIs: for (int i=0; ; i++) { " WHERE PARAMETER_CODE = ?", code); while (result.next()) { - final Integer epsg = getInteger (code, result, 1); - final String name = getString (code, result, 2); - final String remarks = getOptionalString (result, 3); - final boolean deprecated = getOptionalBoolean(result, 4); + final Integer epsg = getInteger (code, result, 1); + final String name = getString (code, result, 2); + final String description = getOptionalString (result, 3); + final boolean deprecated = getOptionalBoolean(result, 4); Class<?> type = Double.class; /* * If the parameter appears to have at least one non-null value in the "Parameter File Name" column, @@ -2560,6 +2585,29 @@ next: while (r.next()) { r.close(); } /* + * Determines if the inverse operation can be performed by reversing the parameter sign. + * The EPSG dataset uses "Yes" or "No" value, but SIS scripts use boolean type. We have + * to accept both. + */ + InternationalString isReversible = null; + r = executeQuery("ParameterSign", + "SELECT DISTINCT PARAM_SIGN_REVERSAL FROM [Coordinate_Operation Parameter Usage]" + + " WHERE (PARAMETER_CODE = ?)", epsg); + try { + if (r.next()) { + final String v = r.getString(1); + if (v != null && !r.next()) { + if (v.equalsIgnoreCase("true") || v.equalsIgnoreCase("yes") || v.equals("1")) { + isReversible = SignReversalComment.OPPOSITE; + } else if (v.equalsIgnoreCase("false") || v.equalsIgnoreCase("no") || v.equals("0")) { + isReversible = SignReversalComment.SAME; + } + } + } + } finally { + r.close(); + } + /* * Now creates the parameter descriptor. */ final NumberRange<?> valueDomain; @@ -2569,9 +2617,11 @@ next: while (r.next()) { case 1: valueDomain = MeasurementRange.create(Double.NEGATIVE_INFINITY, false, Double.POSITIVE_INFINITY, false, CollectionsExt.first(units)); break; } + final Map<String, Object> properties = + createProperties("Coordinate_Operation Parameter", name, epsg, isReversible, deprecated); + properties.put(ImmutableIdentifier.DESCRIPTION_KEY, description); @SuppressWarnings({"unchecked", "rawtypes"}) - final ParameterDescriptor<?> descriptor = new DefaultParameterDescriptor( - createProperties("Coordinate_Operation Parameter", name, epsg, remarks, deprecated), + final ParameterDescriptor<?> descriptor = new DefaultParameterDescriptor(properties, 1, 1, type, valueDomain, null, null); returnValue = ensureSingleton(descriptor, returnValue, code); } @@ -2974,6 +3024,7 @@ next: while (r.next()) { } } opProperties.put(ReferencingServices.OPERATION_TYPE_KEY, opType); + opProperties.put(ReferencingServices.PARAMETERS_KEY, parameters); /* * Following restriction will be removed in a future SIS version if the method is added to GeoAPI. */ Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -202,7 +202,7 @@ public abstract class InstallationScript * * @param authority The value given at construction time (e.g. {@code "EPSG"}). * @param resource Index of the SQL script to read, from 0 inclusive to - * <code>{@linkplain #getScriptNames()}.length</code> exclusive. + * <code>{@linkplain #getResourceNames getResourceNames}(authority).length</code> exclusive. * @return A reader for the content of SQL script to execute. * @throws IllegalArgumentException if the given {@code authority} argument is not the expected value. * @throws IndexOutOfBoundsException if the given {@code resource} argument is out of bounds. @@ -239,7 +239,7 @@ public abstract class InstallationScript * * <div class="note"><b>Example 1:</b> * if this {@code InstallationScriptProvider} instance gets the SQL scripts from files in a well-known directory - * and if the names given at {@linkplain #InstallationScriptProvider(String...) construction time} are the + * and if the names given at {@linkplain #InstallationScriptProvider(String, String...) construction time} are the * filenames in that directory, then this method can be implemented as below: * * {@preformat java Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/TableInfo.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/TableInfo.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/TableInfo.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/TableInfo.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -22,6 +22,7 @@ import org.opengis.referencing.crs.*; import org.opengis.referencing.datum.*; import org.opengis.referencing.operation.*; import org.opengis.parameter.ParameterDescriptor; +import org.apache.sis.internal.metadata.WKTKeywords; /** @@ -53,19 +54,31 @@ final class TableInfo { "COORD_REF_SYS_CODE", "COORD_REF_SYS_NAME", "COORD_REF_SYS_KIND", - new Class<?>[] { ProjectedCRS.class, GeographicCRS.class, GeocentricCRS.class, - VerticalCRS.class, CompoundCRS.class, EngineeringCRS.class}, - new String[] {"projected", "geographic", "geocentric", - "vertical", "compound", "engineering"}, + new Class<?>[] { ProjectedCRS.class, GeographicCRS.class, GeocentricCRS.class, + VerticalCRS.class, CompoundCRS.class, EngineeringCRS.class}, + // TemporalCRS.class, ParametricCRS.class (See comment below) + new String[] {"projected", "geographic", "geocentric", + "vertical", "compound", "engineering"}, + // "temporal", "parametric" "SHOW_CRS"), + /* + * Above declaration omitted Temporal and Parametric cases because they are not defined + * by the EPSG registry (at least as of version 8.9). In particular, we are not sure if + * EPSG would chose to use "time" or "temporal". Omitting those types for now does not + * prevent SIS to find CRS of those types; the operation will only be more costly. + */ new TableInfo(CoordinateSystem.class, "[Coordinate System]", "COORD_SYS_CODE", "COORD_SYS_NAME", "COORD_SYS_TYPE", - new Class<?>[] { CartesianCS.class, EllipsoidalCS.class, SphericalCS.class, VerticalCS.class}, - new String[] {"Cartesian", "ellipsoidal", "spherical", "vertical"}, //Really upper-case C. + new Class<?>[] {CartesianCS.class, EllipsoidalCS.class, VerticalCS.class, LinearCS.class, + SphericalCS.class, PolarCS.class, CylindricalCS.class}, + // TimeCS.class, ParametricCS.class, AffineCS.class (see above comment) + new String[] {WKTKeywords.Cartesian, WKTKeywords.ellipsoidal, WKTKeywords.vertical, WKTKeywords.linear, + WKTKeywords.spherical, WKTKeywords.polar, WKTKeywords.cylindrical}, + // WKTKeywords.temporal, WKTKeywords.parametric, WKTKeywords.affine null), new TableInfo(CoordinateSystemAxis.class, @@ -80,8 +93,10 @@ final class TableInfo { "DATUM_CODE", "DATUM_NAME", "DATUM_TYPE", - new Class<?>[] { GeodeticDatum.class, VerticalDatum.class, EngineeringDatum.class}, - new String[] {"geodetic", "vertical", "engineering"}, + new Class<?>[] { GeodeticDatum.class, VerticalDatum.class, EngineeringDatum.class}, + // TemporalDatum.class, ParametricDatum.class (see above comment), + new String[] {"geodetic", "vertical", "engineering"}, + // "temporal", "parametric", null), new TableInfo(Ellipsoid.class, Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -35,6 +35,7 @@ import org.opengis.referencing.operation import org.opengis.referencing.operation.CoordinateOperation; import org.opengis.referencing.operation.OperationMethod; import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.PassThroughOperation; import org.opengis.parameter.GeneralParameterValue; import org.opengis.parameter.ParameterDescriptorGroup; import org.opengis.parameter.ParameterValueGroup; @@ -158,7 +159,7 @@ public class AbstractCoordinateOperation * (i.e., instantiation due to the stochastic nature of the parameters). * * <p><b>Consider this field as final!</b> - * This field is modified only at unmarshalling time by {@link #setOperationVersion(String)}</p> + * This field is modified only at unmarshalling time by {@link #setOperationVersion(String)}.</p> * * @see #getOperationVersion() */ @@ -179,7 +180,7 @@ public class AbstractCoordinateOperation * Area in which this operation is valid, or {@code null} if not available. * * <p><b>Consider this field as final!</b> - * This field is modified only at unmarshalling time by {@link #setDomainOfValidity(Extent)}</p> + * This field is modified only at unmarshalling time by {@link #setDomainOfValidity(Extent)}.</p> * * @see #getDomainOfValidity() */ @@ -189,7 +190,7 @@ public class AbstractCoordinateOperation * Description of domain of usage, or limitations of usage, for which this operation is valid. * * <p><b>Consider this field as final!</b> - * This field is modified only at unmarshalling time by {@link #setScope(InternationalString)}</p> + * This field is modified only at unmarshalling time by {@link #setScope(InternationalString)}.</p> * * @see #getScope() */ @@ -201,7 +202,7 @@ public class AbstractCoordinateOperation * * <p><b>Consider this field as final!</b> * This field is non-final only for the convenience of constructors and for initialization - * at XML unmarshalling time by {@link AbstractSingleOperation#afterUnmarshal(Unmarshaller, Object)}</p> + * at XML unmarshalling time by {@link AbstractSingleOperation#afterUnmarshal(Unmarshaller, Object)}.</p> */ MathTransform transform; @@ -513,7 +514,7 @@ check: for (int isTarget=0; ; isTar /** * Returns the interpolation CRS of the given coordinate operation, or {@code null} if none. */ - private static CoordinateReferenceSystem getInterpolationCRS(final CoordinateOperation operation) { + static CoordinateReferenceSystem getInterpolationCRS(final CoordinateOperation operation) { return (operation instanceof AbstractCoordinateOperation) ? ((AbstractCoordinateOperation) operation).getInterpolationCRS() : null; } @@ -556,33 +557,34 @@ check: for (int isTarget=0; ; isTar * Note that those rules may change in any future SIS version. * * <ul> - * <li>If a {@linkplain org.apache.sis.metadata.iso.quality.DefaultQuantitativeResult quantitative result} - * is found with a linear unit, then this accuracy estimate is converted to - * {@linkplain javax.measure.unit.SI#METRE metres} and returned.</li> - * - * <li>Otherwise, if the operation is a {@linkplain DefaultConversion conversion}, then returns 0 since a - * conversion is by definition accurate up to rounding errors.</li> - * - * <li>Otherwise, if the operation is a {@linkplain DefaultTransformation transformation}, then checks if - * the datum shift were applied with the help of Bursa-Wolf parameters. - * If a datum shift has been applied, returns 25 meters. - * If a datum shift should have been applied but has been omitted, returns 3000 meters. - * - * <div class="note"><b>Note:</b> - * the 3000 meters value is higher than the highest value (999 meters) found in the EPSG - * database version 6.7. The 25 meters value is the next highest value found in the EPSG - * database for a significant number of transformations.</div> - * - * <li>Otherwise, if the operation is a {@linkplain DefaultConcatenatedOperation concatenated operation}, - * returns the sum of the accuracy of all components. This is a conservative scenario where we assume that - * errors cumulate linearly. - * - * <div class="note"><b>Note:</b> - * this is not necessarily the "worst case" scenario since the accuracy could be worst if the math transforms - * are highly non-linear.</div></li> + * <li>If at least one {@linkplain org.apache.sis.metadata.iso.quality.DefaultQuantitativeResult quantitative + * result} is found with a linear unit, then returns the largest result value converted to metres.</li> + * + * <li>Otherwise if the operation is a {@linkplain DefaultConversion conversion}, + * then returns 0 since a conversion is by definition accurate up to rounding errors.</li> + * + * <li>Otherwise if the operation is a {@linkplain DefaultTransformation transformation}, + * then checks if the datum shift were applied with the help of Bursa-Wolf parameters. + * If a datum shift has been applied, returns 25 meters. + * If a datum shift should have been applied but has been omitted, returns 3000 meters. + * + * <div class="note"><b>Note:</b> + * the 3000 meters value is higher than the highest value (999 meters) found in the EPSG + * database version 6.7. The 25 meters value is the next highest value found in the EPSG + * database for a significant number of transformations.</div> + * + * <li>Otherwise if the operation is a {@linkplain DefaultConcatenatedOperation concatenated operation}, + * returns the sum of the accuracy of all components. + * This is a conservative scenario where we assume that errors cumulate linearly. + * + * <div class="note"><b>Note:</b> + * this is not necessarily the "worst case" scenario since the accuracy could be worst + * if the math transforms are highly non-linear.</div></li> * </ul> * * @return The accuracy estimation (always in meters), or NaN if unknown. + * + * @see org.apache.sis.referencing.CRS#getLinearAccuracy(CoordinateOperation) */ public double getLinearAccuracy() { return PositionalAccuracyConstant.getLinearAccuracy(this); @@ -858,12 +860,17 @@ check: for (int isTarget=0; ; isTar super.formatTo(formatter); formatter.newLine(); /* - * If the WKT is a component of a ConcatenatedOperation, do not format the source and target CRS. - * This decision SIS-specific since the WKT 2 specification does not define concatenated operations. - * The choice of content to omit may change in any future version. + * If the WKT is a component of a ConcatenatedOperation, do not format the source CRS since it is identical + * to the target CRS of the previous step, or to the source CRS of the enclosing "ConcatenatedOperation" if + * this step is the first step. + * + * This decision is SIS-specific since the WKT 2 specification does not define concatenated operations. + * This choice may change in any future SIS version. */ - final boolean isComponent = (formatter.getEnclosingElement(1) instanceof ConcatenatedOperation); - if (!isComponent) { + final FormattableObject enclosing = formatter.getEnclosingElement(1); + final boolean isSubOperation = (enclosing instanceof PassThroughOperation); + final boolean isComponent = (enclosing instanceof ConcatenatedOperation); + if (!isSubOperation && !isComponent) { append(formatter, getSourceCRS(), WKTKeywords.SourceCRS); append(formatter, getTargetCRS(), WKTKeywords.TargetCRS); } @@ -880,12 +887,14 @@ check: for (int isTarget=0; ; isTar } if (parameters != null) { formatter.newLine(); + formatter.indent(+1); for (final GeneralParameterValue param : parameters.values()) { WKTUtilities.append(param, formatter); } + formatter.indent(-1); } } - if (!isComponent) { + if (!isSubOperation && !(this instanceof ConcatenatedOperation)) { append(formatter, getInterpolationCRS(), WKTKeywords.InterpolationCRS); final double accuracy = getLinearAccuracy(); if (accuracy > 0) { @@ -900,7 +909,7 @@ check: for (int isTarget=0; ; isTar if (formatter.getConvention().majorVersion() == 1) { formatter.setInvalidWKT(this, null); } - return WKTKeywords.CoordinateOperation; + return isComponent ? "CoordinateOperationStep" : WKTKeywords.CoordinateOperation; } /** Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -18,6 +18,7 @@ package org.apache.sis.referencing.opera import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.IdentifiedObject; +import org.apache.sis.referencing.AbstractIdentifiedObject; import org.apache.sis.referencing.IdentifiedObjects; import org.apache.sis.util.CharSequences; import org.apache.sis.util.Classes; @@ -44,8 +45,8 @@ final class CRSPair { /** * Creates a {@code CRSPair} for the specified source and target CRS. */ - public CRSPair(final CoordinateReferenceSystem sourceCRS, - final CoordinateReferenceSystem targetCRS) + CRSPair(final CoordinateReferenceSystem sourceCRS, + final CoordinateReferenceSystem targetCRS) { this.sourceCRS = sourceCRS; this.targetCRS = targetCRS; @@ -78,24 +79,34 @@ final class CRSPair { } /** - * Returns a name for the given object, truncating it if needed. + * Returns the name of the GeoAPI interface implemented by the specified object, + * followed by the name between brackets. */ - static String shortName(final IdentifiedObject object) { - String name = IdentifiedObjects.getName(object, null); - if (name == null) { - name = Classes.getShortClassName(object); + static String label(final IdentifiedObject object) { + if (object == null) { + return null; + } + Class<? extends IdentifiedObject> type; + if (object instanceof AbstractIdentifiedObject) { + type = ((AbstractIdentifiedObject) object).getInterface(); } else { - int i = 30; // Arbitrary length threshold. + type = Classes.getLeafInterfaces(object.getClass(), IdentifiedObject.class)[0]; + } + String label = Classes.getShortName(type); + String name = IdentifiedObjects.getName(object, null); + if (name != null) { + int i = 30; // Arbitrary length threshold. if (name.length() >= i) { - while (i > 15) { // Arbitrary minimal length. + while (i > 15) { // Arbitrary minimal length. final int c = name.codePointBefore(i); if (Character.isSpaceChar(c)) break; i -= Character.charCount(c); } name = CharSequences.trimWhitespaces(name, 0, i).toString() + '…'; } + label = label + "[“" + name + "”]"; } - return name; + return label; } /** @@ -103,6 +114,6 @@ final class CRSPair { */ @Override public String toString() { - return shortName(sourceCRS) + " → " + shortName(targetCRS); + return label(sourceCRS) + " → " + label(targetCRS); } } Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -19,11 +19,15 @@ package org.apache.sis.referencing.opera import java.io.Serializable; import org.opengis.metadata.extent.Extent; import org.opengis.metadata.extent.GeographicBoundingBox; +import org.opengis.referencing.operation.CoordinateOperation; import org.apache.sis.metadata.iso.extent.DefaultExtent; import org.apache.sis.metadata.iso.extent.Extents; import org.apache.sis.internal.util.CollectionsExt; import org.apache.sis.util.ArgumentChecks; +// Branch-dependent imports +import org.apache.sis.internal.jdk8.Predicate; + /** * Optional information about the context in which a requested coordinate operation will be used. @@ -38,7 +42,7 @@ import org.apache.sis.util.ArgumentCheck * to choose the most suitable coordinate transformation between two CRS. * * <div class="note"><b>Example:</b> - * if a transformation from NAD27 to NAD83 is requested without providing context, then Apache SIS will return the + * if a transformation from NAD27 to WGS84 is requested without providing context, then Apache SIS will return the * transformation applicable to the widest North American surface. But if the user provides a context saying that * he wants to transform coordinates in Texas, then Apache SIS may return another coordinate transformation with * different {@linkplain org.apache.sis.referencing.datum.BursaWolfParameters Bursa-Wolf parameters} more suitable @@ -66,11 +70,6 @@ public class CoordinateOperationContext private Extent areaOfInterest; /** - * The geographic component of the area of interest, computed when first needed. - */ - private transient GeographicBoundingBox bbox; - - /** * The desired accuracy in metres, or 0 for the best accuracy available. * See {@link #getDesiredAccuracy()} for more details about what we mean by <cite>"best accuracy"</cite>. */ @@ -99,6 +98,8 @@ public class CoordinateOperationContext * Returns the spatio-temporal area of interest, or {@code null} if none. * * @return The spatio-temporal area of interest, or {@code null} if none. + * + * @see Extents#getGeographicBoundingBox(Extent) */ public Extent getAreaOfInterest() { return areaOfInterest; @@ -109,32 +110,24 @@ public class CoordinateOperationContext * * @param area The spatio-temporal area of interest, or {@code null} if none. */ - public void setAreaOfInterest(final Extent area) { - areaOfInterest = area; - } - - /** - * Returns the geographic component of the area of interest, or {@code null} if none. - * This convenience method extracts the bounding box from the spatio-temporal {@link Extent}. - * - * @return The geographic area of interest, or {@code null} if none. - */ - public GeographicBoundingBox getGeographicBoundingBox() { - if (bbox == null) { - bbox = Extents.getGeographicBoundingBox(areaOfInterest); + public void setAreaOfInterest(Extent area) { + if (area != null) { + area = new DefaultExtent(area); } - return bbox; + areaOfInterest = area; } /** * Sets the geographic component of the area of interest, or {@code null} if none. * This convenience method set the bounding box into the spatio-temporal {@link Extent}. * + * <p>The reverse operation can be done with <code>{@linkplain Extents#getGeographicBoundingBox(Extent) + * Extents.getGeographicBoundingBox}({@linkplain #getAreaOfInterest()})</code>.</p> + * * @param area The geographic area of interest, or {@code null} if none. */ - public void setGeographicBoundingBox(final GeographicBoundingBox area) { + public void setAreaOfInterest(final GeographicBoundingBox area) { areaOfInterest = setGeographicBoundingBox(areaOfInterest, area); - bbox = area; } /** @@ -177,4 +170,13 @@ public class CoordinateOperationContext ArgumentChecks.ensurePositive("accuracy", accuracy); desiredAccuracy = accuracy; } + + /** + * Returns a filter that can be used for applying additional restrictions on the coordinate operation. + * + * @todo Not yet implemented. + */ + Predicate<CoordinateOperation> getOperationFilter() { + return null; + } } Copied: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java (from r1740152, sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java) URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java?p2=sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java&p1=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java&r1=1740152&r2=1740177&rev=1740177&view=diff ============================================================================== --- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -672,7 +672,7 @@ class CoordinateOperationRegistry { method = DefaultOperationMethod.redimension(method, sourceDimensions, targetDimensions); } catch (IllegalArgumentException ex) { try { - method = factory.getOperationMethod(method.getName().getCode()); + method = factorySIS.getOperationMethod(method.getName().getCode()); method = DefaultOperationMethod.redimension(method, sourceDimensions, targetDimensions); } catch (NoSuchIdentifierException se) { // ex.addSuppressed(se) on the JDK7 branch. @@ -964,10 +964,10 @@ class CoordinateOperationRegistry { if (descriptor != null) { final Identifier name = descriptor.getName(); if (name != null) { - method = factory.getOperationMethod(name.getCode()); + method = factorySIS.getOperationMethod(name.getCode()); } if (method == null) { - method = factory.createOperationMethod(properties, + method = factorySIS.createOperationMethod(properties, sourceCRS.getCoordinateSystem().getDimension(), targetCRS.getCoordinateSystem().getDimension(), descriptor); Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java?rev=1740177&r1=1740176&r2=1740177&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java [UTF-8] Wed Apr 20 17:40:11 2016 @@ -17,27 +17,22 @@ package org.apache.sis.referencing.operation; import java.util.Map; -import java.util.Set; import java.util.List; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; -import java.util.LinkedHashSet; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import org.opengis.util.FactoryException; -import org.opengis.metadata.quality.PositionalAccuracy; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.CoordinateOperation; import org.opengis.referencing.operation.ConcatenatedOperation; import org.opengis.referencing.operation.Transformation; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.MathTransformFactory; +import org.apache.sis.internal.referencing.PositionalAccuracyConstant; import org.apache.sis.internal.system.DefaultFactories; import org.apache.sis.internal.util.UnmodifiableArrayList; -import org.apache.sis.internal.util.CollectionsExt; -import org.apache.sis.util.collection.Containers; import org.apache.sis.util.ComparisonMode; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.resources.Errors; @@ -115,9 +110,8 @@ final class DefaultConcatenatedOperation { super(properties); ArgumentChecks.ensureNonNull("operations", operations); - final boolean setAccuracy = (coordinateOperationAccuracy == null); final List<CoordinateOperation> flattened = new ArrayList<CoordinateOperation>(operations.length); - initialize(properties, operations, flattened, mtFactory, setAccuracy); + initialize(properties, operations, flattened, mtFactory, (coordinateOperationAccuracy == null)); if (flattened.size() < 2) { throw new IllegalArgumentException(Errors.getResources(properties).getString( Errors.Keys.TooFewOccurrences_2, 2, CoordinateOperation.class)); @@ -128,10 +122,6 @@ final class DefaultConcatenatedOperation this.operations = UnmodifiableArrayList.wrap((SingleOperation[]) operations); this.sourceCRS = operations[0].getSourceCRS(); this.targetCRS = operations[operations.length - 1].getTargetCRS(); - if (setAccuracy) { - coordinateOperationAccuracy = CollectionsExt.unmodifiableOrCopy( - (Set<PositionalAccuracy>) coordinateOperationAccuracy); - } checkDimensions(properties); } @@ -150,11 +140,11 @@ final class DefaultConcatenatedOperation * in the given list. This should not happen according ISO 19111 standard, but we try to be safe. * * <div class="section">How coordinate operation accuracy is determined</div> - * If {@code setAccuracy} is {@code true}, then this method collects all accuracy information found in the - * {@link Transformation} instances. This method ignores instances of other kinds for the following reason: + * If {@code setAccuracy} is {@code true}, then this method copies accuracy information found in the single + * {@link Transformation} instance. This method ignores instances of other kinds for the following reason: * some {@link Conversion} instances declare an accuracy, which is typically close to zero. If a concatenated * operation contains such conversion together with a transformation with unknown accuracy, then we do not want - * to declare that a 0 meter error as the concatenated operation accuracy; it would be a false information. + * to declare "0 meter" as the concatenated operation accuracy; it would be a false information. * An other reason is that a concatenated operation typically contains an arbitrary amount of conversions, * but only one transformation. So considering only transformations usually means to pickup only one operation * in the given {@code operations} list, which make things clearer. @@ -177,7 +167,7 @@ final class DefaultConcatenatedOperation final CoordinateOperation[] operations, final List<CoordinateOperation> flattened, final MathTransformFactory mtFactory, - final boolean setAccuracy) + boolean setAccuracy) throws FactoryException { CoordinateReferenceSystem previous = null; @@ -221,16 +211,22 @@ final class DefaultConcatenatedOperation transform = (transform != null) ? mtFactory.createConcatenatedTransform(transform, step) : step; } /* - * Optionally update the coordinate operation accuracy. - * See javadoc for a rational about why we take only transformations in account. + * Optionally copy the coordinate operation accuracy from the transformation (or from a concatenated + * operation on the assumption that its accuracy was computed by the same algorithm than this method). + * See javadoc for a rational about why we take only transformations in account. If more than one + * transformation is found, clear the collection and abandon the attempt to set the accuracy information. + * Instead the user will get a better result by invoking PositionalAccuracyConstant.getLinearAccuracy(…) + * since that method conservatively computes the sum of all linear accuracy. */ - if (setAccuracy && op instanceof Transformation) { - Collection<PositionalAccuracy> candidates = op.getCoordinateOperationAccuracy(); - if (!Containers.isNullOrEmpty(candidates)) { - if (coordinateOperationAccuracy == null) { - coordinateOperationAccuracy = new LinkedHashSet<PositionalAccuracy>(); + if (setAccuracy && (op instanceof Transformation || op instanceof ConcatenatedOperation)) { + if (coordinateOperationAccuracy == null) { + setAccuracy = (PositionalAccuracyConstant.getLinearAccuracy(op) > 0); + if (setAccuracy) { + coordinateOperationAccuracy = op.getCoordinateOperationAccuracy(); } - coordinateOperationAccuracy.addAll(candidates); + } else { + coordinateOperationAccuracy = null; + setAccuracy = false; } } } @@ -346,6 +342,7 @@ final class DefaultConcatenatedOperation protected String formatTo(final Formatter formatter) { super.formatTo(formatter); for (final CoordinateOperation component : operations) { + formatter.newLine(); formatter.append(castOrCopy(component)); } formatter.setInvalidWKT(this, null); @@ -391,8 +388,7 @@ final class DefaultConcatenatedOperation */ private void setSteps(final CoordinateOperation[] steps) throws FactoryException { final List<CoordinateOperation> flattened = new ArrayList<CoordinateOperation>(steps.length); - initialize(null, steps, flattened, DefaultFactories.forBuildin(MathTransformFactory.class), true); + initialize(null, steps, flattened, DefaultFactories.forBuildin(MathTransformFactory.class), coordinateOperationAccuracy == null); operations = UnmodifiableArrayList.wrap(flattened.toArray(new SingleOperation[flattened.size()])); - coordinateOperationAccuracy = CollectionsExt.unmodifiableOrCopy((Set<PositionalAccuracy>) coordinateOperationAccuracy); } }
