001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/model/coverage/AbstractCoverage.java $
002 /*----------------------------------------------------------------------------
003 This file originated as a part of GeoAPI.
004
005 GeoAPI is free software. GeoAPI may be used, modified and
006 redistributed by anyone for any purpose requring only maintaining the
007 copyright and license terms on the source code and derivative files.
008 See the OGC legal page for details.
009
010 The copyright to the GeoAPI interfaces is held by the Open Geospatial
011 Consortium, see http://www.opengeospatial.org/ogc/legal
012 ----------------------------------------------------------------------------*/
013 package org.deegree.model.coverage;
014
015 import java.awt.image.renderable.RenderableImage;
016 import java.io.Serializable;
017 import java.util.ArrayList;
018 import java.util.List;
019
020 import org.deegree.datatypes.CodeList;
021 import org.deegree.model.crs.CRSFactory;
022 import org.deegree.model.crs.CoordinateSystem;
023 import org.deegree.model.metadata.iso19115.Keywords;
024 import org.deegree.model.spatialschema.Envelope;
025 import org.deegree.ogcwebservices.wcs.describecoverage.AxisDescription;
026 import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
027
028 /**
029 * Provides access to an OpenGIS coverage. The essential property of coverage is to be able to generate a value for any
030 * point within its domain. How coverage is represented internally is not a concern.
031 *
032 * For example consider the following different internal representations of coverage:<br>
033 * <OL>
034 * <li>A coverage may be represented by a set of polygons which exhaustively tile a plane (that is each point on the
035 * plane falls in precisely one polygon). The value returned by the coverage for a point is the value of an attribute of
036 * the polygon that contains the point.</li>
037 * <li>A coverage may be represented by a grid of values. The value returned by the coverage for a point is that of the
038 * grid value whose location is nearest the point.</li>
039 * <li>Coverage may be represented by a mathematical function. The value returned by the coverage for a point is just
040 * the return value of the function when supplied the coordinates of the point as arguments.</li>
041 * <li>Coverage may be represented by combination of these. For example, coverage may be represented by a combination of
042 * mathematical functions valid over a set of polynomials.</LI>
043 * </OL>
044 *
045 * A coverage has a corresponding {@link SampleDimension} for each sample dimension in the coverage.
046 *
047 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
048 * @author last edited by: $Author: mschneider $
049 *
050 * @version $Revision: 20326 $, $Date: 2009-10-22 18:41:56 +0200 (Do, 22 Okt 2009) $
051 */
052 public abstract class AbstractCoverage implements Coverage, Serializable {
053
054 private static final long serialVersionUID = 1839111189194771556L;
055
056 protected CoverageOffering coverageOffering = null;
057
058 private CoordinateSystem crs = null;
059
060 private Envelope envelope = null;
061
062 protected int numSources = 0;
063
064 protected Coverage[] sources = null;
065
066 private String[] dimensionNames = null;
067
068 /**
069 * @param coverageOffering
070 * @param env
071 */
072 public AbstractCoverage( CoverageOffering coverageOffering, Envelope env ) {
073 this( coverageOffering, env, null );
074 }
075
076 /**
077 * @param coverageOffering
078 * @param env
079 * @param sources
080 */
081 public AbstractCoverage( CoverageOffering coverageOffering, Envelope env, Coverage[] sources ) {
082 this.coverageOffering = coverageOffering;
083 this.sources = sources;
084 if ( sources != null ) {
085 numSources = sources.length;
086 }
087 // set coverage envelope
088 envelope = env;
089
090 if ( coverageOffering != null ) {
091 // set coordinate system
092 try {
093 CodeList[] cl = coverageOffering.getSupportedCRSs().getNativeSRSs();
094 String code = cl[cl.length - 1].getCodes()[0];
095 crs = CRSFactory.create( code );
096 } catch ( Exception e ) {
097 e.printStackTrace();
098 }
099 buildDimensionNames();
100 }
101 }
102
103 /**
104 *
105 * @param coverageOffering
106 * @param env
107 * @param sources
108 * @param crs
109 */
110 public AbstractCoverage( CoverageOffering coverageOffering, Envelope env, Coverage[] sources, CoordinateSystem crs ) {
111 this.coverageOffering = coverageOffering;
112 this.sources = sources;
113 if ( sources != null ) {
114 numSources = sources.length;
115 }
116 // set coverage envelope
117 envelope = env;
118
119 this.crs = crs;
120 if ( coverageOffering != null ) {
121 buildDimensionNames();
122 }
123 }
124
125 /**
126 * private method to build the dimension names from the coverage axises (x, y, [z]) and the available ranges
127 */
128 private void buildDimensionNames() {
129 AxisDescription[] axisDescription = coverageOffering.getRangeSet().getAxisDescription();
130 dimensionNames = new String[axisDescription.length + envelope.getMax().getCoordinateDimension()];
131 int k = 0;
132 dimensionNames[k++] = "X";
133 dimensionNames[k++] = "Y";
134 if ( envelope.getMax().getCoordinateDimension() == 3 ) {
135 dimensionNames[k++] = "Z";
136 }
137 for ( int i = 0; i < axisDescription.length; i++ ) {
138 dimensionNames[k++] = axisDescription[i].getName();
139 }
140 }
141
142 /**
143 * Specifies the coordinate reference system used when accessing a coverage or grid coverage with the
144 * <code>evaluate(...)</code> methods. It is also the coordinate reference system of the coordinates used with the
145 * math transform gridToCoordinateSystem}).
146 *
147 * This coordinate reference system is usually different than coordinate system of the grid. Grid coverage can be
148 * accessed (re-projected) with new coordinate reference system with the
149 * {@link "org.opengis.coverage.processing.GridCoverageProcessor"} component. In this case, a new instance of a grid
150 * coverage is created. <br>
151 * <br>
152 * Note: If a coverage does not have an associated coordinate reference system, the returned value will be
153 * <code>null</code>. attribute should also be <code>null</code> if the coordinate reference system is
154 * <code>null</code>.
155 *
156 * @return The coordinate reference system used when accessing a coverage or grid coverage with the
157 * <code>evaluate(...)</code> methods, or <code>null</code>.
158 */
159 public CoordinateSystem getCoordinateReferenceSystem() {
160 return crs;
161 }
162
163 /**
164 * The bounding box for the coverage domain in {@linkplain #getCoordinateReferenceSystem coordinate reference
165 * system} coordinates. For grid coverages, the grid cells are centered on each grid coordinate. The envelope for a
166 * 2-D grid coverage includes the following corner positions.
167 *
168 * <blockquote>
169 *
170 * <pre>
171 * (Minimum row - 0.5, Minimum column - 0.5) for the minimum coordinates
172 * (Maximum row - 0.5, Maximum column - 0.5) for the maximum coordinates
173 * </pre>
174 *
175 * </blockquote>
176 *
177 * If a grid coverage does not have any associated coordinate reference system, the minimum and maximum coordinate
178 * points for the envelope will be empty sequences.
179 *
180 * @return The bounding box for the coverage domain in coordinate system coordinates.
181 */
182 public Envelope getEnvelope() {
183 return envelope;
184 }
185
186 /**
187 * The names of each dimension in the coverage. Typically these names are <var>x</var>, <var>y</var>, <var>z</var>
188 * and <var>t</var>. The number of items in the sequence is the number of dimensions in the coverage. Grid coverages
189 * are typically 2D (<var>x</var>, <var>y</var>) while other coverages may be 3D (<var>x</var>, <var>y</var>,
190 * <var>z</var>) or 4D (<var>x</var>, <var>y</var>, <var>z</var>, <var>t</var>). The number of dimensions of the
191 * coverage is the number of entries in the list of dimension names.
192 *
193 * @return The names of each dimension in the coverage.
194 */
195 public String[] getDimensionNames() {
196 return dimensionNames;
197 }
198
199 /**
200 * Retrieve sample dimension information for the coverage. For a grid coverage a sample dimension is a band. The
201 * sample dimension information include such things as description, data type of the value (bit, byte, integer...),
202 * the no data values, minimum and maximum values and a color table if one is associated with the dimension. A
203 * coverage must have at least one sample dimension.
204 *
205 * @param index
206 * Index for sample dimension to retrieve. Indices are numbered 0 to (<var>n</var>-1).
207 * @return Sample dimension information for the coverage, currently always null
208 * @throws IndexOutOfBoundsException
209 * if <code>index</code> is out of bounds.
210 */
211 public SampleDimension getSampleDimension( int index )
212 throws IndexOutOfBoundsException {
213 return null;
214 }
215
216 /**
217 * Number of grid coverages which the grid coverage was derived from. This implementation specification does not
218 * include interfaces for creating collections of coverages therefore this value will usually be one indicating an
219 * adapted grid coverage, or zero indicating a raw grid coverage.
220 *
221 * @return The number of grid coverages which the grid coverage was derived from.
222 */
223 public int getNumSources() {
224 return 0;
225 }
226
227 /**
228 * Returns the source data for a coverage. This is intended to allow applications to establish what
229 * <code>Coverage</code>s will be affected when others are updated, as well as to trace back to the "raw data".
230 *
231 * @param sourceDataIndex
232 * Source coverage index. Indexes start at 0.
233 * @return The source data for a coverage.
234 * @throws IndexOutOfBoundsException
235 * if <code>sourceDataIndex</code> is out of bounds.
236 *
237 * @see #getNumSources
238 * @see "org.opengis.coverage.grid.GridCoverage#getSource"
239 */
240 public Coverage getSource( int sourceDataIndex )
241 throws IndexOutOfBoundsException {
242 if ( sources != null && sources.length >= sourceDataIndex - 1 ) {
243 return sources[sourceDataIndex];
244 }
245 return null;
246 }
247
248 /**
249 * List of metadata keywords for a coverage. If no metadata is available, the sequence will be empty.
250 *
251 * @return the list of metadata keywords for a coverage.
252 *
253 * @see #getMetadataValue
254 * @see javax.media.jai.PropertySource#getPropertyNames()
255 */
256 public String[] getMetadataNames() {
257 String[] keyw = new String[0];
258 Keywords[] keywords = coverageOffering.getKeywords();
259 if ( keywords != null ) {
260 List<String> list = new ArrayList<String>( 100 );
261 for ( int i = 0; i < keywords.length; i++ ) {
262 String[] kw = keywords[i].getKeywords();
263 for ( int k = 0; k < kw.length; k++ ) {
264 list.add( kw[k] );
265 }
266 }
267 keyw = list.toArray( new String[list.size()] );
268 }
269 return keyw;
270 }
271
272 /**
273 * Retrieve the metadata value for a given metadata name.
274 *
275 * @param name
276 * Metadata keyword for which to retrieve data.
277 * @return the metadata value for a given metadata name.
278 * @throws MetadataNameNotFoundException
279 * if there is no value for the specified metadata name.
280 *
281 * @see #getMetadataNames
282 * @see javax.media.jai.PropertySource#getProperty
283 */
284 public String getMetadataValue( String name )
285 throws MetadataNameNotFoundException {
286 return null;
287 }
288
289 /**
290 * Returns 2D view of this coverage as a renderable image. This optional operation allows interoperability with <A
291 * HREF="http://java.sun.com/products/java-media/2D/">Java2D</A>. If this coverage is a
292 * {@link "org.opengis.coverage.grid.GridCoverage"} backed by a {@link java.awt.image.RenderedImage}, the underlying
293 * image can be obtained with:
294 *
295 * <code>getRenderableImage(0,1).{@linkplain RenderableImage#createDefaultRendering()
296 * createDefaultRendering()}</code>
297 *
298 * @param xAxis
299 * Dimension to use for the <var>x</var> axis.
300 * @param yAxis
301 * Dimension to use for the <var>y</var> axis.
302 * @return A 2D view of this coverage as a renderable image.
303 * @throws UnsupportedOperationException
304 * if this optional operation is not supported.
305 * @throws IndexOutOfBoundsException
306 * if <code>xAxis</code> or <code>yAxis</code> is out of bounds.
307 */
308 public abstract RenderableImage getRenderableImage( int xAxis, int yAxis )
309 throws UnsupportedOperationException, IndexOutOfBoundsException;
310
311 /**
312 * returns the {@link CoverageOffering} describing a coverage
313 *
314 * @see CoverageOffering
315 * @return the CoverageOffering describing a coverage
316 */
317 public CoverageOffering getCoverageOffering() {
318 return coverageOffering;
319 }
320
321 }