001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/processing/raster/interpolation/InverseDistanceToPower.java $
002: /*---------------- FILE HEADER ------------------------------------------
003:
004: This file is part of deegree.
005: Copyright (C) 2001-2008 by:
006: EXSE, Department of Geography, University of Bonn
007: http://www.giub.uni-bonn.de/deegree/
008: lat/lon GmbH
009: http://www.lat-lon.de
010:
011: This library is free software; you can redistribute it and/or
012: modify it under the terms of the GNU Lesser General Public
013: License as published by the Free Software Foundation; either
014: version 2.1 of the License, or (at your option) any later version.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: Contact:
026:
027: Andreas Poth
028: lat/lon GmbH
029: Aennchenstr. 19
030: 53177 Bonn
031: Germany
032: E-Mail: poth@lat-lon.de
033:
034: Prof. Dr. Klaus Greve
035: Department of Geography
036: University of Bonn
037: Meckenheimer Allee 166
038: 53115 Bonn
039: Germany
040: E-Mail: greve@giub.uni-bonn.de
041:
042: ---------------------------------------------------------------------------*/
043: package org.deegree.processing.raster.interpolation;
044:
045: import java.util.ArrayList;
046: import java.util.Collections;
047: import java.util.List;
048:
049: import org.deegree.datatypes.values.Interval;
050: import org.deegree.datatypes.values.Values;
051: import org.deegree.io.quadtree.IndexException;
052: import org.deegree.io.quadtree.Quadtree;
053: import org.deegree.model.spatialschema.Envelope;
054: import org.deegree.model.spatialschema.GeometryFactory;
055:
056: /**
057: * Class for interpolating a set of data tuples (x, y, value) onto
058: * a grid using Inverse Distance to Power algorithm
059: *
060: * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
061: * @author last edited by: $Author: rbezema $
062: *
063: * @version $Revision: 10609 $, $Date: 2008-03-18 01:46:37 -0700 (Tue, 18 Mar 2008) $
064: */
065: public class InverseDistanceToPower extends Interpolation {
066:
067: private double power = 2;
068:
069: /**
070: *
071: * @param data
072: * @param power
073: */
074: public InverseDistanceToPower(Quadtree<?> data, double power) {
075: super (data);
076: this .power = power;
077: }
078:
079: /**
080: *
081: * @param data
082: * @param ignoreValues
083: * @param power
084: */
085: public InverseDistanceToPower(Quadtree<?> data,
086: Values ignoreValues, double power) {
087: super (data, ignoreValues);
088: this .power = power;
089: }
090:
091: /**
092: *
093: * @param data
094: * @param ignoreValues
095: * @param searchRadius1
096: * @param searchRadius2
097: * @param searchRadiusAngle
098: * @param minData
099: * @param maxData
100: * @param noValue
101: * @param autoincreaseSearchRadius1
102: * @param autoincreaseSearchRadius2
103: * @param power
104: */
105: public InverseDistanceToPower(Quadtree<?> data,
106: Values ignoreValues, double searchRadius1,
107: double searchRadius2, double searchRadiusAngle,
108: int minData, int maxData, double noValue,
109: double autoincreaseSearchRadius1,
110: double autoincreaseSearchRadius2, double power) {
111: super (data, ignoreValues, searchRadius1, searchRadius2,
112: searchRadiusAngle, minData, maxData, noValue,
113: autoincreaseSearchRadius1, autoincreaseSearchRadius2);
114: this .power = power;
115: }
116:
117: /**
118: * calculates the interpolated value for a position defined by x and y
119: *
120: * @param x
121: * @param y
122: * @return the interpolated value
123: * @throws InterpolationException
124: */
125: @Override
126: public double calcInterpolatedValue(double x, double y,
127: double searchRadius1, double searchRadius2)
128: throws InterpolationException {
129: double tmpSR1 = searchRadius1;
130: double tmpSR2 = searchRadius2;
131:
132: try {
133: Envelope searchRadius = GeometryFactory.createEnvelope(x
134: - tmpSR1, y - tmpSR2, x + tmpSR1, y + tmpSR2, null);
135: List<?> foundValues = data.query(searchRadius);
136:
137: List<DataTuple> values = new ArrayList<DataTuple>();
138: for (Object obj : foundValues) {
139: DataTuple tuple = (DataTuple) obj;
140:
141: boolean ignore = false;
142:
143: if (ignoreValues != null
144: && ignoreValues.getInterval().length > 0) {
145: for (Interval interval : ignoreValues.getInterval()) {
146: double min = Double.parseDouble(interval
147: .getMin().getValue());
148: double max = Double.parseDouble(interval
149: .getMax().getValue());
150: if (tuple.value > min && tuple.value < max) {
151: ignore = true;
152: }
153: }
154: }
155:
156: if (!ignore) {
157: double dx = Math.abs(tuple.x - x);
158: double dy = Math.abs(tuple.y - y);
159: /*
160: if ( dx == 0 && dy == 0 ) {
161: // System.out.println( "Call with already existing value!" );
162: return tuple.value;
163: }
164: */
165: double dist = Math.sqrt(dx * dx + dy * dy);
166: double weight = Math.pow(dist, power);
167: values
168: .add(new DataTuple(dist, tuple.value,
169: weight));
170: }
171: }
172:
173: if (values.size() < minData) {
174: if (autoincreaseSearchRadius1 == 0
175: && autoincreaseSearchRadius2 == 0) {
176: return noValue;
177: }
178:
179: tmpSR1 += autoincreaseSearchRadius1;
180: tmpSR2 += autoincreaseSearchRadius2;
181: //System.out.print( " Increasing the search radius to " + tmpSR1 + " and " + tmpSR2 +"\r" );
182: return calcInterpolatedValue(x, y, tmpSR1, tmpSR2);
183: }
184:
185: if (values.size() > maxData) {
186: Collections.sort(values);
187: values = values.subList(0, maxData);
188: }
189:
190: double valueSum = 0;
191:
192: double weightSum = 0;
193:
194: for (Object obj : values) {
195: // in the data tuple, x is interpreted as the distance, y is the value and
196: // "value" is the weight
197: DataTuple tuple = (DataTuple) obj;
198: valueSum += (tuple.y / tuple.value);
199: weightSum += (1 / tuple.value);
200: }
201:
202: double result = (valueSum / weightSum);
203:
204: if (Double.isInfinite(result)) {
205: return noValue;
206: }
207:
208: if (Double.isNaN(result)) {
209: return noValue;
210: }
211:
212: return result;
213: } catch (IndexException e) {
214: throw new InterpolationException(e);
215: }
216: }
217: }
|