LTP GCOV extension - code coverage report
Current view: directory - alg - gdal_crs.c
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 264
Code covered: 81.4 % Executed lines: 215

       1                 : /******************************************************************************
       2                 :  * $Id: gdal_crs.c 16614 2009-03-17 23:46:39Z rouault $
       3                 :  *
       4                 :  * Project:  Mapinfo Image Warper
       5                 :  * Purpose:  Implemention of the GDALTransformer wrapper around CRS.C functions
       6                 :  *           to build a polynomial transformation based on ground control 
       7                 :  *           points.
       8                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       9                 :  *
      10                 :  ***************************************************************************
      11                 : 
      12                 :     CRS.C - Center for Remote Sensing rectification routines
      13                 : 
      14                 :     Written By: Brian J. Buckley
      15                 : 
      16                 :             At: The Center for Remote Sensing
      17                 :                 Michigan State University
      18                 :                 302 Berkey Hall
      19                 :                 East Lansing, MI  48824
      20                 :                 (517)353-7195
      21                 : 
      22                 :     Written: 12/19/91
      23                 : 
      24                 :     Last Update: 12/26/91 Brian J. Buckley
      25                 :     Last Update:  1/24/92 Brian J. Buckley
      26                 :       Added printout of trnfile. Triggered by BDEBUG.
      27                 :     Last Update:  1/27/92 Brian J. Buckley
      28                 :       Fixed bug so that only the active control points were used.
      29                 : 
      30                 : 
      31                 :     Copyright (c) 1992, Michigan State University
      32                 :    
      33                 :     Permission is hereby granted, free of charge, to any person obtaining a
      34                 :     copy of this software and associated documentation files (the "Software"),
      35                 :     to deal in the Software without restriction, including without limitation
      36                 :     the rights to use, copy, modify, merge, publish, distribute, sublicense,
      37                 :     and/or sell copies of the Software, and to permit persons to whom the
      38                 :     Software is furnished to do so, subject to the following conditions:
      39                 :     
      40                 :     The above copyright notice and this permission notice shall be included
      41                 :     in all copies or substantial portions of the Software.
      42                 :     
      43                 :     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      44                 :     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      45                 :     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      46                 :     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      47                 :     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      48                 :     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      49                 :     DEALINGS IN THE SOFTWARE.
      50                 : 
      51                 :  ****************************************************************************/
      52                 : 
      53                 : #include "gdal_alg.h"
      54                 : #include "cpl_conv.h"
      55                 : #include "cpl_minixml.h"
      56                 : #include "cpl_string.h"
      57                 : 
      58                 : CPL_CVSID("$Id: gdal_crs.c 16614 2009-03-17 23:46:39Z rouault $");
      59                 : 
      60                 : #define MAXORDER 3
      61                 : 
      62                 : struct Control_Points
      63                 : {
      64                 :     int  count;
      65                 :     double *e1;
      66                 :     double *n1;
      67                 :     double *e2;
      68                 :     double *n2;
      69                 :     int *status;
      70                 : };
      71                 : 
      72                 : CPL_C_START
      73                 : CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg );
      74                 : void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree );
      75                 : CPL_C_END
      76                 : 
      77                 : /* crs.c */
      78                 : static int CRS_georef(double, double, double *, double *, 
      79                 :                               double [], double [], int);
      80                 : static int CRS_compute_georef_equations(struct Control_Points *,
      81                 :     double [], double [], double [], double [], int);
      82                 : 
      83                 : 
      84                 : static char *CRS_error_message[] = {
      85                 :     "Failed to compute GCP transform: Not enough points available",
      86                 :     "Failed to compute GCP transform: Transform is not solvable",
      87                 :     "Failed to compute GCP transform: Not enough memory"
      88                 :     "Failed to compute GCP transform: Parameter error",
      89                 :     "Failed to compute GCP transform: Internal error"
      90                 : };
      91                 : 
      92                 : typedef struct
      93                 : {
      94                 :     GDALTransformerInfo sTI;
      95                 : 
      96                 :     double adfToGeoX[20];
      97                 :     double adfToGeoY[20];
      98                 :     
      99                 :     double adfFromGeoX[20];
     100                 :     double adfFromGeoY[20];
     101                 : 
     102                 :     int    nOrder;
     103                 :     int    bReversed;
     104                 : 
     105                 :     int       nGCPCount;
     106                 :     GDAL_GCP *pasGCPList;
     107                 :     
     108                 : } GCPTransformInfo;
     109                 : 
     110                 : 
     111                 : /************************************************************************/
     112                 : /*                      GDALCreateGCPTransformer()                      */
     113                 : /************************************************************************/
     114                 : 
     115                 : /**
     116                 :  * Create GCP based polynomial transformer.
     117                 :  *
     118                 :  * Computes least squares fit polynomials from a provided set of GCPs,
     119                 :  * and stores the coefficients for later transformation of points between
     120                 :  * pixel/line and georeferenced coordinates. 
     121                 :  *
     122                 :  * The return value should be used as a TransformArg in combination with
     123                 :  * the transformation function GDALGCPTransform which fits the 
     124                 :  * GDALTransformerFunc signature.  The returned transform argument should
     125                 :  * be deallocated with GDALDestroyGCPTransformer when no longer needed.
     126                 :  *
     127                 :  * This function may fail (returning NULL) if the provided set of GCPs
     128                 :  * are inadequate for the requested order, the determinate is zero or they
     129                 :  * are otherwise "ill conditioned".  
     130                 :  *
     131                 :  * Note that 2nd order requires at least 6 GCPs, and 3rd order requires at
     132                 :  * least 10 gcps.  If nReqOrder is 0 the highest order possible with the
     133                 :  * provided gcp count will be used.
     134                 :  *
     135                 :  * @param nGCPCount the number of GCPs in pasGCPList.
     136                 :  * @param pasGCPList an array of GCPs to be used as input.
     137                 :  * @param nReqOrder the requested polynomial order.  It should be 1, 2 or 3.
     138                 :  * 
     139                 :  * @return the transform argument or NULL if creation fails. 
     140                 :  */
     141                 : 
     142                 : void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, 
     143                 :                                 int nReqOrder, int bReversed )
     144                 : 
     145              37 : {
     146                 :     GCPTransformInfo *psInfo;
     147                 :     double *padfGeoX, *padfGeoY, *padfRasterX, *padfRasterY;
     148                 :     int    *panStatus, iGCP;
     149                 :     int    nCRSresult;
     150                 :     struct Control_Points sPoints;
     151                 : 
     152              37 :     if( nReqOrder == 0 )
     153                 :     {
     154              32 :         if( nGCPCount >= 10 )
     155               0 :             nReqOrder = 2; /*for now we avoid 3rd order since it is unstable*/
     156              32 :         else if( nGCPCount >= 6 )
     157               3 :             nReqOrder = 2;
     158                 :         else
     159              29 :             nReqOrder = 1;
     160                 :     }
     161                 :     
     162              37 :     psInfo = (GCPTransformInfo *) CPLCalloc(sizeof(GCPTransformInfo),1);
     163              37 :     psInfo->bReversed = bReversed;
     164              37 :     psInfo->nOrder = nReqOrder;
     165                 : 
     166              37 :     psInfo->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
     167              37 :     psInfo->nGCPCount = nGCPCount;
     168                 : 
     169              37 :     strcpy( psInfo->sTI.szSignature, "GTI" );
     170              37 :     psInfo->sTI.pszClassName = "GDALGCPTransformer";
     171              37 :     psInfo->sTI.pfnTransform = GDALGCPTransform;
     172              37 :     psInfo->sTI.pfnCleanup = GDALDestroyGCPTransformer;
     173              37 :     psInfo->sTI.pfnSerialize = GDALSerializeGCPTransformer;
     174                 : 
     175                 : /* -------------------------------------------------------------------- */
     176                 : /*      Allocate and initialize the working points list.                */
     177                 : /* -------------------------------------------------------------------- */
     178              37 :     padfGeoX = (double *) CPLCalloc(sizeof(double),nGCPCount);
     179              37 :     padfGeoY = (double *) CPLCalloc(sizeof(double),nGCPCount);
     180              37 :     padfRasterX = (double *) CPLCalloc(sizeof(double),nGCPCount);
     181              37 :     padfRasterY = (double *) CPLCalloc(sizeof(double),nGCPCount);
     182              37 :     panStatus = (int *) CPLCalloc(sizeof(int),nGCPCount);
     183                 :     
     184             197 :     for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
     185                 :     {
     186             160 :         panStatus[iGCP] = 1;
     187             160 :         padfGeoX[iGCP] = pasGCPList[iGCP].dfGCPX;
     188             160 :         padfGeoY[iGCP] = pasGCPList[iGCP].dfGCPY;
     189             160 :         padfRasterX[iGCP] = pasGCPList[iGCP].dfGCPPixel;
     190             160 :         padfRasterY[iGCP] = pasGCPList[iGCP].dfGCPLine;
     191                 :     }
     192                 : 
     193              37 :     sPoints.count = nGCPCount;
     194              37 :     sPoints.e1 = padfRasterX;
     195              37 :     sPoints.n1 = padfRasterY;
     196              37 :     sPoints.e2 = padfGeoX;
     197              37 :     sPoints.n2 = padfGeoY;
     198              37 :     sPoints.status = panStatus;
     199                 :     
     200                 : /* -------------------------------------------------------------------- */
     201                 : /*      Compute the forward and reverse polynomials.                    */
     202                 : /* -------------------------------------------------------------------- */
     203              37 :     nCRSresult = CRS_compute_georef_equations( &sPoints,
     204                 :                                       psInfo->adfToGeoX, psInfo->adfToGeoY,
     205                 :                                       psInfo->adfFromGeoX, psInfo->adfFromGeoY,
     206                 :                                       nReqOrder );
     207                 : 
     208              37 :     CPLFree( padfGeoX );
     209              37 :     CPLFree( padfGeoY );
     210              37 :     CPLFree( padfRasterX );
     211              37 :     CPLFree( padfRasterY );
     212              37 :     CPLFree( panStatus );
     213                 : 
     214              37 :     if (nCRSresult != 1)
     215                 :     {
     216               0 :         CPLError( CE_Failure, CPLE_AppDefined, "%s", CRS_error_message[-nCRSresult]);
     217               0 :         GDALDestroyGCPTransformer( psInfo );
     218               0 :         return NULL;
     219                 :     }
     220                 :     else
     221                 :     {
     222              37 :         return psInfo;
     223                 :     }
     224                 : }
     225                 : 
     226                 : /************************************************************************/
     227                 : /*                     GDALDestroyGCPTransformer()                      */
     228                 : /************************************************************************/
     229                 : 
     230                 : /**
     231                 :  * Destroy GCP transformer.
     232                 :  *
     233                 :  * This function is used to destroy information about a GCP based
     234                 :  * polynomial transformation created with GDALCreateGCPTransformer(). 
     235                 :  *
     236                 :  * @param pTransformArg the transform arg previously returned by 
     237                 :  * GDALCreateGCPTransformer(). 
     238                 :  */
     239                 : 
     240                 : void GDALDestroyGCPTransformer( void *pTransformArg )
     241                 : 
     242              37 : {
     243              37 :     GCPTransformInfo *psInfo = (GCPTransformInfo *) pTransformArg;
     244                 : 
     245              37 :     VALIDATE_POINTER0( pTransformArg, "GDALDestroyGCPTransformer" );
     246                 : 
     247              37 :     GDALDeinitGCPs( psInfo->nGCPCount, psInfo->pasGCPList );
     248              37 :     CPLFree( psInfo->pasGCPList );
     249                 : 
     250              37 :     CPLFree( pTransformArg );
     251                 : }
     252                 : 
     253                 : /************************************************************************/
     254                 : /*                          GDALGCPTransform()                          */
     255                 : /************************************************************************/
     256                 : 
     257                 : /**
     258                 :  * Transforms point based on GCP derived polynomial model.
     259                 :  *
     260                 :  * This function matches the GDALTransformerFunc signature, and can be
     261                 :  * used to transform one or more points from pixel/line coordinates to
     262                 :  * georeferenced coordinates (SrcToDst) or vice versa (DstToSrc). 
     263                 :  *
     264                 :  * @param pTransformArg return value from GDALCreateGCPTransformer(). 
     265                 :  * @param bDstToSrc TRUE if transformation is from the destination 
     266                 :  * (georeferenced) coordinates to pixel/line or FALSE when transforming
     267                 :  * from pixel/line to georeferenced coordinates.
     268                 :  * @param nPointCount the number of values in the x, y and z arrays.
     269                 :  * @param x array containing the X values to be transformed.
     270                 :  * @param y array containing the Y values to be transformed.
     271                 :  * @param z array containing the Z values to be transformed.
     272                 :  * @param panSuccess array in which a flag indicating success (TRUE) or
     273                 :  * failure (FALSE) of the transformation are placed.
     274                 :  *
     275                 :  * @return TRUE.
     276                 :  */
     277                 : 
     278                 : int GDALGCPTransform( void *pTransformArg, int bDstToSrc, 
     279                 :                       int nPointCount, 
     280                 :                       double *x, double *y, double *z, 
     281                 :                       int *panSuccess )
     282                 : 
     283           12566 : {
     284                 :     int    i;
     285           12566 :     GCPTransformInfo *psInfo = (GCPTransformInfo *) pTransformArg;
     286                 : 
     287           12566 :     if( psInfo->bReversed )
     288               0 :         bDstToSrc = !bDstToSrc;
     289                 :     
     290          294829 :     for( i = 0; i < nPointCount; i++ )
     291                 :     {
     292          282263 :         if( x[i] == HUGE_VAL || y[i] == HUGE_VAL )
     293                 :         {
     294               0 :             panSuccess[i] = FALSE;
     295               0 :             continue;
     296                 :         }
     297                 : 
     298          282263 :         if( bDstToSrc )
     299                 :         {
     300          273286 :             CRS_georef( x[i], y[i], x + i, y + i, 
     301                 :                         psInfo->adfFromGeoX, psInfo->adfFromGeoY, 
     302                 :                         psInfo->nOrder );
     303                 :         }
     304                 :         else
     305                 :         {
     306            8977 :             CRS_georef( x[i], y[i], x + i, y + i, 
     307                 :                         psInfo->adfToGeoX, psInfo->adfToGeoY, 
     308                 :                         psInfo->nOrder );
     309                 :         }
     310          282263 :         panSuccess[i] = TRUE;
     311                 :     }
     312                 : 
     313           12566 :     return TRUE;
     314                 : }
     315                 : 
     316                 : /************************************************************************/
     317                 : /*                    GDALSerializeGCPTransformer()                     */
     318                 : /************************************************************************/
     319                 : 
     320                 : CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg )
     321                 : 
     322               3 : {
     323                 :     CPLXMLNode *psTree;
     324               3 :     GCPTransformInfo *psInfo = (GCPTransformInfo *) pTransformArg;
     325                 : 
     326               3 :     VALIDATE_POINTER1( pTransformArg, "GDALSerializeGCPTransformer", NULL );
     327                 : 
     328               3 :     psTree = CPLCreateXMLNode( NULL, CXT_Element, "GCPTransformer" );
     329                 : 
     330                 : /* -------------------------------------------------------------------- */
     331                 : /*      Serialize Order and bReversed.                                  */
     332                 : /* -------------------------------------------------------------------- */
     333               3 :     CPLCreateXMLElementAndValue( 
     334                 :         psTree, "Order", 
     335                 :         CPLSPrintf( "%d", psInfo->nOrder ) );
     336                 :                          
     337               3 :     CPLCreateXMLElementAndValue( 
     338                 :         psTree, "Reversed", 
     339                 :         CPLSPrintf( "%d", psInfo->bReversed ) );
     340                 :                                  
     341                 : /* -------------------------------------------------------------------- */
     342                 : /*  Attach GCP List.            */
     343                 : /* -------------------------------------------------------------------- */
     344               3 :     if( psInfo->nGCPCount > 0 )
     345                 :     {
     346                 :         int iGCP;
     347                 :         CPLXMLNode *psGCPList = CPLCreateXMLNode( psTree, CXT_Element, 
     348               3 :                                                   "GCPList" );
     349                 : 
     350              15 :         for( iGCP = 0; iGCP < psInfo->nGCPCount; iGCP++ )
     351                 :         {
     352                 :             CPLXMLNode *psXMLGCP;
     353              12 :             GDAL_GCP *psGCP = psInfo->pasGCPList + iGCP;
     354                 : 
     355              12 :             psXMLGCP = CPLCreateXMLNode( psGCPList, CXT_Element, "GCP" );
     356                 : 
     357              12 :             CPLSetXMLValue( psXMLGCP, "#Id", psGCP->pszId );
     358                 : 
     359              12 :             if( psGCP->pszInfo != NULL && strlen(psGCP->pszInfo) > 0 )
     360               0 :                 CPLSetXMLValue( psXMLGCP, "Info", psGCP->pszInfo );
     361                 : 
     362              12 :             CPLSetXMLValue( psXMLGCP, "#Pixel", 
     363                 :                             CPLSPrintf( "%.4f", psGCP->dfGCPPixel ) );
     364                 : 
     365              12 :             CPLSetXMLValue( psXMLGCP, "#Line", 
     366                 :                             CPLSPrintf( "%.4f", psGCP->dfGCPLine ) );
     367                 : 
     368              12 :             CPLSetXMLValue( psXMLGCP, "#X", 
     369                 :                             CPLSPrintf( "%.12E", psGCP->dfGCPX ) );
     370                 : 
     371              12 :             CPLSetXMLValue( psXMLGCP, "#Y", 
     372                 :                             CPLSPrintf( "%.12E", psGCP->dfGCPY ) );
     373                 : 
     374              12 :             if( psGCP->dfGCPZ != 0.0 )
     375               0 :                 CPLSetXMLValue( psXMLGCP, "#GCPZ", 
     376                 :                                 CPLSPrintf( "%.12E", psGCP->dfGCPZ ) );
     377                 :         }
     378                 :     }
     379                 : 
     380               3 :     return psTree;
     381                 : }
     382                 : 
     383                 : /************************************************************************/
     384                 : /*               GDALDeserializeReprojectionTransformer()               */
     385                 : /************************************************************************/
     386                 : 
     387                 : void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree )
     388                 : 
     389               4 : {
     390               4 :     GDAL_GCP *pasGCPList = 0;
     391               4 :     int nGCPCount = 0;
     392                 :     void *pResult;
     393                 :     int nReqOrder;
     394                 :     int bReversed;
     395                 : 
     396                 :     /* -------------------------------------------------------------------- */
     397                 :     /*      Check for GCPs.                                                 */
     398                 :     /* -------------------------------------------------------------------- */
     399               4 :     CPLXMLNode *psGCPList = CPLGetXMLNode( psTree, "GCPList" );
     400                 : 
     401               4 :     if( psGCPList != NULL )
     402                 :     {
     403               4 :         int  nGCPMax = 0;
     404                 :         CPLXMLNode *psXMLGCP;
     405                 :          
     406                 :         // Count GCPs.
     407              24 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     408              16 :              psXMLGCP = psXMLGCP->psNext )
     409              16 :             nGCPMax++;
     410                 :          
     411               4 :         pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
     412                 : 
     413              24 :         for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL; 
     414              16 :              psXMLGCP = psXMLGCP->psNext )
     415                 :         {
     416              16 :             GDAL_GCP *psGCP = pasGCPList + nGCPCount;
     417                 : 
     418              16 :             if( !EQUAL(psXMLGCP->pszValue,"GCP") || 
     419                 :                 psXMLGCP->eType != CXT_Element )
     420                 :                 continue;
     421                 :              
     422              16 :             GDALInitGCPs( 1, psGCP );
     423                 :              
     424              16 :             CPLFree( psGCP->pszId );
     425              16 :             psGCP->pszId = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Id",""));
     426                 :              
     427              16 :             CPLFree( psGCP->pszInfo );
     428              16 :             psGCP->pszInfo = CPLStrdup(CPLGetXMLValue(psXMLGCP,"Info",""));
     429                 :              
     430              16 :             psGCP->dfGCPPixel = atof(CPLGetXMLValue(psXMLGCP,"Pixel","0.0"));
     431              16 :             psGCP->dfGCPLine = atof(CPLGetXMLValue(psXMLGCP,"Line","0.0"));
     432                 :              
     433              16 :             psGCP->dfGCPX = atof(CPLGetXMLValue(psXMLGCP,"X","0.0"));
     434              16 :             psGCP->dfGCPY = atof(CPLGetXMLValue(psXMLGCP,"Y","0.0"));
     435              16 :             psGCP->dfGCPZ = atof(CPLGetXMLValue(psXMLGCP,"Z","0.0"));
     436              16 :             nGCPCount++;
     437                 :         }
     438                 :     }
     439                 : 
     440                 : /* -------------------------------------------------------------------- */
     441                 : /*      Get other flags.                                                */
     442                 : /* -------------------------------------------------------------------- */
     443               4 :     nReqOrder = atoi(CPLGetXMLValue(psTree,"Order","3"));
     444               4 :     bReversed = atoi(CPLGetXMLValue(psTree,"Reversed","0"));
     445                 : 
     446                 : /* -------------------------------------------------------------------- */
     447                 : /*      Generate transformation.                                        */
     448                 : /* -------------------------------------------------------------------- */
     449               4 :     pResult = GDALCreateGCPTransformer( nGCPCount, pasGCPList, nReqOrder, 
     450                 :                                         bReversed );
     451                 :     
     452                 : /* -------------------------------------------------------------------- */
     453                 : /*      Cleanup GCP copy.                                               */
     454                 : /* -------------------------------------------------------------------- */
     455               4 :     GDALDeinitGCPs( nGCPCount, pasGCPList );
     456               4 :     CPLFree( pasGCPList );
     457                 : 
     458               4 :     return pResult;
     459                 : }
     460                 : 
     461                 : /************************************************************************/
     462                 : /* ==================================================================== */
     463                 : /*      Everything below this point derived from the CRS.C from GRASS.  */
     464                 : /* ==================================================================== */
     465                 : /************************************************************************/
     466                 : 
     467                 : 
     468                 : /* STRUCTURE FOR USE INTERNALLY WITH THESE FUNCTIONS.  THESE FUNCTIONS EXPECT
     469                 :    SQUARE MATRICES SO ONLY ONE VARIABLE IS GIVEN (N) FOR THE MATRIX SIZE */
     470                 : 
     471                 : struct MATRIX
     472                 : {
     473                 :     int     n;     /* SIZE OF THIS MATRIX (N x N) */
     474                 :     double *v;
     475                 : };
     476                 : 
     477                 : /* CALCULATE OFFSET INTO ARRAY BASED ON R/C */
     478                 : 
     479                 : #define M(row,col) m->v[(((row)-1)*(m->n))+(col)-1]
     480                 : 
     481                 : 
     482                 : #define MSUCCESS     1 /* SUCCESS */
     483                 : #define MNPTERR      0 /* NOT ENOUGH POINTS */
     484                 : #define MUNSOLVABLE -1 /* NOT SOLVABLE */
     485                 : #define MMEMERR     -2 /* NOT ENOUGH MEMORY */
     486                 : #define MPARMERR    -3 /* PARAMETER ERROR */
     487                 : #define MINTERR     -4 /* INTERNAL ERROR */
     488                 : 
     489                 : /***************************************************************************/
     490                 : /*
     491                 :     FUNCTION PROTOTYPES FOR STATIC (INTERNAL) FUNCTIONS
     492                 : */
     493                 : /***************************************************************************/
     494                 : 
     495                 : static int calccoef(struct Control_Points *,double *,double *,int);
     496                 : static int calcls(struct Control_Points *,struct MATRIX *,
     497                 :                   double *,double *,double *,double *);
     498                 : static int exactdet(struct Control_Points *,struct MATRIX *,
     499                 :                     double *,double *,double *,double *);
     500                 : static int solvemat(struct MATRIX *,double *,double *,double *,double *);
     501                 : static double term(int,double,double);
     502                 : 
     503                 : /***************************************************************************/
     504                 : /*
     505                 :     TRANSFORM A SINGLE COORDINATE PAIR.
     506                 : */
     507                 : /***************************************************************************/
     508                 : 
     509                 : static int 
     510                 : CRS_georef (
     511                 :     double e1,  /* EASTINGS TO BE TRANSFORMED */
     512                 :     double n1,  /* NORTHINGS TO BE TRANSFORMED */
     513                 :     double *e,  /* EASTINGS TO BE TRANSFORMED */
     514                 :     double *n,  /* NORTHINGS TO BE TRANSFORMED */
     515                 :     double E[], /* EASTING COEFFICIENTS */
     516                 :     double N[], /* NORTHING COEFFICIENTS */
     517                 :     int order  /* ORDER OF TRANSFORMATION TO BE PERFORMED, MUST MATCH THE
     518                 :                ORDER USED TO CALCULATE THE COEFFICIENTS */
     519                 : )
     520          282263 :   {
     521                 :   double e3, e2n, en2, n3, e2, en, n2;
     522                 : 
     523          282263 :   switch(order)
     524                 :     {
     525                 :     case 1:
     526                 : 
     527          280119 :       *e = E[0] + E[1] * e1 + E[2] * n1;
     528          280119 :       *n = N[0] + N[1] * e1 + N[2] * n1;
     529          280119 :       break;
     530                 : 
     531                 :     case 2:
     532                 : 
     533            2144 :       e2 = e1 * e1;
     534            2144 :       n2 = n1 * n1;
     535            2144 :       en = e1 * n1;
     536                 : 
     537            2144 :       *e = E[0]      + E[1] * e1 + E[2] * n1 +
     538                 :            E[3] * e2 + E[4] * en + E[5] * n2;
     539            2144 :       *n = N[0]      + N[1] * e1 + N[2] * n1 +
     540                 :            N[3] * e2 + N[4] * en + N[5] * n2;
     541            2144 :       break;
     542                 : 
     543                 :     case 3:
     544                 : 
     545               0 :       e2  = e1 * e1;
     546               0 :       en  = e1 * n1;
     547               0 :       n2  = n1 * n1;
     548               0 :       e3  = e1 * e2;
     549               0 :       e2n = e2 * n1;
     550               0 :       en2 = e1 * n2;
     551               0 :       n3  = n1 * n2;
     552                 : 
     553               0 :       *e = E[0]      +
     554                 :            E[1] * e1 + E[2] * n1  +
     555                 :            E[3] * e2 + E[4] * en  + E[5] * n2  +
     556                 :            E[6] * e3 + E[7] * e2n + E[8] * en2 + E[9] * n3;
     557               0 :       *n = N[0]      +
     558                 :            N[1] * e1 + N[2] * n1  +
     559                 :            N[3] * e2 + N[4] * en  + N[5] * n2  +
     560                 :            N[6] * e3 + N[7] * e2n + N[8] * en2 + N[9] * n3;
     561               0 :       break;
     562                 : 
     563                 :     default:
     564                 : 
     565               0 :       return(MPARMERR);
     566                 :     }
     567                 : 
     568          282263 :   return(MSUCCESS);
     569                 :   }
     570                 : 
     571                 : /***************************************************************************/
     572                 : /*
     573                 :     COMPUTE THE GEOREFFERENCING COEFFICIENTS BASED ON A SET OF CONTROL POINTS
     574                 : */
     575                 : /***************************************************************************/
     576                 : 
     577                 : static int 
     578                 : CRS_compute_georef_equations (struct Control_Points *cp, 
     579                 :                                       double E12[], double N12[], 
     580                 :                                       double E21[], double N21[], 
     581                 :                                       int order)
     582              37 : {
     583                 :     double *tempptr;
     584                 :     int status;
     585                 : 
     586              37 :     if(order < 1 || order > MAXORDER)
     587               0 :         return(MPARMERR);
     588                 : 
     589                 :     /* CALCULATE THE FORWARD TRANSFORMATION COEFFICIENTS */
     590                 : 
     591              37 :     status = calccoef(cp,E12,N12,order);
     592              37 :     if(status != MSUCCESS)
     593               0 :         return(status);
     594                 : 
     595                 :     /* SWITCH THE 1 AND 2 EASTING AND NORTHING ARRAYS */
     596                 : 
     597              37 :     tempptr = cp->e1;
     598              37 :     cp->e1 = cp->e2;
     599              37 :     cp->e2 = tempptr;
     600              37 :     tempptr = cp->n1;
     601              37 :     cp->n1 = cp->n2;
     602              37 :     cp->n2 = tempptr;
     603                 : 
     604                 :     /* CALCULATE THE BACKWARD TRANSFORMATION COEFFICIENTS */
     605                 : 
     606              37 :     status = calccoef(cp,E21,N21,order);
     607                 : 
     608                 :     /* SWITCH THE 1 AND 2 EASTING AND NORTHING ARRAYS BACK */
     609                 : 
     610              37 :     tempptr = cp->e1;
     611              37 :     cp->e1 = cp->e2;
     612              37 :     cp->e2 = tempptr;
     613              37 :     tempptr = cp->n1;
     614              37 :     cp->n1 = cp->n2;
     615              37 :     cp->n2 = tempptr;
     616                 : 
     617              37 :     return(status);
     618                 : }
     619                 : 
     620                 : /***************************************************************************/
     621                 : /*
     622                 :     COMPUTE THE GEOREFFERENCING COEFFICIENTS BASED ON A SET OF CONTROL POINTS
     623                 : */
     624                 : /***************************************************************************/
     625                 : 
     626                 : static int 
     627                 : calccoef (struct Control_Points *cp, double E[], double N[], int order)
     628              74 : {
     629                 :     struct MATRIX m;
     630                 :     double *a;
     631                 :     double *b;
     632                 :     int numactive;   /* NUMBER OF ACTIVE CONTROL POINTS */
     633                 :     int status, i;
     634                 : 
     635                 :     /* CALCULATE THE NUMBER OF VALID CONTROL POINTS */
     636                 : 
     637             394 :     for(i = numactive = 0 ; i < cp->count ; i++)
     638                 :     {
     639             320 :         if(cp->status[i] > 0)
     640             320 :             numactive++;
     641                 :     }
     642                 : 
     643                 :     /* CALCULATE THE MINIMUM NUMBER OF CONTROL POINTS NEEDED TO DETERMINE
     644                 :        A TRANSFORMATION OF THIS ORDER */
     645                 : 
     646              74 :     m.n = ((order + 1) * (order + 2)) / 2;
     647                 : 
     648              74 :     if(numactive < m.n)
     649               0 :         return(MNPTERR);
     650                 : 
     651                 :     /* INITIALIZE MATRIX */
     652                 : 
     653              74 :     m.v = (double *)CPLCalloc(m.n*m.n,sizeof(double));
     654              74 :     if(m.v == NULL)
     655                 :     {
     656               0 :         return(MMEMERR);
     657                 :     }
     658              74 :     a = (double *)CPLCalloc(m.n,sizeof(double));
     659              74 :     if(a == NULL)
     660                 :     {
     661               0 :         CPLFree((char *)m.v);
     662               0 :         return(MMEMERR);
     663                 :     }
     664              74 :     b = (double *)CPLCalloc(m.n,sizeof(double));
     665              74 :     if(b == NULL)
     666                 :     {
     667               0 :         CPLFree((char *)m.v);
     668               0 :         CPLFree((char *)a);
     669               0 :         return(MMEMERR);
     670                 :     }
     671                 : 
     672              74 :     if(numactive == m.n)
     673               0 :         status = exactdet(cp,&m,a,b,E,N);
     674                 :     else
     675              74 :         status = calcls(cp,&m,a,b,E,N);
     676                 : 
     677              74 :     CPLFree((char *)m.v);
     678              74 :     CPLFree((char *)a);
     679              74 :     CPLFree((char *)b);
     680                 : 
     681              74 :     return(status);
     682                 : }
     683                 : 
     684                 : /***************************************************************************/
     685                 : /*
     686                 :     CALCULATE THE TRANSFORMATION COEFFICIENTS WITH EXACTLY THE MINIMUM
     687                 :     NUMBER OF CONTROL POINTS REQUIRED FOR THIS TRANSFORMATION.
     688                 : */
     689                 : /***************************************************************************/
     690                 : 
     691                 : static int exactdet (
     692                 :     struct Control_Points *cp,
     693                 :     struct MATRIX *m,
     694                 :     double a[],
     695                 :     double b[],
     696                 :     double E[],     /* EASTING COEFFICIENTS */
     697                 :     double N[]     /* NORTHING COEFFICIENTS */
     698                 : )
     699               0 :   {
     700                 :   int pntnow, currow, j;
     701                 : 
     702               0 :   currow = 1;
     703               0 :   for(pntnow = 0 ; pntnow < cp->count ; pntnow++)
     704                 :     {
     705               0 :     if(cp->status[pntnow] > 0)
     706                 :       {
     707                 :       /* POPULATE MATRIX M */
     708                 : 
     709               0 :       for(j = 1 ; j <= m->n ; j++)
     710                 :         {
     711               0 :         M(currow,j) = term(j,cp->e1[pntnow],cp->n1[pntnow]);
     712                 :         }
     713                 : 
     714                 :       /* POPULATE MATRIX A AND B */
     715                 : 
     716               0 :       a[currow-1] = cp->e2[pntnow];
     717               0 :       b[currow-1] = cp->n2[pntnow];
     718                 : 
     719               0 :       currow++;
     720                 :       }
     721                 :     }
     722                 : 
     723               0 :   if(currow - 1 != m->n)
     724               0 :     return(MINTERR);
     725                 : 
     726               0 :   return(solvemat(m,a,b,E,N));
     727                 :   }
     728                 : 
     729                 : /***************************************************************************/
     730                 : /*
     731                 :     CALCULATE THE TRANSFORMATION COEFFICIENTS WITH MORE THAN THE MINIMUM
     732                 :     NUMBER OF CONTROL POINTS REQUIRED FOR THIS TRANSFORMATION.  THIS
     733                 :     ROUTINE USES THE LEAST SQUARES METHOD TO COMPUTE THE COEFFICIENTS.
     734                 : */
     735                 : /***************************************************************************/
     736                 : 
     737                 : static int calcls (
     738                 :     struct Control_Points *cp,
     739                 :     struct MATRIX *m,
     740                 :     double a[],
     741                 :     double b[],
     742                 :     double E[],     /* EASTING COEFFICIENTS */
     743                 :     double N[]     /* NORTHING COEFFICIENTS */
     744                 : )
     745              74 : {
     746              74 :     int i, j, n, numactive = 0;
     747                 : 
     748                 :     /* INITIALIZE THE UPPER HALF OF THE MATRIX AND THE TWO COLUMN VECTORS */
     749                 : 
     750             314 :     for(i = 1 ; i <= m->n ; i++)
     751                 :     {
     752             774 :         for(j = i ; j <= m->n ; j++)
     753             534 :             M(i,j) = 0.0;
     754             240 :         a[i-1] = b[i-1] = 0.0;
     755                 :     }
     756                 : 
     757                 :     /* SUM THE UPPER HALF OF THE MATRIX AND THE COLUMN VECTORS ACCORDING TO
     758                 :        THE LEAST SQUARES METHOD OF SOLVING OVER DETERMINED SYSTEMS */
     759                 : 
     760             394 :     for(n = 0 ; n < cp->count ; n++)
     761                 :     {
     762             320 :         if(cp->status[n] > 0)
     763                 :         {
     764             320 :             numactive++;
     765            1424 :             for(i = 1 ; i <= m->n ; i++)
     766                 :             {
     767            3744 :                 for(j = i ; j <= m->n ; j++)
     768            2640 :                     M(i,j) += term(i,cp->e1[n],cp->n1[n]) * term(j,cp->e1[n],cp->n1[n]);
     769                 : 
     770            1104 :                 a[i-1] += cp->e2[n] * term(i,cp->e1[n],cp->n1[n]);
     771            1104 :                 b[i-1] += cp->n2[n] * term(i,cp->e1[n],cp->n1[n]);
     772                 :             }
     773                 :         }
     774                 :     }
     775                 : 
     776              74 :     if(numactive <= m->n)
     777               0 :         return(MINTERR);
     778                 : 
     779                 :     /* TRANSPOSE VALUES IN UPPER HALF OF M TO OTHER HALF */
     780                 : 
     781             240 :     for(i = 2 ; i <= m->n ; i++)
     782                 :     {
     783             460 :         for(j = 1 ; j < i ; j++)
     784             294 :             M(i,j) = M(j,i);
     785                 :     }
     786                 : 
     787              74 :     return(solvemat(m,a,b,E,N));
     788                 : }
     789                 : 
     790                 : /***************************************************************************/
     791                 : /*
     792                 :     CALCULATE THE X/Y TERM BASED ON THE TERM NUMBER
     793                 : 
     794                 : ORDER\TERM   1    2    3    4    5    6    7    8    9   10
     795                 :   1        e0n0 e1n0 e0n1
     796                 :   2        e0n0 e1n0 e0n1 e2n0 e1n1 e0n2
     797                 :   3        e0n0 e1n0 e0n1 e2n0 e1n1 e0n2 e3n0 e2n1 e1n2 e0n3
     798                 : */
     799                 : /***************************************************************************/
     800                 : 
     801                 : static double term (int term, double e, double n)
     802            7488 : {
     803            7488 :     switch(term)
     804                 :     {
     805            2064 :       case  1: return((double)1.0);
     806            2064 :       case  2: return((double)e);
     807            2064 :       case  3: return((double)n);
     808             432 :       case  4: return((double)(e*e));
     809             432 :       case  5: return((double)(e*n));
     810             432 :       case  6: return((double)(n*n));
     811               0 :       case  7: return((double)(e*e*e));
     812               0 :       case  8: return((double)(e*e*n));
     813               0 :       case  9: return((double)(e*n*n));
     814               0 :       case 10: return((double)(n*n*n));
     815                 :     }
     816               0 :     return((double)0.0);
     817                 : }
     818                 : 
     819                 : /***************************************************************************/
     820                 : /*
     821                 :     SOLVE FOR THE 'E' AND 'N' COEFFICIENTS BY USING A SOMEWHAT MODIFIED
     822                 :     GAUSSIAN ELIMINATION METHOD.
     823                 : 
     824                 :     | M11 M12 ... M1n | | E0   |   | a0   |
     825                 :     | M21 M22 ... M2n | | E1   | = | a1   |
     826                 :     |  .   .   .   .  | | .    |   | .    |
     827                 :     | Mn1 Mn2 ... Mnn | | En-1 |   | an-1 |
     828                 : 
     829                 :     and
     830                 : 
     831                 :     | M11 M12 ... M1n | | N0   |   | b0   |
     832                 :     | M21 M22 ... M2n | | N1   | = | b1   |
     833                 :     |  .   .   .   .  | | .    |   | .    |
     834                 :     | Mn1 Mn2 ... Mnn | | Nn-1 |   | bn-1 |
     835                 : */
     836                 : /***************************************************************************/
     837                 : 
     838                 : static int solvemat (struct MATRIX *m,
     839                 :   double a[], double b[], double E[], double N[])
     840              74 : {
     841                 :     int i, j, i2, j2, imark;
     842                 :     double factor, temp;
     843                 :     double  pivot;  /* ACTUAL VALUE OF THE LARGEST PIVOT CANDIDATE */
     844                 : 
     845             314 :     for(i = 1 ; i <= m->n ; i++)
     846                 :     {
     847             240 :         j = i;
     848                 : 
     849                 :         /* find row with largest magnitude value for pivot value */
     850                 : 
     851             240 :         pivot = M(i,j);
     852             240 :         imark = i;
     853             534 :         for(i2 = i + 1 ; i2 <= m->n ; i2++)
     854                 :         {
     855             294 :             temp = fabs(M(i2,j));
     856             294 :             if(temp > fabs(pivot))
     857                 :             {
     858             184 :                 pivot = M(i2,j);
     859             184 :                 imark = i2;
     860                 :             }
     861                 :         }
     862                 : 
     863                 :         /* if the pivot is very small then the points are nearly co-linear */
     864                 :         /* co-linear points result in an undefined matrix, and nearly */
     865                 :         /* co-linear points results in a solution with rounding error */
     866                 : 
     867             240 :         if(pivot == 0.0)
     868               0 :             return(MUNSOLVABLE);
     869                 : 
     870                 :         /* if row with highest pivot is not the current row, switch them */
     871                 :  
     872             240 :         if(imark != i)
     873                 :         {
     874             588 :             for(j2 = 1 ; j2 <= m->n ; j2++)
     875                 :             {
     876             459 :                 temp = M(imark,j2);
     877             459 :                 M(imark,j2) = M(i,j2);
     878             459 :                 M(i,j2) = temp;
     879                 :             }
     880                 : 
     881             129 :             temp = a[imark-1];
     882             129 :             a[imark-1] = a[i-1];
     883             129 :             a[i-1] = temp;
     884                 : 
     885             129 :             temp = b[imark-1];
     886             129 :             b[imark-1] = b[i-1];
     887             129 :             b[i-1] = temp;
     888                 :         }
     889                 : 
     890                 :         /* compute zeros above and below the pivot, and compute
     891                 :            values for the rest of the row as well */
     892                 : 
     893            1068 :         for(i2 = 1 ; i2 <= m->n ; i2++)
     894                 :         {
     895             828 :             if(i2 != i)
     896                 :             {
     897             588 :                 factor = M(i2,j) / pivot;
     898            2034 :                 for(j2 = j ; j2 <= m->n ; j2++)
     899            1446 :                     M(i2,j2) -= factor * M(i,j2);
     900             588 :                 a[i2-1] -= factor * a[i-1];
     901             588 :                 b[i2-1] -= factor * b[i-1];
     902                 :             }
     903                 :         }
     904                 :     }
     905                 : 
     906                 :     /* SINCE ALL OTHER VALUES IN THE MATRIX ARE ZERO NOW, CALCULATE THE
     907                 :        COEFFICIENTS BY DIVIDING THE COLUMN VECTORS BY THE DIAGONAL VALUES. */
     908                 : 
     909             314 :     for(i = 1 ; i <= m->n ; i++)
     910                 :     {
     911             240 :         E[i-1] = a[i-1] / M(i,i);
     912             240 :         N[i-1] = b[i-1] / M(i,i);
     913                 :     }
     914                 : 
     915              74 :     return(MSUCCESS);
     916                 : }

Generated by: LTP GCOV extension version 1.5