Source Code Cross Referenced for AbstractCoverage.java in  » GIS » GeoTools-2.4.1 » org » geotools » coverage » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » GeoTools 2.4.1 » org.geotools.coverage 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *    GeoTools - OpenSource mapping toolkit
0003:         *    http://geotools.org
0004:         *    (C) 2003-2006, Geotools Project Management Committee (PMC)
0005:         *    (C) 2001, Institut de Recherche pour le Développement
0006:         *
0007:         *    This library is free software; you can redistribute it and/or
0008:         *    modify it under the terms of the GNU Lesser General Public
0009:         *    License as published by the Free Software Foundation; either
0010:         *    version 2.1 of the License, or (at your option) any later version.
0011:         *
0012:         *    This library is distributed in the hope that it will be useful,
0013:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015:         *    Lesser General Public License for more details.
0016:         *
0017:         *    This package contains documentation from OpenGIS specifications.
0018:         *    OpenGIS consortium's work is fully acknowledged here.
0019:         */
0020:        package org.geotools.coverage;
0021:
0022:        // J2SE dependencies
0023:        import java.awt.Dimension;
0024:        import java.awt.EventQueue;
0025:        import java.awt.Frame;
0026:        import java.awt.Rectangle;
0027:        import java.awt.RenderingHints;
0028:        import java.awt.Shape;
0029:        import java.awt.event.WindowAdapter;
0030:        import java.awt.event.WindowEvent;
0031:        import java.awt.geom.AffineTransform;
0032:        import java.awt.geom.NoninvertibleTransformException;
0033:        import java.awt.geom.Point2D;
0034:        import java.awt.geom.Rectangle2D;
0035:        import java.awt.image.ColorModel;
0036:        import java.awt.image.RenderedImage;
0037:        import java.awt.image.SampleModel;
0038:        import java.awt.image.renderable.ParameterBlock;
0039:        import java.awt.image.renderable.RenderContext;
0040:        import java.awt.image.renderable.RenderableImage;
0041:        import java.io.IOException;
0042:        import java.io.StringWriter;
0043:        import java.lang.reflect.Array;
0044:        import java.util.Arrays;
0045:        import java.util.Collections;
0046:        import java.util.HashSet;
0047:        import java.util.List;
0048:        import java.util.Locale;
0049:        import java.util.Map;
0050:        import java.util.Set;
0051:        import java.util.Vector;
0052:
0053:        // JAI dependencies
0054:        import javax.media.jai.ImageFunction;
0055:        import javax.media.jai.ImageLayout;
0056:        import javax.media.jai.InterpolationNearest; // For Javadoc
0057:        import javax.media.jai.JAI;
0058:        import javax.media.jai.PlanarImage;
0059:        import javax.media.jai.PropertySource;
0060:        import javax.media.jai.PropertySourceImpl;
0061:        import javax.media.jai.TiledImage;
0062:        import javax.media.jai.iterator.RectIterFactory;
0063:        import javax.media.jai.iterator.WritableRectIter;
0064:        import javax.media.jai.operator.ImageFunctionDescriptor; // For Javadoc
0065:        import javax.media.jai.util.CaselessStringKey; // For Javadoc
0066:        import javax.media.jai.widget.ScrollingImagePanel;
0067:
0068:        // OpenGIS dependencies
0069:        import org.opengis.coverage.CannotEvaluateException;
0070:        import org.opengis.coverage.CommonPointRule;
0071:        import org.opengis.coverage.Coverage;
0072:        import org.opengis.coverage.GeometryValuePair;
0073:        import org.opengis.coverage.MetadataNameNotFoundException;
0074:        import org.opengis.coverage.grid.GridCoverage; // For javadoc
0075:        import org.opengis.coverage.grid.GridGeometry; // For javadoc
0076:        import org.opengis.coverage.processing.GridCoverageProcessor; // For javadoc
0077:        import org.opengis.referencing.crs.CoordinateReferenceSystem;
0078:        import org.opengis.referencing.cs.AxisDirection;
0079:        import org.opengis.referencing.cs.CoordinateSystem;
0080:        import org.opengis.geometry.DirectPosition;
0081:        import org.opengis.geometry.Envelope;
0082:        import org.opengis.geometry.Geometry;
0083:        import org.opengis.temporal.Period;
0084:        import org.opengis.util.InternationalString;
0085:        import org.opengis.util.Record;
0086:        import org.opengis.util.RecordType;
0087:
0088:        // Geotools dependencies
0089:        import org.geotools.geometry.GeneralDirectPosition;
0090:        import org.geotools.geometry.GeneralEnvelope;
0091:        import org.geotools.referencing.CRS;
0092:        import org.geotools.referencing.operation.matrix.GeneralMatrix;
0093:        import org.geotools.referencing.operation.matrix.XAffineTransform;
0094:        import org.geotools.util.logging.Logging;
0095:        import org.geotools.util.SimpleInternationalString;
0096:
0097:        // Resources
0098:        import org.geotools.io.LineWriter;
0099:        import org.geotools.resources.Utilities;
0100:        import org.geotools.resources.XArray;
0101:        import org.geotools.resources.image.ImageUtilities;
0102:        import org.geotools.resources.i18n.Errors;
0103:        import org.geotools.resources.i18n.ErrorKeys;
0104:
0105:        /**
0106:         * Base class of all coverage type. The essential property of coverage is to be able
0107:         * to generate a value for any point within its domain.  How coverage is represented
0108:         * internally is not a concern. For example consider the following different internal
0109:         * representations of coverage:
0110:         * <p>
0111:         * <ul>
0112:         *   <li>A coverage may be represented by a set of polygons which exhaustively tile a
0113:         *       plane (that is each point on the plane falls in precisely one polygon). The
0114:         *       value returned by the coverage for a point is the value of an attribute of
0115:         *       the polygon that contains the point.</li>
0116:         *   <li>A coverage may be represented by a grid of values. The value returned by the
0117:         *       coverage for a point is that of the grid value whose location is nearest the
0118:         *       point.</li>
0119:         *   <li>Coverage may be represented by a mathematical function. The value returned
0120:         *       by the coverage for a point is just the return value of the function when
0121:         *       supplied the coordinates of the point as arguments.</li>
0122:         *   <li>Coverage may be represented by combination of these. For example, coverage
0123:         *       may be represented by a combination of mathematical functions valid over a
0124:         *       set of polynomials.</li>
0125:         * </ul>
0126:         *
0127:         * @since 2.1
0128:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/coverage/src/main/java/org/geotools/coverage/AbstractCoverage.java $
0129:         * @version $Id: AbstractCoverage.java 27848 2007-11-12 13:10:32Z desruisseaux $
0130:         * @author Martin Desruisseaux
0131:         */
0132:        public abstract class AbstractCoverage extends PropertySourceImpl
0133:                implements  Coverage {
0134:            /**
0135:             * For compatibility during cross-version serialization.
0136:             */
0137:            private static final long serialVersionUID = -2989320942499746295L;
0138:
0139:            /**
0140:             * The set of default axis name.
0141:             */
0142:            private static final String[] DIMENSION_NAMES = { "x", "y", "z",
0143:                    "t" };
0144:
0145:            /**
0146:             * The sequence of string to returns when there is no metadata.
0147:             */
0148:            private static final String[] NO_PROPERTIES = new String[0];
0149:
0150:            /**
0151:             * The sample dimension to make visible by {@link #getRenderableImage}.
0152:             */
0153:            private static final int VISIBLE_BAND = 0;
0154:
0155:            /**
0156:             * The coverage name.
0157:             */
0158:            private final InternationalString name;
0159:
0160:            /**
0161:             * The coordinate reference system, or {@code null} if there is none.
0162:             */
0163:            protected final CoordinateReferenceSystem crs;
0164:
0165:            /**
0166:             * Constructs a coverage using the specified coordinate reference system. If the coordinate
0167:             * reference system is {@code null}, then the subclasses must override {@link #getDimension()}.
0168:             * 
0169:             * @param name   The coverage name.
0170:             * @param crs    The coordinate reference system. This specifies the CRS used when accessing
0171:             *               a coverage or grid coverage with the {@code evaluate(...)} methods.
0172:             * @param source The source for this coverage, or {@code null} if none. Source may be (but is
0173:             *               not limited to) a {@link PlanarImage} or an other {@code AbstractCoverage}
0174:             *               object.
0175:             * @param properties The set of properties for this coverage, or {@code null} if there is
0176:             *               none. "Properties" in <cite>Java Advanced Imaging</cite> is what OpenGIS
0177:             *               calls "Metadata". Keys are {@link String} objects ({@link CaselessStringKey}
0178:             *               are accepted as well), while values may be any {@link Object}.
0179:             */
0180:            protected AbstractCoverage(final CharSequence name,
0181:                    final CoordinateReferenceSystem crs,
0182:                    final PropertySource source, final Map properties) {
0183:                super (properties, source);
0184:                this .name = SimpleInternationalString.wrap(name);
0185:                this .crs = crs;
0186:            }
0187:
0188:            /**
0189:             * Constructs a new coverage with the same parameters than the specified coverage.
0190:             * <p>
0191:             * <strong>Note:</strong> This constructor keeps a strong reference to the source
0192:             * coverage (through {@link PropertySourceImpl}). In many cases, it is not a problem
0193:             * since {@link GridCoverage} will retains a strong reference to its source anyway.
0194:             * 
0195:             * @param name The name for this coverage, or {@code null} for the same than {@code coverage}.
0196:             * @param coverage The source coverage.
0197:             */
0198:            protected AbstractCoverage(final CharSequence name,
0199:                    final Coverage coverage) {
0200:                super (
0201:                        null,
0202:                        (coverage instanceof  PropertySource) ? (PropertySource) coverage
0203:                                : null);
0204:                final InternationalString n = SimpleInternationalString
0205:                        .wrap(name);
0206:                if (coverage instanceof  AbstractCoverage) {
0207:                    final AbstractCoverage source = (AbstractCoverage) coverage;
0208:                    this .name = (n != null) ? n : source.name;
0209:                    this .crs = source.crs;
0210:                } else {
0211:                    this .name = (n != null) ? n
0212:                            : new SimpleInternationalString(coverage.toString());
0213:                    this .crs = coverage.getCoordinateReferenceSystem();
0214:                }
0215:            }
0216:
0217:            /**
0218:             * Returns the coverage name. The default implementation returns the name
0219:             * specified at construction time.
0220:             */
0221:            public InternationalString getName() {
0222:                return name;
0223:            }
0224:
0225:            /**
0226:             * Returns the dimension of this coverage. This is a shortcut for
0227:             * <code>{@linkplain #crs}.getCoordinateSystem().getDimension()</code>.
0228:             */
0229:            public final int getDimension() {
0230:                return crs.getCoordinateSystem().getDimension();
0231:            }
0232:
0233:            /**
0234:             * Returns the coordinate reference system to which the objects in its domain are
0235:             * referenced. This is the CRS used when accessing a coverage or grid coverage with
0236:             * the {@code evaluate(...)} methods. This coordinate reference system is usually
0237:             * different than coordinate system of the grid. It is the target coordinate reference
0238:             * system of the {@link GridGeometry#getGridToCRS gridToCRS} math transform.
0239:             * <p>
0240:             * Grid coverage can be accessed (re-projected) with new coordinate reference system
0241:             * with the {@link GridCoverageProcessor} component. In this case, a new instance of
0242:             * a grid coverage is created.
0243:             *
0244:             * @return The coordinate reference system used when accessing a coverage or
0245:             *         grid coverage with the {@code evaluate(...)} methods.
0246:             * 
0247:             * @see org.geotools.coverage.grid.GeneralGridGeometry#getGridToCRS
0248:             */
0249:            public CoordinateReferenceSystem getCoordinateReferenceSystem() {
0250:                return crs;
0251:            }
0252:
0253:            /**
0254:             * Returns the names of each dimension in this coverage. Typically these
0255:             * names are "x", "y", "z" and "t". The number of items in the sequence is
0256:             * the number of dimensions in the coverage. Grid coverages are typically
0257:             * 2D (<var>x</var>, <var>y</var>) while other coverages may be
0258:             * 3D (<var>x</var>, <var>y</var>, <var>z</var>) or
0259:             * 4D (<var>x</var>, <var>y</var>, <var>z</var>, <var>t</var>).
0260:             * The {@linkplain #getDimension number of dimensions} of the coverage is
0261:             * the number of entries in the list of dimension names.
0262:             * <p>
0263:             * The default implementation ask for
0264:             * {@linkplain CoordinateSystem coordinate system} axis names, or returns
0265:             * "x", "y"... if this coverage has no CRS.
0266:             * 
0267:             * @return The names of each dimension. The array's length is equals to
0268:             *         {@link #getDimension}.
0269:             *
0270:             * @deprecated This information can be obtained from the underlying coordinate system.
0271:             */
0272:            public InternationalString[] getDimensionNames() {
0273:                final InternationalString[] names;
0274:                if (crs != null) {
0275:                    final CoordinateSystem cs = crs.getCoordinateSystem();
0276:                    names = new InternationalString[cs.getDimension()];
0277:                    for (int i = 0; i < names.length; i++) {
0278:                        names[i] = new SimpleInternationalString(cs.getAxis(i)
0279:                                .getName().getCode());
0280:                    }
0281:                } else {
0282:                    names = (InternationalString[]) XArray.resize(
0283:                            DIMENSION_NAMES, getDimension());
0284:                    for (int i = DIMENSION_NAMES.length; i < names.length; i++) {
0285:                        names[i] = new SimpleInternationalString("dim"
0286:                                + (i + 1));
0287:                    }
0288:                }
0289:                return names;
0290:            }
0291:
0292:            /**
0293:             * Returns the names of each dimension in this coverage.
0294:             * 
0295:             * @deprecated Replaced by {@link #getDimensionNames()}.
0296:             */
0297:            public final String[] getDimensionNames(final Locale locale) {
0298:                final InternationalString[] inter = getDimensionNames();
0299:                final String[] names = new String[inter.length];
0300:                for (int i = 0; i < names.length; i++) {
0301:                    names[i] = inter[i].toString(locale);
0302:                }
0303:                return names;
0304:            }
0305:
0306:            /**
0307:             * Returns the bounding box for the coverage domain in
0308:             * {@linkplain #getCoordinateReferenceSystem coordinate reference system} coordinates. May
0309:             * be {@code null} if this coverage has no associated coordinate reference system. For grid
0310:             * coverages, the grid cells are centered on each grid coordinate. The envelope for a 2-D
0311:             * grid coverage includes the following corner positions.
0312:             * 
0313:             * <blockquote><pre>
0314:             *  (Minimum row - 0.5, Minimum column - 0.5) for the minimum coordinates
0315:             *  (Maximum row - 0.5, Maximum column - 0.5) for the maximum coordinates
0316:             * </pre></blockquote>
0317:             * 
0318:             * The default implementation returns the domain of validity of the CRS, if there is one.
0319:             * 
0320:             * @return The bounding box for the coverage domain in coordinate system coordinates.
0321:             */
0322:            public Envelope getEnvelope() {
0323:                return CRS.getEnvelope(crs);
0324:            }
0325:
0326:            /**
0327:             * Returns the extent of the domain of the coverage. Extents may be specified in space,
0328:             * time or space-time. The collection must contains at least one element.
0329:             * <p>
0330:             * <strong>This method is not yet implemented.</strong>
0331:             *
0332:             * @since 2.3
0333:             *
0334:             * @todo Proposed default implementation: invokes {@link #getEnvelope}, extract
0335:             *       the spatial and temporal parts and put them in a {@link Extent} object.
0336:             */
0337:            public Set/*<Extent>*/getDomainExtents() {
0338:                throw unsupported();
0339:            }
0340:
0341:            /**
0342:             * Returns the set of domain objects in the domain.
0343:             * The collection must contains at least one element.
0344:             * <p>
0345:             * <strong>This method is not yet implemented.</strong>
0346:             *
0347:             * @since 2.3
0348:             *
0349:             * @todo Proposed default implementation: invokes {@link #getEnvelope}, extract the
0350:             *       spatial and temporal parts, get the grid geometry and create on-the-fly a
0351:             *       {@link DomainObject} for each cell.
0352:             */
0353:            public Set/*<? extends DomainObject>*/getDomainElements() {
0354:                throw unsupported();
0355:            }
0356:
0357:            /**
0358:             * Returns the set of attribute values in the range. The range of a coverage shall be a
0359:             * homogeneous collection of records. That is, the range shall have a constant dimension
0360:             * over the entire domain, and each field of the record shall provide a value of the same
0361:             * attribute type over the entire domain.
0362:             * <p>
0363:             * In the case of a {@linkplain DiscreteCoverage discrete coverage}, the size of the range
0364:             * collection equals that of the {@linkplain #getDomainElements domains} collection. In other
0365:             * words, there is one instance of {@link AttributeValues} for each instance of
0366:             * {@link DomainObject}. Usually, these are stored values that are accessed by the
0367:             * {@link #evaluate(DirectPosition,Collection) evaluate} operation.
0368:             * <p>
0369:             * In the case of a {@linkplain ContinuousCoverage continuous coverage}, there is a transfinite
0370:             * number of instances of {@link AttributeValues} for each {@link DomainObject}. A few instances
0371:             * may be stored as input for the {@link #evaluate(DirectPosition,Collection) evaluate}
0372:             * operation, but most are generated as needed by that operation.
0373:             * <p>
0374:             * <B>NOTE:</B> ISO 19123 does not specify how the {@linkplain #getDomainElements domain}
0375:             * and {@linkplain #getRangeElements range} associations are to be implemented. The relevant
0376:             * data may be generated in real time, it may be held in persistent local storage, or it may
0377:             * be electronically accessible from remote locations.
0378:             * <p>
0379:             * <strong>This method is not yet implemented.</strong>
0380:             *
0381:             * @since 2.3
0382:             */
0383:            public Set/*<AttributeValues>*/getRangeElements() {
0384:                throw unsupported();
0385:            }
0386:
0387:            /**
0388:             * Describes the range of the coverage. It consists of a list of attribute name/data type pairs.
0389:             * A simple list is the most common form of range type, but {@code RecordType} can be used
0390:             * recursively to describe more complex structures. The range type for a specific coverage
0391:             * shall be specified in an application schema.
0392:             * <p>
0393:             * <strong>This method is not yet implemented.</strong>
0394:             *
0395:             * @since 2.3
0396:             */
0397:            public RecordType getRangeType() {
0398:                throw unsupported();
0399:            }
0400:
0401:            /**
0402:             * Identifies the procedure to be used for evaluating the coverage at a position that falls
0403:             * either on a boundary between geometric objects or within the boundaries of two or more
0404:             * overlapping geometric objects. The geometric objects are either {@linkplain DomainObject
0405:             * domain objects} or {@linkplain ValueObject value objects}.
0406:             * <p>
0407:             * <strong>This method is not yet implemented.</strong>
0408:             *
0409:             * @since 2.3
0410:             */
0411:            public CommonPointRule getCommonPointRule() {
0412:                throw unsupported();
0413:            }
0414:
0415:            /**
0416:             * Returns the dictionary of <var>geometry</var>-<var>value</var> pairs that contain the
0417:             * {@linkplain DomainObject objects} in the domain of the coverage each paired with its
0418:             * record of feature attribute values. In the case of an analytical coverage, the operation
0419:             * shall return the empty set.
0420:             * <p>
0421:             * <strong>This method is not yet implemented.</strong>
0422:             *
0423:             * @since 2.3
0424:             */
0425:            public Set list() {
0426:                throw unsupported();
0427:            }
0428:
0429:            /**
0430:             * Returns the set of <var>geometry</var>-<var>value</var> pairs that contain
0431:             * {@linkplain DomainObject domain objects} that lie within the specified geometry and period.
0432:             * If {@code s} is null, the operation shall return all <var>geometry</var>-<var>value</var>
0433:             * pairs that contain {@linkplain DomainObject domain objects} within {@code t}. If the value
0434:             * of {@code t} is null, the operation shall return all <var>geometry</var>-<var>value</var>
0435:             * pair that contain {@linkplain DomainObject domain objects} within {@code s}. In the case
0436:             * of an analytical coverage, the operation shall return the empty set.
0437:             * <p>
0438:             * <strong>This method is not yet implemented.</strong>
0439:             *
0440:             * @since 2.3
0441:             */
0442:            public Set select(Geometry arg0, Period arg1) {
0443:                throw unsupported();
0444:            }
0445:
0446:            /**
0447:             * Returns the sequence of <var>geometry</var>-<var>value</var> pairs that include the
0448:             * {@linkplain DomainObject domain objects} nearest to the direct position and their
0449:             * distances from the direction position. The sequence shall be ordered by distance from
0450:             * the direct position, beginning with the record containing the {@linkplain DomainObject
0451:             * domain object} nearest to the direct position. The length of the sequence (the number
0452:             * of <var>geometry</var>-<var>value</var> pairs returned) shall be no greater than the
0453:             * number specified by the parameter {@code limit}. The default shall be to return a single
0454:             * <var>geometry</var>-<var>value</var> pair. The operation shall return a warning if the
0455:             * last {@linkplain DomainObject domain object} in the sequence is at a distance from the
0456:             * direct position equal to the distance of other {@linkplain DomainObject domain objects}
0457:             * that are not included in the sequence. In the case of an analytical coverage, the operation
0458:             * shall return the empty set.
0459:             * <p>
0460:             * <B>NOTE:</B> This operation is useful when the domain of a coverage does not exhaustively
0461:             * partition the extent of the coverage. Even in that case, the first element of the sequence
0462:             * returned may be the <var>geometry</var>-<var>value</var> pair that contains the input direct
0463:             * position.
0464:             * <p>
0465:             * <strong>This method is not yet implemented.</strong>
0466:             *
0467:             * @since 2.3
0468:             */
0469:            public List find(DirectPosition p, int limit) {
0470:                throw unsupported();
0471:            }
0472:
0473:            /**
0474:             * Returns the nearest <var>geometry</var>-<var>value</var> pair
0475:             * from the specified direct position. This is a shortcut for
0476:             * <code>{@linkplain #find(DirectPosition,int) find}(p,1)</code>.
0477:             *
0478:             * @since 2.3
0479:             */
0480:            public GeometryValuePair find(final DirectPosition p) {
0481:                final List pairs = find(p, 1);
0482:                return pairs.isEmpty() ? null : (GeometryValuePair) pairs
0483:                        .get(0);
0484:            }
0485:
0486:            /**
0487:             * Invoked when an unsupported operation is invoked.
0488:             */
0489:            private static final UnsupportedOperationException unsupported() {
0490:                throw new UnsupportedOperationException(
0491:                        "This method is currently not implemented. "
0492:                                + "It may be implemented by next version of coverage module.");
0493:            }
0494:
0495:            /**
0496:             * Returns a localized error message for the specified array.
0497:             */
0498:            private static String formatErrorMessage(final Object array) {
0499:                String text = "<null>";
0500:                if (array != null) {
0501:                    Class type = array.getClass();
0502:                    if (type.isArray()) {
0503:                        type = type.getComponentType();
0504:                    }
0505:                    text = Utilities.getShortName(type);
0506:                }
0507:                return Errors.format(ErrorKeys.CANT_CONVERT_FROM_TYPE_$1, text);
0508:            }
0509:
0510:            /**
0511:             * Returns a set of records of feature attribute values for the specified direct position. The
0512:             * parameter {@code list} is a sequence of feature attribute names each of which identifies a
0513:             * field of the range type. If {@code list} is null, the operation shall return a value for
0514:             * every field of the range type. Otherwise, it shall return a value for each field included in
0515:             * {@code list}. If the direct position passed is not in the domain of the coverage, then an
0516:             * exception is thrown. If the input direct position falls within two or more geometric objects
0517:             * within the domain, the operation shall return records of feature attribute values computed
0518:             * according to the {@linkplain #getCommonPointRule common point rule}.
0519:             * <P>
0520:             * <B>NOTE:</B> Normally, the operation will return a single record of feature attribute values.
0521:             *
0522:             * @since 2.3
0523:             *
0524:             * @deprecated Current implementation is incorrect, since it ignores the {@link #list} argument.
0525:             */
0526:            public Set/*<Record>*/evaluate(final DirectPosition coord,
0527:                    final Set/*<String>*/list) {
0528:                final Set set = new HashSet();
0529:                final Object array = evaluate(coord);
0530:                try {
0531:                    final int length = Array.getLength(array);
0532:                    for (int index = 0; index < length; index++) {
0533:                        set.add(Array.get(array, index));
0534:                    }
0535:                } catch (IllegalArgumentException exception) {
0536:                    throw new CannotEvaluateException(formatErrorMessage(set),
0537:                            exception);
0538:                }
0539:                return set;
0540:            }
0541:
0542:            /**
0543:             * Returns a sequence of boolean values for a given point in the coverage. A value for each
0544:             * {@linkplain SampleDimension sample dimension} is included in the sequence. The default
0545:             * interpolation type used when accessing grid values for points which fall between grid
0546:             * cells is {@linkplain InterpolationNearest nearest neighbor}, but it can be changed by
0547:             * some {@linkplain org.geotools.coverage.grid.Interpolator2D subclasses}. The CRS of the
0548:             * point is the same as the grid coverage {@linkplain #getCoordinateReferenceSystem coordinate
0549:             * reference system}.
0550:             * 
0551:             * @param  coord The coordinate point where to evaluate.
0552:             * @param  dest An array in which to store values, or {@code null} to create a new array.
0553:             * @return The {@code dest} array, or a newly created array if {@code dest} was null.
0554:             * @throws PointOutsideCoverageException if the evaluation failed because the input point
0555:             *         has invalid coordinates.
0556:             * @throws CannotEvaluateException if the values can't be computed at the specified coordinate
0557:             *         for an other reason. It may be thrown if the coverage data type can't be converted
0558:             *         to {@code boolean} by an identity or widening conversion. Subclasses may relax this
0559:             *         constraint if appropriate.
0560:             */
0561:            public boolean[] evaluate(final DirectPosition coord, boolean[] dest)
0562:                    throws CannotEvaluateException {
0563:                final Object array = evaluate(coord);
0564:                try {
0565:                    final int length = Array.getLength(array);
0566:                    if (dest == null) {
0567:                        dest = new boolean[length];
0568:                    }
0569:                    for (int i = 0; i < length; i++) {
0570:                        dest[i] = Array.getBoolean(array, i);
0571:                    }
0572:                } catch (IllegalArgumentException exception) {
0573:                    throw new CannotEvaluateException(
0574:                            formatErrorMessage(array), exception);
0575:                }
0576:                return dest;
0577:            }
0578:
0579:            /**
0580:             * Returns a sequence of byte values for a given point in the coverage. A value for each
0581:             * {@linkplain SampleDimension sample dimension} is included in the sequence. The default
0582:             * interpolation type used when accessing grid values for points which fall between grid
0583:             * cells is {@linkplain InterpolationNearest nearest neighbor}, but it can be changed by
0584:             * some {@linkplain org.geotools.coverage.grid.Interpolator2D subclasses}. The CRS of the
0585:             * point is the same as the grid coverage {@linkplain #getCoordinateReferenceSystem coordinate
0586:             * reference system}.
0587:             * 
0588:             * @param  coord The coordinate point where to evaluate.
0589:             * @param  dest An array in which to store values, or {@code null} to create a new array.
0590:             * @return The {@code dest} array, or a newly created array if {@code dest} was null.
0591:             * @throws PointOutsideCoverageException if the evaluation failed because the input point
0592:             *         has invalid coordinates.
0593:             * @throws PointOutsideCoverageException if the evaluation failed because the input point
0594:             *         has invalid coordinates.
0595:             * @throws CannotEvaluateException if the values can't be computed at the specified coordinate
0596:             *         for an other reason. It may be thrown if the coverage data type can't be converted
0597:             *         to {@code byte} by an identity or widening conversion. Subclasses may relax this
0598:             *         constraint if appropriate.
0599:             */
0600:            public byte[] evaluate(final DirectPosition coord, byte[] dest)
0601:                    throws CannotEvaluateException {
0602:                final Object array = evaluate(coord);
0603:                try {
0604:                    final int length = Array.getLength(array);
0605:                    if (dest == null) {
0606:                        dest = new byte[length];
0607:                    }
0608:                    for (int i = 0; i < length; i++) {
0609:                        dest[i] = Array.getByte(array, i);
0610:                    }
0611:                } catch (IllegalArgumentException exception) {
0612:                    throw new CannotEvaluateException(
0613:                            formatErrorMessage(array), exception);
0614:                }
0615:                return dest;
0616:            }
0617:
0618:            /**
0619:             * Returns a sequence of integer values for a given point in the coverage. A value for each
0620:             * {@linkplain SampleDimension sample dimension} is included in the sequence. The default
0621:             * interpolation type used when accessing grid values for points which fall between grid
0622:             * cells is {@linkplain InterpolationNearest nearest neighbor}, but it can be changed by
0623:             * some {@linkplain org.geotools.coverage.grid.Interpolator2D subclasses}. The CRS of the
0624:             * point is the same as the grid coverage {@linkplain #getCoordinateReferenceSystem coordinate
0625:             * reference system}.
0626:             * 
0627:             * @param  coord The coordinate point where to evaluate.
0628:             * @param  dest An array in which to store values, or {@code null} to create a new array.
0629:             * @return The {@code dest} array, or a newly created array if {@code dest} was null.
0630:             * @throws PointOutsideCoverageException if the evaluation failed because the input point
0631:             *         has invalid coordinates.
0632:             * @throws CannotEvaluateException if the values can't be computed at the specified coordinate
0633:             *         for an other reason. It may be thrown if the coverage data type can't be converted
0634:             *         to {@code int} by an identity or widening conversion. Subclasses may relax this
0635:             *         constraint if appropriate.
0636:             */
0637:            public int[] evaluate(final DirectPosition coord, int[] dest)
0638:                    throws CannotEvaluateException {
0639:                final Object array = evaluate(coord);
0640:                try {
0641:                    final int length = Array.getLength(array);
0642:                    if (dest == null) {
0643:                        dest = new int[length];
0644:                    }
0645:                    for (int i = 0; i < length; i++) {
0646:                        dest[i] = Array.getInt(array, i);
0647:                    }
0648:                } catch (IllegalArgumentException exception) {
0649:                    throw new CannotEvaluateException(
0650:                            formatErrorMessage(array), exception);
0651:                }
0652:                return dest;
0653:            }
0654:
0655:            /**
0656:             * Returns a sequence of float values for a given point in the coverage. A value for each
0657:             * {@linkplain SampleDimension sample dimension} is included in the sequence. The default
0658:             * interpolation type used when accessing grid values for points which fall between grid
0659:             * cells is {@linkplain InterpolationNearest nearest neighbor}, but it can be changed by
0660:             * some {@linkplain org.geotools.coverage.grid.Interpolator2D subclasses}. The CRS of the
0661:             * point is the same as the grid coverage {@linkplain #getCoordinateReferenceSystem coordinate
0662:             * reference system}.
0663:             * 
0664:             * @param  coord The coordinate point where to evaluate.
0665:             * @param  dest An array in which to store values, or {@code null} to create a new array.
0666:             * @return The {@code dest} array, or a newly created array if {@code dest} was null.
0667:             * @throws PointOutsideCoverageException if the evaluation failed because the input point
0668:             *         has invalid coordinates.
0669:             * @throws CannotEvaluateException if the values can't be computed at the specified coordinate
0670:             *         for an other reason. It may be thrown if the coverage data type can't be converted
0671:             *         to {@code float} by an identity or widening conversion. Subclasses may relax this
0672:             *         constraint if appropriate.
0673:             */
0674:            public float[] evaluate(final DirectPosition coord, float[] dest)
0675:                    throws CannotEvaluateException {
0676:                final Object array = evaluate(coord);
0677:                try {
0678:                    final int length = Array.getLength(array);
0679:                    if (dest == null) {
0680:                        dest = new float[length];
0681:                    }
0682:                    for (int i = 0; i < length; i++) {
0683:                        dest[i] = Array.getFloat(array, i);
0684:                    }
0685:                } catch (IllegalArgumentException exception) {
0686:                    throw new CannotEvaluateException(
0687:                            formatErrorMessage(array), exception);
0688:                }
0689:                return dest;
0690:            }
0691:
0692:            /**
0693:             * Returns a sequence of double values for a given point in the coverage. A value for each
0694:             * {@linkplain SampleDimension sample dimension} is included in the sequence. The default
0695:             * interpolation type used when accessing grid values for points which fall between grid
0696:             * cells is {@linkplain InterpolationNearest nearest neighbor}, but it can be changed by
0697:             * some {@linkplain org.geotools.coverage.grid.Interpolator2D subclasses}. The CRS of the
0698:             * point is the same as the grid coverage {@linkplain #getCoordinateReferenceSystem coordinate
0699:             * reference system}.
0700:             * 
0701:             * @param  coord The coordinate point where to evaluate.
0702:             * @param  dest An array in which to store values, or {@code null} to create a new array.
0703:             * @return The {@code dest} array, or a newly created array if {@code dest} was null.
0704:             * @throws PointOutsideCoverageException if the evaluation failed because the input point
0705:             *         has invalid coordinates.
0706:             * @throws CannotEvaluateException if the values can't be computed at the specified coordinate
0707:             *         for an other reason. It may be thrown if the coverage data type can't be converted
0708:             *         to {@code double} by an identity or widening conversion. Subclasses may relax this
0709:             *         constraint if appropriate.
0710:             */
0711:            public double[] evaluate(final DirectPosition coord, double[] dest)
0712:                    throws CannotEvaluateException {
0713:                final Object array = evaluate(coord);
0714:                try {
0715:                    final int length = Array.getLength(array);
0716:                    if (dest == null) {
0717:                        dest = new double[length];
0718:                    }
0719:                    for (int i = 0; i < length; i++) {
0720:                        dest[i] = Array.getDouble(array, i);
0721:                    }
0722:                } catch (IllegalArgumentException exception) {
0723:                    throw new CannotEvaluateException(
0724:                            formatErrorMessage(array), exception);
0725:                }
0726:                return dest;
0727:            }
0728:
0729:            /**
0730:             * Returns a set of {@linkplain DomainObject domain objects} for the specified record of feature
0731:             * attribute values. Normally, this method returns the set of {@linkplain DomainObject objects}
0732:             * in the domain that are associated with values equal to those in the input record. However,
0733:             * the operation may return other {@linkplain DomainObject objects} derived from those in the
0734:             * domain, as specified by the application schema.
0735:             * <p>
0736:             * <B>Example:</B> The {@code evaluateInverse} operation could return a set
0737:             * of contours derived from the feature attribute values associated with the
0738:             * {@linkplain org.opengis.coverage.grid.GridPoint grid points} of a grid coverage.
0739:             * <p>
0740:             * <strong>This method is not yet implemented.</strong>
0741:             *
0742:             * @since 2.3
0743:             */
0744:            public Set evaluateInverse(Record v) {
0745:                throw unsupported();
0746:            }
0747:
0748:            /**
0749:             * Returns 2D view of this grid coverage as a renderable image. This method
0750:             * allows interoperability with Java2D.
0751:             * 
0752:             * @param xAxis Dimension to use for the <var>x</var> display axis.
0753:             * @param yAxis Dimension to use for the <var>y</var> display axis.
0754:             * @return A 2D view of this grid coverage as a renderable image.
0755:             */
0756:            public RenderableImage getRenderableImage(final int xAxis,
0757:                    final int yAxis) {
0758:                return new Renderable(xAxis, yAxis);
0759:            }
0760:
0761:            /////////////////////////////////////////////////////////////////////////
0762:            ////////////////                                         ////////////////
0763:            ////////////////     RenderableImage / ImageFunction     ////////////////
0764:            ////////////////                                         ////////////////
0765:            /////////////////////////////////////////////////////////////////////////
0766:
0767:            /**
0768:             * A view of a {@linkplain AbstractCoverage coverage} as a renderable image. Renderable images
0769:             * allow interoperability with <A HREF="http://java.sun.com/products/java-media/2D/">Java2D</A>
0770:             * for a two-dimensional slice of a coverage (which may or may not be a
0771:             * {@linkplain org.geotools.coverage.grid.GridCoverage2D grid coverage}).
0772:             * 
0773:             * @version $Id: AbstractCoverage.java 27848 2007-11-12 13:10:32Z desruisseaux $
0774:             * @author Martin Desruisseaux
0775:             * 
0776:             * @see AbstractCoverage#getRenderableImage
0777:             */
0778:            protected class Renderable extends PropertySourceImpl implements 
0779:                    RenderableImage, ImageFunction {
0780:                /**
0781:                 * The two dimensional view of the coverage's envelope.
0782:                 */
0783:                private final Rectangle2D bounds;
0784:
0785:                /**
0786:                 * Dimension to use for <var>x</var> axis.
0787:                 */
0788:                protected final int xAxis;
0789:
0790:                /**
0791:                 * Dimension to use for <var>y</var> axis.
0792:                 */
0793:                protected final int yAxis;
0794:
0795:                /**
0796:                 * A coordinate point where to evaluate the function. The point dimension is equals to the
0797:                 * {@linkplain AbstractCoverage#getDimension coverage's dimension}. The {@linkplain #xAxis
0798:                 * x} and {@link #yAxis y} ordinates will be ignored, since they will vary for each pixel
0799:                 * to be evaluated. Other ordinates, if any, should be set to a fixed value. For example a
0800:                 * coverage may be three-dimensional, where the third dimension is the time axis. In such
0801:                 * case, {@code coordinate.ord[2]} should be set to the point in time where to evaluate the
0802:                 * coverage. By default, all ordinates are initialized to 0. Subclasses should set the
0803:                 * desired values in their constructor if needed.
0804:                 */
0805:                protected final GeneralDirectPosition coordinate = new GeneralDirectPosition(
0806:                        getDimension());
0807:
0808:                /**
0809:                 * Constructs a renderable image.
0810:                 * 
0811:                 * @param xAxis Dimension to use for <var>x</var> axis.
0812:                 * @param yAxis Dimension to use for <var>y</var> axis.
0813:                 */
0814:                public Renderable(final int xAxis, final int yAxis) {
0815:                    super (null, AbstractCoverage.this );
0816:                    this .xAxis = xAxis;
0817:                    this .yAxis = yAxis;
0818:                    final Envelope envelope = getEnvelope();
0819:                    bounds = new Rectangle2D.Double(envelope.getMinimum(xAxis),
0820:                            envelope.getMinimum(yAxis), envelope
0821:                                    .getLength(xAxis), envelope
0822:                                    .getLength(yAxis));
0823:                }
0824:
0825:                /**
0826:                 * Returns {@code null} to indicate that no source information is available.
0827:                 */
0828:                public Vector getSources() {
0829:                    return null;
0830:                }
0831:
0832:                /**
0833:                 * Returns {@code true} if successive renderings with the same arguments
0834:                 * may produce different results. The default implementation returns {@code false}.
0835:                 * 
0836:                 * @see org.geotools.coverage.grid.GridCoverage2D#isDataEditable
0837:                 */
0838:                public boolean isDynamic() {
0839:                    return false;
0840:                }
0841:
0842:                /**
0843:                 * Returns {@code false} since values are not complex.
0844:                 */
0845:                public boolean isComplex() {
0846:                    return false;
0847:                }
0848:
0849:                /**
0850:                 * Gets the width in coverage coordinate space.
0851:                 * 
0852:                 * @see AbstractCoverage#getEnvelope
0853:                 * @see AbstractCoverage#getCoordinateReferenceSystem
0854:                 */
0855:                public float getWidth() {
0856:                    return (float) bounds.getWidth();
0857:                }
0858:
0859:                /**
0860:                 * Gets the height in coverage coordinate space.
0861:                 * 
0862:                 * @see AbstractCoverage#getEnvelope
0863:                 * @see AbstractCoverage#getCoordinateReferenceSystem
0864:                 */
0865:                public float getHeight() {
0866:                    return (float) bounds.getHeight();
0867:                }
0868:
0869:                /**
0870:                 * Gets the minimum <var>X</var> coordinate of the rendering-independent image
0871:                 * data. This is the {@linkplain AbstractCoverage#getEnvelope coverage's envelope}
0872:                 * minimal value for the {@linkplain #xAxis x axis}.
0873:                 * 
0874:                 * @see AbstractCoverage#getEnvelope
0875:                 * @see AbstractCoverage#getCoordinateReferenceSystem
0876:                 */
0877:                public float getMinX() {
0878:                    return (float) bounds.getX();
0879:                }
0880:
0881:                /**
0882:                 * Gets the minimum <var>Y</var> coordinate of the rendering-independent image
0883:                 * data. This is the {@linkplain AbstractCoverage#getEnvelope coverage's envelope}
0884:                 * minimal value for the {@linkplain #yAxis y axis}.
0885:                 * 
0886:                 * @see AbstractCoverage#getEnvelope
0887:                 * @see AbstractCoverage#getCoordinateReferenceSystem
0888:                 */
0889:                public float getMinY() {
0890:                    return (float) bounds.getY();
0891:                }
0892:
0893:                /**
0894:                 * Returns a rendered image with a default width and height in pixels.
0895:                 * 
0896:                 * @return A rendered image containing the rendered data
0897:                 */
0898:                public RenderedImage createDefaultRendering() {
0899:                    return createScaledRendering(512, 0, null);
0900:                }
0901:
0902:                /**
0903:                 * Creates a rendered image with width {@code width} and height {@code height} in pixels.
0904:                 * If {@code width} is 0, it will be computed automatically from {@code height}. Conversely,
0905:                 * if {@code height} is 0, il will be computed automatically from {@code width}.
0906:                 * <p>
0907:                 * The default implementation creates a render context with {@link #createRenderContext}
0908:                 * and invokes {@link #createRendering(RenderContext)}.
0909:                 * 
0910:                 * @param width  The width of rendered image in pixels, or 0.
0911:                 * @param height The height of rendered image in pixels, or 0.
0912:                 * @param hints  Rendering hints, or {@code null}.
0913:                 * @return A rendered image containing the rendered data
0914:                 */
0915:                public RenderedImage createScaledRendering(int width,
0916:                        int height, final RenderingHints hints) {
0917:                    final double boundsWidth = bounds.getWidth();
0918:                    final double boundsHeight = bounds.getHeight();
0919:                    if (!(width > 0)) { // Use '!' in order to catch NaN
0920:                        if (!(height > 0)) {
0921:                            throw new IllegalArgumentException(Errors
0922:                                    .format(ErrorKeys.UNSPECIFIED_IMAGE_SIZE));
0923:                        }
0924:                        width = (int) Math.round(height
0925:                                * (boundsWidth / boundsHeight));
0926:                    } else if (!(height > 0)) {
0927:                        height = (int) Math.round(width
0928:                                * (boundsHeight / boundsWidth));
0929:                    }
0930:                    return createRendering(createRenderContext(new Rectangle(0,
0931:                            0, width, height), hints));
0932:                }
0933:
0934:                /**
0935:                 * Creates a rendered image using a given render context. This method will uses an
0936:                 * "{@link ImageFunctionDescriptor ImageFunction}" operation if possible (i.e. if
0937:                 * the area of interect is rectangular and the affine transform contains only
0938:                 * translation and scale coefficients).
0939:                 * 
0940:                 * @param context The render context to use to produce the rendering.
0941:                 * @return A rendered image containing the rendered data
0942:                 */
0943:                public RenderedImage createRendering(final RenderContext context) {
0944:                    final AffineTransform crsToGrid = context.getTransform();
0945:                    final Shape area = context.getAreaOfInterest();
0946:                    final Rectangle gridBounds;
0947:                    if (true) {
0948:                        /*
0949:                         * Computes the grid bounds for the coverage bounds (or the area of interest).
0950:                         * The default implementation of Rectangle uses Math.floor and Math.ceil for
0951:                         * computing a box which contains fully the Rectangle2D. But in our particular
0952:                         * case, we really want to round toward the nearest integer.
0953:                         */
0954:                        final Rectangle2D bounds = XAffineTransform.transform(
0955:                                crsToGrid, (area != null) ? area.getBounds2D()
0956:                                        : this .bounds, null);
0957:                        final int xmin = (int) Math.round(bounds.getMinX());
0958:                        final int ymin = (int) Math.round(bounds.getMinY());
0959:                        final int xmax = (int) Math.round(bounds.getMaxX());
0960:                        final int ymax = (int) Math.round(bounds.getMaxY());
0961:                        gridBounds = new Rectangle(xmin, ymin, xmax - xmin,
0962:                                ymax - ymin);
0963:                    }
0964:                    /*
0965:                     * Computes some properties of the image to be created.
0966:                     */
0967:                    final Dimension tileSize = ImageUtilities
0968:                            .toTileSize(gridBounds.getSize());
0969:                    final GridSampleDimension band = GridSampleDimension
0970:                            .wrap(getSampleDimension(VISIBLE_BAND));
0971:                    final ColorModel colorModel = band.getColorModel(
0972:                            VISIBLE_BAND, getNumSampleDimensions());
0973:                    final SampleModel sampleModel = colorModel
0974:                            .createCompatibleSampleModel(tileSize.width,
0975:                                    tileSize.height);
0976:                    /*
0977:                     * If the image can be created using the ImageFunction operation, do it.
0978:                     * It allow JAI to defer the computation until a tile is really requested.
0979:                     */
0980:                    final PlanarImage image;
0981:                    if ((area == null || area instanceof  Rectangle2D)
0982:                            && crsToGrid.getShearX() == 0
0983:                            && crsToGrid.getShearY() == 0) {
0984:                        image = JAI
0985:                                .create(
0986:                                        "ImageFunction",
0987:                                        new ParameterBlock()
0988:                                                .add(this )
0989:                                                // The functional description
0990:                                                .add(gridBounds.width)
0991:                                                // The image width
0992:                                                .add(gridBounds.height)
0993:                                                // The image height
0994:                                                .add(
0995:                                                        (float) (1 / crsToGrid
0996:                                                                .getScaleX()))
0997:                                                // The X scale factor
0998:                                                .add(
0999:                                                        (float) (1 / crsToGrid
1000:                                                                .getScaleY()))
1001:                                                // The Y scale factor
1002:                                                .add(
1003:                                                        (float) crsToGrid
1004:                                                                .getTranslateX()) // The X translation
1005:                                                .add(
1006:                                                        (float) crsToGrid
1007:                                                                .getTranslateY()), // The Y translation
1008:                                        new RenderingHints(
1009:                                                JAI.KEY_IMAGE_LAYOUT,
1010:                                                new ImageLayout()
1011:                                                        .setMinX(gridBounds.x)
1012:                                                        .setMinY(gridBounds.y)
1013:                                                        .setTileWidth(
1014:                                                                tileSize.width)
1015:                                                        .setTileHeight(
1016:                                                                tileSize.height)
1017:                                                        .setSampleModel(
1018:                                                                sampleModel)
1019:                                                        .setColorModel(
1020:                                                                colorModel)));
1021:                    } else {
1022:                        /*
1023:                         * Creates immediately a rendered image using a given render context. This block
1024:                         * is run when the image can't be created with JAI's ImageFunction operator, for
1025:                         * example because the affine transform swap axis or because there is an area of
1026:                         * interest.
1027:                         */
1028:                        // Clones the coordinate point in order to allow multi-thread
1029:                        // invocation.
1030:                        final GeneralDirectPosition coordinate = new GeneralDirectPosition(
1031:                                this .coordinate);
1032:                        final TiledImage tiled = new TiledImage(gridBounds.x,
1033:                                gridBounds.y, gridBounds.width,
1034:                                gridBounds.height, 0, 0, sampleModel,
1035:                                colorModel);
1036:                        final Point2D.Double point2D = new Point2D.Double();
1037:                        final int numBands = tiled.getNumBands();
1038:                        final double[] samples = new double[numBands];
1039:                        final double[] padNaNs = new double[numBands];
1040:                        Arrays.fill(padNaNs, Double.NaN);
1041:                        final WritableRectIter iterator = RectIterFactory
1042:                                .createWritable(tiled, gridBounds);
1043:                        if (!iterator.finishedLines())
1044:                            try {
1045:                                int y = gridBounds.y;
1046:                                do {
1047:                                    iterator.startPixels();
1048:                                    if (!iterator.finishedPixels()) {
1049:                                        int x = gridBounds.x;
1050:                                        do {
1051:                                            point2D.x = x;
1052:                                            point2D.y = y;
1053:                                            crsToGrid.inverseTransform(point2D,
1054:                                                    point2D);
1055:                                            if (area == null
1056:                                                    || area.contains(point2D)) {
1057:                                                coordinate.ordinates[xAxis] = point2D.x;
1058:                                                coordinate.ordinates[yAxis] = point2D.y;
1059:                                                iterator.setPixel(evaluate(
1060:                                                        coordinate, samples));
1061:                                            } else {
1062:                                                iterator.setPixel(padNaNs);
1063:                                            }
1064:                                            x++;
1065:                                        } while (!iterator.nextPixelDone());
1066:                                        assert (x == gridBounds.x
1067:                                                + gridBounds.width);
1068:                                        y++;
1069:                                    }
1070:                                } while (!iterator.nextLineDone());
1071:                                assert (y == gridBounds.y + gridBounds.height);
1072:                            } catch (NoninvertibleTransformException exception) {
1073:                                // TODO: give cause to constructor when we will be allowed to target J2SE 1.5.
1074:                                final IllegalArgumentException e = new IllegalArgumentException(
1075:                                        Errors.format(
1076:                                                ErrorKeys.ILLEGAL_ARGUMENT_$1,
1077:                                                "context"));
1078:                                e.initCause(exception);
1079:                                throw e;
1080:                            }
1081:                        image = tiled;
1082:                    }
1083:                    /*
1084:                     * Adds a 'gridToCRS' property to the image. This is an important
1085:                     * information for constructing a GridCoverage from this image later.
1086:                     */
1087:                    try {
1088:                        image.setProperty("gridToCRS", crsToGrid
1089:                                .createInverse());
1090:                    } catch (NoninvertibleTransformException exception) {
1091:                        // Can't add the property. Too bad, the image has been created
1092:                        // anyway. Maybe the user know what he is doing...
1093:                        Logging.unexpectedException("org.geotools.coverage",
1094:                                Renderable.class, "createRendering", exception);
1095:                    }
1096:                    return image;
1097:                }
1098:
1099:                /**
1100:                 * Initializes a render context with an affine transform that maps the coverage envelope
1101:                 * to the specified destination rectangle. The affine transform mays swap axis in order to
1102:                 * normalize their order (i.e. make them appear in the (<var>x</var>,<var>y</var>) order),
1103:                 * so that the image appears properly oriented when rendered.
1104:                 * 
1105:                 * @param gridBounds The two-dimensional destination rectangle.
1106:                 * @param hints      The rendering hints, or {@code null} if none.
1107:                 * @return A render context initialized with an affine transform from the coverage
1108:                 *         to the grid coordinate system. This transform is the inverse of
1109:                 *         {@link org.geotools.coverage.grid.GridGeometry2D#getGridToCRS2D}.
1110:                 * 
1111:                 * @see org.geotools.coverage.grid.GridGeometry2D#getGridToCRS2D
1112:                 */
1113:                protected RenderContext createRenderContext(
1114:                        final Rectangle2D gridBounds, final RenderingHints hints) {
1115:                    final GeneralMatrix matrix;
1116:                    final GeneralEnvelope srcEnvelope = new GeneralEnvelope(
1117:                            bounds);
1118:                    final GeneralEnvelope dstEnvelope = new GeneralEnvelope(
1119:                            gridBounds);
1120:                    if (crs != null) {
1121:                        final CoordinateSystem cs = crs.getCoordinateSystem();
1122:                        final AxisDirection[] axis = new AxisDirection[] {
1123:                                cs.getAxis(xAxis).getDirection(),
1124:                                cs.getAxis(yAxis).getDirection() };
1125:                        final AxisDirection[] normalized = (AxisDirection[]) axis
1126:                                .clone();
1127:                        if (false) {
1128:                            // Normalize axis: Is it really a good idea?
1129:                            // We should provide a rendering hint for configuring that.
1130:                            Arrays.sort(normalized);
1131:                            for (int i = normalized.length; --i >= 0;) {
1132:                                normalized[i] = normalized[i].absolute();
1133:                            }
1134:                        }
1135:                        normalized[1] = normalized[1].opposite(); // Image's Y axis is downward.
1136:                        matrix = new GeneralMatrix(srcEnvelope, axis,
1137:                                dstEnvelope, normalized);
1138:                    } else {
1139:                        matrix = new GeneralMatrix(srcEnvelope, dstEnvelope);
1140:                    }
1141:                    return new RenderContext(matrix.toAffineTransform2D(),
1142:                            hints);
1143:                }
1144:
1145:                /**
1146:                 * Returns the number of elements per value at each position. This is
1147:                 * the maximum value plus 1 allowed in {@code getElements(...)} methods
1148:                 * invocation. The default implementation returns the number of sample
1149:                 * dimensions in the coverage.
1150:                 */
1151:                public int getNumElements() {
1152:                    return getNumSampleDimensions();
1153:                }
1154:
1155:                /**
1156:                 * Returns all values of a given element for a specified set of coordinates.
1157:                 * This method is automatically invoked at rendering time for populating an
1158:                 * image tile, providing that the rendered image is created using the
1159:                 * "{@link ImageFunctionDescriptor ImageFunction}" operator and the image
1160:                 * type is not {@code double}. The default implementation invokes
1161:                 * {@link AbstractCoverage#evaluate(DirectPosition,float[])} recursively.
1162:                 */
1163:                public void getElements(final float startX, final float startY,
1164:                        final float deltaX, final float deltaY,
1165:                        final int countX, final int countY, final int element,
1166:                        final float[] real, final float[] imag) {
1167:                    int index = 0;
1168:                    float[] buffer = null;
1169:                    // Clones the coordinate point in order to allow multi-thread invocation.
1170:                    final GeneralDirectPosition coordinate = new GeneralDirectPosition(
1171:                            this .coordinate);
1172:                    coordinate.ordinates[1] = startY;
1173:                    for (int j = 0; j < countY; j++) {
1174:                        coordinate.ordinates[0] = startX;
1175:                        for (int i = 0; i < countX; i++) {
1176:                            buffer = evaluate(coordinate, buffer);
1177:                            real[index++] = buffer[element];
1178:                            coordinate.ordinates[0] += deltaX;
1179:                        }
1180:                        coordinate.ordinates[1] += deltaY;
1181:                    }
1182:                }
1183:
1184:                /**
1185:                 * Returns all values of a given element for a specified set of coordinates.
1186:                 * This method is automatically invoked at rendering time for populating an
1187:                 * image tile, providing that the rendered image is created using the
1188:                 * "{@link ImageFunctionDescriptor ImageFunction}" operator and the image
1189:                 * type is {@code double}. The default implementation invokes
1190:                 * {@link AbstractCoverage#evaluate(DirectPosition,double[])} recursively.
1191:                 */
1192:                public void getElements(final double startX,
1193:                        final double startY, final double deltaX,
1194:                        final double deltaY, final int countX,
1195:                        final int countY, final int element,
1196:                        final double[] real, final double[] imag) {
1197:                    int index = 0;
1198:                    double[] buffer = null;
1199:                    // Clones the coordinate point in order to allow multi-thread invocation.
1200:                    final GeneralDirectPosition coordinate = new GeneralDirectPosition(
1201:                            this .coordinate);
1202:                    coordinate.ordinates[1] = startY;
1203:                    for (int j = 0; j < countY; j++) {
1204:                        coordinate.ordinates[0] = startX;
1205:                        for (int i = 0; i < countX; i++) {
1206:                            buffer = evaluate(coordinate, buffer);
1207:                            real[index++] = buffer[element];
1208:                            coordinate.ordinates[0] += deltaX;
1209:                        }
1210:                        coordinate.ordinates[1] += deltaY;
1211:                    }
1212:                }
1213:            }
1214:
1215:            /**
1216:             * Display this coverage in a windows. This convenience method is used for debugging purpose.
1217:             * The exact appareance of the windows and the tools provided may changes in future versions.
1218:             *
1219:             * @param  xAxis Dimension to use for the <var>x</var> display axis.
1220:             * @param  yAxis Dimension to use for the <var>y</var> display axis.
1221:             *
1222:             * @deprecated Use {@link #show(String, int, int)}.
1223:             */
1224:            public void show(final int xAxis, final int yAxis) {
1225:                show(null, xAxis, yAxis);
1226:            }
1227:
1228:            /**
1229:             * Display this coverage in a windows. This convenience method is used for debugging purpose.
1230:             * The exact appareance of the windows and the tools provided may changes in future versions.
1231:             *
1232:             * @param  title The window title, or {@code null} for default value.
1233:             * @param  xAxis Dimension to use for the <var>x</var> display axis.
1234:             * @param  yAxis Dimension to use for the <var>y</var> display axis.
1235:             *
1236:             * @since 2.3
1237:             */
1238:            public void show(String title, final int xAxis, final int yAxis) {
1239:                if (title == null || (title = title.trim()).length() == 0) {
1240:                    title = String.valueOf(getName());
1241:                }
1242:                // In the following line, the constructor display immediately the viewer.
1243:                new Viewer(title, getRenderableImage(xAxis, yAxis)
1244:                        .createDefaultRendering());
1245:            }
1246:
1247:            /**
1248:             * A trivial viewer implementation to be used by {@link AbstractCoverage#show(String,int,int)}
1249:             * method.
1250:             * <p>
1251:             * <strong>Implementation note:</strong>
1252:             * We use AWT Frame, not Swing JFrame, because {@link ScrollingImagePane} is an AWT
1253:             * component. Swing is an overhead in this context without clear benefict. Note also
1254:             * that {@code ScrollingImagePanel} includes the scroll bar, so there is no need to
1255:             * put this component in an other {@code JScrollPane}.
1256:             */
1257:            private static final class Viewer extends WindowAdapter implements 
1258:                    Runnable {
1259:                /**
1260:                 * The frame to dispose once closed.
1261:                 */
1262:                private final Frame frame;
1263:
1264:                /**
1265:                 * Displays the specified image in a window with the specified title.
1266:                 */
1267:                public Viewer(final String title, final RenderedImage image) {
1268:                    final int width = Math.max(Math.min(image.getWidth(), 800),
1269:                            24);
1270:                    final int height = Math.max(Math
1271:                            .min(image.getHeight(), 600), 24);
1272:                    frame = new Frame(title);
1273:                    frame.add(new ScrollingImagePanel(image, width, height));
1274:                    frame.addWindowListener(this );
1275:                    EventQueue.invokeLater(this );
1276:                }
1277:
1278:                /**
1279:                 * Display the window in the event queue.
1280:                 * Required because 'pack()' is invoked before 'setVisible(true)'.
1281:                 */
1282:                public void run() {
1283:                    frame.pack();
1284:                    frame.setVisible(true);
1285:                }
1286:
1287:                /**
1288:                 * Invoked when the user dispose the window.
1289:                 */
1290:                public void windowClosing(WindowEvent e) {
1291:                    frame.dispose();
1292:                }
1293:            }
1294:
1295:            /**
1296:             * Display this coverage in a windows. This convenience method is used for
1297:             * debugging purpose. The exact appareance of the windows and the tools
1298:             * provided may changes in future versions.
1299:             *
1300:             * @param  title The window title, or {@code null} for default value.
1301:             *
1302:             * @since 2.3
1303:             */
1304:            public void show(final String title) {
1305:                show(title, 0, 1);
1306:            }
1307:
1308:            /**
1309:             * Displays this coverage in a windows. This convenience method is used for debugging purpose.
1310:             * The exact appareance of the windows and the tools provided may changes in future versions.
1311:             */
1312:            public void show() {
1313:                show(null);
1314:            }
1315:
1316:            /**
1317:             * Returns the source data for a coverage. The default implementation returns an empty list.
1318:             */
1319:            public List getSources() {
1320:                return Collections.EMPTY_LIST;
1321:            }
1322:
1323:            /**
1324:             * List of metadata keywords for a coverage. If no metadata is available,
1325:             * the sequence will be empty. The default implementation gets the list of
1326:             * metadata names from the {@link #getPropertyNames()} method.
1327:             * 
1328:             * @return the list of metadata keywords for a coverage.
1329:             *
1330:             * @deprecated Use {@link #getPropertyNames()} instead.
1331:             */
1332:            public String[] getMetadataNames() {
1333:                final String[] list = getPropertyNames();
1334:                return (list != null) ? list : NO_PROPERTIES;
1335:            }
1336:
1337:            /**
1338:             * Retrieve the metadata value for a given metadata name. The default
1339:             * implementation query the {@link #getProperty(String)} method.
1340:             * 
1341:             * @param name Metadata keyword for which to retrieve data.
1342:             * @return the metadata value for a given metadata name.
1343:             * @throws MetadataNameNotFoundException
1344:             *             if there is no value for the specified metadata name.
1345:             *
1346:             * @deprecated Use {@link #getProperty(String)} instead.
1347:             */
1348:            public String getMetadataValue(final String name)
1349:                    throws MetadataNameNotFoundException {
1350:                final Object value = getProperty(name);
1351:                if (value == java.awt.Image.UndefinedProperty) {
1352:                    throw new MetadataNameNotFoundException(Errors.format(
1353:                            ErrorKeys.UNDEFINED_PROPERTY_$1, name));
1354:                }
1355:                return (value != null) ? value.toString() : null;
1356:            }
1357:
1358:            /**
1359:             * Returns the default locale for logging, error messages, <cite>etc.</cite>.
1360:             */
1361:            public Locale getLocale() {
1362:                return Locale.getDefault();
1363:            }
1364:
1365:            /**
1366:             * Returns a string representation of this coverage. This string is for
1367:             * debugging purpose only and may change in future version.
1368:             */
1369:            //@Override
1370:            public String toString() {
1371:                final StringWriter buffer = new StringWriter();
1372:                buffer.write(Utilities.getShortClassName(this ));
1373:                buffer.write("[\"");
1374:                buffer.write(String.valueOf(getName()));
1375:                buffer.write('"');
1376:                final Envelope envelope = getEnvelope();
1377:                if (envelope != null) {
1378:                    buffer.write(", ");
1379:                    buffer.write(envelope.toString());
1380:                }
1381:                if (crs != null) {
1382:                    buffer.write(", ");
1383:                    buffer.write(Utilities.getShortClassName(crs));
1384:                    buffer.write("[\"");
1385:                    buffer.write(crs.getName().getCode());
1386:                    buffer.write("\"]");
1387:                }
1388:                buffer.write(']');
1389:                final String lineSeparator = System.getProperty(
1390:                        "line.separator", "\n");
1391:                final LineWriter filter = new LineWriter(buffer, lineSeparator
1392:                        + "    ");
1393:                final int n = getNumSampleDimensions();
1394:                try {
1395:                    filter.write(lineSeparator);
1396:                    for (int i = 0; i < n; i++) {
1397:                        filter.write(getSampleDimension(i).toString());
1398:                    }
1399:                    filter.flush();
1400:                } catch (IOException exception) {
1401:                    // Should not happen
1402:                    throw new AssertionError(exception);
1403:                }
1404:                return buffer.toString();
1405:            }
1406:
1407:            /**
1408:             * Provides a hint that a coverage will no longer be accessed from a reference in user space.
1409:             * This can be used as a hint in situations where waiting for garbage collection would be
1410:             * overly conservative. The results of referencing a coverage after a call to {@code dispose}
1411:             * are undefined, except if this method returned {@code false}.
1412:             * <p>
1413:             * This method can work in a <cite>conservative</cite> mode or a <cite>forced</cite> mode,
1414:             * determined by the {@code force} argument:
1415:             *
1416:             * <ul>
1417:             *   <li><p>If {@code force} is {@code false} (the recommanded value), this method may process
1418:             *   only under some conditions. For example a grid coverage may dispose its planar image only
1419:             *   if it has no {@linkplain PlanarImage#getSinks sinks}. This method returns {@code true} if
1420:             *   it disposed at least some resources, or {@code false} if this method vetoed against the
1421:             *   disposal. In the later case, no resources were disposed and this coverage can still be
1422:             *   used.</p></li>
1423:             *
1424:             *   <li><p>If {@code force} is {@code true}, then this method processes inconditionnally and
1425:             *   returns always {@code true}. This is a more risky behavior.</p></li>
1426:             * </ul>
1427:             *
1428:             * The conservative mode ({@code force = false}) performs its safety checks on a
1429:             * <cite>best-effort</cite> basis, with no guarantees. Therefore, it would be wrong to write
1430:             * a program that depended on the safety checks for its correctness. In case of doubt about
1431:             * whatever this coverage still in use or not, it is safer to rely on the garbage collector.
1432:             *
1433:             * @param  force {@code true} for forcing an inconditionnal disposal, or {@code false} for
1434:             *         performing a conservative disposal. The recommanded value is {@code false}.
1435:             * @return {@code true} if this method disposed at least some resources, or {@code false}
1436:             *         if this method vetoed against the disposal.
1437:             *
1438:             * @see PlanarImage#dispose
1439:             *
1440:             * @since 2.4
1441:             */
1442:            public boolean dispose(boolean force) {
1443:                return true;
1444:            }
1445:
1446:            /**
1447:             * @deprecated Use {@link #dispose(boolean)} instead.
1448:             */
1449:            public void dispose() {
1450:                dispose(false);
1451:            }
1452:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.