Пример #1
0
int GDALRPCTransform( void *pTransformArg, int bDstToSrc, 
                      int nPointCount, 
                      double *padfX, double *padfY, double *padfZ,
                      int *panSuccess )

{
    VALIDATE_POINTER1( pTransformArg, "GDALRPCTransform", 0 );

    GDALRPCTransformInfo *psTransform = (GDALRPCTransformInfo *) pTransformArg;
    GDALRPCInfo *psRPC = &(psTransform->sRPC);
    int i;

    if( psTransform->bReversed )
        bDstToSrc = !bDstToSrc;

    int bands[1] = {1};
    int nRasterXSize = 0, nRasterYSize = 0;

/* -------------------------------------------------------------------- */
/*      Lazy opening of the optionnal DEM file.                         */
/* -------------------------------------------------------------------- */
    if(psTransform->pszDEMPath != NULL &&
       psTransform->bHasTriedOpeningDS == FALSE)
    {
        int bIsValid = FALSE;
        psTransform->bHasTriedOpeningDS = TRUE;
        psTransform->poDS = (GDALDataset *)
                                GDALOpen( psTransform->pszDEMPath, GA_ReadOnly );
        if(psTransform->poDS != NULL && psTransform->poDS->GetRasterCount() >= 1)
        {
            const char* pszSpatialRef = psTransform->poDS->GetProjectionRef();
            if (pszSpatialRef != NULL && pszSpatialRef[0] != '\0')
            {
                OGRSpatialReference* poWGSSpaRef =
                        new OGRSpatialReference(SRS_WKT_WGS84);
                OGRSpatialReference* poDSSpaRef =
                        new OGRSpatialReference(pszSpatialRef);
                if(!poWGSSpaRef->IsSame(poDSSpaRef))
                    psTransform->poCT =OGRCreateCoordinateTransformation(
                                                    poWGSSpaRef, poDSSpaRef );
                delete poWGSSpaRef;
                delete poDSSpaRef;
            }

            if (psTransform->poDS->GetGeoTransform(
                                psTransform->adfGeoTransform) == CE_None &&
                GDALInvGeoTransform( psTransform->adfGeoTransform,
                                     psTransform->adfReverseGeoTransform ))
            {
                bIsValid = TRUE;
            }
        }

        if (!bIsValid && psTransform->poDS != NULL)
        {
            GDALClose(psTransform->poDS);
            psTransform->poDS = NULL;
        }
    }
    if (psTransform->poDS)
    {
        nRasterXSize = psTransform->poDS->GetRasterXSize();
        nRasterYSize = psTransform->poDS->GetRasterYSize();
    }

/* -------------------------------------------------------------------- */
/*      The simple case is transforming from lat/long to pixel/line.    */
/*      Just apply the equations directly.                              */
/* -------------------------------------------------------------------- */
    if( bDstToSrc )
    {
        for( i = 0; i < nPointCount; i++ )
        {
            if(psTransform->poDS)
            {
                double dfX, dfY;
                //check if dem is not in WGS84 and transform points padfX[i], padfY[i]
                if(psTransform->poCT)
                {
                    double dfXOrig = padfX[i];
                    double dfYOrig = padfY[i];
                    double dfZOrig = padfZ[i];
                    if (!psTransform->poCT->Transform(
                                                1, &dfXOrig, &dfYOrig, &dfZOrig))
                    {
                        panSuccess[i] = FALSE;
                        continue;
                    }
                    GDALApplyGeoTransform( psTransform->adfReverseGeoTransform,
                                           dfXOrig, dfYOrig, &dfX, &dfY );
                }
                else
                    GDALApplyGeoTransform( psTransform->adfReverseGeoTransform,
                                           padfX[i], padfY[i], &dfX, &dfY );
                int dX = int(dfX);
                int dY = int(dfY);

                if (!(dX >= 0 && dY >= 0 &&
                      dX+2 <= nRasterXSize && dY+2 <= nRasterYSize))
                {
                    panSuccess[i] = FALSE;
                    continue;
                }

                double dfDEMH(0);
                double dfDeltaX = dfX - dX;
                double dfDeltaY = dfY - dY;
                
                if(psTransform->eResampleAlg == DRA_Cubic)
                {
                    int dXNew = dX - 1;
                    int dYNew = dY - 1;
                    if (!(dXNew >= 0 && dYNew >= 0 && dXNew + 4 <= nRasterXSize && dYNew + 4 <= nRasterYSize))
                    {
                        panSuccess[i] = FALSE;
                        continue;
                    }
                    //cubic interpolation
                    int adElevData[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
                    CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dXNew, dYNew, 4, 4,
                                                              &adElevData, 4, 4,
                                                              GDT_Int32, 1, bands, 0, 0, 0);
                    if(eErr != CE_None)
                    {
                        panSuccess[i] = FALSE;
                        continue;
                    }

                    double dfSumH(0);
                    for ( int i = 0; i < 5; i++ )
                    {
                        // Loop across the X axis
                        for ( int j = 0; j < 5; j++ )
                        {
                            // Calculate the weight for the specified pixel according
                            // to the bicubic b-spline kernel we're using for
                            // interpolation
                            int dKernIndX = j - 1;
                            int dKernIndY = i - 1;
                            double dfPixelWeight = BiCubicKernel(dKernIndX - dfDeltaX) * BiCubicKernel(dKernIndY - dfDeltaY);

                            // Create a sum of all values
                            // adjusted for the pixel's calculated weight
                            dfSumH += adElevData[j + i * 4] * dfPixelWeight;
                        }
                    }
                    dfDEMH = dfSumH;
                }
                else if(psTransform->eResampleAlg == DRA_Bilinear)
                {
                    if (!(dX >= 0 && dY >= 0 && dX + 2 <= nRasterXSize && dY + 2 <= nRasterYSize))
                    {
                        panSuccess[i] = FALSE;
                        continue;
                    }
                    //bilinear interpolation
                    int anElevData[4] = {0,0,0,0};
                    CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dX, dY, 2, 2,
                                                              &anElevData, 2, 2,
                                                              GDT_Int32, 1, bands, 0, 0, 0);
                    if(eErr != CE_None)
                    {
                        panSuccess[i] = FALSE;
                        continue;
                    }
                    double dfDeltaX1 = 1.0 - dfDeltaX;                
                    double dfDeltaY1 = 1.0 - dfDeltaY;

                    double dfXZ1 = anElevData[0] * dfDeltaX1 + anElevData[1] * dfDeltaX;
                    double dfXZ2 = anElevData[2] * dfDeltaX1 + anElevData[3] * dfDeltaX;
                    double dfYZ = dfXZ1 * dfDeltaY1 + dfXZ2 * dfDeltaY;
                    dfDEMH = dfYZ;
                }
                else
                {
                    if (!(dX >= 0 && dY >= 0 && dX <= nRasterXSize && dY <= nRasterYSize))
                    {
                        panSuccess[i] = FALSE;
                        continue;
                    }
                    CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dX, dY, 1, 1,
                                                              &dfDEMH, 1, 1,
                                                              GDT_Int32, 1, bands, 0, 0, 0);
                    if(eErr != CE_None)
                    {
                        panSuccess[i] = FALSE;
                        continue;
                    }              
                }                

                RPCTransformPoint( psRPC, padfX[i], padfY[i], 
                                   padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
                                                psTransform->dfHeightScale, 
                                   padfX + i, padfY + i );
            }
            else
                RPCTransformPoint( psRPC, padfX[i], padfY[i], 
                                   padfZ[i] + psTransform->dfHeightOffset *
                                              psTransform->dfHeightScale, 
                                   padfX + i, padfY + i );
            panSuccess[i] = TRUE;
        }

        return TRUE;
    }

