@@ -5620,31 +5620,26 @@ CPLErr netCDFDataset::AddProjectionVars(bool bDefsOnly,
56205620 return CE_Failure;
56215621
56225622 // Optional GDAL custom projection tags.
5623- if (bWriteGDALTags)
5623+ if (bWriteGDALTags && bWriteGeoTransform && m_bHasGeoTransform )
56245624 {
5625- std::string osGeoTransform = m_gt.ToString (" " );
5625+ GDALGeoTransform gt (m_gt);
5626+ if (!bBottomUp)
5627+ {
5628+ // Change origin from top to bottom and sign of coefficients
5629+ // indexed by row
5630+ gt.yorig += nRasterYSize * gt.yscale ;
5631+ gt.xorig += nRasterYSize * gt.xrot ;
5632+ gt.xrot = -gt.xrot ;
5633+ gt.yscale = -gt.yscale ;
5634+ }
5635+ std::string osGeoTransform = gt.ToString (" " );
56265636 CPLDebug (" GDAL_netCDF" , " szGeoTransform = %s" ,
56275637 osGeoTransform.c_str ());
56285638
5629- // if( strlen(pszProj4Defn) > 0 ) {
5630- // nc_put_att_text(cdfid, NCDFVarID, "proj4",
5631- // strlen(pszProj4Defn), pszProj4Defn);
5632- // }
5633-
5634- // For now, write the geotransform for back-compat or else
5635- // the old (1.8.1) driver overrides the CF geotransform with
5636- // empty values from dfNN, dfSN, dfEE, dfWE;
5637-
5638- // TODO: fix this in 1.8 branch, and then remove this here.
5639- if (bWriteGeoTransform && m_bHasGeoTransform)
5640- {
5641- {
5642- const int status = nc_put_att_text (
5643- cdfid, NCDFVarID, NCDF_GEOTRANSFORM,
5644- osGeoTransform.size (), osGeoTransform.c_str ());
5645- NCDF_ERR (status);
5646- }
5647- }
5639+ const int status = nc_put_att_text (
5640+ cdfid, NCDFVarID, NCDF_GEOTRANSFORM, osGeoTransform.size (),
5641+ osGeoTransform.c_str ());
5642+ NCDF_ERR (status);
56485643 }
56495644
56505645 // Write projection variable to band variable.
@@ -5657,7 +5652,13 @@ CPLErr netCDFDataset::AddProjectionVars(bool bDefsOnly,
56575652 const bool bIsRotatedPole =
56585653 pszCFProjection != nullptr &&
56595654 EQUAL (pszCFProjection, ROTATED_POLE_VAR_NAME);
5660- if (bIsRotatedPole)
5655+
5656+ if (m_bHasGeoTransform && !m_gt.IsAxisAligned ())
5657+ {
5658+ // Do not write X/Y coordinate arrays
5659+ }
5660+
5661+ else if (bIsRotatedPole)
56615662 {
56625663 // Rename dims to rlat/rlon.
56635664 papszDimName
@@ -5873,49 +5874,55 @@ CPLErr netCDFDataset::AddProjectionVars(bool bDefsOnly,
58735874 return CE_Failure;
58745875 }
58755876
5876- // Get Y values.
5877- const double dfY0 = (!bBottomUp) ? m_gt.yorig :
5878- // Invert latitude values.
5879- m_gt.yorig + (m_gt.yscale * nRasterYSize);
5880- const double dfDY = m_gt.yscale ;
5877+ // Make sure we are in data mode.
5878+ SetDefineMode (false );
58815879
5882- for (int j = 0 ; j < nRasterYSize; j++)
5880+ int status = NC_NOERR;
5881+
5882+ if (m_gt.IsAxisAligned ())
58835883 {
5884- // The data point is centered inside the pixel.
5885- if (!bBottomUp)
5886- padYVal[j] = dfY0 + (j + 0.5 ) * dfDY;
5887- else // Invert latitude values.
5888- padYVal[j] = dfY0 - (j + 0.5 ) * dfDY;
5889- }
5890- startX[0 ] = 0 ;
5891- countX[0 ] = nRasterXSize;
5884+ // Get Y values.
5885+ const double dfY0 =
5886+ (!bBottomUp) ? m_gt.yorig :
5887+ // Invert latitude values.
5888+ m_gt.yorig + (m_gt.yscale * nRasterYSize);
5889+ const double dfDY = m_gt.yscale ;
58925890
5893- // Get X values.
5894- const double dfX0 = m_gt.xorig ;
5895- const double dfDX = m_gt.xscale ;
5891+ for (int j = 0 ; j < nRasterYSize; j++)
5892+ {
5893+ // The data point is centered inside the pixel.
5894+ if (!bBottomUp)
5895+ padYVal[j] = dfY0 + (j + 0.5 ) * dfDY;
5896+ else // Invert latitude values.
5897+ padYVal[j] = dfY0 - (j + 0.5 ) * dfDY;
5898+ }
5899+ startX[0 ] = 0 ;
5900+ countX[0 ] = nRasterXSize;
58965901
5897- for (int i = 0 ; i < nRasterXSize; i++)
5898- {
5899- // The data point is centered inside the pixel.
5900- padXVal[i] = dfX0 + (i + 0.5 ) * dfDX;
5901- }
5902- startY[0 ] = 0 ;
5903- countY[0 ] = nRasterYSize;
5902+ // Get X values.
5903+ const double dfX0 = m_gt.xorig ;
5904+ const double dfDX = m_gt.xscale ;
59045905
5905- // Write X/Y values.
5906+ for (int i = 0 ; i < nRasterXSize; i++)
5907+ {
5908+ // The data point is centered inside the pixel.
5909+ padXVal[i] = dfX0 + (i + 0.5 ) * dfDX;
5910+ }
5911+ startY[0 ] = 0 ;
5912+ countY[0 ] = nRasterYSize;
59065913
5907- // Make sure we are in data mode.
5908- SetDefineMode (false );
5914+ // Write X/Y values.
59095915
5910- CPLDebug (" GDAL_netCDF" , " Writing X values" );
5911- int status =
5912- nc_put_vara_double (cdfid, nVarXID, startX, countX, padXVal);
5913- NCDF_ERR (status);
5916+ CPLDebug (" GDAL_netCDF" , " Writing X values" );
5917+ status =
5918+ nc_put_vara_double (cdfid, nVarXID, startX, countX, padXVal);
5919+ NCDF_ERR (status);
59145920
5915- CPLDebug (" GDAL_netCDF" , " Writing Y values" );
5916- status =
5917- nc_put_vara_double (cdfid, nVarYID, startY, countY, padYVal);
5918- NCDF_ERR (status);
5921+ CPLDebug (" GDAL_netCDF" , " Writing Y values" );
5922+ status =
5923+ nc_put_vara_double (cdfid, nVarYID, startY, countY, padYVal);
5924+ NCDF_ERR (status);
5925+ }
59195926
59205927 if (pfnProgress)
59215928 pfnProgress (0.20 , nullptr , pProgressData);
@@ -5979,10 +5986,37 @@ CPLErr netCDFDataset::AddProjectionVars(bool bDefsOnly,
59795986 if (!bHasGeoloc)
59805987 {
59815988 // Fill values to transform.
5982- for (int i = 0 ; i < nRasterXSize; i++)
5989+ if (m_gt.IsAxisAligned ())
5990+ {
5991+ for (int i = 0 ; i < nRasterXSize; i++)
5992+ {
5993+ padLatVal[i] = padYVal[j];
5994+ padLonVal[i] = padXVal[i];
5995+ }
5996+ }
5997+ else
59835998 {
5984- padLatVal[i] = padYVal[j];
5985- padLonVal[i] = padXVal[i];
5999+ for (int i = 0 ; i < nRasterXSize; i++)
6000+ {
6001+ if (!bBottomUp)
6002+ {
6003+ padLatVal[i] = m_gt.yorig +
6004+ (i + 0.5 ) * m_gt.yrot +
6005+ (j + 0.5 ) * m_gt.yscale ;
6006+ padLonVal[i] = m_gt.xorig +
6007+ (i + 0.5 ) * m_gt.xscale +
6008+ (j + 0.5 ) * m_gt.xrot ;
6009+ }
6010+ else
6011+ {
6012+ padLatVal[i] =
6013+ m_gt.yorig + (i + 0.5 ) * m_gt.yrot +
6014+ (nRasterYSize - j - 0.5 ) * m_gt.yscale ;
6015+ padLonVal[i] =
6016+ m_gt.xorig + (i + 0.5 ) * m_gt.xscale +
6017+ (nRasterYSize - j - 0.5 ) * m_gt.xrot ;
6018+ }
6019+ }
59866020 }
59876021
59886022 // Do the transform.
@@ -6041,7 +6075,7 @@ CPLErr netCDFDataset::AddProjectionVars(bool bDefsOnly,
60416075 } // Projected
60426076
60436077 // If not projected/geographic and has geoloc
6044- else if (!bIsGeographic && bHasGeoloc)
6078+ else if (!bIsGeographic && bHasGeoloc && m_gt. IsAxisAligned () )
60456079 {
60466080 // Use
60476081 // https://cfconventions.org/Data/cf-conventions/cf-conventions-1.9/cf-conventions.html#_two_dimensional_latitude_longitude_coordinate_variables
0 commit comments