Opened 16 years ago

Closed 10 years ago

#2496 closed defect (duplicate)

gdal_rpc.cpp GDALCreateRPCTransformer incorrect linear approximator

Reported by: jaredrubinaz Owned by: warmerdam
Priority: normal Milestone:
Component: default Version: svn-trunk
Severity: normal Keywords: RPC transform latitude longitude
Cc:

Description

When I used the corner coordinates returned by gdal for an image with RPC coefficients and reproject from ground to image coordinates, the image coordinates are way off. Based upon walking through the simple linear approximator in GDALCreateRPCTranformer method, it looks like values [2] and [4] of adfGTFromLL are swapped. When I reproject the corner coordinates they are within 15-20 image coordinates..which I would expect.

In addition, when building the transform, the psRPCInfo->dfHEIGHT_OFF should be used for elevation instead of 0.0.

So the following update is needed, in addition to using psRPCInfo->dfHEIGHT_OF instead of 0.0

adfGTFromLL[2] = (dfRefLineDelta - dfRefLine) / dfLLDelta;

should be adfGTFromLL[4] = (dfRefLineDelta - dfRefLine) / dfLLDelta;

and

adfGTFromLL[4] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta; should be adfGTFromLL[2] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;

thanks Jared

Below is how I reimplemented the code block



void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed, 
                                double dfPixErrThreshold )

{
    GDALRPCTransformInfo *psTransform;

/* -------------------------------------------------------------------- */
/*      Initialize core info.                                           */
/* -------------------------------------------------------------------- */
    psTransform = (GDALRPCTransformInfo *) 
        CPLCalloc(sizeof(GDALRPCTransformInfo),1);

    memcpy( &(psTransform->sRPC), psRPCInfo, sizeof(GDALRPCInfo) );
    psTransform->bReversed = bReversed;
    psTransform->dfPixErrThreshold = dfPixErrThreshold;

    strcpy( psTransform->sTI.szSignature, "GTI" );
    psTransform->sTI.pszClassName = "GDALRPCTransformer";
    psTransform->sTI.pfnTransform = GDALRPCTransform;
    psTransform->sTI.pfnCleanup = GDALDestroyRPCTransformer;
    psTransform->sTI.pfnSerialize = NULL;

/* -------------------------------------------------------------------- */
/*      Establish a reference point for calcualating an affine          */
/*      geotransform approximate transformation.                        */
/* -------------------------------------------------------------------- */
    double adfGTFromLL[6], dfRefPixel, dfRefLine;

    double dfRefLong = (psRPCInfo->dfMIN_LONG + psRPCInfo->dfMAX_LONG) * 0.5;
    double dfRefLat  = (psRPCInfo->dfMIN_LAT  + psRPCInfo->dfMAX_LAT ) * 0.5;

	 //    RPCTransformPoint( psRPCInfo, dfRefLong, dfRefLat, 0.0, 
	 //                       &dfRefPixel, &dfRefLine );
	
	 // AFA - Use the height offset instead
    RPCTransformPoint( psRPCInfo, dfRefLong, dfRefLat, psRPCInfo->dfHEIGHT_OFF, 
                       &dfRefPixel, &dfRefLine );

/* -------------------------------------------------------------------- */
/*      Transform nearby locations to establish affine direction        */
/*      vectors.                                                        */
/* -------------------------------------------------------------------- */
    double dfRefPixelDelta, dfRefLineDelta, dfLLDelta = 0.0001;
    
	 //  RPCTransformPoint( psRPCInfo, dfRefLong+dfLLDelta, dfRefLat, 0.0, 
	 //                       &dfRefPixelDelta, &dfRefLineDelta );

	 // AFA - Use the height offset instead
    RPCTransformPoint( psRPCInfo, dfRefLong+dfLLDelta, dfRefLat, psRPCInfo->dfHEIGHT_OFF, 
                       &dfRefPixelDelta, &dfRefLineDelta );

    adfGTFromLL[1] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;
	 //    adfGTFromLL[2] = (dfRefLineDelta - dfRefLine) / dfLLDelta;
	 // AFA Correction
    adfGTFromLL[4] = (dfRefLineDelta - dfRefLine) / dfLLDelta;
    
	 //    RPCTransformPoint( psRPCInfo, dfRefLong, dfRefLat+dfLLDelta, 0.0, 
	 //                       &dfRefPixelDelta, &dfRefLineDelta );

	 // AFA - Use the height offset instead
    RPCTransformPoint( psRPCInfo, dfRefLong, dfRefLat+dfLLDelta, psRPCInfo->dfHEIGHT_OFF, 
                       &dfRefPixelDelta, &dfRefLineDelta );

	 //    adfGTFromLL[4] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;
	 // AFA Correction
    adfGTFromLL[2] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;
    adfGTFromLL[5] = (dfRefLineDelta - dfRefLine) / dfLLDelta;

    adfGTFromLL[0] = dfRefPixel 
        - adfGTFromLL[1] * dfRefLong - adfGTFromLL[2] * dfRefLat;
    adfGTFromLL[3] = dfRefLine 
        - adfGTFromLL[4] * dfRefLong - adfGTFromLL[5] * dfRefLat;

    GDALInvGeoTransform( adfGTFromLL, psTransform->adfPLToLatLongGeoTransform);
    
    return psTransform;
}

Jared

Change History (1)

comment:1 by Even Rouault, 10 years ago

Milestone: 1.8.1
Resolution: duplicate
Status: newclosed

Hum, it looks like it has just been independantly fixed by r26963, #5395

Note: See TracTickets for help on using tickets.