001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/processing/raster/interpolation/InverseDistanceToPower.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.util.ArrayList; 039 import java.util.Collections; 040 import java.util.List; 041 042 import org.deegree.datatypes.values.Interval; 043 import org.deegree.datatypes.values.Values; 044 import org.deegree.io.quadtree.IndexException; 045 import org.deegree.io.quadtree.Quadtree; 046 import org.deegree.model.spatialschema.Envelope; 047 import org.deegree.model.spatialschema.GeometryFactory; 048 049 /** 050 * Class for interpolating a set of data tuples (x, y, value) onto a grid using Inverse Distance to 051 * Power algorithm 052 * 053 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 054 * @author last edited by: $Author: mschneider $ 055 * 056 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 057 */ 058 public class InverseDistanceToPower extends Interpolation { 059 060 private double power = 2; 061 062 /** 063 * 064 * @param data 065 * @param power 066 */ 067 public InverseDistanceToPower( Quadtree<?> data, double power ) { 068 super( data ); 069 this.power = power; 070 } 071 072 /** 073 * 074 * @param data 075 * @param ignoreValues 076 * @param power 077 */ 078 public InverseDistanceToPower( Quadtree<?> data, Values ignoreValues, double power ) { 079 super( data, ignoreValues ); 080 this.power = power; 081 } 082 083 /** 084 * 085 * @param data 086 * @param ignoreValues 087 * @param searchRadius1 088 * @param searchRadius2 089 * @param searchRadiusAngle 090 * @param minData 091 * @param maxData 092 * @param noValue 093 * @param autoincreaseSearchRadius1 094 * @param autoincreaseSearchRadius2 095 * @param power 096 */ 097 public InverseDistanceToPower( Quadtree<?> data, Values ignoreValues, double searchRadius1, double searchRadius2, 098 double searchRadiusAngle, int minData, int maxData, double noValue, 099 double autoincreaseSearchRadius1, double autoincreaseSearchRadius2, double power ) { 100 super( data, ignoreValues, searchRadius1, searchRadius2, searchRadiusAngle, minData, maxData, noValue, 101 autoincreaseSearchRadius1, autoincreaseSearchRadius2 ); 102 this.power = power; 103 } 104 105 /** 106 * calculates the interpolated value for a position defined by x and y 107 * 108 * @param x 109 * @param y 110 * @return the interpolated value 111 * @throws InterpolationException 112 */ 113 @Override 114 public double calcInterpolatedValue( double x, double y, double searchRadius1, double searchRadius2 ) 115 throws InterpolationException { 116 double tmpSR1 = searchRadius1; 117 double tmpSR2 = searchRadius2; 118 119 try { 120 Envelope searchRadius = GeometryFactory.createEnvelope( x - tmpSR1, y - tmpSR2, x + tmpSR1, y + tmpSR2, 121 null ); 122 List<?> foundValues = data.query( searchRadius ); 123 124 List<DataTuple> values = new ArrayList<DataTuple>(); 125 for ( Object obj : foundValues ) { 126 DataTuple tuple = (DataTuple) obj; 127 128 boolean ignore = false; 129 130 if ( ignoreValues != null && ignoreValues.getInterval().length > 0 ) { 131 for ( Interval interval : ignoreValues.getInterval() ) { 132 double min = Double.parseDouble( interval.getMin().getValue() ); 133 double max = Double.parseDouble( interval.getMax().getValue() ); 134 if ( tuple.value > min && tuple.value < max ) { 135 ignore = true; 136 } 137 } 138 } 139 140 if ( !ignore ) { 141 double dx = Math.abs( tuple.x - x ); 142 double dy = Math.abs( tuple.y - y ); 143 /* 144 * if ( dx == 0 && dy == 0 ) { // System.out.println( "Call with already 145 * existing value!" ); return tuple.value; } 146 */ 147 double dist = Math.sqrt( dx * dx + dy * dy ); 148 double weight = Math.pow( dist, power ); 149 values.add( new DataTuple( dist, tuple.value, weight ) ); 150 } 151 } 152 153 if ( values.size() < minData ) { 154 if ( autoincreaseSearchRadius1 == 0 && autoincreaseSearchRadius2 == 0 ) { 155 return noValue; 156 } 157 158 tmpSR1 += autoincreaseSearchRadius1; 159 tmpSR2 += autoincreaseSearchRadius2; 160 // System.out.print( " Increasing the search radius to " + tmpSR1 + " and " + tmpSR2 161 // +"\r" ); 162 return calcInterpolatedValue( x, y, tmpSR1, tmpSR2 ); 163 } 164 165 if ( values.size() > maxData ) { 166 Collections.sort( values ); 167 values = values.subList( 0, maxData ); 168 } 169 170 double valueSum = 0; 171 172 double weightSum = 0; 173 174 for ( Object obj : values ) { 175 // in the data tuple, x is interpreted as the distance, y is the value and 176 // "value" is the weight 177 DataTuple tuple = (DataTuple) obj; 178 valueSum += ( tuple.y / tuple.value ); 179 weightSum += ( 1 / tuple.value ); 180 } 181 182 double result = ( valueSum / weightSum ); 183 184 if ( Double.isInfinite( result ) ) { 185 return noValue; 186 } 187 188 if ( Double.isNaN( result ) ) { 189 return noValue; 190 } 191 192 return result; 193 } catch ( IndexException e ) { 194 throw new InterpolationException( e ); 195 } 196 } 197 }