/* -------------------------------------------------------------------- */
/*      Compute the inverse (pixel/line/height to lat/long).  This      */
/*      function uses an iterative method from an initial linear        */
/*      approximation.                                                  */
/* -------------------------------------------------------------------- */
    for( i = 0; i < nPointCount; i++ )
    {
        double dfResultX, dfResultY;

        if(psTransform->poDS)
        {
            RPCInverseTransformPoint( psTransform, padfX[i], padfY[i], 
                      padfZ[i] + psTransform->dfHeightOffset *
                                 psTransform->dfHeightScale,
                      &dfResultX, &dfResultY );

            double dfX, dfY;
            //check if dem is not in WGS84 and transform points padfX[i], padfY[i]
            if(psTransform->poCT)
            {
                double dfZ = 0;
                if (!psTransform->poCT->Transform(1, &dfResultX, &dfResultY, &dfZ))
                {
                    panSuccess[i] = FALSE;
                    continue;
                }
            }

            GDALApplyGeoTransform( psTransform->adfReverseGeoTransform,
                                    dfResultX, dfResultY, &dfX, &dfY );
            int dX = int(dfX);
            int dY = int(dfY);

            double dfDEMH(0);
            double dfDeltaX = dfX - dX;
            double dfDeltaY = dfY - dY;

            if(psTransform->eResampleAlg == DRA_Cubic)
            {
                int dXNew = dX - 1;
                int dYNew = dY - 1;
                if (!(dXNew >= 0 && dYNew >= 0 && dXNew + 4 <= nRasterXSize && dYNew + 4 <= nRasterYSize))
                {
                    panSuccess[i] = FALSE;
                    continue;
                }
                //cubic interpolation
                int adElevData[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
                CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dXNew, dYNew, 4, 4,
                                                          &adElevData, 4, 4,
                                                          GDT_Int32, 1, bands, 0, 0, 0);
                if(eErr != CE_None)
                {
                    panSuccess[i] = FALSE;
                    continue;
                }

                double dfSumH(0);
                for ( int i = 0; i < 5; i++ )
                {
                    // Loop across the X axis
                    for ( int j = 0; j < 5; j++ )
                    {
                        // Calculate the weight for the specified pixel according
                        // to the bicubic b-spline kernel we're using for
                        // interpolation
                        int dKernIndX = j - 1;
                        int dKernIndY = i - 1;
                        double dfPixelWeight = BiCubicKernel(dKernIndX - dfDeltaX) * BiCubicKernel(dKernIndY - dfDeltaY);

                        // Create a sum of all values
                        // adjusted for the pixel's calculated weight
                        dfSumH += adElevData[j + i * 4] * dfPixelWeight;
                    }
                }
                dfDEMH = dfSumH;
            }
            else if(psTransform->eResampleAlg == DRA_Bilinear)
            {
                if (!(dX >= 0 && dY >= 0 && dX + 2 <= nRasterXSize && dY + 2 <= nRasterYSize))
                {
                    panSuccess[i] = FALSE;
                    continue;
                }
                //bilinear interpolation
                int adElevData[4] = {0,0,0,0};
                CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dX, dY, 2, 2,
                                                          &adElevData, 2, 2,
                                                          GDT_Int32, 1, bands, 0, 0, 0);
                if(eErr != CE_None)
                {
                    panSuccess[i] = FALSE;
                    continue;
                }
                double dfDeltaX1 = 1.0 - dfDeltaX;                
                double dfDeltaY1 = 1.0 - dfDeltaY;

                double dfXZ1 = adElevData[0] * dfDeltaX1 + adElevData[1] * dfDeltaX;
                double dfXZ2 = adElevData[2] * dfDeltaX1 + adElevData[3] * dfDeltaX;
                double dfYZ = dfXZ1 * dfDeltaY1 + dfXZ2 * dfDeltaY;
                dfDEMH = dfYZ;
            }
            else
            {
                if (!(dX >= 0 && dY >= 0 && dX <= nRasterXSize && dY <= nRasterYSize))
                {
                    panSuccess[i] = FALSE;
                    continue;
                }
                CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dX, dY, 1, 1,
                                                          &dfDEMH, 1, 1,
                                                          GDT_Int32, 1, bands, 0, 0, 0);
                if(eErr != CE_None)
                {
                    panSuccess[i] = FALSE;
                    continue;
                }           
            }

            RPCInverseTransformPoint( psTransform, padfX[i], padfY[i], 
                                      padfZ[i] + (psTransform->dfHeightOffset + dfDEMH) *
                                                  psTransform->dfHeightScale,
                                      &dfResultX, &dfResultY );
        }
        else
        {
            RPCInverseTransformPoint( psTransform, padfX[i], padfY[i], 
                                      padfZ[i] + psTransform->dfHeightOffset *
                                                 psTransform->dfHeightScale,
                                      &dfResultX, &dfResultY );

        }
        padfX[i] = dfResultX;
        padfY[i] = dfResultY;

        panSuccess[i] = TRUE;
    }

    return TRUE;
}
Пример #2
0
static
int GDALRPCGetDEMHeight( GDALRPCTransformInfo *psTransform,
                         double dfX, double dfY, double* pdfDEMH )
{

    int bGotNoDataValue = FALSE;
    double dfNoDataValue = 0;
    int nRasterXSize = psTransform->poDS->GetRasterXSize();
    int nRasterYSize = psTransform->poDS->GetRasterYSize();
    dfNoDataValue = psTransform->poDS->GetRasterBand(1)->GetNoDataValue( &bGotNoDataValue );

    int bands[1] = {1};

    int dX = int(dfX);
    int dY = int(dfY);
    double dfDEMH(0);
    double dfDeltaX = dfX - dX;
    double dfDeltaY = dfY - dY;

    if(psTransform->eResampleAlg == DRA_Cubic)
    {
        int dXNew = dX - 1;
        int dYNew = dY - 1;
        if (!(dXNew >= 0 && dYNew >= 0 && dXNew + 4 <= nRasterXSize && dYNew + 4 <= nRasterYSize))
        {
            return FALSE;
        }
        //cubic interpolation
        double adfElevData[16] = {0};
        CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dXNew, dYNew, 4, 4,
                      &adfElevData, 4, 4,
                      GDT_Float64, 1, bands, 0, 0, 0);
        if(eErr != CE_None)
        {
            return FALSE;
        }

        double dfSumH(0), dfSumWeight(0);
        for ( int k_i = 0; k_i < 4; k_i++ )
        {
            // Loop across the X axis
            for ( int k_j = 0; k_j < 4; k_j++ )
            {
                // Calculate the weight for the specified pixel according
                // to the bicubic b-spline kernel we're using for
                // interpolation
                int dKernIndX = k_j - 1;
                int dKernIndY = k_i - 1;
                double dfPixelWeight = BiCubicKernel(dKernIndX - dfDeltaX) * BiCubicKernel(dKernIndY - dfDeltaY);

                // Create a sum of all values
                // adjusted for the pixel's calculated weight
                double dfElev = adfElevData[k_j + k_i * 4];
                if( bGotNoDataValue && ARE_REAL_EQUAL(dfNoDataValue, dfElev) )
                    continue;

                dfSumH += dfElev * dfPixelWeight;
                dfSumWeight += dfPixelWeight;
            }
        }
        if( dfSumWeight == 0.0 )
        {
            return FALSE;
        }
        dfDEMH = dfSumH / dfSumWeight;
    }
    else if(psTransform->eResampleAlg == DRA_Bilinear)
    {
        if (!(dX >= 0 && dY >= 0 && dX + 2 <= nRasterXSize && dY + 2 <= nRasterYSize))
        {
            return FALSE;
        }
        //bilinear interpolation
        double adfElevData[4] = {0,0,0,0};
        CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dX, dY, 2, 2,
                      &adfElevData, 2, 2,
                      GDT_Float64, 1, bands, 0, 0, 0);
        if(eErr != CE_None)
        {
            return FALSE;
        }
        if( bGotNoDataValue )
        {
            // TODO: we could perhaps use a valid sample if there's one
            int bFoundNoDataElev = FALSE;
            for(int k_i=0; k_i<4; k_i++)
            {
                if( ARE_REAL_EQUAL(dfNoDataValue, adfElevData[k_i]) )
                    bFoundNoDataElev = TRUE;
            }
            if( bFoundNoDataElev )
            {
                return FALSE;
            }
        }
        double dfDeltaX1 = 1.0 - dfDeltaX;
        double dfDeltaY1 = 1.0 - dfDeltaY;

        double dfXZ1 = adfElevData[0] * dfDeltaX1 + adfElevData[1] * dfDeltaX;
        double dfXZ2 = adfElevData[2] * dfDeltaX1 + adfElevData[3] * dfDeltaX;
        double dfYZ = dfXZ1 * dfDeltaY1 + dfXZ2 * dfDeltaY;
        dfDEMH = dfYZ;
    }
    else
    {
        if (!(dX >= 0 && dY >= 0 && dX < nRasterXSize && dY < nRasterYSize))
        {
            return FALSE;
        }
        CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dX, dY, 1, 1,
                      &dfDEMH, 1, 1,
                      GDT_Float64, 1, bands, 0, 0, 0);
        if(eErr != CE_None ||
                (bGotNoDataValue && ARE_REAL_EQUAL(dfNoDataValue, dfDEMH)) )
        {
            return FALSE;
        }
    }

    *pdfDEMH = dfDEMH;

    return TRUE;
}