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 }