001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/coverage/AbstractCoverage.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2008 by:
006 EXSE, Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/deegree/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 This library is free software; you can redistribute it and/or
012 modify it under the terms of the GNU Lesser General Public
013 License as published by the Free Software Foundation; either
014 version 2.1 of the License, or (at your option) any later version.
015
016 This library is distributed in the hope that it will be useful,
017 but WITHOUT ANY WARRANTY; without even the implied warranty of
018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019 Lesser General Public License for more details.
020
021 You should have received a copy of the GNU Lesser General Public
022 License along with this library; if not, write to the Free Software
023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024
025 Contact:
026
027 Andreas Poth
028 lat/lon GmbH
029 Aennchenstr. 19
030 53115 Bonn
031 Germany
032 E-Mail: poth@lat-lon.de
033
034 Prof. Dr. Klaus Greve
035 Department of Geography
036 University of Bonn
037 Meckenheimer Allee 166
038 53115 Bonn
039 Germany
040 E-Mail: greve@giub.uni-bonn.de
041
042
043 ---------------------------------------------------------------------------*/
044 package org.deegree.model.coverage;
045
046 import java.awt.image.renderable.RenderableImage;
047 import java.io.Serializable;
048 import java.util.ArrayList;
049 import java.util.List;
050
051 import org.deegree.datatypes.CodeList;
052 import org.deegree.model.crs.CRSFactory;
053 import org.deegree.model.crs.CoordinateSystem;
054 import org.deegree.model.metadata.iso19115.Keywords;
055 import org.deegree.model.spatialschema.Envelope;
056 import org.deegree.model.spatialschema.Position;
057 import org.deegree.ogcwebservices.wcs.describecoverage.AxisDescription;
058 import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
059 import org.opengis.pt.PT_CoordinatePoint;
060 import org.opengis.pt.PT_Envelope;
061
062 /**
063 * Provides access to an OpenGIS coverage. The essential property of coverage is to be able to
064 * generate a value for any point within its domain. How coverage is represented internally is not a
065 * concern.
066 *
067 * For example consider the following different internal representations of coverage:<br>
068 * <OL>
069 * <li>A coverage may be represented by a set of polygons which exhaustively tile a plane (that is
070 * each point on the plane falls in precisely one polygon). The value returned by the coverage for a
071 * point is the value of an attribute of the polygon that contains the point.</li>
072 * <li>A coverage may be represented by a grid of values. The value returned by the coverage for a
073 * point is that of the grid value whose location is nearest the point.</li>
074 * <li>Coverage may be represented by a mathematical function. The value returned by the coverage
075 * for a point is just the return value of the function when supplied the coordinates of the point
076 * as arguments.</li>
077 * <li>Coverage may be represented by combination of these. For example, coverage may be
078 * represented by a combination of mathematical functions valid over a set of polynomials.</LI>
079 * </OL>
080 *
081 * A coverage has a corresponding {@link SampleDimension} for each sample dimension in the coverage.
082 *
083 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
084 * @author last edited by: $Author: apoth $
085 *
086 * @version $Revision: 9343 $, $Date: 2007-12-27 14:30:32 +0100 (Do, 27 Dez 2007) $
087 */
088 public abstract class AbstractCoverage implements Coverage, Serializable {
089
090 protected CoverageOffering coverageOffering = null;
091
092 private CoordinateSystem crs = null;
093
094 private PT_Envelope envelope = null;
095
096 protected int numSources = 0;
097
098 protected Coverage[] sources = null;
099
100 private String[] dimensionNames = null;
101
102 /**
103 * @param coverageOffering
104 * @param env
105 */
106 public AbstractCoverage( CoverageOffering coverageOffering, Envelope env ) {
107 this( coverageOffering, env, null );
108 }
109
110 /**
111 * @param coverageOffering
112 * @param env
113 * @param sources
114 */
115 public AbstractCoverage( CoverageOffering coverageOffering, Envelope env, Coverage[] sources ) {
116 this.coverageOffering = coverageOffering;
117 this.sources = sources;
118 if ( sources != null ) {
119 numSources = sources.length;
120 }
121 // set coverage envelope
122 Position min = env.getMin();
123 Position max = env.getMax();
124 PT_CoordinatePoint minCP = new PT_CoordinatePoint( min.getX(), min.getY() );
125 PT_CoordinatePoint maxCP = new PT_CoordinatePoint( max.getX(), max.getY() );
126 envelope = new PT_Envelope();
127 envelope.minCP = minCP;
128 envelope.maxCP = maxCP;
129
130 if ( coverageOffering != null ) {
131 // set coordinate system
132 try {
133 CodeList[] cl = coverageOffering.getSupportedCRSs().getNativeSRSs();
134 String code = cl[cl.length - 1].getCodes()[0];
135 crs = CRSFactory.create( code );
136 } catch ( Exception e ) {
137 e.printStackTrace();
138 }
139 buildDimensionNames();
140 }
141 }
142
143 /**
144 *
145 * @param coverageOffering
146 * @param env
147 * @param sources
148 * @param crs
149 */
150 public AbstractCoverage( CoverageOffering coverageOffering, Envelope env, Coverage[] sources, CoordinateSystem crs ) {
151 this.coverageOffering = coverageOffering;
152 this.sources = sources;
153 if ( sources != null ) {
154 numSources = sources.length;
155 }
156 // set coverage envelope
157 Position min = env.getMin();
158 Position max = env.getMax();
159 PT_CoordinatePoint minCP = new PT_CoordinatePoint( min.getX(), min.getY() );
160 PT_CoordinatePoint maxCP = new PT_CoordinatePoint( max.getX(), max.getY() );
161 envelope = new PT_Envelope();
162 envelope.minCP = minCP;
163 envelope.maxCP = maxCP;
164
165 this.crs = crs;
166 if ( coverageOffering != null ) {
167 buildDimensionNames();
168 }
169 }
170
171 /**
172 * private method to build the dimension names from the coverage axises (x, y, [z]) and the
173 * available ranges
174 */
175 private void buildDimensionNames() {
176 AxisDescription[] axisDescription = coverageOffering.getRangeSet().getAxisDescription();
177 dimensionNames = new String[axisDescription.length + envelope.maxCP.ord.length];
178 int k = 0;
179 dimensionNames[k++] = "X";
180 dimensionNames[k++] = "Y";
181 if ( envelope.maxCP.ord.length == 3 ) {
182 dimensionNames[k++] = "Z";
183 }
184 for ( int i = 0; i < axisDescription.length; i++ ) {
185 dimensionNames[k++] = axisDescription[i].getName();
186 }
187 }
188
189 /**
190 * Specifies the coordinate reference system used when accessing a coverage or grid coverage
191 * with the <code>evaluate(...)</code> methods. It is also the coordinate reference system of
192 * the coordinates used with the math transform gridToCoordinateSystem}).
193 *
194 * This coordinate reference system is usually different than coordinate system of the grid.
195 * Grid coverage can be accessed (re-projected) with new coordinate reference system with the
196 * {@link "org.opengis.coverage.processing.GridCoverageProcessor"} component. In this case, a
197 * new instance of a grid coverage is created. <br>
198 * <br>
199 * Note: If a coverage does not have an associated coordinate reference system, the returned
200 * value will be <code>null</code>. attribute should also be <code>null</code> if the
201 * coordinate reference system is <code>null</code>.
202 *
203 * @return The coordinate reference system used when accessing a coverage or grid coverage with
204 * the <code>evaluate(...)</code> methods, or <code>null</code>.
205 */
206 public CoordinateSystem getCoordinateReferenceSystem() {
207 return crs;
208 }
209
210 /**
211 * The bounding box for the coverage domain in
212 * {@linkplain #getCoordinateReferenceSystem coordinate reference system} coordinates. For grid
213 * coverages, the grid cells are centered on each grid coordinate. The envelope for a 2-D grid
214 * coverage includes the following corner positions.
215 *
216 * <blockquote>
217 *
218 * <pre>
219 * (Minimum row - 0.5, Minimum column - 0.5) for the minimum coordinates
220 * (Maximum row - 0.5, Maximum column - 0.5) for the maximum coordinates
221 * </pre>
222 *
223 * </blockquote>
224 *
225 * If a grid coverage does not have any associated coordinate reference system, the minimum and
226 * maximum coordinate points for the envelope will be empty sequences.
227 *
228 * @return The bounding box for the coverage domain in coordinate system coordinates.
229 */
230 public PT_Envelope getEnvelope() {
231 return envelope;
232 }
233
234 /**
235 * The names of each dimension in the coverage. Typically these names are <var>x</var>, <var>y</var>,
236 * <var>z</var> and <var>t</var>. The number of items in the sequence is the number of
237 * dimensions in the coverage. Grid coverages are typically 2D (<var>x</var>, <var>y</var>)
238 * while other coverages may be 3D (<var>x</var>, <var>y</var>, <var>z</var>) or 4D (<var>x</var>,
239 * <var>y</var>, <var>z</var>, <var>t</var>). The number of dimensions of the coverage is the
240 * number of entries in the list of dimension names.
241 *
242 * @return The names of each dimension in the coverage.
243 */
244 public String[] getDimensionNames() {
245 return dimensionNames;
246 }
247
248 /**
249 * Retrieve sample dimension information for the coverage. For a grid coverage a sample
250 * dimension is a band. The sample dimension information include such things as description,
251 * data type of the value (bit, byte, integer...), the no data values, minimum and maximum
252 * values and a color table if one is associated with the dimension. A coverage must have at
253 * least one sample dimension.
254 *
255 * @param index
256 * Index for sample dimension to retrieve. Indices are numbered 0 to (<var>{@linkplain #getNumSampleDimensions n}</var>-1).
257 * @return Sample dimension information for the coverage.
258 * @throws IndexOutOfBoundsException
259 * if <code>index</code> is out of bounds.
260 */
261 public SampleDimension getSampleDimension( int index )
262 throws IndexOutOfBoundsException {
263 return null;
264 }
265
266 /**
267 * Number of grid coverages which the grid coverage was derived from. This implementation
268 * specification does not include interfaces for creating collections of coverages therefore
269 * this value will usually be one indicating an adapted grid coverage, or zero indicating a raw
270 * grid coverage.
271 *
272 * @return The number of grid coverages which the grid coverage was derived from.
273 */
274 public int getNumSources() {
275 return 0;
276 }
277
278 /**
279 * Returns the source data for a coverage. This is intended to allow applications to establish
280 * what <code>Coverage</code>s will be affected when others are updated, as well as to trace
281 * back to the "raw data".
282 *
283 * @param sourceDataIndex
284 * Source coverage index. Indexes start at 0.
285 * @return The source data for a coverage.
286 * @throws IndexOutOfBoundsException
287 * if <code>sourceDataIndex</code> is out of bounds.
288 *
289 * @see #getNumSources
290 * @see "org.opengis.coverage.grid.GridCoverage#getSource"
291 */
292 public Coverage getSource( int sourceDataIndex )
293 throws IndexOutOfBoundsException {
294 if ( sources != null && sources.length >= sourceDataIndex - 1 ) {
295 return sources[sourceDataIndex];
296 }
297 return null;
298 }
299
300 /**
301 * List of metadata keywords for a coverage. If no metadata is available, the sequence will be
302 * empty.
303 *
304 * @return the list of metadata keywords for a coverage.
305 *
306 * @see #getMetadataValue
307 * @see javax.media.jai.PropertySource#getPropertyNames()
308 */
309 public String[] getMetadataNames() {
310 String[] keyw = new String[0];
311 Keywords[] keywords = coverageOffering.getKeywords();
312 if ( keywords != null ) {
313 List<String> list = new ArrayList<String>( 100 );
314 for ( int i = 0; i < keywords.length; i++ ) {
315 String[] kw = keywords[i].getKeywords();
316 for ( int k = 0; k < kw.length; k++ ) {
317 list.add( kw[k] );
318 }
319 }
320 keyw = list.toArray( new String[list.size()] );
321 }
322 return keyw;
323 }
324
325 /**
326 * Retrieve the metadata value for a given metadata name.
327 *
328 * @param name
329 * Metadata keyword for which to retrieve data.
330 * @return the metadata value for a given metadata name.
331 * @throws MetadataNameNotFoundException
332 * if there is no value for the specified metadata name.
333 *
334 * @see #getMetadataNames
335 * @see javax.media.jai.PropertySource#getProperty
336 */
337 public String getMetadataValue( String name )
338 throws MetadataNameNotFoundException {
339 return null;
340 }
341
342 /**
343 * Returns 2D view of this coverage as a renderable image. This optional operation allows
344 * interoperability with <A HREF="http://java.sun.com/products/java-media/2D/">Java2D</A>. If
345 * this coverage is a {@link "org.opengis.coverage.grid.GridCoverage"} backed by a
346 * {@link java.awt.image.RenderedImage}, the underlying image can be obtained with:
347 *
348 * <code>getRenderableImage(0,1).{@linkplain RenderableImage#createDefaultRendering()
349 * createDefaultRendering()}</code>
350 *
351 * @param xAxis
352 * Dimension to use for the <var>x</var> axis.
353 * @param yAxis
354 * Dimension to use for the <var>y</var> axis.
355 * @return A 2D view of this coverage as a renderable image.
356 * @throws UnsupportedOperationException
357 * if this optional operation is not supported.
358 * @throws IndexOutOfBoundsException
359 * if <code>xAxis</code> or <code>yAxis</code> is out of bounds.
360 */
361 public abstract RenderableImage getRenderableImage( int xAxis, int yAxis )
362 throws UnsupportedOperationException, IndexOutOfBoundsException;
363
364 /**
365 * returns the {@link CoverageOffering} describing a coverage
366 *
367 * @see CoverageOffering
368 * @return the CoverageOffering describing a coverage
369 */
370 public CoverageOffering getCoverageOffering() {
371 return coverageOffering;
372 }
373
374 }