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 }