/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2010-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2010-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.cs; import java.util.Set; import java.util.Collection; import java.io.Serializable; import org.opengis.util.GenericName; import org.opengis.util.InternationalString; import org.apache.sis.io.wkt.Formatter; import org.apache.sis.io.wkt.FormattableObject; import org.opengis.metadata.extent.Extent; import org.opengis.coverage.grid.GridEnvelope; import org.opengis.coverage.grid.GridGeometry; import org.opengis.metadata.Identifier; import org.opengis.referencing.datum.Datum; import org.opengis.referencing.datum.GeodeticDatum; import org.opengis.referencing.datum.VerticalDatum; import org.opengis.referencing.datum.TemporalDatum; import org.opengis.referencing.cs.TimeCS; import org.opengis.referencing.cs.VerticalCS; import org.opengis.referencing.cs.CartesianCS; import org.opengis.referencing.cs.EllipsoidalCS; import org.opengis.referencing.cs.CoordinateSystem; import org.opengis.referencing.crs.SingleCRS; import org.opengis.referencing.crs.TemporalCRS; import org.opengis.referencing.crs.VerticalCRS; import org.opengis.referencing.crs.ProjectedCRS; import org.opengis.referencing.crs.GeographicCRS; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.Projection; import org.opengis.referencing.operation.MathTransform; import org.geotoolkit.io.wkt.Formattable; import org.geotoolkit.lang.Decorator; /** * An implementation of {@link CoordinateReferenceSystem} delegating every method * calls to the wrapped CRS, except the coordinate system. The axes will be instances * of {@link DiscreteCoordinateSystemAxis} built from the ordinate values given at * construction time. * <p> * This class implements {@link GridGeometry}. But the <cite>grid to CRS</cite> transform * returned by the later is correct only if every axes are regular. This is not verified * because the threshold for determining if an axis is regular or not is at caller choice. * * @author Martin Desruisseaux (Geomatys) * @version 3.20 * * @since 3.15 * @module */ @Decorator(CoordinateReferenceSystem.class) class DiscreteCRS<T extends CoordinateReferenceSystem> extends FormattableObject implements CoordinateReferenceSystem, GridGeometry, Formattable, Serializable { /** * For cross-version compatibility. */ private static final long serialVersionUID = -6401567052946218355L; /** * The wrapped projected CRS. */ protected final T crs; /** * The coordinate system. */ protected final DiscreteCS cs; /** * The grid to CRS transform, created only when first needed. */ transient MathTransform gridToCRS; /** * Creates a new instance wrapping the given CRS with the given coordinate system. * * @param crs The CRS to wrap. * @param cs The coordinate system. */ DiscreteCRS(final T crs, final DiscreteCS cs) { this.crs = crs; this.cs = cs; } /** * Returns the name of the wrapped CRS. */ @Override public final Identifier getName() { return crs.getName(); } /** * Returns the alias of the wrapped CRS. */ @Override public final Collection<GenericName> getAlias() { return crs.getAlias(); } /** * Returns the identifiers of the wrapped CRS. */ @Override public final Set<Identifier> getIdentifiers() { return crs.getIdentifiers(); } /** * Returns the coordinate system built at construction time from the given axes. */ @Override public CoordinateSystem getCoordinateSystem() { return cs; } /** * A discrete geographic CRS. */ static final class Geographic extends DiscreteCRS<GeographicCRS> implements GeographicCRS { private static final long serialVersionUID = -6614621727541494429L; Geographic(final GeographicCRS crs, final double[]... ordinates) { super(crs, new DiscreteCS.Ellipsoidal(crs.getCoordinateSystem(), ordinates)); } @Override public EllipsoidalCS getCoordinateSystem() {return (EllipsoidalCS) cs;} @Override public GeodeticDatum getDatum() {return crs.getDatum();} } /** * A discrete projected CRS. */ static final class Projected extends DiscreteCRS<ProjectedCRS> implements ProjectedCRS { private static final long serialVersionUID = 7468800070780104601L; Projected(final ProjectedCRS crs, final double[]... ordinates) { super(crs, new DiscreteCS.Cartesian(crs.getCoordinateSystem(), ordinates)); } @Override public CartesianCS getCoordinateSystem() {return (CartesianCS) cs;} @Override public GeodeticDatum getDatum() {return crs.getDatum();} @Override public GeographicCRS getBaseCRS() {return crs.getBaseCRS();} @Override public Projection getConversionFromBase() {return crs.getConversionFromBase();} } /** * A discrete vertical CRS. */ static final class Vertical extends DiscreteCRS<VerticalCRS> implements VerticalCRS { private static final long serialVersionUID = -4037988222135517657L; Vertical(final VerticalCRS crs, final double[]... ordinates) { super(crs, new DiscreteCS.Vertical(crs.getCoordinateSystem(), ordinates)); } @Override public VerticalCS getCoordinateSystem() {return (VerticalCS) cs;} @Override public VerticalDatum getDatum() {return crs.getDatum();} } /** * A discrete temporal CRS. */ static final class Temporal extends DiscreteCRS<TemporalCRS> implements TemporalCRS { private static final long serialVersionUID = -4154329164568410034L; Temporal(final TemporalCRS crs, final double[]... ordinates) { super(crs, new DiscreteCS.Time(crs.getCoordinateSystem(), ordinates)); } @Override public TimeCS getCoordinateSystem() {return (TimeCS) cs;} @Override public TemporalDatum getDatum() {return crs.getDatum();} } /** * A discrete single CRS of unknown type. */ static final class Single extends DiscreteCRS<SingleCRS> implements SingleCRS { private static final long serialVersionUID = 1616462096697283316L; Single(final SingleCRS crs, final double[]... ordinates) { super(crs, new DiscreteCS(crs.getCoordinateSystem(), ordinates)); } @Override public Datum getDatum() {return crs.getDatum();} } /** * Returns the grid range. The {@linkplain GridEnvelope#getLow() lower} values are * always 0, and the {@linkplain GridEnvelope#getHigh() upper} values are determined * by the number of discrete ordinates for each axes. */ @Override public final GridEnvelope getExtent() { return cs.getExtent(); } @Override @Deprecated public final GridEnvelope getGridRange() { return cs.getGridRange(); } /** * Returns the transform from grid coordinates to CRS coordinates mapping pixel center. * This method assumes that all axes are regular (this is not verified). */ @Override public synchronized MathTransform getGridToCRS() { if (gridToCRS == null) { gridToCRS = cs.getGridToCRS(this); } return gridToCRS; } /** * Returns the domain of validity of the wrapped CRS. */ @Override public final Extent getDomainOfValidity() { return crs.getDomainOfValidity(); } /** * Returns the scope of the wrapped CRS. */ @Override public final InternationalString getScope() { return crs.getScope(); } /** * Returns the remarks of the wrapped CRS. */ @Override public final InternationalString getRemarks() { return crs.getRemarks(); } /** * Delegates the formatting to the wrapped CRS if possible. It is okay to delegate to the * wrapped CRS despite having different CS, because the WKT representation of that CS is * not changed. */ @Override public String formatTo(final Formatter formatter) { if (crs instanceof Formattable) { return ((Formattable) crs).formatTo(formatter); } else { return null; } } /** * Returns the WKT formatted by the wrapped CRS. * See the javadoc comment in {@link #formatWKT(Formatter)}. */ @Override public final String toWKT() throws UnsupportedOperationException { return crs.toWKT(); } /** * Returns the string representation of the wrapped CRS. * This is usually the same than the WKT representation. */ @Override public final String toString() { return crs.toString(); } /** * Returns a hash code value for this CRS. */ @Override public final int hashCode() { return crs.hashCode() + 31 * cs.hashCode(); } /** * Compares this CS with the given object for equality. * * @param other The object to compare with this CRS for equality. */ @Override public final boolean equals(final Object other) { if (other != null && other.getClass() == getClass()) { final DiscreteCRS<?> that = (DiscreteCRS<?>) other; return crs.equals(that.crs) && cs.equals(that.cs); } return false; } }