LCOV - code coverage report
Current view: directory - alg - gdalgrid.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 368 47 12.8 %
Date: 2010-01-09 Functions: 11 2 18.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalgrid.cpp 18041 2009-11-17 14:14:43Z dron $
       3                 :  *
       4                 :  * Project:  GDAL Gridding API.
       5                 :  * Purpose:  Implementation of GDAL scattered data gridder.
       6                 :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2007, Andrey Kiselev <dron@ak4719.spb.edu>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "cpl_vsi.h"
      31                 : #include "gdalgrid.h"
      32                 : 
      33                 : CPL_CVSID("$Id: gdalgrid.cpp 18041 2009-11-17 14:14:43Z dron $");
      34                 : 
      35                 : #define TO_RADIANS (3.14159265358979323846 / 180.0)
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                   GDALGridInverseDistanceToAPower()                  */
      39                 : /************************************************************************/
      40                 : 
      41                 : /**
      42                 :  * Inverse distance to a power.
      43                 :  *
      44                 :  * The Inverse Distance to a Power gridding method is a weighted average
      45                 :  * interpolator. You should supply the input arrays with the scattered data
      46                 :  * values including coordinates of every data point and output grid geometry.
      47                 :  * The function will compute interpolated value for the given position in
      48                 :  * output grid.
      49                 :  *
      50                 :  * For every grid node the resulting value \f$Z\f$ will be calculated using
      51                 :  * formula:
      52                 :  *
      53                 :  * \f[
      54                 :  *      Z=\frac{\sum_{i=1}^n{\frac{Z_i}{r_i^p}}}{\sum_{i=1}^n{\frac{1}{r_i^p}}}
      55                 :  * \f]
      56                 :  *
      57                 :  *  where 
      58                 :  *  <ul>
      59                 :  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
      60                 :  *      <li> \f$r_i\f$ is an Euclidean distance from the grid node
      61                 :  *           to point \f$i\f$,
      62                 :  *      <li> \f$p\f$ is a weighting power,
      63                 :  *      <li> \f$n\f$ is a total number of points in search ellipse.
      64                 :  *  </ul>
      65                 :  *
      66                 :  *  In this method the weighting factor \f$w\f$ is
      67                 :  *
      68                 :  *  \f[
      69                 :  *      w=\frac{1}{r^p}
      70                 :  *  \f]
      71                 :  *
      72                 :  * @param poOptions Algorithm parameters. This should point to
      73                 :  * GDALGridInverseDistanceToAPowerOptions object. 
      74                 :  * @param nPoints Number of elements in input arrays.
      75                 :  * @param padfX Input array of X coordinates. 
      76                 :  * @param padfY Input array of Y coordinates. 
      77                 :  * @param padfZ Input array of Z values. 
      78                 :  * @param dfXPoint X coordinate of the point to compute.
      79                 :  * @param dfYPoint Y coordinate of the point to compute.
      80                 :  * @param nXPoint X position of the point to compute.  
      81                 :  * @param nYPoint Y position of the point to compute.
      82                 :  * @param pdfValue Pointer to variable where the computed grid node value
      83                 :  * will be returned.
      84                 :  *
      85                 :  * @return CE_None on success or CE_Failure if something goes wrong.
      86                 :  */
      87                 : 
      88                 : CPLErr
      89               0 : GDALGridInverseDistanceToAPower( const void *poOptions, GUInt32 nPoints,
      90                 :                                  const double *padfX, const double *padfY,
      91                 :                                  const double *padfZ,
      92                 :                                  double dfXPoint, double dfYPoint,
      93                 :                                  double *pdfValue )
      94                 : {
      95                 :     // TODO: For optimization purposes pre-computed parameters should be moved
      96                 :     // out of this routine to the calling function.
      97                 : 
      98                 :     // Pre-compute search ellipse parameters
      99                 :     double      dfRadius1 =
     100               0 :         ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfRadius1;
     101                 :     double      dfRadius2 =
     102               0 :         ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfRadius2;
     103                 :     double  dfR12;
     104                 : 
     105               0 :     dfRadius1 *= dfRadius1;
     106               0 :     dfRadius2 *= dfRadius2;
     107               0 :     dfR12 = dfRadius1 * dfRadius2;
     108                 : 
     109                 :     // Compute coefficients for coordinate system rotation.
     110               0 :     double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
     111                 :     const double dfAngle = TO_RADIANS
     112               0 :         * ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfAngle;
     113               0 :     const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
     114               0 :     if ( bRotated )
     115                 :     {
     116               0 :         dfCoeff1 = cos(dfAngle);
     117               0 :         dfCoeff2 = sin(dfAngle);
     118                 :     }
     119                 : 
     120                 :     const double    dfPower =
     121               0 :         ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfPower;
     122                 :     const double    dfSmoothing =
     123               0 :         ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfSmoothing;
     124                 :     const GUInt32   nMaxPoints = 
     125               0 :         ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->nMaxPoints;
     126               0 :     double  dfNominator = 0.0, dfDenominator = 0.0;
     127               0 :     GUInt32 i, n = 0;
     128                 : 
     129               0 :     for ( i = 0; i < nPoints; i++ )
     130                 :     {
     131               0 :         double  dfRX = padfX[i] - dfXPoint;
     132               0 :         double  dfRY = padfY[i] - dfYPoint;
     133                 :         const double dfR2 =
     134               0 :             dfRX * dfRX + dfRY * dfRY + dfSmoothing * dfSmoothing;
     135                 : 
     136               0 :         if ( bRotated )
     137                 :         {
     138               0 :             double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
     139               0 :             double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
     140                 : 
     141               0 :             dfRX = dfRXRotated;
     142               0 :             dfRY = dfRYRotated;
     143                 :         }
     144                 : 
     145                 :         // Is this point located inside the search ellipse?
     146               0 :         if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
     147                 :         {
     148               0 :             if ( CPLIsEqual(dfR2, 0.0) )
     149                 :             {
     150               0 :                 (*pdfValue) = padfZ[i];
     151               0 :                 return CE_None;
     152                 :             }
     153                 :             else
     154                 :             {
     155               0 :                 const double  dfW = pow( sqrt(dfR2), dfPower );
     156               0 :                 dfNominator += padfZ[i] / dfW;
     157               0 :                 dfDenominator += 1.0 / dfW;
     158               0 :                 n++;
     159               0 :                 if ( nMaxPoints > 0 && n > nMaxPoints )
     160               0 :                     break;
     161                 :             }
     162                 :         }
     163                 :     }
     164                 : 
     165               0 :     if ( n < ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->nMinPoints
     166                 :          || dfDenominator == 0.0 )
     167                 :     {
     168                 :         (*pdfValue) =
     169               0 :             ((GDALGridInverseDistanceToAPowerOptions*)poOptions)->dfNoDataValue;
     170                 :     }
     171                 :     else
     172               0 :         (*pdfValue) = dfNominator / dfDenominator;
     173                 : 
     174               0 :     return CE_None;
     175                 : }
     176                 : 
     177                 : /************************************************************************/
     178                 : /*              GDALGridInverseDistanceToAPowerNoSearch()               */
     179                 : /************************************************************************/
     180                 : 
     181                 : /**
     182                 :  * Inverse distance to a power for whole data set.
     183                 :  *
     184                 :  * This is somewhat optimized version of the Inverse Distance to a Power
     185                 :  * method. It is used when the search ellips is not set. The algorithm and
     186                 :  * parameters are the same as in GDALGridInverseDistanceToAPower(), but this
     187                 :  * implementation works faster, because of no search.
     188                 :  *
     189                 :  * @see GDALGridInverseDistanceToAPower()
     190                 :  */
     191                 : 
     192                 : CPLErr
     193               0 : GDALGridInverseDistanceToAPowerNoSearch( const void *poOptions, GUInt32 nPoints,
     194                 :                                          const double *padfX, const double *padfY,
     195                 :                                          const double *padfZ,
     196                 :                                          double dfXPoint, double dfYPoint,
     197                 :                                          double *pdfValue )
     198                 : {
     199                 :     const double    dfPower =
     200               0 :         ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfPower;
     201                 :     const double    dfSmoothing =
     202               0 :         ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfSmoothing;
     203               0 :     double  dfNominator = 0.0, dfDenominator = 0.0;
     204                 :     GUInt32 i;
     205                 : 
     206               0 :     for ( i = 0; i < nPoints; i++ )
     207                 :     {
     208               0 :         const double dfRX = padfX[i] - dfXPoint;
     209               0 :         const double dfRY = padfY[i] - dfYPoint;
     210                 :         const double dfR2 =
     211               0 :             dfRX * dfRX + dfRY * dfRY + dfSmoothing * dfSmoothing;
     212                 : 
     213               0 :         if ( CPLIsEqual(dfR2, 0.0) )
     214                 :         {
     215               0 :             (*pdfValue) = padfZ[i];
     216               0 :             return CE_None;
     217                 :         }
     218                 :         else
     219                 :         {
     220               0 :             const double dfW = pow( sqrt(dfR2), dfPower );
     221               0 :             dfNominator += padfZ[i] / dfW;
     222               0 :             dfDenominator += 1.0 / dfW;
     223                 :         }
     224                 :     }
     225                 : 
     226               0 :     if ( dfDenominator == 0.0 )
     227                 :     {
     228                 :         (*pdfValue) =
     229               0 :             ((GDALGridInverseDistanceToAPowerOptions*)poOptions)->dfNoDataValue;
     230                 :     }
     231                 :     else
     232               0 :         (*pdfValue) = dfNominator / dfDenominator;
     233                 : 
     234               0 :     return CE_None;
     235                 : }
     236                 : /************************************************************************/
     237                 : /*                        GDALGridMovingAverage()                       */
     238                 : /************************************************************************/
     239                 : 
     240                 : /**
     241                 :  * Moving average.
     242                 :  *
     243                 :  * The Moving Average is a simple data averaging algorithm. It uses a moving
     244                 :  * window of elliptic form to search values and averages all data points
     245                 :  * within the window. Search ellipse can be rotated by specified angle, the
     246                 :  * center of ellipse located at the grid node. Also the minimum number of data
     247                 :  * points to average can be set, if there are not enough points in window, the
     248                 :  * grid node considered empty and will be filled with specified NODATA value.
     249                 :  *
     250                 :  * Mathematically it can be expressed with the formula:
     251                 :  *
     252                 :  * \f[
     253                 :  *      Z=\frac{\sum_{i=1}^n{Z_i}}{n}
     254                 :  * \f]
     255                 :  *
     256                 :  *  where 
     257                 :  *  <ul>
     258                 :  *      <li> \f$Z\f$ is a resulting value at the grid node,
     259                 :  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
     260                 :  *      <li> \f$n\f$ is a total number of points in search ellipse.
     261                 :  *  </ul>
     262                 :  *
     263                 :  * @param poOptions Algorithm parameters. This should point to
     264                 :  * GDALGridMovingAverageOptions object. 
     265                 :  * @param nPoints Number of elements in input arrays.
     266                 :  * @param padfX Input array of X coordinates. 
     267                 :  * @param padfY Input array of Y coordinates. 
     268                 :  * @param padfZ Input array of Z values. 
     269                 :  * @param dfXPoint X coordinate of the point to compute.
     270                 :  * @param dfYPoint Y coordinate of the point to compute.
     271                 :  * @param pdfValue Pointer to variable where the computed grid node value
     272                 :  * will be returned.
     273                 :  *
     274                 :  * @return CE_None on success or CE_Failure if something goes wrong.
     275                 :  */
     276                 : 
     277                 : CPLErr
     278               0 : GDALGridMovingAverage( const void *poOptions, GUInt32 nPoints,
     279                 :                        const double *padfX, const double *padfY,
     280                 :                        const double *padfZ,
     281                 :                        double dfXPoint, double dfYPoint, double *pdfValue )
     282                 : {
     283                 :     // TODO: For optimization purposes pre-computed parameters should be moved
     284                 :     // out of this routine to the calling function.
     285                 : 
     286                 :     // Pre-compute search ellipse parameters
     287               0 :     double  dfRadius1 = ((GDALGridMovingAverageOptions *)poOptions)->dfRadius1;
     288               0 :     double  dfRadius2 = ((GDALGridMovingAverageOptions *)poOptions)->dfRadius2;
     289                 :     double  dfR12;
     290                 : 
     291               0 :     dfRadius1 *= dfRadius1;
     292               0 :     dfRadius2 *= dfRadius2;
     293               0 :     dfR12 = dfRadius1 * dfRadius2;
     294                 : 
     295                 :     // Compute coefficients for coordinate system rotation.
     296               0 :     double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
     297                 :     const double    dfAngle =
     298               0 :         TO_RADIANS * ((GDALGridMovingAverageOptions *)poOptions)->dfAngle;
     299               0 :     const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
     300               0 :     if ( bRotated )
     301                 :     {
     302               0 :         dfCoeff1 = cos(dfAngle);
     303               0 :         dfCoeff2 = sin(dfAngle);
     304                 :     }
     305                 : 
     306               0 :     double  dfAccumulator = 0.0;
     307               0 :     GUInt32 i = 0, n = 0;
     308                 : 
     309               0 :     while ( i < nPoints )
     310                 :     {
     311               0 :         double  dfRX = padfX[i] - dfXPoint;
     312               0 :         double  dfRY = padfY[i] - dfYPoint;
     313                 : 
     314               0 :         if ( bRotated )
     315                 :         {
     316               0 :             double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
     317               0 :             double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
     318                 : 
     319               0 :             dfRX = dfRXRotated;
     320               0 :             dfRY = dfRYRotated;
     321                 :         }
     322                 : 
     323                 :         // Is this point located inside the search ellipse?
     324               0 :         if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
     325                 :         {
     326               0 :             dfAccumulator += padfZ[i];
     327               0 :             n++;
     328                 :         }
     329                 : 
     330               0 :         i++;
     331                 :     }
     332                 : 
     333               0 :     if ( n < ((GDALGridMovingAverageOptions *)poOptions)->nMinPoints
     334                 :          || n == 0 )
     335                 :     {
     336                 :         (*pdfValue) =
     337               0 :             ((GDALGridMovingAverageOptions *)poOptions)->dfNoDataValue;
     338                 :     }
     339                 :     else
     340               0 :         (*pdfValue) = dfAccumulator / n;
     341                 : 
     342               0 :     return CE_None;
     343                 : }
     344                 : 
     345                 : /************************************************************************/
     346                 : /*                        GDALGridNearestNeighbor()                     */
     347                 : /************************************************************************/
     348                 : 
     349                 : /**
     350                 :  * Nearest neighbor.
     351                 :  *
     352                 :  * The Nearest Neighbor method doesn't perform any interpolation or smoothing,
     353                 :  * it just takes the value of nearest point found in grid node search ellipse
     354                 :  * and returns it as a result. If there are no points found, the specified
     355                 :  * NODATA value will be returned.
     356                 :  *
     357                 :  * @param poOptions Algorithm parameters. This should point to
     358                 :  * GDALGridNearestNeighborOptions object. 
     359                 :  * @param nPoints Number of elements in input arrays.
     360                 :  * @param padfX Input array of X coordinates. 
     361                 :  * @param padfY Input array of Y coordinates. 
     362                 :  * @param padfZ Input array of Z values. 
     363                 :  * @param dfXPoint X coordinate of the point to compute.
     364                 :  * @param dfYPoint Y coordinate of the point to compute.
     365                 :  * @param pdfValue Pointer to variable where the computed grid node value
     366                 :  * will be returned.
     367                 :  *
     368                 :  * @return CE_None on success or CE_Failure if something goes wrong.
     369                 :  */
     370                 : 
     371                 : CPLErr
     372           14641 : GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
     373                 :                          const double *padfX, const double *padfY,
     374                 :                          const double *padfZ,
     375                 :                          double dfXPoint, double dfYPoint, double *pdfValue )
     376                 : {
     377                 :     // TODO: For optimization purposes pre-computed parameters should be moved
     378                 :     // out of this routine to the calling function.
     379                 : 
     380                 :     // Pre-compute search ellipse parameters
     381                 :     double  dfRadius1 =
     382           14641 :         ((GDALGridNearestNeighborOptions *)poOptions)->dfRadius1;
     383                 :     double  dfRadius2 =
     384           14641 :         ((GDALGridNearestNeighborOptions *)poOptions)->dfRadius2;
     385                 :     double  dfR12;
     386                 : 
     387           14641 :     dfRadius1 *= dfRadius1;
     388           14641 :     dfRadius2 *= dfRadius2;
     389           14641 :     dfR12 = dfRadius1 * dfRadius2;
     390                 : 
     391                 :     // Compute coefficients for coordinate system rotation.
     392           14641 :     double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
     393                 :     const double    dfAngle =
     394           14641 :         TO_RADIANS * ((GDALGridNearestNeighborOptions *)poOptions)->dfAngle;
     395           14641 :     const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
     396           14641 :     if ( bRotated )
     397                 :     {
     398               0 :         dfCoeff1 = cos(dfAngle);
     399               0 :         dfCoeff2 = sin(dfAngle);
     400                 :     }
     401                 : 
     402                 :     // If the nearest point will not be found, its value remains as NODATA.
     403                 :     double      dfNearestValue =
     404           14641 :         ((GDALGridNearestNeighborOptions *)poOptions)->dfNoDataValue;
     405                 :     // Nearest distance will be initialized with a largest ellipse semi-axis.
     406                 :     // All nearest points should be located in this range.
     407           14641 :     double      dfNearestR = MAX(dfRadius1, dfRadius2);
     408           14641 :     GUInt32 i = 0;
     409                 : 
     410       214388163 :     while ( i < nPoints )
     411                 :     {
     412       214358881 :         double  dfRX = padfX[i] - dfXPoint;
     413       214358881 :         double  dfRY = padfY[i] - dfYPoint;
     414                 : 
     415       214358881 :         if ( bRotated )
     416                 :         {
     417               0 :             double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
     418               0 :             double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
     419                 : 
     420               0 :             dfRX = dfRXRotated;
     421               0 :             dfRY = dfRYRotated;
     422                 :         }
     423                 : 
     424                 :         // Is this point located inside the search ellipse?
     425       214358881 :         if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
     426                 :         {
     427       214358881 :             const double    dfR2 = dfRX * dfRX + dfRY * dfRY;
     428       214358881 :             if ( dfNearestR == 0.0 || dfR2 < dfNearestR )
     429                 :             {
     430         8305158 :                 dfNearestR = dfR2;
     431         8305158 :                 dfNearestValue = padfZ[i];
     432                 :             }
     433                 :         }
     434                 : 
     435       214358881 :         i++;
     436                 :     }
     437                 : 
     438           14641 :     (*pdfValue) = dfNearestValue;
     439                 : 
     440           14641 :     return CE_None;
     441                 : }
     442                 : 
     443                 : /************************************************************************/
     444                 : /*                      GDALGridDataMetricMinimum()                     */
     445                 : /************************************************************************/
     446                 : 
     447                 : /**
     448                 :  * Minimum data value (data metric).
     449                 :  *
     450                 :  * Minimum value found in grid node search ellipse. If there are no points
     451                 :  * found, the specified NODATA value will be returned.
     452                 :  *
     453                 :  * \f[
     454                 :  *      Z=\min{(Z_1,Z_2,\ldots,Z_n)}
     455                 :  * \f]
     456                 :  *
     457                 :  *  where 
     458                 :  *  <ul>
     459                 :  *      <li> \f$Z\f$ is a resulting value at the grid node,
     460                 :  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
     461                 :  *      <li> \f$n\f$ is a total number of points in search ellipse.
     462                 :  *  </ul>
     463                 :  *
     464                 :  * @param poOptions Algorithm parameters. This should point to
     465                 :  * GDALGridDataMetricsOptions object. 
     466                 :  * @param nPoints Number of elements in input arrays.
     467                 :  * @param padfX Input array of X coordinates. 
     468                 :  * @param padfY Input array of Y coordinates. 
     469                 :  * @param padfZ Input array of Z values. 
     470                 :  * @param dfXPoint X coordinate of the point to compute.
     471                 :  * @param dfYPoint Y coordinate of the point to compute.
     472                 :  * @param pdfValue Pointer to variable where the computed grid node value
     473                 :  * will be returned.
     474                 :  *
     475                 :  * @return CE_None on success or CE_Failure if something goes wrong.
     476                 :  */
     477                 : 
     478                 : CPLErr
     479               0 : GDALGridDataMetricMinimum( const void *poOptions, GUInt32 nPoints,
     480                 :                            const double *padfX, const double *padfY,
     481                 :                            const double *padfZ,
     482                 :                            double dfXPoint, double dfYPoint, double *pdfValue )
     483                 : {
     484                 :     // TODO: For optimization purposes pre-computed parameters should be moved
     485                 :     // out of this routine to the calling function.
     486                 : 
     487                 :     // Pre-compute search ellipse parameters
     488                 :     double  dfRadius1 =
     489               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
     490                 :     double  dfRadius2 =
     491               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
     492                 :     double  dfR12;
     493                 : 
     494               0 :     dfRadius1 *= dfRadius1;
     495               0 :     dfRadius2 *= dfRadius2;
     496               0 :     dfR12 = dfRadius1 * dfRadius2;
     497                 : 
     498                 :     // Compute coefficients for coordinate system rotation.
     499               0 :     double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
     500                 :     const double dfAngle =
     501               0 :         TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
     502               0 :     const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
     503               0 :     if ( bRotated )
     504                 :     {
     505               0 :         dfCoeff1 = cos(dfAngle);
     506               0 :         dfCoeff2 = sin(dfAngle);
     507                 :     }
     508                 : 
     509               0 :     double      dfMinimumValue=0.0;
     510               0 :     GUInt32     i = 0, n = 0;
     511                 : 
     512               0 :     while ( i < nPoints )
     513                 :     {
     514               0 :         double  dfRX = padfX[i] - dfXPoint;
     515               0 :         double  dfRY = padfY[i] - dfYPoint;
     516                 : 
     517               0 :         if ( bRotated )
     518                 :         {
     519               0 :             double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
     520               0 :             double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
     521                 : 
     522               0 :             dfRX = dfRXRotated;
     523               0 :             dfRY = dfRYRotated;
     524                 :         }
     525                 : 
     526                 :         // Is this point located inside the search ellipse?
     527               0 :         if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
     528                 :         {
     529               0 :             if ( n )
     530                 :             {
     531               0 :                 if ( dfMinimumValue > padfZ[i] )
     532               0 :                     dfMinimumValue = padfZ[i];
     533                 :             }
     534                 :             else
     535               0 :                 dfMinimumValue = padfZ[i];
     536               0 :             n++;
     537                 :         }
     538                 : 
     539               0 :         i++;
     540                 :     }
     541                 : 
     542               0 :     if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints
     543                 :          || n == 0 )
     544                 :     {
     545                 :         (*pdfValue) =
     546               0 :             ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
     547                 :     }
     548                 :     else
     549               0 :         (*pdfValue) = dfMinimumValue;
     550                 : 
     551               0 :     return CE_None;
     552                 : }
     553                 : 
     554                 : /************************************************************************/
     555                 : /*                      GDALGridDataMetricMaximum()                     */
     556                 : /************************************************************************/
     557                 : 
     558                 : /**
     559                 :  * Maximum data value (data metric).
     560                 :  *
     561                 :  * Maximum value found in grid node search ellipse. If there are no points
     562                 :  * found, the specified NODATA value will be returned.
     563                 :  *
     564                 :  * \f[
     565                 :  *      Z=\max{(Z_1,Z_2,\ldots,Z_n)}
     566                 :  * \f]
     567                 :  *
     568                 :  *  where 
     569                 :  *  <ul>
     570                 :  *      <li> \f$Z\f$ is a resulting value at the grid node,
     571                 :  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
     572                 :  *      <li> \f$n\f$ is a total number of points in search ellipse.
     573                 :  *  </ul>
     574                 :  *
     575                 :  * @param poOptions Algorithm parameters. This should point to
     576                 :  * GDALGridDataMetricsOptions object. 
     577                 :  * @param nPoints Number of elements in input arrays.
     578                 :  * @param padfX Input array of X coordinates. 
     579                 :  * @param padfY Input array of Y coordinates. 
     580                 :  * @param padfZ Input array of Z values. 
     581                 :  * @param dfXPoint X coordinate of the point to compute.
     582                 :  * @param dfYPoint Y coordinate of the point to compute.
     583                 :  * @param pdfValue Pointer to variable where the computed grid node value
     584                 :  * will be returned.
     585                 :  *
     586                 :  * @return CE_None on success or CE_Failure if something goes wrong.
     587                 :  */
     588                 : 
     589                 : CPLErr
     590               0 : GDALGridDataMetricMaximum( const void *poOptions, GUInt32 nPoints,
     591                 :                            const double *padfX, const double *padfY,
     592                 :                            const double *padfZ,
     593                 :                            double dfXPoint, double dfYPoint, double *pdfValue )
     594                 : {
     595                 :     // TODO: For optimization purposes pre-computed parameters should be moved
     596                 :     // out of this routine to the calling function.
     597                 : 
     598                 :     // Pre-compute search ellipse parameters
     599                 :     double  dfRadius1 =
     600               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
     601                 :     double  dfRadius2 =
     602               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
     603                 :     double  dfR12;
     604                 : 
     605               0 :     dfRadius1 *= dfRadius1;
     606               0 :     dfRadius2 *= dfRadius2;
     607               0 :     dfR12 = dfRadius1 * dfRadius2;
     608                 : 
     609                 :     // Compute coefficients for coordinate system rotation.
     610               0 :     double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
     611                 :     const double    dfAngle =
     612               0 :         TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
     613               0 :     const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
     614               0 :     if ( bRotated )
     615                 :     {
     616               0 :         dfCoeff1 = cos(dfAngle);
     617               0 :         dfCoeff2 = sin(dfAngle);
     618                 :     }
     619                 : 
     620               0 :     double      dfMaximumValue=0.0;
     621               0 :     GUInt32     i = 0, n = 0;
     622                 : 
     623               0 :     while ( i < nPoints )
     624                 :     {
     625               0 :         double  dfRX = padfX[i] - dfXPoint;
     626               0 :         double  dfRY = padfY[i] - dfYPoint;
     627                 : 
     628               0 :         if ( bRotated )
     629                 :         {
     630               0 :             double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
     631               0 :             double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
     632                 : 
     633               0 :             dfRX = dfRXRotated;
     634               0 :             dfRY = dfRYRotated;
     635                 :         }
     636                 : 
     637                 :         // Is this point located inside the search ellipse?
     638               0 :         if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
     639                 :         {
     640               0 :             if ( n )
     641                 :             {
     642               0 :                 if ( dfMaximumValue < padfZ[i] )
     643               0 :                     dfMaximumValue = padfZ[i];
     644                 :             }
     645                 :             else
     646               0 :                 dfMaximumValue = padfZ[i];
     647               0 :             n++;
     648                 :         }
     649                 : 
     650               0 :         i++;
     651                 :     }
     652                 : 
     653               0 :     if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints
     654                 :          || n == 0 )
     655                 :     {
     656                 :         (*pdfValue) =
     657               0 :             ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
     658                 :     }
     659                 :     else
     660               0 :         (*pdfValue) = dfMaximumValue;
     661                 : 
     662               0 :     return CE_None;
     663                 : }
     664                 : 
     665                 : /************************************************************************/
     666                 : /*                       GDALGridDataMetricRange()                      */
     667                 : /************************************************************************/
     668                 : 
     669                 : /**
     670                 :  * Data range (data metric).
     671                 :  *
     672                 :  * A difference between the minimum and maximum values found in grid node
     673                 :  * search ellipse. If there are no points found, the specified NODATA
     674                 :  * value will be returned.
     675                 :  *
     676                 :  * \f[
     677                 :  *      Z=\max{(Z_1,Z_2,\ldots,Z_n)}-\min{(Z_1,Z_2,\ldots,Z_n)}
     678                 :  * \f]
     679                 :  *
     680                 :  *  where 
     681                 :  *  <ul>
     682                 :  *      <li> \f$Z\f$ is a resulting value at the grid node,
     683                 :  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
     684                 :  *      <li> \f$n\f$ is a total number of points in search ellipse.
     685                 :  *  </ul>
     686                 :  *
     687                 :  * @param poOptions Algorithm parameters. This should point to
     688                 :  * GDALGridDataMetricsOptions object. 
     689                 :  * @param nPoints Number of elements in input arrays.
     690                 :  * @param padfX Input array of X coordinates. 
     691                 :  * @param padfY Input array of Y coordinates. 
     692                 :  * @param padfZ Input array of Z values. 
     693                 :  * @param dfXPoint X coordinate of the point to compute.
     694                 :  * @param dfYPoint Y coordinate of the point to compute.
     695                 :  * @param pdfValue Pointer to variable where the computed grid node value
     696                 :  * will be returned.
     697                 :  *
     698                 :  * @return CE_None on success or CE_Failure if something goes wrong.
     699                 :  */
     700                 : 
     701                 : CPLErr
     702               0 : GDALGridDataMetricRange( const void *poOptions, GUInt32 nPoints,
     703                 :                          const double *padfX, const double *padfY,
     704                 :                          const double *padfZ,
     705                 :                          double dfXPoint, double dfYPoint, double *pdfValue )
     706                 : {
     707                 :     // TODO: For optimization purposes pre-computed parameters should be moved
     708                 :     // out of this routine to the calling function.
     709                 : 
     710                 :     // Pre-compute search ellipse parameters
     711                 :     double  dfRadius1 =
     712               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
     713                 :     double  dfRadius2 =
     714               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
     715                 :     double  dfR12;
     716                 : 
     717               0 :     dfRadius1 *= dfRadius1;
     718               0 :     dfRadius2 *= dfRadius2;
     719               0 :     dfR12 = dfRadius1 * dfRadius2;
     720                 : 
     721                 :     // Compute coefficients for coordinate system rotation.
     722               0 :     double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
     723                 :     const double    dfAngle =
     724               0 :         TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
     725               0 :     const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
     726               0 :     if ( bRotated )
     727                 :     {
     728               0 :         dfCoeff1 = cos(dfAngle);
     729               0 :         dfCoeff2 = sin(dfAngle);
     730                 :     }
     731                 : 
     732               0 :     double      dfMaximumValue=0.0, dfMinimumValue=0.0;
     733               0 :     GUInt32     i = 0, n = 0;
     734                 : 
     735               0 :     while ( i < nPoints )
     736                 :     {
     737               0 :         double  dfRX = padfX[i] - dfXPoint;
     738               0 :         double  dfRY = padfY[i] - dfYPoint;
     739                 : 
     740               0 :         if ( bRotated )
     741                 :         {
     742               0 :             double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
     743               0 :             double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
     744                 : 
     745               0 :             dfRX = dfRXRotated;
     746               0 :             dfRY = dfRYRotated;
     747                 :         }
     748                 : 
     749                 :         // Is this point located inside the search ellipse?
     750               0 :         if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
     751                 :         {
     752               0 :             if ( n )
     753                 :             {
     754               0 :                 if ( dfMinimumValue > padfZ[i] )
     755               0 :                     dfMinimumValue = padfZ[i];
     756               0 :                 if ( dfMaximumValue < padfZ[i] )
     757               0 :                     dfMaximumValue = padfZ[i];
     758                 :             }
     759                 :             else
     760               0 :                 dfMinimumValue = dfMaximumValue = padfZ[i];
     761               0 :             n++;
     762                 :         }
     763                 : 
     764               0 :         i++;
     765                 :     }
     766                 : 
     767               0 :     if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints
     768                 :          || n == 0 )
     769                 :     {
     770                 :         (*pdfValue) =
     771               0 :             ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
     772                 :     }
     773                 :     else
     774               0 :         (*pdfValue) = dfMaximumValue - dfMinimumValue;
     775                 : 
     776               0 :     return CE_None;
     777                 : }
     778                 : 
     779                 : /************************************************************************/
     780                 : /*                       GDALGridDataMetricCount()                      */
     781                 : /************************************************************************/
     782                 : 
     783                 : /**
     784                 :  * Number of data points (data metric).
     785                 :  *
     786                 :  * A number of data points found in grid node search ellipse.
     787                 :  *
     788                 :  * \f[
     789                 :  *      Z=n
     790                 :  * \f]
     791                 :  *
     792                 :  *  where 
     793                 :  *  <ul>
     794                 :  *      <li> \f$Z\f$ is a resulting value at the grid node,
     795                 :  *      <li> \f$n\f$ is a total number of points in search ellipse.
     796                 :  *  </ul>
     797                 :  *
     798                 :  * @param poOptions Algorithm parameters. This should point to
     799                 :  * GDALGridDataMetricsOptions object. 
     800                 :  * @param nPoints Number of elements in input arrays.
     801                 :  * @param padfX Input array of X coordinates. 
     802                 :  * @param padfY Input array of Y coordinates. 
     803                 :  * @param padfZ Input array of Z values. 
     804                 :  * @param dfXPoint X coordinate of the point to compute.
     805                 :  * @param dfYPoint Y coordinate of the point to compute.
     806                 :  * @param pdfValue Pointer to variable where the computed grid node value
     807                 :  * will be returned.
     808                 :  *
     809                 :  * @return CE_None on success or CE_Failure if something goes wrong.
     810                 :  */
     811                 : 
     812                 : CPLErr
     813               0 : GDALGridDataMetricCount( const void *poOptions, GUInt32 nPoints,
     814                 :                          const double *padfX, const double *padfY,
     815                 :                          const double *padfZ,
     816                 :                          double dfXPoint, double dfYPoint, double *pdfValue )
     817                 : {
     818                 :     // TODO: For optimization purposes pre-computed parameters should be moved
     819                 :     // out of this routine to the calling function.
     820                 : 
     821                 :     // Pre-compute search ellipse parameters
     822                 :     double  dfRadius1 =
     823               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
     824                 :     double  dfRadius2 =
     825               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
     826                 :     double  dfR12;
     827                 : 
     828               0 :     dfRadius1 *= dfRadius1;
     829               0 :     dfRadius2 *= dfRadius2;
     830               0 :     dfR12 = dfRadius1 * dfRadius2;
     831                 : 
     832                 :     // Compute coefficients for coordinate system rotation.
     833               0 :     double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
     834                 :     const double    dfAngle =
     835               0 :         TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
     836               0 :     const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
     837               0 :     if ( bRotated )
     838                 :     {
     839               0 :         dfCoeff1 = cos(dfAngle);
     840               0 :         dfCoeff2 = sin(dfAngle);
     841                 :     }
     842                 : 
     843               0 :     GUInt32     i = 0, n = 0;
     844                 : 
     845               0 :     while ( i < nPoints )
     846                 :     {
     847               0 :         double  dfRX = padfX[i] - dfXPoint;
     848               0 :         double  dfRY = padfY[i] - dfYPoint;
     849                 : 
     850               0 :         if ( bRotated )
     851                 :         {
     852               0 :             double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
     853               0 :             double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
     854                 : 
     855               0 :             dfRX = dfRXRotated;
     856               0 :             dfRY = dfRYRotated;
     857                 :         }
     858                 : 
     859                 :         // Is this point located inside the search ellipse?
     860               0 :         if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
     861               0 :             n++;
     862                 : 
     863               0 :         i++;
     864                 :     }
     865                 : 
     866               0 :     if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints )
     867                 :     {
     868                 :         (*pdfValue) =
     869               0 :             ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
     870                 :     }
     871                 :     else
     872               0 :         (*pdfValue) = (double)n;
     873                 : 
     874               0 :     return CE_None;
     875                 : }
     876                 : 
     877                 : /************************************************************************/
     878                 : /*                 GDALGridDataMetricAverageDistance()                  */
     879                 : /************************************************************************/
     880                 : 
     881                 : /**
     882                 :  * Average distance (data metric).
     883                 :  *
     884                 :  * An average distance between the grid node (center of the search ellipse)
     885                 :  * and all of the data points found in grid node search ellipse. If there are
     886                 :  * no points found, the specified NODATA value will be returned.
     887                 :  *
     888                 :  * \f[
     889                 :  *      Z=\frac{\sum_{i = 1}^n r_i}{n}
     890                 :  * \f]
     891                 :  *
     892                 :  *  where 
     893                 :  *  <ul>
     894                 :  *      <li> \f$Z\f$ is a resulting value at the grid node,
     895                 :  *      <li> \f$r_i\f$ is an Euclidean distance from the grid node
     896                 :  *           to point \f$i\f$,
     897                 :  *      <li> \f$n\f$ is a total number of points in search ellipse.
     898                 :  *  </ul>
     899                 :  *
     900                 :  * @param poOptions Algorithm parameters. This should point to
     901                 :  * GDALGridDataMetricsOptions object. 
     902                 :  * @param nPoints Number of elements in input arrays.
     903                 :  * @param padfX Input array of X coordinates. 
     904                 :  * @param padfY Input array of Y coordinates. 
     905                 :  * @param padfZ Input array of Z values. 
     906                 :  * @param dfXPoint X coordinate of the point to compute.
     907                 :  * @param dfYPoint Y coordinate of the point to compute.
     908                 :  * @param pdfValue Pointer to variable where the computed grid node value
     909                 :  * will be returned.
     910                 :  *
     911                 :  * @return CE_None on success or CE_Failure if something goes wrong.
     912                 :  */
     913                 : 
     914                 : CPLErr
     915               0 : GDALGridDataMetricAverageDistance( const void *poOptions, GUInt32 nPoints,
     916                 :                                    const double *padfX, const double *padfY,
     917                 :                                    const double *padfZ,
     918                 :                                    double dfXPoint, double dfYPoint,
     919                 :                                    double *pdfValue )
     920                 : {
     921                 :     // TODO: For optimization purposes pre-computed parameters should be moved
     922                 :     // out of this routine to the calling function.
     923                 : 
     924                 :     // Pre-compute search ellipse parameters
     925                 :     double  dfRadius1 =
     926               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
     927                 :     double  dfRadius2 =
     928               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
     929                 :     double  dfR12;
     930                 : 
     931               0 :     dfRadius1 *= dfRadius1;
     932               0 :     dfRadius2 *= dfRadius2;
     933               0 :     dfR12 = dfRadius1 * dfRadius2;
     934                 : 
     935                 :     // Compute coefficients for coordinate system rotation.
     936               0 :     double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
     937                 :     const double    dfAngle =
     938               0 :         TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
     939               0 :     const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
     940               0 :     if ( bRotated )
     941                 :     {
     942               0 :         dfCoeff1 = cos(dfAngle);
     943               0 :         dfCoeff2 = sin(dfAngle);
     944                 :     }
     945                 : 
     946               0 :     double      dfAccumulator = 0.0;
     947               0 :     GUInt32     i = 0, n = 0;
     948                 : 
     949               0 :     while ( i < nPoints )
     950                 :     {
     951               0 :         double  dfRX = padfX[i] - dfXPoint;
     952               0 :         double  dfRY = padfY[i] - dfYPoint;
     953                 : 
     954               0 :         if ( bRotated )
     955                 :         {
     956               0 :             double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
     957               0 :             double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
     958                 : 
     959               0 :             dfRX = dfRXRotated;
     960               0 :             dfRY = dfRYRotated;
     961                 :         }
     962                 : 
     963                 :         // Is this point located inside the search ellipse?
     964               0 :         if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
     965                 :         {
     966               0 :             dfAccumulator += sqrt( dfRX * dfRX + dfRY * dfRY );
     967               0 :             n++;
     968                 :         }
     969                 : 
     970               0 :         i++;
     971                 :     }
     972                 : 
     973               0 :     if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints
     974                 :          || n == 0 )
     975                 :     {
     976                 :         (*pdfValue) =
     977               0 :             ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
     978                 :     }
     979                 :     else
     980               0 :         (*pdfValue) = dfAccumulator / n;
     981                 : 
     982               0 :     return CE_None;
     983                 : }
     984                 : 
     985                 : /************************************************************************/
     986                 : /*                 GDALGridDataMetricAverageDistance()                  */
     987                 : /************************************************************************/
     988                 : 
     989                 : /**
     990                 :  * Average distance between points (data metric).
     991                 :  *
     992                 :  * An average distance between the data points found in grid node search
     993                 :  * ellipse. The distance between each pair of points within ellipse is
     994                 :  * calculated and average of all distances is set as a grid node value. If
     995                 :  * there are no points found, the specified NODATA value will be returned.
     996                 : 
     997                 :  *
     998                 :  * \f[
     999                 :  *      Z=\frac{\sum_{i = 1}^{n-1}\sum_{j=i+1}^{n} r_{ij}}{\left(n-1\right)\,n-\frac{n+{\left(n-1\right)}^{2}-1}{2}}
    1000                 :  * \f]
    1001                 :  *
    1002                 :  *  where 
    1003                 :  *  <ul>
    1004                 :  *      <li> \f$Z\f$ is a resulting value at the grid node,
    1005                 :  *      <li> \f$r_{ij}\f$ is an Euclidean distance between points
    1006                 :  *           \f$i\f$ and \f$j\f$,
    1007                 :  *      <li> \f$n\f$ is a total number of points in search ellipse.
    1008                 :  *  </ul>
    1009                 :  *
    1010                 :  * @param poOptions Algorithm parameters. This should point to
    1011                 :  * GDALGridDataMetricsOptions object. 
    1012                 :  * @param nPoints Number of elements in input arrays.
    1013                 :  * @param padfX Input array of X coordinates. 
    1014                 :  * @param padfY Input array of Y coordinates. 
    1015                 :  * @param padfZ Input array of Z values. 
    1016                 :  * @param dfXPoint X coordinate of the point to compute.
    1017                 :  * @param dfYPoint Y coordinate of the point to compute.
    1018                 :  * @param pdfValue Pointer to variable where the computed grid node value
    1019                 :  * will be returned.
    1020                 :  *
    1021                 :  * @return CE_None on success or CE_Failure if something goes wrong.
    1022                 :  */
    1023                 : 
    1024                 : CPLErr
    1025               0 : GDALGridDataMetricAverageDistancePts( const void *poOptions, GUInt32 nPoints,
    1026                 :                                       const double *padfX, const double *padfY,
    1027                 :                                       const double *padfZ,
    1028                 :                                       double dfXPoint, double dfYPoint,
    1029                 :                                       double *pdfValue )
    1030                 : {
    1031                 :     // TODO: For optimization purposes pre-computed parameters should be moved
    1032                 :     // out of this routine to the calling function.
    1033                 : 
    1034                 :     // Pre-compute search ellipse parameters
    1035                 :     double  dfRadius1 =
    1036               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
    1037                 :     double  dfRadius2 =
    1038               0 :         ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
    1039                 :     double  dfR12;
    1040                 : 
    1041               0 :     dfRadius1 *= dfRadius1;
    1042               0 :     dfRadius2 *= dfRadius2;
    1043               0 :     dfR12 = dfRadius1 * dfRadius2;
    1044                 : 
    1045                 :     // Compute coefficients for coordinate system rotation.
    1046               0 :     double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
    1047                 :     const double    dfAngle =
    1048               0 :         TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
    1049               0 :     const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
    1050               0 :     if ( bRotated )
    1051                 :     {
    1052               0 :         dfCoeff1 = cos(dfAngle);
    1053               0 :         dfCoeff2 = sin(dfAngle);
    1054                 :     }
    1055                 : 
    1056               0 :     double      dfAccumulator = 0.0;
    1057               0 :     GUInt32     i = 0, n = 0;
    1058                 : 
    1059                 :     // Search for the first point within the search ellipse
    1060               0 :     while ( i < nPoints - 1 )
    1061                 :     {
    1062               0 :         double  dfRX1 = padfX[i] - dfXPoint;
    1063               0 :         double  dfRY1 = padfY[i] - dfYPoint;
    1064                 : 
    1065               0 :         if ( bRotated )
    1066                 :         {
    1067               0 :             double dfRXRotated = dfRX1 * dfCoeff1 + dfRY1 * dfCoeff2;
    1068               0 :             double dfRYRotated = dfRY1 * dfCoeff1 - dfRX1 * dfCoeff2;
    1069                 : 
    1070               0 :             dfRX1 = dfRXRotated;
    1071               0 :             dfRY1 = dfRYRotated;
    1072                 :         }
    1073                 : 
    1074                 :         // Is this point located inside the search ellipse?
    1075               0 :         if ( dfRadius2 * dfRX1 * dfRX1 + dfRadius1 * dfRY1 * dfRY1 <= dfR12 )
    1076                 :         {
    1077                 :             GUInt32 j;
    1078                 :             
    1079                 :             // Search all the remaining points within the ellipse and compute
    1080                 :             // distances between them and the first point
    1081               0 :             for ( j = i + 1; j < nPoints; j++ )
    1082                 :             {
    1083               0 :                 double  dfRX2 = padfX[j] - dfXPoint;
    1084               0 :                 double  dfRY2 = padfY[j] - dfYPoint;
    1085                 :                 
    1086               0 :                 if ( bRotated )
    1087                 :                 {
    1088               0 :                     double dfRXRotated = dfRX2 * dfCoeff1 + dfRY2 * dfCoeff2;
    1089               0 :                     double dfRYRotated = dfRY2 * dfCoeff1 - dfRX2 * dfCoeff2;
    1090                 : 
    1091               0 :                     dfRX2 = dfRXRotated;
    1092               0 :                     dfRY2 = dfRYRotated;
    1093                 :                 }
    1094                 : 
    1095               0 :                 if ( dfRadius2 * dfRX2 * dfRX2 + dfRadius1 * dfRY2 * dfRY2 <= dfR12 )
    1096                 :                 {
    1097               0 :                     const double dfRX = padfX[j] - padfX[i];
    1098               0 :                     const double dfRY = padfY[j] - padfY[i];
    1099                 : 
    1100               0 :                     dfAccumulator += sqrt( dfRX * dfRX + dfRY * dfRY );
    1101               0 :                     n++;
    1102                 :                 }
    1103                 :             }
    1104                 :         }
    1105                 : 
    1106               0 :         i++;
    1107                 :     }
    1108                 : 
    1109               0 :     if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints
    1110                 :          || n == 0 )
    1111                 :     {
    1112                 :         (*pdfValue) =
    1113               0 :             ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
    1114                 :     }
    1115                 :     else
    1116               0 :         (*pdfValue) = dfAccumulator / n;
    1117                 : 
    1118               0 :     return CE_None;
    1119                 : }
    1120                 : 
    1121                 : /************************************************************************/
    1122                 : /*                            GDALGridCreate()                          */
    1123                 : /************************************************************************/
    1124                 : 
    1125                 : /**
    1126                 :  * Create regular grid from the scattered data.
    1127                 :  *
    1128                 :  * This fucntion takes the arrays of X and Y coordinates and corresponding Z
    1129                 :  * values as input and computes regular grid (or call it a raster) from these
    1130                 :  * scattered data. You should supply geometry and extent of the output grid
    1131                 :  * and allocate array sufficient to hold such a grid.
    1132                 :  *
    1133                 :  * @param eAlgorithm Gridding method. 
    1134                 :  * @param poOptions Options to control choosen gridding method.
    1135                 :  * @param nPoints Number of elements in input arrays.
    1136                 :  * @param padfX Input array of X coordinates. 
    1137                 :  * @param padfY Input array of Y coordinates. 
    1138                 :  * @param padfZ Input array of Z values. 
    1139                 :  * @param dfXMin Lowest X border of output grid.
    1140                 :  * @param dfXMax Highest X border of output grid.
    1141                 :  * @param dfYMin Lowest Y border of output grid.
    1142                 :  * @param dfYMax Highest Y border of output grid.
    1143                 :  * @param nXSize Number of columns in output grid.
    1144                 :  * @param nYSize Number of rows in output grid.
    1145                 :  * @param eType Data type of output array.  
    1146                 :  * @param pData Pointer to array where the computed grid will be stored.
    1147                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    1148                 :  * reporting progress or NULL.
    1149                 :  * @param pProgressArg argument to be passed to pfnProgress.  May be NULL.
    1150                 :  *
    1151                 :  * @return CE_None on success or CE_Failure if something goes wrong.
    1152                 :  */
    1153                 : 
    1154                 : CPLErr
    1155               1 : GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
    1156                 :                 GUInt32 nPoints,
    1157                 :                 const double *padfX, const double *padfY, const double *padfZ,
    1158                 :                 double dfXMin, double dfXMax, double dfYMin, double dfYMax,
    1159                 :                 GUInt32 nXSize, GUInt32 nYSize, GDALDataType eType, void *pData,
    1160                 :                 GDALProgressFunc pfnProgress, void *pProgressArg )
    1161                 : {
    1162                 :     CPLAssert( poOptions );
    1163                 :     CPLAssert( padfX );
    1164                 :     CPLAssert( padfY );
    1165                 :     CPLAssert( padfZ );
    1166                 :     CPLAssert( pData );
    1167                 : 
    1168               1 :     if ( pfnProgress == NULL )
    1169               0 :         pfnProgress = GDALDummyProgress;
    1170                 : 
    1171               1 :     if ( nXSize == 0 || nYSize == 0 )
    1172                 :     {
    1173                 :         CPLError( CE_Failure, CPLE_IllegalArg,
    1174               0 :                   "Output raster dimesions should have non-zero size." );
    1175               0 :         return CE_Failure;
    1176                 :     }
    1177                 : 
    1178                 :     GDALGridFunction    pfnGDALGridMethod;
    1179                 : 
    1180               1 :     switch ( eAlgorithm )
    1181                 :     {
    1182                 :         case GGA_InverseDistanceToAPower:
    1183               0 :             if ( ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->
    1184                 :                  dfRadius1 == 0.0 &&
    1185                 :                  ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->
    1186                 :                  dfRadius2 == 0.0 )
    1187               0 :                 pfnGDALGridMethod = GDALGridInverseDistanceToAPowerNoSearch;
    1188                 :             else
    1189               0 :                 pfnGDALGridMethod = GDALGridInverseDistanceToAPower;
    1190               0 :             break;
    1191                 : 
    1192                 :         case GGA_MovingAverage:
    1193               0 :             pfnGDALGridMethod = GDALGridMovingAverage;
    1194               0 :             break;
    1195                 : 
    1196                 :         case GGA_NearestNeighbor:
    1197               1 :             pfnGDALGridMethod = GDALGridNearestNeighbor;
    1198               1 :             break;
    1199                 : 
    1200                 :         case GGA_MetricMinimum:
    1201               0 :             pfnGDALGridMethod = GDALGridDataMetricMinimum;
    1202               0 :             break;
    1203                 : 
    1204                 :         case GGA_MetricMaximum:
    1205               0 :             pfnGDALGridMethod = GDALGridDataMetricMaximum;
    1206               0 :             break;
    1207                 : 
    1208                 :         case GGA_MetricRange:
    1209               0 :             pfnGDALGridMethod = GDALGridDataMetricRange;
    1210               0 :             break;
    1211                 : 
    1212                 :         case GGA_MetricCount:
    1213               0 :             pfnGDALGridMethod = GDALGridDataMetricCount;
    1214               0 :             break;
    1215                 : 
    1216                 :         case GGA_MetricAverageDistance:
    1217               0 :             pfnGDALGridMethod = GDALGridDataMetricAverageDistance;
    1218               0 :             break;
    1219                 : 
    1220                 :         case GGA_MetricAverageDistancePts:
    1221               0 :             pfnGDALGridMethod = GDALGridDataMetricAverageDistancePts;
    1222               0 :             break;
    1223                 : 
    1224                 :         default:
    1225                 :             CPLError( CE_Failure, CPLE_IllegalArg,
    1226               0 :                       "GDAL does not support gridding method %d", eAlgorithm );
    1227               0 :       return CE_Failure;
    1228                 :     }
    1229                 : 
    1230                 :     GUInt32 nXPoint, nYPoint;
    1231               1 :     const double    dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
    1232               1 :     const double    dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
    1233                 : 
    1234                 : /* -------------------------------------------------------------------- */
    1235                 : /*  Allocate a buffer of scanline size, fill it with gridded values     */
    1236                 : /*  and use GDALCopyWords() to copy values into output data array with  */
    1237                 : /*  appropriate data type conversion.                                   */
    1238                 : /* -------------------------------------------------------------------- */
    1239               1 :     double      *padfValues = (double *)VSIMalloc( sizeof(double) * nXSize );
    1240               1 :     GByte       *pabyData = (GByte *)pData;
    1241               1 :     int         nDataTypeSize = GDALGetDataTypeSize(eType) / 8;
    1242               1 :     int         nLineSpace = nXSize * nDataTypeSize;
    1243                 :     
    1244             122 :     for ( nYPoint = 0; nYPoint < nYSize; nYPoint++ )
    1245                 :     {
    1246             121 :         const double    dfYPoint = dfYMin + ( nYPoint + 0.5 ) * dfDeltaY;
    1247                 : 
    1248           14762 :         for ( nXPoint = 0; nXPoint < nXSize; nXPoint++ )
    1249                 :         {
    1250           14641 :             const double    dfXPoint = dfXMin + ( nXPoint + 0.5 ) * dfDeltaX;
    1251                 : 
    1252           14641 :             if ( (*pfnGDALGridMethod)( poOptions, nPoints, padfX, padfY, padfZ,
    1253                 :                                        dfXPoint, dfYPoint,
    1254                 :                                        padfValues + nXPoint ) != CE_None )
    1255                 :             {
    1256                 :                 CPLError( CE_Failure, CPLE_AppDefined,
    1257                 :                           "Gridding failed at X position %lu, Y position %lu",
    1258                 :                           (long unsigned int)nXPoint,
    1259               0 :                           (long unsigned int)nYPoint );
    1260               0 :                 return CE_Failure;
    1261                 :             }
    1262                 :         }
    1263                 : 
    1264                 :         GDALCopyWords( padfValues, GDT_Float64, sizeof(double),
    1265                 :                        pabyData, eType, nDataTypeSize,
    1266             121 :                        nXSize );
    1267             121 :         pabyData += nLineSpace;
    1268                 : 
    1269             121 :         if( !pfnProgress( (double)(nYPoint + 1) / nYSize, NULL, pProgressArg ) )
    1270                 :         {
    1271               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    1272               0 :             return CE_Failure;
    1273                 :         }
    1274                 :     }
    1275                 : 
    1276               1 :     VSIFree( padfValues );
    1277                 : 
    1278               1 :     return CE_None;
    1279                 : }
    1280                 : 

Generated by: LCOV version 1.7