/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.referencing.operation.transform;
import java.util.Arrays;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.ArraysExt;
import org.opengis.referencing.operation.MathTransform1D;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.referencing.operation.transform.AbstractMathTransform1D;
/**
* {@link MathTransform1D} with linear interpolation between values.
*
* @author Johann Sorel (Geomatys)
* @author Remi Marechal (Geomatys).
*
* @deprecated Moved to {@link org.apache.sis.referencing.operation.transform.MathTransforms#interpolate}
*/
@Deprecated
public final class LinearInterpolator1D extends AbstractMathTransform1D {
private final double[] antecedent;
private final double[] values;
private boolean isIncreaseOrder = true;
private final int l;
/**
* <p>In this case an antecedents default table is construct such as : <br/><br/>
*
* [0, 1, ... , N] with N is length of image table values.<p>
*
* @param values image from antecedents table values.
*/
private LinearInterpolator1D(double[] values) {
ArgumentChecks.ensureNonNull("values", values);
this.l = values.length;
if (l < 2)
throw new IllegalArgumentException("table must have more than only two values");
this.values = values;
this.antecedent = new double[l];
for (int v = 0;v<l;v++) this.antecedent[v] = v;
}
/**
* Two tables such as : f(antecedents) = values.
*
* @param antecedents "abscissa" table values.
* @param values image from antecedents table values.
*/
private LinearInterpolator1D(double[] antecedents, double[] values) {
ArgumentChecks.ensureNonNull("values", values);
ArgumentChecks.ensureNonNull("antecedents", antecedents);
this.l = antecedents.length;
if (l<2)
throw new IllegalArgumentException("table must have more than only two values");
if (l != values.length)
throw new IllegalArgumentException("antecedents and values table must have same length");
if (!ArraysExt.isSorted(antecedents, true)) {
final double[] antecedent2 = new double[l];
int id = l;
for (int i = 0; i < l; i++) antecedent2[i] = antecedents[--id];
if (!ArraysExt.isSorted(antecedent2, true))
throw new IllegalArgumentException("antecedents table must be strictly increasing or decreasing");
isIncreaseOrder = false;
}
this.antecedent = antecedents;
this.values = values;
}
/**
* {@inheritDoc }.
*/
@Override
public double transform(double d) throws TransformException {
int ida, idb, idn, idn1;
if (isIncreaseOrder) {
ida = 0; idb = l-1;
idn = 0; idn1 = 1;
} else {
ida = l-1; idb = 0;
idn = 1; idn1 = 0;
}
if (d <= antecedent[ida]) return values[ida];
if (d >= antecedent[idb]) return values[idb];
double x0, x1;
for (int id = 0; id < l-1; id++) {
x0 = antecedent[idn];
x1 = antecedent[idn1];
if (d == x0) return values[idn];
else if (d == x1) return values[idn1];
else if (d > antecedent[idn] && d < antecedent[idn1])
return values[idn] + (values[idn1] - values[idn]) * ((d-x0) / (x1-x0));
idn++;idn1++;
}
return 0;//impossible
}
/**
* {@inheritDoc }.
* Note : for each segment lower sequence point derivative is inclusive
* whereas upper sequence point is exclusive.
*/
@Override
public double derivative(double d) throws TransformException {
int idn, idn1;
if (isIncreaseOrder) {
idn = 0; idn1 = 1;
if (d < antecedent[0] || d >= antecedent[l-1]) return 0;
} else {
idn = 1; idn1 = 0;
if (d <= antecedent[l-1] || d > antecedent[0]) return 0;
}
for (int id = 0; id < l; id++) {
if ((d > antecedent[idn] && d < antecedent[idn1]) || d == antecedent[id])
return (values[idn1]-values[idn]) / (antecedent[idn1]-antecedent[idn]);
idn++;idn1++;
}
return 0;//impossible
}
@Override
public MathTransform1D inverse() throws NoninvertibleTransformException {
if (!ArraysExt.isSorted(values, true)) {
final double[] values2 = new double[l];
int id = l;
for (int i = 0; i < l; i++) values2[i] = values[--id];
if (!ArraysExt.isSorted(values2, true))
throw new NoninvertibleTransformException("non inversible");
}
return new LinearInterpolator1D(values, antecedent);
}
@Override
public boolean isIdentity() {
return Arrays.equals(antecedent, values);
}
public static LinearInterpolator1D create(double[] values){
return new LinearInterpolator1D(values);
}
public static LinearInterpolator1D create(double[] antecedents, double[] values) {
return new LinearInterpolator1D(antecedents, values);
}
}