/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2005-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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.geotools.referencing.piecewise;
import org.geotools.geometry.GeneralDirectPosition;
import org.geotools.referencing.operation.matrix.Matrix1;
import org.geotools.referencing.wkt.UnformattableObjectException;
import org.geotools.renderer.i18n.ErrorKeys;
import org.geotools.renderer.i18n.Errors;
import org.geotools.util.NumberRange;
import org.geotools.util.Utilities;
import org.opengis.geometry.DirectPosition;
import org.opengis.referencing.operation.MathTransform1D;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.opengis.referencing.operation.TransformException;
/**
* Convenience implementation of the {@link DefaultPiecewiseTransform1DElement} .
* @author Simone Giannecchini, GeoSolutions
*
*
*
* @source $URL$
*/
public class DefaultPiecewiseTransform1DElement extends DefaultDomainElement1D implements
PiecewiseTransform1DElement {
/**
*
*/
private static final long serialVersionUID = 7422178060824402864L;
/**
* The math transform
* @uml.property name="transform"
*/
private MathTransform1D transform;
/**
* Inverse {@link MathTransform1D}
*/
private MathTransform1D inverse;
private int hashCode=-1;
/**
* Builds up a {@link DefaultPiecewiseTransform1DElement} which maps a range to a constant value.
*
* @param name
* for this {@link DomainElement1D}
* @param inRange
* for this {@link DomainElement1D}
* @param outVal
* for this {@link DefaultLinearPiecewiseTransform1DElement}
* @throws IllegalArgumentException
* in case the input values are illegal.
*/
public static DefaultPiecewiseTransform1DElement create(
final CharSequence name,
final NumberRange<? extends Number> inRange,
final double value){
return new DefaultConstantPiecewiseTransformElement(name, inRange, value);
}
/**
* Builds up a DefaultPiecewiseTransform1DElement which maps a range to a constant value.
*
* @param name
* for this {@link DomainElement1D}
* @param inRange
* for this {@link DomainElement1D}
* @param outVal
* for this {@link DefaultLinearPiecewiseTransform1DElement}
* @throws IllegalArgumentException
* in case the input values are illegal.
*/
public static DefaultPiecewiseTransform1DElement create(
final CharSequence name,
final NumberRange<? extends Number> inRange,
final byte value){
return new DefaultConstantPiecewiseTransformElement(name, inRange, value);
}
/**
* Builds up a DefaultPiecewiseTransform1DElement which maps a range to a constant value.
*
* @param name
* for this {@link DomainElement1D}
* @param inRange
* for this {@link DomainElement1D}
* @param outVal
* for this {@link DefaultLinearPiecewiseTransform1DElement}
* @throws IllegalArgumentException
* in case the input values are illegal.
*/
public static DefaultPiecewiseTransform1DElement create(
final CharSequence name,
final NumberRange<? extends Number> inRange,
final int value){
return new DefaultConstantPiecewiseTransformElement(name, inRange, value);
}
/**
* Constructor.
*
* @param name
* for this {@link DefaultLinearPiecewiseTransform1DElement}.
* @param inRange
* for this {@link DefaultLinearPiecewiseTransform1DElement}.
* @param outRange
* for this {@link DefaultLinearPiecewiseTransform1DElement}.
*/
public static DefaultPiecewiseTransform1DElement create(
final CharSequence name,
final NumberRange<? extends Number> inRange,
final NumberRange<? extends Number> outRange) {
return new DefaultLinearPiecewiseTransform1DElement(name,inRange,outRange);
}
/**
* Creates a pass-through DefaultPiecewiseTransform1DElement.
*
* @param name
* for this {@link DomainElement1D}.
* @throws IllegalArgumentException
*/
public static DefaultPiecewiseTransform1DElement create(
final CharSequence name)
throws IllegalArgumentException {
return new DefaultPassthroughPiecewiseTransform1DElement(name, NumberRange.create(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
}
/**
* Creates a pass-through DefaultPiecewiseTransform1DElement.
*
* @param name
* for this {@link DomainElement1D}.
* @param valueRange
* for this {@link DomainElement1D}.
* @throws IllegalArgumentException
*/
public static DefaultPiecewiseTransform1DElement create(
final CharSequence name,
final NumberRange<? extends Number> valueRange)
throws IllegalArgumentException {
return new DefaultPassthroughPiecewiseTransform1DElement(name, valueRange);
}
/**
* Protected constructor for {@link DomainElement1D}s that want to build their
* transform later on.
*
* @param name
* for this {@link DomainElement1D}.
* @param valueRange
* for this {@link DomainElement1D}.
* @throws IllegalArgumentException
*/
protected DefaultPiecewiseTransform1DElement(CharSequence name, NumberRange<? extends Number> valueRange)
throws IllegalArgumentException {
super(name, valueRange);
}
/**
* Public constructor for building a {@link DomainElement1D} which applies the
* specified transformation on the values that fall into its definition
* range.
*
* @param name
* for this {@link DomainElement1D}.
* @param valueRange
* for this {@link DomainElement1D}.
* @param transform
* for this {@link DomainElement1D}.
* @throws IllegalArgumentException
*/
protected DefaultPiecewiseTransform1DElement(CharSequence name, NumberRange<? extends Number> valueRange,
final MathTransform1D transform) throws IllegalArgumentException {
super(name, valueRange);
// /////////////////////////////////////////////////////////////////////
//
// Initial checks
//
// /////////////////////////////////////////////////////////////////////
PiecewiseUtilities.ensureNonNull("transform", transform);
this.transform = transform;
}
/**
* Returns a Well Known Text</cite> (WKT) for this object. This operation
* may fails if an object is too complex for the WKT format capability.
*
* @return The Well Know Text for this object.
* @throws UnsupportedOperationException
* If this object can't be formatted as WKT.
*
* XXX Not yet implemented.
*/
public String toWKT() throws UnsupportedOperationException {
throw new UnformattableObjectException("Not yet implemented.", this
.getClass());
}
/**
* Getter for the underlying {@link MathTransform1D} .
* @return the underlying {@link MathTransform1D} .
* @uml.property name="transform"
*/
protected synchronized MathTransform1D getTransform() {
return transform;
}
/**
* Transforms the specified value.
*
* @param value
* The value to transform.
* @return the transformed value.
* @throws TransformException
* if the value can't be transformed.
*/
public synchronized double transform(double value)
throws TransformException {
if (transform == null)
throw new IllegalStateException();
if (contains(value))
return transform.transform(value);
throw new IllegalArgumentException(Errors.format(ErrorKeys.ILLEGAL_ARGUMENT_$1, "Provided value is not contained in this domain"));
}
/**
* Gets the derivative of this function at a value.
*
* @param value
* The value where to evaluate the derivative.
* @return The derivative at the specified point.
* @throws TransformException
* if the derivative can't be evaluated at the specified point.
*/
public synchronized double derivative(double value)
throws TransformException {
if (transform == null)
// @todo TODO
throw new IllegalStateException();
if (contains(value))
return transform.derivative(value);
throw new TransformException(Errors.format(ErrorKeys.TRANSFORM_EVALUATION_$1, new Double(value)));
}
/**
* Transforms the specified {@code ptSrc} and stores the result in
* {@code ptDst}.
*/
public DirectPosition transform(final DirectPosition ptSrc,
DirectPosition ptDst) throws TransformException {
PiecewiseUtilities.checkDimension(ptSrc);
if (ptDst == null) {
ptDst = new GeneralDirectPosition(1);
} else {
PiecewiseUtilities.checkDimension(ptDst);
}
ptDst.setOrdinate(0, transform(ptSrc.getOrdinate(0)));
return ptDst;
}
/**
* Gets the derivative of this transform at a point.
*/
public Matrix derivative(final DirectPosition point)
throws TransformException {
PiecewiseUtilities.ensureNonNull("DirectPosition", point);
PiecewiseUtilities.checkDimension(point);
return new Matrix1(derivative(point.getOrdinate(0)));
}
/*
* (non-Javadoc)
*
* @see org.opengis.referencing.operation.MathTransform#transform(double[],
* int, double[], int, int)
*/
public void transform(double[] arg0, int arg1, double[] arg2, int arg3,
int arg4) throws TransformException {
throw new UnsupportedOperationException(Errors.format(ErrorKeys.UNSUPPORTED_OPERATION_$1, "transform"));
}
/*
* (non-Javadoc)
*
* @see org.opengis.referencing.operation.MathTransform#transform(float[],
* int, float[], int, int)
*/
public void transform(float[] arg0, int arg1, float[] arg2, int arg3,
int arg4) throws TransformException {
throw new UnsupportedOperationException(Errors.format(ErrorKeys.UNSUPPORTED_OPERATION_$1, "transform"));
}
/*
* (non-Javadoc)
*
* @see org.opengis.referencing.operation.MathTransform#transform(float[],
* int, float[], int, int)
*/
public void transform(float[] arg0, int arg1, double[] arg2, int arg3,
int arg4) throws TransformException {
throw new UnsupportedOperationException(Errors.format(ErrorKeys.UNSUPPORTED_OPERATION_$1, "transform"));
}
/*
* (non-Javadoc)
*
* @see org.opengis.referencing.operation.MathTransform#transform(float[],
* int, float[], int, int)
*/
public void transform(double[] arg0, int arg1, float[] arg2, int arg3,
int arg4) throws TransformException {
throw new UnsupportedOperationException(Errors.format(ErrorKeys.UNSUPPORTED_OPERATION_$1, "transform"));
}
/*
* (non-Javadoc)
*
* @see org.opengis.referencing.operation.MathTransform#getSourceDimensions()
*/
public int getSourceDimensions() {
return transform.getSourceDimensions();
}
/*
* (non-Javadoc)
*
* @see org.opengis.referencing.operation.MathTransform#getTargetDimensions()
*/
public int getTargetDimensions() {
return transform.getTargetDimensions();
}
/*
* (non-Javadoc)
*
* @see org.opengis.referencing.operation.MathTransform#inverse()
*/
public synchronized MathTransform1D inverse()
throws NoninvertibleTransformException {
if (inverse != null)
return inverse;
if (transform == null)
throw new IllegalStateException(Errors.format(ErrorKeys.ILLEGAL_STATE));
inverse = (MathTransform1D) transform.inverse();
return inverse;
}
/*
* (non-Javadoc)
*
* @see org.opengis.referencing.operation.MathTransform#isIdentity()
*/
public boolean isIdentity() {
return transform.isIdentity();
}
/**
* @param mathTransform
* @uml.property name="inverse"
*/
protected synchronized void setInverse(MathTransform1D mathTransform) {
if (this.inverse == null)
this.inverse = mathTransform;
else
throw new IllegalStateException(Errors.format(ErrorKeys.ILLEGAL_STATE));
}
/**
* @param transform
* @uml.property name="transform"
*/
protected synchronized void setTransform(MathTransform1D transform) {
PiecewiseUtilities.ensureNonNull("transform", transform);
if (this.transform == null)
this.transform = transform;
else
throw new IllegalStateException(Errors.format(ErrorKeys.ILLEGAL_STATE));
}
public boolean equals(Object obj) {
if(obj==this)
return true;
if(!(obj instanceof DefaultPiecewiseTransform1DElement))
return false;
final DefaultPiecewiseTransform1DElement that=(DefaultPiecewiseTransform1DElement) obj;
if(getEquivalenceClass()!=(that.getEquivalenceClass()))
return false;
if (!Utilities.equals(transform, that.transform))
return false;
if (!Utilities.equals(inverse, that.inverse))
return false;
return super.equals(obj);
}
/*
* (non-Javadoc)
* @see org.geotools.referencing.piecewise.DefaultDomainElement1D#toString()
*/
public String toString() {
final StringBuilder buffer= new StringBuilder(super.toString());
buffer.append("\n").append("wkt transform=").append(this.transform.toWKT());
return buffer.toString();
}
protected Class<?> getEquivalenceClass(){
return DefaultPiecewiseTransform1DElement.class;
}
@Override
public int hashCode() {
if(hashCode>=0)
return hashCode;
hashCode=37;
hashCode=Utilities.hash(transform,hashCode);
hashCode=Utilities.hash( inverse,hashCode);
hashCode=Utilities.hash( super.hashCode(),hashCode);
return hashCode;
}
public static DefaultPiecewiseTransform1DElement create(String string,
NumberRange<? extends Number> range,
MathTransform1D mathTransform1D) {
return new DefaultPiecewiseTransform1DElement(string, range, mathTransform1D);
}
}