sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1600997 - in /sis/branches/JDK8/core: sis-feature/src/main/java/org/apache/sis/feature/ sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ sis-referencing/src/test/java/org/apache/sis/referencing/operation/transf...
Date Fri, 06 Jun 2014 20:25:35 GMT
Author: desruisseaux
Date: Fri Jun  6 20:25:35 2014
New Revision: 1600997

URL: http://svn.apache.org/r1600997
Log:
Cleaning and port of a first non-linear class.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PowerTransform1D.java
  (with props)
Modified:
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/PassThroughTransformTest.java

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java?rev=1600997&r1=1600996&r2=1600997&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
[UTF-8] Fri Jun  6 20:25:35 2014
@@ -170,7 +170,7 @@ public abstract class AbstractAssociatio
      * Sets the features. All previous values are replaced by the given collection.
      *
      * <p>The default implementation ensures that the given collection contains at
most one element,
-     * then delegates to {@link #setValue(AbstractFeature)}.</p>
+     * then delegates to {@link #setValue(Feature)}.</p>
      *
      * @param  values The new values.
      * @throws IllegalArgumentException if the given collection contains too many elements.

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java?rev=1600997&r1=1600996&r2=1600997&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
[UTF-8] Fri Jun  6 20:25:35 2014
@@ -150,7 +150,7 @@ public abstract class AbstractFeature im
      * }
      *
      * <div class="note"><b>Note:</b> This method is useful for storing
non-default {@code Attribute} or
-     * {@code Association} implementations in this feature. When default implementations
are sufficient,
+     * {@code FeatureAssociation} implementations in this feature. When default implementations
are sufficient,
      * the {@link #setPropertyValue(String, Object)} method is preferred.</div>
      *
      * @param  property The property to set.
@@ -239,11 +239,11 @@ public abstract class AbstractFeature im
      *
      * <table class="sis">
      *   <caption>Class of returned value</caption>
-     *   <tr><th>Property type</th>           <th>max. occurs</th>
<th>Method invoked</th>                  <th>Return type</th></tr>
-     *   <tr><td>{@link AttributeType}</td>   <td>0 or 1</td>
     <td>{@link Attribute#getValue()}</td>    <td>{@link Object}</td></tr>
-     *   <tr><td>{@code AttributeType}</td>   <td>2 or more</td>
  <td>{@link Attribute#getValues()}</td>   <td>{@code Collection<?>}</td></tr>
-     *   <tr><td>{@link AssociationRole}</td> <td>0 or 1</td>
     <td>{@link Association#getValue()}</td>  <td>{@link Feature}</td></tr>
-     *   <tr><td>{@code AssociationRole}</td> <td>2 or more</td>
  <td>{@link Association#getValues()}</td> <td>{@code Collection<Feature>}</td></tr>
+     *   <tr><th>Property type</th>           <th>max. occurs</th>
<th>Method invoked</th>                         <th>Return type</th></tr>
+     *   <tr><td>{@link AttributeType}</td>   <td>0 or 1</td>
     <td>{@link Attribute#getValue()}</td>           <td>{@link Object}</td></tr>
+     *   <tr><td>{@code AttributeType}</td>   <td>2 or more</td>
  <td>{@link Attribute#getValues()}</td>          <td>{@code Collection<?>}</td></tr>
+     *   <tr><td>{@link AssociationRole}</td> <td>0 or 1</td>
     <td>{@link FeatureAssociation#getValue()}</td>  <td>{@link Feature}</td></tr>
+     *   <tr><td>{@code AssociationRole}</td> <td>2 or more</td>
  <td>{@link FeatureAssociation#getValues()}</td> <td>{@code Collection<Feature>}</td></tr>
      * </table>
      *
      * <div class="note"><b>Note:</b> “max. occurs” is the {@linkplain
DefaultAttributeType#getMaximumOccurs() maximum

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PowerTransform1D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PowerTransform1D.java?rev=1600997&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PowerTransform1D.java
(added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PowerTransform1D.java
[UTF-8] Fri Jun  6 20:25:35 2014
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.referencing.operation.transform;
+
+import java.io.Serializable;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.MathTransform1D;
+import org.apache.sis.internal.util.Numerics;
+import org.apache.sis.util.ComparisonMode;
+
+
+/**
+ * Raises the given value at some fixed power. Current implementation is defined mostly for
the
+ * needs of the {@link ExponentialTransform1D#concatenateLog(LogarithmicTransform1D, boolean)}.
+ * Future version may expand on that.
+ *
+ * <p>Before to make this class public (if we do), we need to revisit the class name,
define
+ * parameters and improve the {@link #concatenate(MathTransform, boolean)} method.</p>
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.5 (derived from geotk-3.17)
+ * @version 0.5
+ * @module
+ */
+final class PowerTransform1D extends AbstractMathTransform1D implements Serializable {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = 4618931749313510016L;
+
+    /**
+     * The power.
+     */
+    final double power;
+
+    /**
+     * The inverse of this transform. Created only when first needed.
+     * Serialized in order to avoid rounding error if this transform
+     * is actually the one which was created from the inverse.
+     */
+    private PowerTransform1D inverse;
+
+    /**
+     * Constructs a new exponential transform. This constructor is provided for subclasses
only.
+     * Instances should be created using the {@linkplain #create(double) factory method},
which
+     * may returns optimized implementations for some particular argument values.
+     *
+     * @param power The power at which to raise the values.
+     */
+    protected PowerTransform1D(final double power) {
+        this.power = power;
+    }
+
+    /**
+     * Constructs a new power transform.
+     *
+     * @param power The power at which to raise the values.
+     * @return The math transform.
+     */
+    public static MathTransform1D create(final double power) {
+        if (power == 1) return IdentityTransform1D.INSTANCE;
+        if (power == 0) return new ConstantTransform1D(1);
+        return new PowerTransform1D(power);
+    }
+
+    /**
+     * Creates the inverse transform of this object.
+     */
+    @Override
+    public MathTransform1D inverse() {
+        if (inverse == null) {
+            inverse = new PowerTransform1D(1 / power);
+            inverse.inverse = this;
+        }
+        return inverse;
+    }
+
+    /**
+     * Gets the derivative of this function at a value.
+     */
+    @Override
+    public double derivative(final double value) {
+        return power * Math.pow(value, power - 1);
+    }
+
+    /**
+     * Transforms the specified value.
+     */
+    @Override
+    public double transform(final double value) {
+        return Math.pow(value, power);
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final double[] srcPts, int srcOff, final double[] dstPts, int dstOff,
int numPts) {
+        if (srcPts!=dstPts || srcOff>=dstOff) {
+            while (--numPts >= 0) {
+                dstPts[dstOff++] = Math.pow(srcPts[srcOff++], power);
+            }
+        } else {
+            srcOff += numPts;
+            dstOff += numPts;
+            while (--numPts >= 0) {
+                dstPts[--dstOff] = Math.pow(srcPts[--srcOff], power);
+            }
+        }
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final float[] srcPts, int srcOff, final float[] dstPts, int dstOff,
int numPts) {
+        if (srcPts!=dstPts || srcOff>=dstOff) {
+            while (--numPts >= 0) {
+                dstPts[dstOff++] = (float) Math.pow(srcPts[srcOff++], power);
+            }
+        } else {
+            srcOff += numPts;
+            dstOff += numPts;
+            while (--numPts >= 0) {
+                dstPts[--dstOff] = (float) Math.pow(srcPts[--srcOff], power);
+            }
+        }
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final double[] srcPts, int srcOff, final float[] dstPts, int dstOff,
int numPts) {
+        while (--numPts >= 0) {
+            dstPts[dstOff++] = (float) Math.pow(srcPts[srcOff++], power);
+        }
+    }
+
+    /**
+     * Transforms many coordinates in a list of ordinal values.
+     */
+    @Override
+    public void transform(final float[] srcPts, int srcOff, final double[] dstPts, int dstOff,
int numPts) {
+        while (--numPts >= 0) {
+            dstPts[dstOff++] = Math.pow(srcPts[srcOff++], power);
+        }
+    }
+
+    /**
+     * Concatenates in an optimized way a {@link MathTransform} {@code other} to this {@code
MathTransform}.
+     *
+     * @param  other The math transform to apply.
+     * @param  applyOtherFirst {@code true} if the transformation order is {@code other}
followed by {@code this},
+     *         or {@code false} if the transformation order is {@code this} followed by {@code
other}.
+     * @return The combined math transform, or {@code null} if no optimized combined transform
is available.
+     */
+    @Override
+    final MathTransform concatenate(final MathTransform other, final boolean applyOtherFirst)
{
+        if (other instanceof PowerTransform1D) {
+            return create(power + ((PowerTransform1D) other).power);
+        }
+        // TODO: more optimization could go here for logarithmic and exponential cases.
+        return super.concatenate(other, applyOtherFirst);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected int computeHashCode() {
+        return super.computeHashCode() + Numerics.hashCode(Double.doubleToLongBits(power));
+    }
+
+    /**
+     * Compares the specified object with this math transform for equality.
+     */
+    @Override
+    public boolean equals(final Object object, final ComparisonMode mode) {
+        if (object == this) {
+            return true; // Slight optimization
+        }
+        if (super.equals(object, mode)) {
+            return Numerics.equals(power, ((PowerTransform1D) object).power);
+        }
+        return false;
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PowerTransform1D.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PowerTransform1D.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/PassThroughTransformTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/PassThroughTransformTest.java?rev=1600997&r1=1600996&r2=1600997&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/PassThroughTransformTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/PassThroughTransformTest.java
[UTF-8] Fri Jun  6 20:25:35 2014
@@ -23,13 +23,14 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.referencing.operation.matrix.Matrix3;
 import org.apache.sis.internal.util.Numerics;
+import org.apache.sis.util.ArraysExt;
 
 // Test imports
 import org.junit.Test;
 import org.opengis.test.CalculationType;
 import org.opengis.test.ToleranceModifier;
 import org.apache.sis.test.TestUtilities;
-import org.apache.sis.util.ArraysExt;
+import org.apache.sis.test.DependsOn;
 
 import static org.junit.Assert.*;
 
@@ -37,14 +38,12 @@ import static org.junit.Assert.*;
 /**
  * Tests {@link PassThroughTransform}.
  *
- * <p>The {@link DimensionFilter} class is also tested in order to ensure that it
- * can gives back the original transform.</p>
- *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.5 (derived from geotk-2.0)
  * @version 0.5
  * @module
  */
+@DependsOn(LinearTransformTest.class)
 public final strictfp class PassThroughTransformTest extends MathTransformTestCase {
     /**
      * The random number generator to be used in this test.
@@ -102,16 +101,15 @@ public final strictfp class PassThroughT
     }
 
     /**
-     * Tests the general pass-through transform. This test needs a non-linear sub-transform
-     * for preventing the factory method to optimize.
+     * Tests the general pass-through transform.
+     * This test uses a non-linear sub-transform for preventing the factory method to optimize.
      *
      * @throws TransformException Should never happen.
      */
 //    TODO
 //    @Test
 //    public void testPassthrough() throws TransformException {
-//        final ParameterValueGroup param = mtFactory.getDefaultParameters("Exponential");
-//        runTest(mtFactory.createParameterizedTransform(param), PassThroughTransform.class);
+//        runTest(ExponentialTransform1D.create(10, -2), PassThroughTransform.class);
 //    }
 
     /**
@@ -126,20 +124,13 @@ public final strictfp class PassThroughT
     {
         random = TestUtilities.createRandomNumberGenerator();
         /*
-         * Tests many combinations of "first affected ordinate" and "number of trailing ordinates"
-         * parameters. For each combination we create a passthrough transform, test it with
the
-         * "verifyTransform" method, then try to split it back to the original transform
using
-         * the DimensionFilter class.
+         * Test many combinations of "first affected ordinate" and "number of trailing ordinates"
parameters.
+         * For each combination we create a passthrough transform, test it with the 'verifyTransform'
method.
          */
-// TODO final DimensionFilter filter = new DimensionFilter(mtFactory);
         for (int firstAffectedOrdinate=0; firstAffectedOrdinate<=3; firstAffectedOrdinate++)
{
-            final int firstTrailingOrdinate = firstAffectedOrdinate + subTransform.getSourceDimensions();
             for (int numTrailingOrdinates=0; numTrailingOrdinates<=3; numTrailingOrdinates++)
{
                 final int numAdditionalOrdinates = firstAffectedOrdinate + numTrailingOrdinates;
                 transform = PassThroughTransform.create(firstAffectedOrdinate, subTransform,
numTrailingOrdinates);
-                /*
-                 * Test the PassthroughTransform.
-                 */
                 if (numAdditionalOrdinates == 0) {
                     assertSame("Failed to recognize that no passthrough was needed.", subTransform,
transform);
                     continue;
@@ -151,28 +142,6 @@ public final strictfp class PassThroughT
                 assertEquals ("Wrong number of target dimensions.",
                         subTransform.getTargetDimensions() + numAdditionalOrdinates, transform.getTargetDimensions());
                 verifyTransform(subTransform, firstAffectedOrdinate);
-                /*
-                 * Split the PassthroughTransform back to the original sub-transform.
-                 */
-//              if (firstAffectedOrdinate != 0) {
-//                  filter.addSourceDimensionRange(0, firstAffectedOrdinate);
-//                  assertTrue("Expected an identity transform.", filter.separate(transform).isIdentity());
-//                  filter.clear();
-//              }
-//              if (numTrailingOrdinates != 0) {
-//                  filter.addSourceDimensionRange(firstTrailingOrdinate, transform.getSourceDimensions());
-//                  assertTrue("Expected an identity transform.", filter.separate(transform).isIdentity());
-//                  filter.clear();
-//              }
-//              filter.addSourceDimensionRange(firstAffectedOrdinate, firstTrailingOrdinate);
-//              assertEquals("Expected the sub-transform.", subTransform, filter.separate(transform));
-//              final int[] expectedDimensions = new int[subTransform.getTargetDimensions()];
-//              for (int i=0; i<expectedDimensions.length; i++) {
-//                  expectedDimensions[i] = firstAffectedOrdinate + i;
-//              }
-//              assertTrue("Unexpected output dimensions",
-//                      Arrays.equals(expectedDimensions, filter.getTargetDimensions()));
-//              filter.clear();
             }
         }
     }
@@ -218,31 +187,37 @@ public final strictfp class PassThroughT
                 Arrays.equals(passthroughData, expectedData));
         /*
          * Now process to the transform and compares the results with the expected ones.
-         * We perform a copy of the source data before to transform them in order to use
-         * the same values for running the GeoAPI tests as the next step.
          */
         tolerance         = 0; // Results should be strictly identical because we used the
same inputs.
         toleranceModifier = null;
-        final float[] sourceAsFloat = Numerics.copyAsFloats(passthroughData);
-        transform.transform(passthroughData, 0, passthroughData, 0, numPts);
-        assertCoordinatesEqual("Expected a plain copy.", passthroughDim,
-                expectedData, 0, passthroughData, 0, numPts, CalculationType.IDENTITY);
+        final double[] transformedData = new double[expectedData.length];
+        transform.transform(passthroughData, 0, transformedData, 0, numPts);
+        assertCoordinatesEqual("Direct transform.", passthroughDim,
+                expectedData, 0, transformedData, 0, numPts, CalculationType.DIRECT_TRANSFORM);
         /*
-         * Verify the consistency between different 'transform(…)' methods.
-         * We use a relatively high tolerance threshold because result are
-         * computed using inputs stored as float values.
+         * Test inverse transform.
          */
-        tolerance         = 1E-4f;
+        tolerance         = 1E-8;
         toleranceModifier = ToleranceModifier.RELATIVE;
+        Arrays.fill(transformedData, Double.NaN);
+        transform.inverse().transform(expectedData, 0, transformedData, 0, numPts);
+        assertCoordinatesEqual("Inverse transform.", passthroughDim,
+                passthroughData, 0, transformedData, 0, numPts, CalculationType.INVERSE_TRANSFORM);
+        /*
+         * Verify the consistency between different 'transform(…)' methods.
+         */
+        final float[] sourceAsFloat = Numerics.copyAsFloats(passthroughData);
         final float[] targetAsFloat = verifyConsistency(sourceAsFloat);
         assertEquals("Unexpected length of transformed array.", expectedData.length, targetAsFloat.length);
-        assertCoordinatesEqual("A transformed value is wrong.", passthroughDim,
-                expectedData, 0, targetAsFloat, 0, numPts, CalculationType.DIRECT_TRANSFORM);
         /*
-         * Test inverse transform.
+         * We use a relatively high tolerance threshold because result are
+         * computed using inputs stored as float values.
          */
-        transform.inverse().transform(passthroughData, 0, passthroughData, 0, numPts);
-        assertCoordinatesEqual("A transformed value is wrong.", passthroughDim,
-                sourceAsFloat, 0, passthroughData, 0, numPts, CalculationType.DIRECT_TRANSFORM);
+        if (transform instanceof LinearTransform) {
+            tolerance         = 1E-4;
+            toleranceModifier = ToleranceModifier.RELATIVE;
+            assertCoordinatesEqual("A transformed value is wrong.", passthroughDim,
+                    expectedData, 0, targetAsFloat, 0, numPts, CalculationType.DIRECT_TRANSFORM);
+        }
     }
 }



Mime
View raw message