[gdal-dev] [PATCH] Support Mercator_2SP in GeoTIFF
Trent Piepho
tpiepho at gmail.com
Sun Nov 3 17:48:26 PST 2013
Mercator_[12]SP are both the same projection in GeoTIFF. Lacking a
definition in the official specification, the intention appears to be that
for Mercator_2SP the latitude of true scale (lat_ts) should be specified in
ProjStdParallel1GeoKey and for Mercator_2SP the scale at origin (k) should
be specified in ProjScaleAtNatOriginGeoKey.
Current behavior when creating a GTiff with 2SP is to drop lat_ts and create
a default k value of 1.0, which will product an incorrect projection. When
reading, a default k of 1.0 is used and lat_ts is ignored, also changing the
projection.
This patches changes the behavior to supply ProjScaleAtNatOriginGeoKey for
Mercator_1SP or ProjStdParallel1GeoKey for Mercator_2SP when writing.
For reading either or both values are supplied when present by libgeotiff's
normalization code. If neither is present, a default k of 1.0 is created.
GDAL's GTiff driver is changed to create a 2SP projection is lat_ts is
present, 1SP otherwise. It emits a warning of both last_ts and scale are
present (and ignores scale).
---
gdal/frmts/gtiff/gt_wkt_srs.cpp | 28 ++++++++++---
gdal/frmts/gtiff/libgeotiff/geo_normalize.c | 59 ++++++++++++++++++++++++++-
2 files changed, 80 insertions(+), 7 deletions(-)
diff --git a/gdal/frmts/gtiff/gt_wkt_srs.cpp b/gdal/frmts/gtiff/gt_wkt_srs.cpp
index 5934df5..0afb101 100644
--- a/gdal/frmts/gtiff/gt_wkt_srs.cpp
+++ b/gdal/frmts/gtiff/gt_wkt_srs.cpp
@@ -737,9 +737,21 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
break;
case CT_Mercator:
- oSRS.SetMercator( adfParm[0], adfParm[1],
- adfParm[4],
- adfParm[5], adfParm[6] );
+ /* If a lat_ts was specified use 2SP, otherwise use 1SP */
+ if (psDefn->ProjParmId[2] == ProjStdParallel1GeoKey)
+ {
+ if (psDefn->ProjParmId[4] == ProjScaleAtNatOriginGeoKey)
+ CPLError( CE_Warning, CPLE_AppDefined,
+ "Mercator projection should not define both StdParallel1 and ScaleAtNatOrigin.\n"
+ "Using StdParallel1 and ignoring ScaleAtNatOrigin.\n" );
+ oSRS.SetMercator2SP( adfParm[2],
+ adfParm[0], adfParm[1],
+ adfParm[5], adfParm[6]);
+ }
+ else
+ oSRS.SetMercator( adfParm[0], adfParm[1],
+ adfParm[4],
+ adfParm[5], adfParm[6] );
if (psDefn->Projection == 1024 || psDefn->Projection == 9841) // override hack for google mercator.
{
@@ -1510,14 +1522,18 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
GTIFKeySet(psGTIF, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1,
poSRS->GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 ) );
- GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
- poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
-
GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
+
+ if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) )
+ GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
+ poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
+ else
+ GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
+ poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
}
else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
diff --git a/gdal/frmts/gtiff/libgeotiff/geo_normalize.c b/gdal/frmts/gtiff/libgeotiff/geo_normalize.c
index 4761ea0..75705ee 100644
--- a/gdal/frmts/gtiff/libgeotiff/geo_normalize.c
+++ b/gdal/frmts/gtiff/libgeotiff/geo_normalize.c
@@ -1495,8 +1495,65 @@ static void GTIFFetchProjParms( GTIF * psGTIF, GTIFDefn * psDefn )
break;
/* -------------------------------------------------------------------- */
- case CT_LambertConfConic_1SP:
case CT_Mercator:
+/* -------------------------------------------------------------------- */
+ if( GTIFKeyGet(psGTIF, ProjNatOriginLongGeoKey,
+ &dfNatOriginLong, 0, 1 ) == 0
+ && GTIFKeyGet(psGTIF, ProjFalseOriginLongGeoKey,
+ &dfNatOriginLong, 0, 1 ) == 0
+ && GTIFKeyGet(psGTIF, ProjCenterLongGeoKey,
+ &dfNatOriginLong, 0, 1 ) == 0 )
+ dfNatOriginLong = 0.0;
+
+ if( GTIFKeyGet(psGTIF, ProjNatOriginLatGeoKey,
+ &dfNatOriginLat, 0, 1 ) == 0
+ && GTIFKeyGet(psGTIF, ProjFalseOriginLatGeoKey,
+ &dfNatOriginLat, 0, 1 ) == 0
+ && GTIFKeyGet(psGTIF, ProjCenterLatGeoKey,
+ &dfNatOriginLat, 0, 1 ) == 0 )
+ dfNatOriginLat = 0.0;
+
+
+ if( GTIFKeyGet(psGTIF, ProjStdParallel1GeoKey,
+ &dfStdParallel1, 0, 1 ) == 0 )
+ dfStdParallel1 = NAN;
+
+ if( GTIFKeyGet(psGTIF, ProjScaleAtNatOriginGeoKey,
+ &dfNatOriginScale, 0, 1 ) == 0 )
+ {
+ /* Default only if dfStdParallel1 isn't defined */
+ if( isnan(dfStdParallel1) )
+ dfNatOriginScale = 1.0;
+ else
+ dfNatOriginScale = NAN;
+ }
+
+ /* notdef: should transform to decimal degrees at this point */
+
+ psDefn->ProjParm[0] = dfNatOriginLat;
+ psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;
+ psDefn->ProjParm[1] = dfNatOriginLong;
+ psDefn->ProjParmId[1] = ProjNatOriginLongGeoKey;
+ if( !isnan(dfStdParallel1) )
+ {
+ psDefn->ProjParm[2] = dfStdParallel1;
+ psDefn->ProjParmId[2] = ProjStdParallel1GeoKey;
+ }
+ if( !isnan(dfNatOriginScale) )
+ {
+ psDefn->ProjParm[4] = dfNatOriginScale;
+ psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
+ }
+ psDefn->ProjParm[5] = dfFalseEasting;
+ psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
+ psDefn->ProjParm[6] = dfFalseNorthing;
+ psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
+
+ psDefn->nParms = 7;
+ break;
+
+/* -------------------------------------------------------------------- */
+ case CT_LambertConfConic_1SP:
case CT_ObliqueStereographic:
case CT_TransverseMercator:
case CT_TransvMercator_SouthOriented:
--
1.7.10.4
More information about the gdal-dev
mailing list