001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/processing/raster/interpolation/Interpolation.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    package org.deegree.processing.raster.interpolation;
037    
038    import java.net.URI;
039    import java.net.URISyntaxException;
040    
041    import org.deegree.datatypes.values.Interval;
042    import org.deegree.datatypes.values.TypedLiteral;
043    import org.deegree.datatypes.values.Values;
044    import org.deegree.framework.log.ILogger;
045    import org.deegree.framework.log.LoggerFactory;
046    import org.deegree.graphics.transformation.WorldToScreenTransform;
047    import org.deegree.io.quadtree.IndexException;
048    import org.deegree.io.quadtree.Quadtree;
049    import org.deegree.model.coverage.grid.FloatGridCoverage;
050    import org.deegree.model.spatialschema.Envelope;
051    
052    /**
053     * <code>Interpolation</code> is the abstract base class for all interpolation algorithms. Data
054     * representation is done via the Quadtree interface.
055     *
056     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
057     * @author last edited by: $Author: mschneider $
058     *
059     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
060     */
061    public abstract class Interpolation {
062    
063        /**
064         *
065         */
066        protected Quadtree<?> data;
067    
068        private static URI type = null;
069        static {
070            try {
071                type = new URI( "xsd:integer" );
072            } catch ( URISyntaxException never_happens ) {
073                // nottin
074            }
075        }
076    
077        protected Values ignoreValues = new Values( new Interval[0], new TypedLiteral[0], new TypedLiteral( "-9999", type ) );
078    
079        protected double searchRadius1 = 0;
080    
081        protected double searchRadius2 = 0;
082    
083        protected double searchRadiusAngle = 0;
084    
085        protected int minData = 3;
086    
087        protected int maxData = Integer.MAX_VALUE;
088    
089        protected double noValue = -9999;
090    
091        protected double autoincreaseSearchRadius1 = 0;
092    
093        protected double autoincreaseSearchRadius2 = 0;
094    
095        private static final ILogger LOG = LoggerFactory.getLogger( Interpolation.class );
096    
097        /**
098         *
099         * @param data
100         */
101        protected Interpolation( Quadtree<?> data ) {
102            this.data = data;
103            searchRadius1 = calcSearchRadius();
104            searchRadius2 = searchRadius1;
105        }
106    
107        /**
108         *
109         * @param data
110         * @param ignoreValues
111         */
112        protected Interpolation( Quadtree<?> data, Values ignoreValues ) {
113            this.data = data;
114            this.ignoreValues = ignoreValues;
115            searchRadius1 = calcSearchRadius();
116            searchRadius2 = searchRadius1;
117        }
118    
119        /**
120         *
121         * @param data
122         * @param ignoreValues
123         * @param searchRadius1
124         * @param searchRadius2
125         * @param searchRadiusAngle
126         * @param minData
127         * @param maxData
128         * @param noValue
129         * @param autoincreaseSearchRadius1
130         * @param autoincreaseSearchRadius2
131         */
132        protected Interpolation( Quadtree<?> data, Values ignoreValues, double searchRadius1, double searchRadius2,
133                                 double searchRadiusAngle, int minData, int maxData, double noValue,
134                                 double autoincreaseSearchRadius1, double autoincreaseSearchRadius2 ) {
135            this.data = data;
136            this.ignoreValues = ignoreValues;
137            // this.envelope = envelope;
138            this.searchRadius1 = searchRadius1;
139            this.searchRadius2 = searchRadius2;
140            this.searchRadiusAngle = searchRadiusAngle;
141            this.minData = minData;
142            this.maxData = maxData;
143            this.noValue = noValue;
144            this.autoincreaseSearchRadius1 = autoincreaseSearchRadius1;
145            this.autoincreaseSearchRadius2 = autoincreaseSearchRadius2;
146        }
147    
148        private double calcSearchRadius() {
149            try {
150                double w = data.getRootBoundingBox().getWidth();
151                double h = data.getRootBoundingBox().getHeight();
152                // default search radius is 20% of the target envelope
153                return Math.sqrt( w * w + h * h ) / 5d;
154            } catch ( IndexException e ) {
155                LOG.logError( e.getLocalizedMessage(), e );
156            }
157            return 0;
158        }
159    
160        /**
161         * performs the interpolation
162         *
163         * @param width
164         *            width of the result grid in number of cells
165         * @param height
166         *            height of the result grid in number of cells
167         * @return result grid as an instance of
168         * @see org.deegree.model.coverage.grid.GridCoverage
169         * @throws InterpolationException
170         */
171        public FloatGridCoverage interpolate( int width, int height )
172                                throws InterpolationException {
173    
174            Envelope envelope = null;
175    
176            try {
177                envelope = data.getRootBoundingBox();
178            } catch ( IndexException e ) {
179                LOG.logError( e.getLocalizedMessage(), e );
180            }
181    
182            WorldToScreenTransform trans = new WorldToScreenTransform( envelope.getMin().getX(), envelope.getMin().getY(),
183                                                                       envelope.getMax().getX(), envelope.getMax().getY(),
184                                                                       0, 0, width - 1, height - 1 );
185    
186            float[][][] data = new float[1][height][width];
187            for ( int i = 0; i < data[0][0].length; i++ ) {
188                for ( int j = 0; j < data[0].length; j++ ) {
189                    data[0][j][i] = (float) calcInterpolatedValue( trans.getSourceX( i ), trans.getSourceY( j ),
190                                                                   searchRadius1, searchRadius2 );
191                }
192            }
193    
194            // the CoverageOffering is passed as null here, desired? TODO
195            FloatGridCoverage result = new FloatGridCoverage( null, envelope, data );
196    
197            return result;
198        }
199    
200        /**
201         * calculates the interpolated value for a position defined by x and y
202         *
203         * @param x
204         * @param y
205         * @param searchRadius1
206         * @param searchRadius2
207         * @return the interpolated value
208         * @throws InterpolationException
209         */
210        public abstract double calcInterpolatedValue( double x, double y, double searchRadius1, double searchRadius2 )
211                                throws InterpolationException;
212    
213    }