Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -437,7 +437,7 @@ public abstract class NormalizedProjecti context = initializer.context; eccentricitySquared = initializer.eccentricitySquared.value; eccentricity = sqrt(eccentricitySquared); // DoubleDouble.sqrt() does not make any difference here. - inverse = new Inverse(); + inverse = new Inverse(this); } /** @@ -450,7 +450,7 @@ public abstract class NormalizedProjecti context = other.context; eccentricity = other.eccentricity; eccentricitySquared = other.eccentricitySquared; - inverse = new Inverse(); + inverse = new Inverse(this); } /** @@ -725,20 +725,34 @@ public abstract class NormalizedProjecti * Inverse of a normalized map projection. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.6 * @module */ - private final class Inverse extends AbstractMathTransform2D.Inverse { + private static final class Inverse extends AbstractMathTransform2D.Inverse implements Serializable { /** * For cross-version compatibility. */ - private static final long serialVersionUID = -9138242780765956870L; + private static final long serialVersionUID = 6014176098150309651L; + + /** + * The enclosing transform. + */ + private final NormalizedProjection forward; /** * Default constructor. */ - Inverse() { + Inverse(final NormalizedProjection forward) { + this.forward = forward; + } + + /** + * Returns the inverse of this math transform. + */ + @Override + public MathTransform2D inverse() { + return forward; } /** @@ -752,15 +766,15 @@ public abstract class NormalizedProjecti final boolean derivate) throws TransformException { if (!derivate) { - inverseTransform(srcPts, srcOff, dstPts, dstOff); + forward.inverseTransform(srcPts, srcOff, dstPts, dstOff); return null; } else { if (dstPts == null) { dstPts = new double[DIMENSION]; dstOff = 0; } - inverseTransform(srcPts, srcOff, dstPts, dstOff); - return Matrices.inverse(NormalizedProjection.this.transform(dstPts, dstOff, null, 0, true)); + forward.inverseTransform(srcPts, srcOff, dstPts, dstOff); + return Matrices.inverse(forward.transform(dstPts, dstOff, null, 0, true)); } } @@ -775,7 +789,7 @@ public abstract class NormalizedProjecti if (srcPts == dstPts && srcOff < dstOff) { super.transform(srcPts, srcOff, dstPts, dstOff, numPts); } else while (--numPts >= 0) { - inverseTransform(srcPts, srcOff, dstPts, dstOff); + forward.inverseTransform(srcPts, srcOff, dstPts, dstOff); srcOff += DIMENSION; dstOff += DIMENSION; } @@ -796,7 +810,7 @@ public abstract class NormalizedProjecti * - false if applyOtherFirst == false since we have (inverse projection) → (affine) → (projection). * - true if applyOtherFirst == true since we have (projection) → (affine) → (inverse projection). */ - return NormalizedProjection.this.tryConcatenate(applyOtherFirst, m, factory); + return forward.tryConcatenate(applyOtherFirst, m, factory); } return super.tryConcatenate(applyOtherFirst, other, factory); }
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ZonedGridSystem.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ZonedGridSystem.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ZonedGridSystem.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ZonedGridSystem.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -131,7 +131,7 @@ public class ZonedGridSystem extends Abs final MatrixSIS normalize = initializer.context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION); normalize.convertBefore(0, null, zoneWidth / -2); projection = (AbstractMathTransform) new TransverseMercator(initializer).createMapProjection(factory); - inverse = new Inverse(); + inverse = new Inverse(this); } @@ -185,15 +185,20 @@ public class ZonedGridSystem extends Abs * Inverse of a zoned grid system. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ - private final class Inverse extends AbstractMathTransform2D.Inverse { + private static final class Inverse extends AbstractMathTransform2D.Inverse implements Serializable { /** * For cross-version compatibility. */ - private static final long serialVersionUID = 1900563285661407519L; + private static final long serialVersionUID = -4417726238412154175L; + + /** + * The enclosing transform. + */ + private final ZonedGridSystem forward; /** * The projection that performs the actual work after we removed the zone number. @@ -203,15 +208,24 @@ public class ZonedGridSystem extends Abs /** * Default constructor. */ - Inverse() throws FactoryException { + Inverse(final ZonedGridSystem forward) throws FactoryException { + this.forward = forward; try { - inverseProjection = (AbstractMathTransform) projection.inverse(); + inverseProjection = (AbstractMathTransform) forward.projection.inverse(); } catch (NoninvertibleTransformException e) { throw new FactoryException(e); // Should not happen. } } /** + * Returns the inverse of this math transform. + */ + @Override + public MathTransform2D inverse() { + return forward; + } + + /** * Inverse transforms the specified {@code srcPts} and stores the result in {@code dstPts}. * If the derivative has been requested, then this method will delegate the derivative * calculation to the enclosing class and inverts the resulting matrix. @@ -228,7 +242,7 @@ public class ZonedGridSystem extends Abs dstPts[dstOff ] = x; dstPts[dstOff+1] = y; final Matrix derivative = inverseProjection.transform(dstPts, dstOff, dstPts, dstOff, derivate); - dstPts[dstOff] += zone * zoneWidth + initialLongitude; + dstPts[dstOff] += zone * forward.zoneWidth + forward.initialLongitude; return derivative; } } Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/package-info.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -159,7 +159,7 @@ * @author Martin Desruisseaux (Geomatys) * @author Rémi Maréchal (Geomatys) * @author Adrian Custer (Geomatys) - * @version 0.8 + * @version 1.0 * * @see <a href="http://www.remotesensing.org/geotiff/proj_list">Projections list on RemoteSensing.org</a> * @see <a href="http://mathworld.wolfram.com/MapProjection.html">Map projections on MathWorld</a> Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -18,7 +18,6 @@ package org.apache.sis.referencing.opera import java.util.List; import java.util.Arrays; -import java.io.Serializable; import org.opengis.util.FactoryException; import org.opengis.geometry.DirectPosition; import org.opengis.geometry.MismatchedDimensionException; @@ -988,31 +987,20 @@ public abstract class AbstractMathTransf /** * Base class for implementations of inverse math transforms. - * This inner class is the inverse of the enclosing {@link AbstractMathTransform}. + * Subclasses need to implement the {@link #inverse()} method. * * <div class="section">Serialization</div> - * Instances of this class are serializable only if the enclosing math transform is also serializable. - * Serialized math transforms are not guaranteed to be compatible with future SIS versions. - * Serialization, if allowed, should be used only for short term storage or RMI between applications + * This object may or may not be serializable, at implementation choices. + * Most Apache SIS implementations are serializable, but the serialized objects are not guaranteed to be compatible + * with future SIS versions. Serialization should be used only for short term storage or RMI between applications * running the same SIS version. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.6 + * @version 1.0 * @since 0.5 * @module */ - protected abstract class Inverse extends AbstractMathTransform implements Serializable { - /** - * Serial number for inter-operability with different versions. This serial number is - * especially important for inner classes, since the default {@code serialVersionUID} - * computation will not produce consistent results across implementations of different - * Java compiler. This is because different compilers may generate different names for - * synthetic members used in the implementation of inner classes. See: - * - * http://developer.java.sun.com/developer/bugParade/bugs/4211550.html - */ - private static final long serialVersionUID = 3528274816628012283L; - + protected abstract static class Inverse extends AbstractMathTransform { /** * Constructs an inverse math transform. */ @@ -1021,29 +1009,32 @@ public abstract class AbstractMathTransf /** * Gets the dimension of input points. - * The implementation returns the dimension of output points of the enclosing math transform. + * The default implementation returns the dimension of output points + * of the {@linkplain #inverse() inverse} math transform. * * @return {@inheritDoc} */ @Override - public final int getSourceDimensions() { - return AbstractMathTransform.this.getTargetDimensions(); + public int getSourceDimensions() { + return inverse().getTargetDimensions(); } /** * Gets the dimension of output points. - * The implementation returns the dimension of input points of the enclosing math transform. + * The default implementation returns the dimension of input points + * of the {@linkplain #inverse() inverse} math transform. * * @return {@inheritDoc} */ @Override - public final int getTargetDimensions() { - return AbstractMathTransform.this.getSourceDimensions(); + public int getTargetDimensions() { + return inverse().getSourceDimensions(); } /** * Gets the derivative of this transform at a point. - * The default implementation computes the inverse of the matrix returned by the enclosing math transform. + * The default implementation computes the inverse of the matrix + * returned by the {@linkplain #inverse() inverse} math transform. * * @return {@inheritDoc} * @throws NullPointerException if the derivative depends on coordinate and {@code point} is {@code null}. @@ -1055,28 +1046,27 @@ public abstract class AbstractMathTransf if (point != null) { point = this.transform(point, null); } - return Matrices.inverse(AbstractMathTransform.this.derivative(point)); + return Matrices.inverse(inverse().derivative(point)); } /** - * Returns the inverse of this math transform, which is the enclosing math transform. + * Returns the inverse of this math transform. + * The returned transform should be the enclosing math transform. * - * @return the enclosing math transform. + * @return the inverse of this transform. */ @Override - public MathTransform inverse() { - return AbstractMathTransform.this; - } + public abstract MathTransform inverse(); /** * Tests whether this transform does not move any points. - * The default implementation delegates this tests to the enclosing math transform. + * The default implementation delegates this tests to the {@linkplain #inverse() inverse} math transform. * * @return {@inheritDoc} */ @Override public boolean isIdentity() { - return AbstractMathTransform.this.isIdentity(); + return inverse().isIdentity(); } /** @@ -1086,13 +1076,13 @@ public abstract class AbstractMathTransf */ @Override protected int computeHashCode() { - return super.computeHashCode() + 31*AbstractMathTransform.this.hashCode(); + return super.computeHashCode() + 31 * inverse().hashCode(); } /** * Compares the specified object with this inverse math transform for equality. - * The default implementation tests if {@code object} in an instance of the same class - * than {@code this}, and if so compares their enclosing {@code AbstractMathTransform}. + * The default implementation tests if {@code object} in an instance of the same class than {@code this}, + * and if so compares their {@linkplain #inverse() inverse} {@code MathTransform}. * * @return {@inheritDoc} */ @@ -1102,7 +1092,13 @@ public abstract class AbstractMathTransf return true; // Slight optimization } if (object != null && object.getClass() == getClass()) { - return AbstractMathTransform.this.equals(((Inverse) object).inverse(), mode); + final MathTransform other = ((Inverse) object).inverse(); + final MathTransform inverse = inverse(); + if (inverse instanceof LenientComparable) { + return ((LenientComparable) inverse).equals(other, mode); + } else { + return inverse.equals(other); + } } else { return false; } @@ -1118,7 +1114,12 @@ public abstract class AbstractMathTransf if (parameters != null) { return parameters.beforeFormat(transforms, index, inverse); } else { - return AbstractMathTransform.this.beforeFormat(transforms, index, !inverse); + final MathTransform inv = inverse(); + if (inv instanceof AbstractMathTransform) { + return ((AbstractMathTransform) inv).beforeFormat(transforms, index, !inverse); + } else { + return index; + } } } @@ -1143,7 +1144,7 @@ public abstract class AbstractMathTransf return WKTKeywords.Param_MT; } else { formatter.newLine(); - formatter.append((FormattableObject) AbstractMathTransform.this); + formatter.append((FormattableObject) inverse()); return WKTKeywords.Inverse_MT; } } Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform1D.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform1D.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform1D.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform1D.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -156,22 +156,17 @@ public abstract class AbstractMathTransf * This inner class is the inverse of the enclosing {@link AbstractMathTransform1D}. * * <div class="section">Serialization</div> - * Instances of this class are serializable only if the enclosing math transform is also serializable. - * Serialized math transforms are not guaranteed to be compatible with future SIS versions. - * Serialization, if allowed, should be used only for short term storage or RMI between applications + * This object may or may not be serializable, at implementation choices. + * Most Apache SIS implementations are serializable, but the serialized objects are not guaranteed to be compatible + * with future SIS versions. Serialization should be used only for short term storage or RMI between applications * running the same SIS version. * * @author Martin Desruisseaux (Geomatys) - * @version 0.7 + * @version 1.0 * @since 0.7 * @module */ - protected abstract class Inverse extends AbstractMathTransform.Inverse implements MathTransform1D { - /** - * Serial number for inter-operability with different versions. - */ - private static final long serialVersionUID = 2018412413506158560L; - + protected abstract static class Inverse extends AbstractMathTransform.Inverse implements MathTransform1D { /** * Constructs an inverse math transform. */ @@ -179,12 +174,11 @@ public abstract class AbstractMathTransf } /** - * Returns the enclosing math transform. + * Returns the inverse of this math transform. + * The returned transform should be the enclosing math transform. */ @Override - public MathTransform1D inverse() { - return (MathTransform1D) super.inverse(); - } + public abstract MathTransform1D inverse(); /** * Transforms a single point in the given array and opportunistically computes its derivative if requested. Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform2D.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -319,22 +319,17 @@ public abstract class AbstractMathTransf * This inner class is the inverse of the enclosing {@link AbstractMathTransform2D}. * * <div class="section">Serialization</div> - * Instances of this class are serializable only if the enclosing math transform is also serializable. - * Serialized math transforms are not guaranteed to be compatible with future SIS versions. - * Serialization, if allowed, should be used only for short term storage or RMI between applications + * This object may or may not be serializable, at implementation choices. + * Most Apache SIS implementations are serializable, but the serialized objects are not guaranteed to be compatible + * with future SIS versions. Serialization should be used only for short term storage or RMI between applications * running the same SIS version. * * @author Martin Desruisseaux (Geomatys) - * @version 0.5 + * @version 1.0 * @since 0.5 * @module */ - protected abstract class Inverse extends AbstractMathTransform.Inverse implements MathTransform2D { - /** - * Serial number for inter-operability with different versions. - */ - private static final long serialVersionUID = 5751908928042026412L; - + protected abstract static class Inverse extends AbstractMathTransform.Inverse implements MathTransform2D { /** * Constructs an inverse math transform. */ @@ -342,12 +337,11 @@ public abstract class AbstractMathTransf } /** - * Returns the enclosing math transform. + * Returns the inverse of this math transform. + * The returned transform should be the enclosing math transform. */ @Override - public MathTransform2D inverse() { - return (MathTransform2D) super.inverse(); - } + public abstract MathTransform2D inverse(); /** * Transforms the specified {@code ptSrc} and stores the result in {@code ptDst}. Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -299,7 +299,7 @@ public class EllipsoidToCentricTransform final MatrixSIS normalize = context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION); normalize.convertBefore(2, a, null); // Divide ellipsoidal height by a. } - inverse = new Inverse(); + inverse = new Inverse(this); } /** @@ -779,20 +779,34 @@ next: while (--numPts >= 0) { * to ellipsoidal coordinates (λ,φ) or (λ,φ,<var>h</var>). * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.7 + * @version 1.0 * @since 0.7 * @module */ - private final class Inverse extends AbstractMathTransform.Inverse implements Serializable { + private static final class Inverse extends AbstractMathTransform.Inverse implements Serializable { /** * Serial number for inter-operability with different versions. */ - private static final long serialVersionUID = 6942084702259211803L; + private static final long serialVersionUID = 33004303758761821L; + + /** + * The enclosing transform. + */ + private final EllipsoidToCentricTransform forward; /** * Creates the inverse of the enclosing transform. */ - Inverse() { + Inverse(final EllipsoidToCentricTransform forward) { + this.forward = forward; + } + + /** + * Returns the inverse of this math transform. + */ + @Override + public MathTransform inverse() { + return forward; } /** @@ -801,7 +815,7 @@ next: while (--numPts >= 0) { */ @Override protected ContextualParameters getContextualParameters() { - return context.inverse(GeocentricToGeographic.PARAMETERS); + return forward.context.inverse(GeocentricToGeographic.PARAMETERS); } /** @@ -812,7 +826,7 @@ next: while (--numPts >= 0) { @Override public ParameterValueGroup getParameterValues() { final ParameterValueGroup pg = getParameterDescriptors().createValue(); - pg.values().addAll(EllipsoidToCentricTransform.this.getParameterValues().values()); + pg.values().addAll(forward.getParameterValues().values()); return pg; } @@ -830,7 +844,7 @@ next: while (--numPts >= 0) { public ParameterDescriptorGroup getParameterDescriptors() { return new DefaultParameterDescriptorGroup(Collections.singletonMap(ParameterDescriptorGroup.NAME_KEY, new ImmutableIdentifier(Citations.SIS, Constants.SIS, "Centric to ellipsoid (radians domain)")), - EllipsoidToCentricTransform.this.getParameterDescriptors()); + forward.getParameterDescriptors()); } /** @@ -860,14 +874,14 @@ next: while (--numPts >= 0) { { final double[] point; final int offset; - if (derivate && (dstPts == null || !withHeight)) { + if (derivate && (dstPts == null || !forward.withHeight)) { point = new double[3]; offset = 0; } else { point = dstPts; offset = dstOff; } - inverseTransform(srcPts, srcOff, point, offset, 1); + forward.inverseTransform(srcPts, srcOff, point, offset, 1); if (!derivate) { return null; } @@ -876,9 +890,9 @@ next: while (--numPts >= 0) { dstPts[dstOff+1] = point[1]; } // We need to keep h during matrix inversion because (λ,φ,h) values are not independent. - Matrix matrix = EllipsoidToCentricTransform.this.derivative(new DirectPositionView(point, offset, 3)); + Matrix matrix = forward.derivative(new DirectPositionView.Double(point, offset, 3)); matrix = Matrices.inverse(matrix); - if (!withHeight) { + if (!forward.withHeight) { matrix = MatrixSIS.castOrCopy(matrix).removeRows(2, 3); // Drop height only after matrix inversion is done. } return matrix; @@ -892,7 +906,7 @@ next: while (--numPts >= 0) { public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws TransformException { - inverseTransform(srcPts, srcOff, dstPts, dstOff, numPts); + forward.inverseTransform(srcPts, srcOff, dstPts, dstOff, numPts); } /** @@ -918,7 +932,7 @@ next: while (--numPts >= 0) { protected MathTransform tryConcatenate(final boolean applyOtherFirst, final MathTransform other, final MathTransformFactory factory) throws FactoryException { - if (!applyOtherFirst && withHeight && other instanceof LinearTransform && other.getTargetDimensions() == 2) { + if (!applyOtherFirst && forward.withHeight && other instanceof LinearTransform && other.getTargetDimensions() == 2) { /* * Found a 3×4 matrix after this transform. We can reduce to a 3×3 matrix only if no dimension * use the column that we are about to drop (i.e. all coefficients in that column are zero). @@ -929,7 +943,7 @@ next: while (--numPts >= 0) { matrix.getElement(2,2) == 0) { matrix = MatrixSIS.castOrCopy(matrix).removeColumns(2, 3); - final MathTransform tr2D = create2D().inverse(); + final MathTransform tr2D = forward.create2D().inverse(); if (factory != null) { return factory.createConcatenatedTransform(tr2D, factory.createAffineTransform(matrix)); } else { @@ -951,7 +965,7 @@ next: while (--numPts >= 0) { @Override final int beforeFormat(final List<Object> transforms, int index, final boolean inverse) { index = super.beforeFormat(transforms, index, inverse); - if (!withHeight) { + if (!forward.withHeight) { transforms.add(++index, new Geographic3Dto2D.WKT(false)); } return index; Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -18,6 +18,7 @@ package org.apache.sis.referencing.opera import java.util.Arrays; import java.util.Objects; +import java.io.Serializable; import javax.measure.Unit; import javax.measure.Quantity; import org.opengis.util.FactoryException; @@ -382,7 +383,7 @@ public class InterpolatedTransform exten * To overridden by the two-dimensional transform case. */ InterpolatedTransform.Inverse createInverse() { - return new Inverse(); + return new Inverse(this); } /** @@ -416,15 +417,20 @@ public class InterpolatedTransform exten * * @author Rueben Schulz (UBC) * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.7 + * @version 1.0 * @since 0.7 * @module */ - class Inverse extends AbstractMathTransform.Inverse { + static class Inverse extends AbstractMathTransform.Inverse implements Serializable { /** * Serial number for inter-operability with different versions. */ - private static final long serialVersionUID = -6779719408779847014L; + private static final long serialVersionUID = 4335801994727826360L; + + /** + * The enclosing transform. + */ + private final InterpolatedTransform forward; /** * Difference allowed in iterative computations, in units of grid cell size. @@ -434,15 +440,24 @@ public class InterpolatedTransform exten /** * Creates an inverse transform. */ - Inverse() { - tolerance = grid.getCellPrecision(); - if (!(tolerance > 0)) { // Use ! for catching NaN. + Inverse(final InterpolatedTransform forward) { + this.forward = forward; + tolerance = forward.grid.getCellPrecision(); + if (!(tolerance > 0)) { // Use ! for catching NaN. throw new IllegalArgumentException(Errors.format( Errors.Keys.ValueNotGreaterThanZero_2, "grid.cellPrecision", tolerance)); } } /** + * Returns the inverse of this math transform. + */ + @Override + public MathTransform inverse() { + return forward; + } + + /** * Transforms a single coordinate in a list of ordinal values, * and optionally returns the derivative at that location. * @@ -452,6 +467,7 @@ public class InterpolatedTransform exten public final Matrix transform(final double[] srcPts, final int srcOff, double[] dstPts, int dstOff, final boolean derivate) throws TransformException { + final int dimension = forward.dimension; if (dstPts == null) { dstPts = new double[dimension]; dstOff = 0; @@ -462,7 +478,7 @@ public class InterpolatedTransform exten final double[] vector = new double[dimension]; int it = Formulas.MAXIMUM_ITERATIONS; do { - grid.interpolateInCell(xi, yi, vector); + forward.grid.interpolateInCell(xi, yi, vector); final double ox = xi; final double oy = yi; xi = x - vector[0]; @@ -487,8 +503,8 @@ public class InterpolatedTransform exten dstPts[dstOff ] = xi; // Shall not be done before above loop. dstPts[dstOff+1] = yi; if (derivate) { - return Matrices.inverse(InterpolatedTransform.this.derivative( - new DirectPositionView(dstPts, dstOff, dimension))); + return Matrices.inverse(forward.derivative( + new DirectPositionView.Double(dstPts, dstOff, dimension))); } return null; } @@ -505,6 +521,7 @@ public class InterpolatedTransform exten public final void transform(double[] srcPts, int srcOff, final double[] dstPts, int dstOff, int numPts) throws TransformException { + final int dimension = forward.dimension; int inc = dimension; if (srcPts == dstPts) { switch (IterationStrategy.suggest(srcOff, inc, dstOff, inc, numPts)) { @@ -531,7 +548,7 @@ nextPoint: while (--numPts >= 0) { final double y = yi = srcPts[srcOff+1]; int it = Formulas.MAXIMUM_ITERATIONS; do { - grid.interpolateInCell(xi, yi, vector); + forward.grid.interpolateInCell(xi, yi, vector); final double ox = xi; final double oy = yi; xi = x - vector[0]; Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform2D.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform2D.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform2D.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/InterpolatedTransform2D.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -84,14 +84,14 @@ final class InterpolatedTransform2D exte */ @Override InterpolatedTransform.Inverse createInverse() { - return new Inverse(); + return new Inverse(this); } /** * The inverse of the enclosing {@link InterpolatedTransform2D}. * * @author Martin Desruisseaux (Geomatys) - * @version 0.7 + * @version 1.0 * @since 0.7 * @module */ @@ -99,12 +99,13 @@ final class InterpolatedTransform2D exte /** * Serial number for inter-operability with different versions. */ - private static final long serialVersionUID = 5739665311481484972L; + private static final long serialVersionUID = 4802773675799229357L; /** * Constructs the inverse of an interpolated transform. */ - Inverse() { + Inverse(final InterpolatedTransform2D forward) { + super(forward); } /** Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IterationStrategy.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IterationStrategy.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IterationStrategy.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/IterationStrategy.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -95,7 +95,7 @@ public enum IterationStrategy { DESCENDING(false), /** - * Copies the points to transform in a temporary array before to apply the transform. + * Copy the points to transform in a temporary array before to apply the transform. * The temporary array will be used for fetching the source ordinates. * * <p>This algorithm can be used as a fallback for any unknown enumeration.</p> @@ -103,7 +103,7 @@ public enum IterationStrategy { BUFFER_SOURCE(true), /** - * Writes the transformed points in a temporary array and copies them to the + * Write the transformed points in a temporary array and copies them to the * destination subarray when the transformation is finished. * * <p>Developers are allowed to ignore this value and fallback on the same algorithm Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearInterpolator1D.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearInterpolator1D.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearInterpolator1D.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/LinearInterpolator1D.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -97,7 +97,7 @@ final class LinearInterpolator1D extends return; } } - inverse = new Inverse(); + inverse = new Inverse(this); } /** @@ -303,16 +303,30 @@ final class LinearInterpolator1D extends * a bilinear search for locating the lower and upper <var>x</var> values as integers, then interpolates the * <var>x</var> real value. */ - private final class Inverse extends AbstractMathTransform1D.Inverse implements MathTransform1D { + private static final class Inverse extends AbstractMathTransform1D.Inverse implements MathTransform1D, Serializable { /** * For cross-version compatibility. */ - private static final long serialVersionUID = 3179638888992528901L; + private static final long serialVersionUID = -5112948223332095009L; + + /** + * The enclosing transform. + */ + private final LinearInterpolator1D forward; /** * Creates a new inverse transform. */ - Inverse() { + Inverse(final LinearInterpolator1D forward) { + this.forward = forward; + } + + /** + * Returns the inverse of this math transform. + */ + @Override + public MathTransform1D inverse() { + return forward; } /** @@ -326,7 +340,7 @@ final class LinearInterpolator1D extends final boolean derivate) throws TransformException { final double d, x, y = srcPts[srcOff]; - final double[] values = LinearInterpolator1D.this.values; + final double[] values = forward.values; int i = Arrays.binarySearch(values, y); if (i >= 0) { x = i; @@ -361,7 +375,7 @@ final class LinearInterpolator1D extends */ @Override public double transform(final double y) { - final double[] values = LinearInterpolator1D.this.values; + final double[] values = forward.values; int i = Arrays.binarySearch(values, y); if (i >= 0) { return i; @@ -390,7 +404,7 @@ final class LinearInterpolator1D extends */ @Override public double derivative(final double y) { - final double[] values = LinearInterpolator1D.this.values; + final double[] values = forward.values; int i = Arrays.binarySearch(values, y); if (i < 0) { i = ~i; Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -16,10 +16,12 @@ */ package org.apache.sis.referencing.operation.transform; +import java.util.Map; import java.util.List; import java.util.Collections; import java.awt.geom.AffineTransform; import org.opengis.util.FactoryException; +import org.opengis.geometry.Envelope; import org.opengis.geometry.MismatchedDimensionException; import org.opengis.referencing.operation.Matrix; import org.opengis.referencing.operation.MathTransform; @@ -51,7 +53,7 @@ import org.apache.sis.util.Static; * GeoAPI factory interfaces instead. * * @author Martin Desruisseaux (Geomatys) - * @version 0.7 + * @version 1.0 * * @see MathTransformFactory * @@ -177,6 +179,45 @@ public final class MathTransforms extend } /** + * Creates a transform defined as one transform applied globally except in sub-areas where more accurate + * transforms are available. Such constructs appear in some datum shift files. The result of transforming + * a point by the returned {@code MathTransform} is as if iterating over all given {@link Envelope}s in + * no particular order, find the smallest one containing the point to transform (envelope border considered + * inclusive), then use the associated {@link MathTransform} for transforming the point. + * If the point is not found in any envelope, then the global transform is applied. + * + * <p>The following constraints apply:</p> + * <ul> + * <li>The global transform must be a reasonable approximation of the specialized transforms + * (this is required for calculating the inverse transform).</li> + * <li>All transforms in the {@code specializations} map must have the same number of source and target + * dimensions than the {@code global} transform.</li> + * <li>All envelopes in the {@code specializations} map must have the same number of dimensions + * than the global transform <em>source</em> dimensions.</li> + * <li>In current implementation, each envelope must either be fully included in another envelope, + * or not overlap any other envelope.</li> + * </ul> + * + * @param global the transform to use globally where there is no suitable specialization. + * @param specializations more accurate transforms available in some sub-areas. + * @return a transform applying the given global transform except in sub-areas where specializations are available. + * @throws IllegalArgumentException if a constraint is not meet. + * + * @since 1.0 + */ + public static MathTransform specialize(final MathTransform global, final Map<Envelope,MathTransform> specializations) { + ArgumentChecks.ensureNonNull("generic", global); + ArgumentChecks.ensureNonNull("specializations", specializations); + if (specializations.isEmpty()) { + return global; + } else if (global.getSourceDimensions() == 2 && global.getTargetDimensions() == 2) { + return new SpecializableTransform2D(global, specializations); + } else { + return new SpecializableTransform(global, specializations); + } + } + + /** * Puts together a list of independent math transforms, each of them operating on a subset of ordinate values. * This method is often used for defining 4-dimensional (<var>x</var>,<var>y</var>,<var>z</var>,<var>t</var>) * transform as an aggregation of 3 simpler transforms operating on (<var>x</var>,<var>y</var>), (<var>z</var>) @@ -443,7 +484,8 @@ public final class MathTransforms extend return ((AbstractMathTransform) transform).transform(srcPts, srcOff, dstPts, dstOff, true); } // Must be calculated before to transform the coordinate. - final Matrix derivative = transform.derivative(new DirectPositionView(srcPts, srcOff, transform.getSourceDimensions())); + final Matrix derivative = transform.derivative( + new DirectPositionView.Double(srcPts, srcOff, transform.getSourceDimensions())); if (dstPts != null) { transform.transform(srcPts, srcOff, dstPts, dstOff, 1); } Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -318,7 +318,7 @@ public class PassThroughTransform extend { Matrix derivative = null; if (derivate) { - derivative = derivative(new DirectPositionView(srcPts, srcOff, getSourceDimensions())); + derivative = derivative(new DirectPositionView.Double(srcPts, srcOff, getSourceDimensions())); } if (dstPts != null) { transform(srcPts, srcOff, dstPts, dstOff, 1); Copied: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java (from r1825995, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java) URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java?p2=sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java&p1=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java&r1=1825995&r2=1826248&rev=1826248&view=diff ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/SpecializableTransform.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -23,7 +23,7 @@ import java.io.Serializable; import org.opengis.geometry.Envelope; import org.opengis.geometry.DirectPosition; import org.opengis.geometry.MismatchedDimensionException; -import org.opengis.geometry.MismatchedReferenceSystemException; +import org.apache.sis.geometry.MismatchedReferenceSystemException; import org.opengis.referencing.operation.Matrix; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/package-info.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/package-info.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/package-info.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/package-info.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -61,7 +61,7 @@ * * @author Martin Desruisseaux (IRD, Geomatys) * @author Adrian Custer (Geomatys) - * @version 0.7 + * @version 1.0 * @since 0.5 * @module */ Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractDirectPositionTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractDirectPositionTest.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractDirectPositionTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/AbstractDirectPositionTest.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -26,17 +26,52 @@ import static org.apache.sis.test.Assert * Tests the static methods provided in {@link AbstractDirectPosition}. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.3 + * @version 1.0 * @since 0.3 * @module */ public final strictfp class AbstractDirectPositionTest extends TestCase { /** - * Tests {@link AbstractDirectPosition#isSimplePrecision(double[])}. + * Tests {@link AbstractDirectPosition#parse(CharSequence)}. */ @Test - public void testIsSimplePrecision() { - assertTrue (AbstractDirectPosition.isSimplePrecision(2, 0.5, 0.25, Double.NaN, Double.POSITIVE_INFINITY)); - assertFalse(AbstractDirectPosition.isSimplePrecision(2, 0.5, 1.0 / 3)); + public void testParse() { + assertArrayEquals(new double[] {6, 10, 2}, AbstractDirectPosition.parse("POINT(6 10 2)"), STRICT); + assertArrayEquals(new double[] {3, 14, 2}, AbstractDirectPosition.parse("POINT M [ 3 14 2 ] "), STRICT); + assertArrayEquals(new double[] {2, 10, 8}, AbstractDirectPosition.parse("POINT Z 2 10 8"), STRICT); + assertArrayEquals(new double[] {}, AbstractDirectPosition.parse("POINT()"), STRICT); + assertArrayEquals(new double[] {}, AbstractDirectPosition.parse("POINT ( ) "), STRICT); + } + + /** + * Tests {@link AbstractDirectPosition#parse(CharSequence)} with invalid input strings. + */ + @Test + public void testParsingFailures() { + try { + AbstractDirectPosition.parse("POINT(6 10 2"); + fail("Parsing should fails because of missing parenthesis."); + } catch (IllegalArgumentException e) { + // This is the expected exception. + final String message = e.getMessage(); + assertTrue(message, message.contains("POINT(6 10 2")); + assertTrue(message, message.contains("‘)’")); + } + try { + AbstractDirectPosition.parse("POINT 6 10 2)"); + fail("Parsing should fails because of missing parenthesis."); + } catch (IllegalArgumentException e) { + // This is the expected exception. + } + try { + AbstractDirectPosition.parse("POINT(6 10 2) x"); + fail("Parsing should fails because of extra characters."); + } catch (IllegalArgumentException e) { + // This is the expected exception. + final String message = e.getMessage(); + assertTrue(message, message.contains("POINT(6 10 2) x")); + assertTrue(message, message.contains("“x”") || // English locale + message.contains("« x »")); // French locale + } } } Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/ArrayEnvelopeTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/ArrayEnvelopeTest.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/ArrayEnvelopeTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/ArrayEnvelopeTest.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -16,11 +16,12 @@ */ package org.apache.sis.geometry; +import org.apache.sis.io.wkt.Formatter; import org.apache.sis.test.DependsOn; import org.apache.sis.test.TestCase; import org.junit.Test; -import static org.junit.Assert.*; +import static org.apache.sis.test.Assert.*; /** @@ -28,7 +29,7 @@ import static org.junit.Assert.*; * This is the base class of {@link GeneralEnvelope} and {@link ImmutableEnvelope}. * * @author Michael Hausegger - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ @@ -64,6 +65,21 @@ public final strictfp class ArrayEnvelop } /** + * Tests the {@link ArrayEnvelope#formatTo(Formatter)} method. + * Contrarily to {@code toString()}, the precision depends on the CRS. + */ + @Test + public void testFormatWKT() { + ArrayEnvelope envelope = new ArrayEnvelope(new double[] {4, -10, 50, 2}); + assertMultilinesEquals("BOX[ 4 -10,\n" + + " 50 2]", envelope.toWKT()); + envelope.crs = AbstractEnvelopeTest.WGS84; + assertMultilinesEquals("BOX[ 4.00000000 -10.00000000,\n" + + " 50.00000000 2.00000000]", envelope.toWKT()); + + } + + /** * Tests envelope construction from a the pseudo-Well Known Text (WKT) representation of a Bounding Box (BBOX). */ @Test Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralDirectPositionTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralDirectPositionTest.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralDirectPositionTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralDirectPositionTest.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -17,6 +17,7 @@ package org.apache.sis.geometry; import java.util.Arrays; +import org.apache.sis.io.wkt.Formatter; import org.apache.sis.test.TestCase; import org.apache.sis.test.DependsOn; import org.junit.Test; @@ -30,7 +31,7 @@ import static org.apache.sis.geometry.Ab * Tests the {@link GeneralDirectPosition} class. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.3 + * @version 1.0 * @since 0.3 * @module */ @@ -49,10 +50,23 @@ public final strictfp class GeneralDirec } /** + * Tests the {@link GeneralDirectPosition#formatTo(Formatter)} method. + * Contrarily to {@code toString()}, the precision depends on the CRS. + */ + @Test + public void testFormatWKT() { + final GeneralDirectPosition position = new GeneralDirectPosition(6, 10); + assertEquals("POINT[6 10]", position.toWKT()); + position.setCoordinateReferenceSystem(WGS84); + assertEquals("POINT[6.00000000 10.00000000]", position.toWKT()); // 1 cm precision on Earth. + validate(position); + } + + /** * Tests the {@link GeneralDirectPosition#toString()} method. */ @Test - public void testWktFormatting() { + public void testToString() { final GeneralDirectPosition position = new GeneralDirectPosition(6, 10, 2); assertEquals("POINT(6 10 2)", position.toString()); validate(position); @@ -62,7 +76,7 @@ public final strictfp class GeneralDirec * Tests the {@link GeneralDirectPosition#GeneralDirectPosition(CharSequence)} constructor. */ @Test - public void testWktParsing() { + public void testConstructor() { assertEquals("POINT(6 10 2)", new GeneralDirectPosition("POINT(6 10 2)").toString()); assertEquals("POINT(3 14 2)", new GeneralDirectPosition("POINT M [ 3 14 2 ] ").toString()); assertEquals("POINT(2 10 8)", new GeneralDirectPosition("POINT Z 2 10 8").toString()); @@ -71,40 +85,6 @@ public final strictfp class GeneralDirec } /** - * Tests the {@link GeneralDirectPosition#GeneralDirectPosition(CharSequence)} constructor - * with invalid input strings. - */ - @Test - @SuppressWarnings("ResultOfObjectAllocationIgnored") - public void testWktParsingFailures() { - try { - new GeneralDirectPosition("POINT(6 10 2"); - fail("Parsing should fails because of missing parenthesis."); - } catch (IllegalArgumentException e) { - // This is the expected exception. - final String message = e.getMessage(); - assertTrue(message, message.contains("POINT(6 10 2")); - assertTrue(message, message.contains("‘)’")); - } - try { - new GeneralDirectPosition("POINT 6 10 2)"); - fail("Parsing should fails because of missing parenthesis."); - } catch (IllegalArgumentException e) { - // This is the expected exception. - } - try { - new GeneralDirectPosition("POINT(6 10 2) x"); - fail("Parsing should fails because of extra characters."); - } catch (IllegalArgumentException e) { - // This is the expected exception. - final String message = e.getMessage(); - assertTrue(message, message.contains("POINT(6 10 2) x")); - assertTrue(message, message.contains("“x”") || // English locale - message.contains("« x »")); // French locale - } - } - - /** * Tests {@link GeneralDirectPosition#clone()}. */ @Test Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/FormulasTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/FormulasTest.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/FormulasTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/FormulasTest.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -18,6 +18,7 @@ package org.apache.sis.internal.referenc import org.apache.sis.internal.metadata.ReferencingServices; import org.apache.sis.measure.Longitude; +import org.apache.sis.referencing.datum.HardCodedDatum; import org.apache.sis.test.TestCase; import org.junit.Test; @@ -28,7 +29,7 @@ import static org.junit.Assert.*; * Tests {@link Formulas}. * * @author Martin Desruisseaux (Geomatys) - * @version 0.7 + * @version 1.0 * @since 0.4 * @module */ @@ -90,6 +91,14 @@ public final strictfp class FormulasTest } /** + * Tests {@link Formulas#scaleComparedToEarth(Ellipsoid)}. + */ + @Test + public void testScaleComparedToEarth() { + assertEquals(1, Formulas.scaleComparedToEarth(HardCodedDatum.WGS84.getEllipsoid()), 1E-14); + } + + /** * Tests {@link Formulas#getSemiMinor(double, double)}. */ @Test Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -39,7 +39,7 @@ import static org.apache.sis.internal.re * * @author Martin Desruisseaux (Geomatys) * @version 0.8 - * @since 0.5 (derived from 0.4) + * @since 0.4 * @module */ public final strictfp class ReferencingUtilitiesTest extends TestCase { Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/WKTUtilitiesTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/WKTUtilitiesTest.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/WKTUtilitiesTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/WKTUtilitiesTest.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -17,6 +17,7 @@ package org.apache.sis.internal.referencing; import org.opengis.referencing.cs.*; +import org.apache.sis.referencing.crs.HardCodedCRS; import org.apache.sis.internal.metadata.WKTKeywords; import org.apache.sis.test.DependsOn; import org.apache.sis.test.TestCase; @@ -30,7 +31,7 @@ import static org.apache.sis.internal.re * Tests {@link WKTUtilities}. * * @author Martin Desruisseaux (Geomatys) - * @version 0.7 + * @version 1.0 * @since 0.7 * @module */ @@ -55,4 +56,15 @@ public final strictfp class WKTUtilities assertEquals(WKTKeywords.temporal, toType(CoordinateSystem.class, TimeCS .class)); assertEquals(WKTKeywords.vertical, toType(CoordinateSystem.class, VerticalCS .class)); } + + /** + * Tests {@link WKTUtilities#suggestFractionDigits(CoordinateReferenceSystem, double[]...)}. + */ + @Test + public void testSuggestFractionDigits() { + assertArrayEquals(new int[] {8, 9}, WKTUtilities.suggestFractionDigits(HardCodedCRS.WGS84, new double[][] { + {40, -10}, + {50, -10.000000001} + })); + } } Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/CoordinateDomain.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -32,7 +32,7 @@ import org.apache.sis.referencing.datum. * This class can generate random number suitable for their domain. * * @author Martin Desruisseaux (Geomatys) - * @version 0.6 + * @version 1.0 * @since 0.5 * @module */ @@ -215,6 +215,14 @@ public strictfp class CoordinateDomain { -10, 10); /** + * Values in the -100 to 100 range in all dimensions. + */ + public static final CoordinateDomain RANGE_100 = new CoordinateDomain( + -100, 100, + -100, 100, + -100, 100); + + /** * The domain of the coordinates to test. */ final double xmin, xmax, ymin, ymax, zmin, zmax; Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/PseudoTransform.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/PseudoTransform.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/PseudoTransform.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/PseudoTransform.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -96,7 +96,7 @@ strictfp class PseudoTransform extends A final boolean derivate) throws TransformException { final Matrix derivative = derivate ? derivative( - new DirectPositionView(srcPts, srcOff, getSourceDimensions())) : null; + new DirectPositionView.Double(srcPts, srcOff, getSourceDimensions())) : null; System.arraycopy(srcPts, srcOff, buffer, 0, sourceDimension); for (int i=0; i<targetDimension; i++) { double v = buffer[i % sourceDimension]; Copied: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java (from r1825995, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java) URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java?p2=sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java&p1=sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java&r1=1825995&r2=1826248&rev=1826248&view=diff ============================================================================== --- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/SpecializableTransformTest.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -133,7 +133,6 @@ public final strictfp class Specializabl public void testForwardConsistency() throws TransformException { transform = create(false); tolerance = 1E-14; - isDerivativeSupported = false; // Actually supported, but our test transform has discontinuities. verifyInDomain(CoordinateDomain.RANGE_10, -672445632505596619L); } @@ -150,7 +149,6 @@ public final strictfp class Specializabl public void testInverseConsistency() throws TransformException { transform = create(false).inverse(); tolerance = 1E-12; - isDerivativeSupported = false; // Actually supported, but our test transform has discontinuities. verifyInDomain(CoordinateDomain.RANGE_100, 4308397764777385180L); } Modified: sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original) +++ sis/trunk/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -25,7 +25,7 @@ import org.junit.BeforeClass; * All tests from the {@code sis-referencing} module, in approximative dependency order. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.3 * @module */ @@ -131,6 +131,7 @@ import org.junit.BeforeClass; org.apache.sis.referencing.operation.transform.PolarToCartesianTest.class, org.apache.sis.referencing.operation.transform.CartesianToPolarTest.class, org.apache.sis.referencing.operation.transform.CoordinateSystemTransformTest.class, + org.apache.sis.referencing.operation.transform.SpecializableTransformTest.class, org.apache.sis.referencing.operation.DefaultFormulaTest.class, org.apache.sis.referencing.operation.DefaultOperationMethodTest.class, org.apache.sis.referencing.operation.AbstractSingleOperationTest.class, Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java [UTF-8] (original) +++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -21,6 +21,8 @@ import java.util.HashMap; import org.apache.sis.util.Debug; import org.apache.sis.util.Static; import org.apache.sis.util.ComparisonMode; +import org.apache.sis.math.DecimalFunctions; +import org.opengis.referencing.operation.Matrix; // For javadoc import static java.lang.Math.max; import static java.lang.Math.abs; @@ -30,7 +32,7 @@ import static java.lang.Math.abs; * Miscellaneous utilities methods working on floating point numbers. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.3 * @module */ @@ -156,6 +158,22 @@ public final class Numerics extends Stat } /** + * Returns {@code true} if every values in the given {@code double} array could be casted to the + * {@code float} type without precision lost. This method treats all {@code NaN} values as equal. + * + * @param values the value to test for their precision. + * @return {@code true} if every values can be casted to the {@code float} type without precision lost. + */ + public static boolean isSimplePrecision(final double... values) { + for (final double value : values) { + if (Double.doubleToLongBits(value) != Double.doubleToLongBits((float) value)) { + return false; + } + } + return true; + } + + /** * Returns a copy of the given array where each value has been casted to the {@code float} type. * * @param data the array to copy, or {@code null}. @@ -428,4 +446,51 @@ public final class Numerics extends Stat } return bits; } + + /** + * Suggests an amount of fraction digits to use for formatting numbers in each column of the given matrix. + * The number of fraction digits may be negative if we could round the numbers to 10, 100, <i>etc</i>. + * + * @param rows the matrix rows. It is not required that each row has the same length. + * @return suggested amount of fraction digits as an array as long as the longest row. + * + * @see org.apache.sis.referencing.operation.matrix.Matrices#toString(Matrix) + */ + public static int[] suggestFractionDigits(final double[][] rows) { + int length = 0; + final int n = rows.length - 1; + for (int j=0; j <= n; j++) { + final int rl = rows[j].length; + if (rl > length) length = rl; + } + final int[] fractionDigits = new int[length]; + for (int i=0; i<length; i++) { + double min = Double.POSITIVE_INFINITY; + double max = Double.NEGATIVE_INFINITY; + boolean isInteger = true; + for (final double[] row : rows) { + if (row.length > i) { + final double value = row[i]; + if (value < min) min = value; + if (value > max) max = value; + if (isInteger && Math.floor(value) != value && !Double.isNaN(value)) { + isInteger = false; + } + } + } + if (!isInteger) { + final double delta; + final boolean strict; + if (min < max) { + delta = (max - min) / n; + strict = (n == 1); + } else { + delta = Math.max(Math.abs(min), Math.abs(max)) * 1E-6; // The 1E-6 factor is arbitrary. + strict = false; + } + fractionDigits[i] = DecimalFunctions.fractionDigitsForDelta(delta, strict); + } + } + return fractionDigits; + } } Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/IndexedResourceBundle.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/IndexedResourceBundle.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/IndexedResourceBundle.java [UTF-8] (original) +++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/IndexedResourceBundle.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -40,6 +40,8 @@ import org.apache.sis.util.CharSequences import org.apache.sis.util.logging.Logging; import org.apache.sis.internal.system.Loggers; import org.apache.sis.internal.util.MetadataServices; +import org.apache.sis.measure.RangeFormat; +import org.apache.sis.measure.Range; /** @@ -68,7 +70,7 @@ import org.apache.sis.internal.util.Meta * multiple threads. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.3 * @module */ @@ -418,6 +420,9 @@ public class IndexedResourceBundle exten replacement = Classes.getShortName(getPublicType((Class<?>) element)); } else if (element instanceof CodeList<?>) { replacement = MetadataServices.getInstance().getCodeTitle((CodeList<?>) element, getLocale()); + } else if (element instanceof Range<?>) { + final Range<?> range = (Range<?>) element; + replacement = new RangeFormat(getLocale(), range.getElementType()).format(range); } /* * No need to check for Numbers or Dates instances, since they are Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/util/NumericsTest.java URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/util/NumericsTest.java?rev=1826248&r1=1826247&r2=1826248&view=diff ============================================================================== --- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/util/NumericsTest.java [UTF-8] (original) +++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/util/NumericsTest.java [UTF-8] Thu Mar 8 15:44:56 2018 @@ -34,7 +34,7 @@ import static org.junit.Assert.*; * Tests the {@link Numerics} class. * * @author Martin Desruisseaux (Geomatys) - * @version 0.6 + * @version 1.0 * @since 0.3 * @module */ @@ -69,6 +69,15 @@ public final strictfp class NumericsTest } /** + * Tests {@link Numerics#isSimplePrecision(double[])}. + */ + @Test + public void testIsSimplePrecision() { + assertTrue (Numerics.isSimplePrecision(2, 0.5, 0.25, Double.NaN, Double.POSITIVE_INFINITY)); + assertFalse(Numerics.isSimplePrecision(2, 0.5, 1.0 / 3)); + } + + /** * Tests the {@link Numerics#epsilonEqual(double, double, ComparisonMode)} method. */ @Test @@ -162,4 +171,17 @@ public final strictfp class NumericsTest final float recomposed = StrictMath.scalb((float) expected, e); assertEquals(value, StrictMath.copySign(recomposed, value), 0f); } + + /** + * Tests {@link Numerics#suggestFractionDigits(double[][])}. + */ + @Test + public void testSuggestFractionDigits() { + final int[] f = Numerics.suggestFractionDigits(new double[][] { + {10, 100, 0.1, 1000.1}, + {15, 140.1, 0.4, Double.NaN}, + {20, 400, 0.5, Double.NaN} + }); + assertArrayEquals(new int[] {0, -2, 1, 3}, f); + } }
