Source Code Cross Referenced for Crop.java in  » GIS » GeoTools-2.4.1 » org » geotools » coverage » processing » operation » 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.processing.operation 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2006, Geotools Project Managment Committee (PMC)
005:         *
006:         *    This library is free software; you can redistribute it and/or
007:         *    modify it under the terms of the GNU Lesser General Public
008:         *    License as published by the Free Software Foundation; either
009:         *    version 2.1 of the License, or (at your option) any later version.
010:         *
011:         *    This library is distributed in the hope that it will be useful,
012:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014:         *    Lesser General Public License for more details.
015:         */
016:        package org.geotools.coverage.processing.operation;
017:
018:        import java.awt.Polygon;
019:        import java.awt.geom.AffineTransform;
020:
021:        import org.geotools.coverage.grid.GridCoverage2D;
022:        import org.geotools.coverage.grid.GridGeometry2D;
023:        import org.geotools.coverage.processing.CannotCropException;
024:        import org.geotools.coverage.processing.Operation2D;
025:        import org.geotools.factory.Hints;
026:        import org.geotools.geometry.Envelope2D;
027:        import org.geotools.geometry.GeneralEnvelope;
028:        import org.geotools.metadata.iso.citation.Citations;
029:        import org.geotools.parameter.DefaultParameterDescriptor;
030:        import org.geotools.parameter.DefaultParameterDescriptorGroup;
031:        import org.geotools.referencing.CRS;
032:        import org.geotools.referencing.operation.matrix.XAffineTransform;
033:        import org.geotools.resources.i18n.ErrorKeys;
034:        import org.geotools.resources.i18n.Errors;
035:        import org.opengis.coverage.Coverage;
036:        import org.opengis.coverage.processing.OperationNotFoundException;
037:        import org.opengis.geometry.Envelope;
038:        import org.opengis.metadata.spatial.PixelOrientation;
039:        import org.opengis.parameter.ParameterDescriptor;
040:        import org.opengis.parameter.ParameterValue;
041:        import org.opengis.parameter.ParameterValueGroup;
042:        import org.opengis.referencing.crs.CoordinateReferenceSystem;
043:
044:        /**
045:         * The crop operation is responsible for selecting geographic subarea of the
046:         * source coverage. The CoverageCrop operation does not merely wrap the JAI Crop
047:         * operation but it goes beyond that as far as capabilities.
048:         * 
049:         * <p>
050:         * The key point is that the CoverageCrop operation aims to perform a spatial
051:         * crop, i.e. cropping the underlying raster by providing a spatial
052:         * {@link Envelope} (if the envelope is not 2D only the 2D part of it will be
053:         * used). This means that, depending on the grid-to-world transformation
054:         * existing for the raster we want to crop the crop area in the raster space
055:         * might not be a rectangle, hence JAI's crop may not suffice in order to shrink
056:         * the raster area we would obtain. For this purpose this operation make use of
057:         * either the JAI's Crop or Mosaic operations depending on the conditions in
058:         * which we are working.
059:         * 
060:         * 
061:         * <p>
062:         * <strong>Meaning of the ROI_OPTIMISATION_TOLERANCE parameter</strong> <br>
063:         * In general if the grid-to-world transform is a simple scale and translate
064:         * using JAI's crop should suffice, but when the g2w transform contains
065:         * rotations or skew then we need something more elaborate since a rectangle in
066:         * model space may not map to a rectangle in raster space. We would still be
067:         * able to crop using JAI's crop on this polygon bounds but, depending on how
068:         * this rectangle is built, we would be highly inefficient. In order to overcome
069:         * this problems we use a combination of JAI's crop and mosaic since the mosaic
070:         * can be used to crop a raster using a general ROI instead of a simple
071:         * rectangle. There is a negative effect though. Crop would not create a new
072:         * raster but simply forwards requests back to the origina one (it basically
073:         * create a viewport on the source raster) while the mosaic operation creates a
074:         * new raster. We try to address this trade-off by providing the parameter
075:         * {@link Crop#ROI_OPTIMISATION_TOLERANCE}, which basically tells this
076:         * operation "Use the mosaic operation only if the area that we would load with
077:         * the Mosaic is strictly smaller then (ROI_OPTIMISATION_TOLERANCE)* A' where A'
078:         * is the area of the polygon resulting from converting the crop area from the
079:         * model space to the raster space.
080:         * 
081:         * <p>
082:         * <strong>Meaning of the CONSERVE_ENVELOPE parameter</strong> <br>
083:         * When we crop a coverage using a spatial envelope we may incur in a few issues
084:         * with approximations when applying the grid-to-world transform and its
085:         * inverse. Goal of this parameter is to suggest this operation to conserve the
086:         * input crop envelope, if possible, instead of conserving the original
087:         * grid-to-world transform. This would help when doing something like building a
088:         * mosaic from a single coverage.
089:         * 
090:         * <p>
091:         * <strong>NOTE</strong> that in case we will use the Mosaic operation with a
092:         * ROI, such a ROI will be added as a synthetic property to the resulting
093:         * coverage. The key for this property will be GC_ROI and the type of the object
094:         * {@link Polygon}.
095:         * 
096:         * @todo make this operation work with a general polygon. instead of an
097:         *       envelope.
098:         * @todo make this operation work when having a shear
099:         * @todo make the tolerance for rotations parametric
100:         * @source $URL:
101:         *         http://svn.geotools.org/geotools/branches/2.4.x_rs/modules/library/coverage/src/main/java/org/geotools/coverage/processing/operation/Crop.java $
102:         * @version $Id: Crop.java 27037 2007-09-18 12:58:10Z simboss $
103:         * @author Simone Giannecchini, GeoSolutions
104:         * @since 2.3
105:         * 
106:         * @see javax.media.jai.operator.ScaleDescriptor
107:         */
108:        public class Crop extends Operation2D {
109:            /**
110:             * Serial number for cross-version compatibility.
111:             */
112:            private static final long serialVersionUID = 4466072819239413456L;
113:
114:            /**
115:             * The parameter descriptor used to pass this operation the envelope to use
116:             * when doing the spatial crop.
117:             */
118:            public static final ParameterDescriptor CROP_ENVELOPE = new DefaultParameterDescriptor(
119:                    Citations.GEOTOOLS, "Envelope", Envelope.class, // Value
120:                    // class
121:                    null, // Array of valid values
122:                    null, // Default value
123:                    null, // Minimal value
124:                    null, // Maximal value
125:                    null, // Unit of measure
126:                    false); // Parameter is optional
127:
128:            /**
129:             * The parameter descriptor use to tell this operation to optimize the crop
130:             * using a Mosaic in where the are of the image we would not load is smaller
131:             * than ROI_OPTIMISATION_TOLERANCE*FULL_CROP.
132:             */
133:            public static final ParameterDescriptor ROI_OPTIMISATION_TOLERANCE = new DefaultParameterDescriptor(
134:                    Citations.GEOTOOLS, "ROITolerance", Double.class, // Value class
135:                    null, // Array of valid values
136:                    new Double(0.6), // Default value
137:                    new Double(0), // Minimal value
138:                    new Double(1.0), // Maximal value
139:                    null, // Unit of measure
140:                    true); // Parameter is optional
141:
142:            /**
143:             * The parameter descriptor is basically a simple boolean that tells this
144:             * operation to conserve the envelope that it gets as input.
145:             * 
146:             * <p>
147:             * See this class javadocs for an explanation.
148:             */
149:            public static final ParameterDescriptor CONSERVE_ENVELOPE = new DefaultParameterDescriptor(
150:                    Citations.GEOTOOLS, "ConserveEnvelope", Boolean.class, // Value
151:                    // class
152:                    new Boolean[] { Boolean.TRUE, Boolean.FALSE }, // Array of valid
153:                    // values
154:                    Boolean.FALSE, // Default value
155:                    null, // Minimal value
156:                    null, // Maximal value
157:                    null, // Unit of measure
158:                    true); // Parameter is optional
159:
160:            /**
161:             * 
162:             * @throws OperationNotFoundException
163:             */
164:            public Crop() {
165:                super (new DefaultParameterDescriptorGroup(Citations.GEOTOOLS,
166:                        "CoverageCrop", new ParameterDescriptor[] { SOURCE_0,
167:                                CROP_ENVELOPE, CONSERVE_ENVELOPE,
168:                                ROI_OPTIMISATION_TOLERANCE }));
169:
170:            }
171:
172:            /*
173:             * (non-Javadoc)
174:             * 
175:             * @see org.geotools.coverage.processing.AbstractOperation#doOperation(org.opengis.parameter.ParameterValueGroup,
176:             *      org.geotools.factory.Hints)
177:             */
178:            public Coverage doOperation(ParameterValueGroup parameters,
179:                    Hints hints) {
180:                // /////////////////////////////////////////////////////////////////////
181:                //
182:                // Checking input parameters
183:                //
184:                // ///////////////////////////////////////////////////////////////////
185:                // source coverage
186:                final ParameterValue sourceParameter = parameters
187:                        .parameter("Source");
188:                if (sourceParameter == null
189:                        || !(sourceParameter.getValue() instanceof  GridCoverage2D)) {
190:                    throw new CannotCropException(Errors.format(
191:                            ErrorKeys.NULL_PARAMETER_$2, "Source",
192:                            GridCoverage2D.class.toString()));
193:                }
194:                // crop envelope
195:                final ParameterValue envelopeParameter = parameters
196:                        .parameter("Envelope");
197:                if (envelopeParameter == null
198:                        || !(envelopeParameter.getValue() instanceof  Envelope))
199:                    throw new CannotCropException(Errors.format(
200:                            ErrorKeys.NULL_PARAMETER_$2, "Envelope",
201:                            GeneralEnvelope.class.toString()));
202:                // should we conserve the crop envelope
203:                final ParameterValue conserveEnvelopeParameter = parameters
204:                        .parameter("ConserveEnvelope");
205:                if (conserveEnvelopeParameter == null
206:                        || !(conserveEnvelopeParameter.getValue() instanceof  Boolean))
207:                    throw new CannotCropException(Errors.format(
208:                            ErrorKeys.NULL_PARAMETER_$2, "ConserveEnvelope",
209:                            Double.class.toString()));
210:
211:                // /////////////////////////////////////////////////////////////////////
212:                //
213:                // Initialization
214:                //
215:                // We take the crop envelope and the source envelope then we check their
216:                // crs and we also check if they ever overlap.
217:                //
218:                // /////////////////////////////////////////////////////////////////////
219:                final GridCoverage2D source = (GridCoverage2D) sourceParameter
220:                        .getValue();
221:                // envelope of the source coverage
222:                final Envelope2D sourceEnvelope = source.getEnvelope2D();
223:                // crop envelope
224:                Envelope2D destinationEnvelope = new Envelope2D(
225:                        (Envelope) envelopeParameter.getValue());
226:                CoordinateReferenceSystem sourceCRS, destinationCRS;
227:                sourceCRS = sourceEnvelope.getCoordinateReferenceSystem();
228:                destinationCRS = destinationEnvelope
229:                        .getCoordinateReferenceSystem();
230:                if (destinationCRS == null) {
231:                    // Do not change the user provided object - clone it first.
232:                    final Envelope2D ge = new Envelope2D(destinationEnvelope);
233:                    destinationCRS = source.getCoordinateReferenceSystem2D();
234:                    ge.setCoordinateReferenceSystem(destinationCRS);
235:                    destinationEnvelope = ge;
236:                }
237:
238:                // //
239:                //
240:                // Source and destination crs must to be equals
241:                //
242:                // //
243:                if (!CRS.equalsIgnoreMetadata(sourceCRS, destinationCRS)) {
244:                    throw new CannotCropException(Errors.format(
245:                            ErrorKeys.MISMATCHED_ENVELOPE_CRS_$2, sourceCRS
246:                                    .getName().getCode(), destinationCRS
247:                                    .getName().getCode()));
248:                }
249:                // //
250:                //
251:                // Check the intersection and, if needed, do the crop operation.
252:                //
253:                // //
254:                final GeneralEnvelope intersectionEnvelope = new GeneralEnvelope(
255:                        (Envelope) destinationEnvelope);
256:                intersectionEnvelope.setCoordinateReferenceSystem(source
257:                        .getCoordinateReferenceSystem());
258:                // intersect the envelopes
259:                intersectionEnvelope.intersect(sourceEnvelope);
260:                if (intersectionEnvelope.isEmpty())
261:                    throw new CannotCropException(Errors
262:                            .format(ErrorKeys.CANT_CROP));
263:                // //
264:                //
265:                // Get the grid-to-world transform by keeping into account translation
266:                // of grid geometry constructor for respecting OGC PIXEL-IS-CENTER
267:                // ImageDatum assumption.
268:                //
269:                // //
270:                final AffineTransform sourceGridToWorld = (AffineTransform) ((GridGeometry2D) source
271:                        .getGridGeometry())
272:                        .getGridToCRS2D(PixelOrientation.UPPER_LEFT);
273:                // //
274:                //
275:                // I set the tolerance as half the scale factor of the grid-to-world
276:                // transform. This should more or less means in most cases "don't bother
277:                // to crop if the new envelope is as close to the old one that we go
278:                // deep under pixel size."
279:                //
280:                // //
281:                final double tolerance = XAffineTransform
282:                        .getScale(sourceGridToWorld);
283:                if (!intersectionEnvelope.equals(sourceEnvelope,
284:                        tolerance / 2.0, false)) {
285:                    envelopeParameter.setValue(intersectionEnvelope.clone());
286:                    return CroppedCoverage2D.create(parameters,
287:                            (hints instanceof  Hints) ? (Hints) hints
288:                                    : new Hints(hints), source,
289:                            sourceGridToWorld, tolerance);
290:                } else {
291:                    // //
292:                    //
293:                    // Note that in case we don't crop at all, WE DO NOT UPDATE the
294:                    // envelope. If we did we might end up doing multiple successive
295:                    // crop without actually cropping the image but, still, we would
296:                    // shrink the envelope each time. Just think about having a loop
297:                    // that crops recursively the same coverage specifying each time an
298:                    // envelope whose URC is only a a scale quarter close to the LLC of
299:                    // the old one. We would never crop the raster but we would modify
300:                    // the grid-to-world trasnform each time.
301:                    //
302:                    // //
303:                    return source;
304:                }
305:            }
306:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.