@@ -363,13 +363,13 @@ static double GetPolarConstant(int nReciprocalScale)
363363}
364364
365365/* ***********************************************************************/
366- /* GetLatOrYInterval() */
366+ /* GetYPixelSize() */
367367/* ***********************************************************************/
368368
369369/* * Return the size of a pixel (in degree for non-polar zones, in meters for
370370 * polar zones), along the latitude/Y axis,
371371 * at specified scale and zone */
372- static double GetLatOrYInterval (int nZone, int nReciprocalScale)
372+ static double GetYPixelSize (int nZone, int nReciprocalScale)
373373{
374374 CPLAssert (RPFCADRGIsValidZone (nZone));
375375 const int nZoneIdx = (nZone - 1 ) % MAX_ZONE_NORTHERN_HEMISPHERE;
@@ -398,13 +398,13 @@ static double GetLatOrYInterval(int nZone, int nReciprocalScale)
398398}
399399
400400/* ***********************************************************************/
401- /* GetLonOrXInterval() */
401+ /* GetXPixelSize() */
402402/* ***********************************************************************/
403403
404404/* * Return the size of a pixel (in degree for non-polar zones, in meters for
405405 * polar zones), along the longitude/X axis,
406406 * at specified scale and zone */
407- static double GetLonOrXInterval (int nZone, int nReciprocalScale)
407+ static double GetXPixelSize (int nZone, int nReciprocalScale)
408408{
409409 CPLAssert (RPFCADRGIsValidZone (nZone));
410410 const int nZoneIdx = (nZone - MIN_ZONE) % MAX_ZONE_NORTHERN_HEMISPHERE;
@@ -456,18 +456,31 @@ void RPFGetCADRGResolutionAndInterval(int nZone, int nReciprocalScale,
456456 const double latCst_CADRG =
457457 std::round (latCst_ADRG / RATIO_PITCH_CADRG_OVER_ADRG / 4 / BLOCK_SIZE) *
458458 BLOCK_SIZE;
459- latResolution = sZoneDef .latRes / N * latCst_ADRG / (4 * latCst_CADRG);
459+ double latResolutionLocal =
460+ sZoneDef .latRes / N * latCst_ADRG / (4 * latCst_CADRG);
460461
461462 const double A_s = sZoneDef .A * N;
462463 const double lonCst_ADRG =
463464 std::ceil (A_s / ADRG_BLOCK_SIZE) * ADRG_BLOCK_SIZE;
464465 const double lonCst_CADRG =
465466 std::round (lonCst_ADRG / RATIO_PITCH_CADRG_OVER_ADRG / BLOCK_SIZE) *
466467 BLOCK_SIZE;
467- lonResolution = sZoneDef .lonRes / N * lonCst_ADRG / lonCst_CADRG;
468+ double lonResolutionLocal =
469+ sZoneDef .lonRes / N * lonCst_ADRG / lonCst_CADRG;
468470
469- latInterval = 90.0 / latCst_CADRG;
470- lonInterval = 360.0 / lonCst_CADRG;
471+ double latIntervalLocal = 90.0 / latCst_CADRG;
472+ double lonIntervalLocal = 360.0 / lonCst_CADRG;
473+
474+ if (nZoneIdx + MIN_ZONE == MAX_ZONE_NORTHERN_HEMISPHERE)
475+ {
476+ lonResolutionLocal = latResolutionLocal;
477+ lonIntervalLocal = latIntervalLocal;
478+ }
479+
480+ latResolution = latResolutionLocal;
481+ lonResolution = lonResolutionLocal;
482+ latInterval = latIntervalLocal;
483+ lonInterval = lonIntervalLocal;
471484}
472485
473486/* ***********************************************************************/
@@ -492,7 +505,7 @@ static std::pair<double, double> GetMinMaxLatWithOverlap(int nZone,
492505 const int nZoneIdx = (nZone - MIN_ZONE) % MAX_ZONE_NORTHERN_HEMISPHERE;
493506 const auto &sZoneDef = asARCZoneDefinitions[nZoneIdx];
494507
495- const double latInterval = GetLatOrYInterval (nZone, nReciprocalScale);
508+ const double latInterval = GetYPixelSize (nZone, nReciprocalScale);
496509 const double deltaLatFrame = latInterval * CADRG_FRAME_PIXEL_COUNT;
497510
498511 const double dfMinLat =
@@ -533,7 +546,7 @@ static int GetFrameCountAlongX(int nZone, int nReciprocalScale)
533546{
534547 if (nZone == MAX_ZONE_NORTHERN_HEMISPHERE || nZone == MAX_ZONE)
535548 return GetPolarFrameCount (nReciprocalScale);
536- const double lonInterval = GetLonOrXInterval (nZone, nReciprocalScale);
549+ const double lonInterval = GetXPixelSize (nZone, nReciprocalScale);
537550 const double eastWestPixelCst = 360.0 / lonInterval;
538551 CPLDebugOnly (" CADRG" , " eastWestPixelCst=%f, count=%f" , eastWestPixelCst,
539552 eastWestPixelCst / CADRG_FRAME_PIXEL_COUNT);
@@ -550,7 +563,7 @@ static int GetFrameCountAlongY(int nZone, int nReciprocalScale)
550563{
551564 if (nZone == MAX_ZONE_NORTHERN_HEMISPHERE || nZone == MAX_ZONE)
552565 return GetPolarFrameCount (nReciprocalScale);
553- const double latInterval = GetLatOrYInterval (nZone, nReciprocalScale);
566+ const double latInterval = GetYPixelSize (nZone, nReciprocalScale);
554567 const double deltaLatFrame = latInterval * CADRG_FRAME_PIXEL_COUNT;
555568 const auto [dfMinLatZone, dfMaxLatZone] =
556569 GetMinMaxLatWithOverlap (nZone, nReciprocalScale);
@@ -671,8 +684,7 @@ RPFGetCADRGFramesForEnvelope(int nZoneIn, int nReciprocalScale,
671684 continue ;
672685 }
673686 dfLastMaxLatZone = dfMaxLatZoneNorth;
674- const double latInterval =
675- GetLatOrYInterval (nZone, nReciprocalScale);
687+ const double latInterval = GetYPixelSize (nZone, nReciprocalScale);
676688 const double deltaLatFrame = latInterval * CADRG_FRAME_PIXEL_COUNT;
677689 const double dfFrameMinY =
678690 (std::max (sExtentWGS84 .MinY , dfMinLatZone) - dfMinLatZone) /
@@ -685,8 +697,7 @@ RPFGetCADRGFramesForEnvelope(int nZoneIn, int nReciprocalScale,
685697 const int nFrameMinY = static_cast <int >(dfFrameMinY + EPSILON_1Em3);
686698 const int nFrameMaxY = static_cast <int >(dfFrameMaxY - EPSILON_1Em3);
687699
688- const double lonInterval =
689- GetLonOrXInterval (nZone, nReciprocalScale);
700+ const double lonInterval = GetXPixelSize (nZone, nReciprocalScale);
690701 const double deltaLonFrame = lonInterval * CADRG_FRAME_PIXEL_COUNT;
691702 const double dfFrameMinX =
692703 (std::max (sExtentWGS84 .MinX , dfMinLonZone) - dfMinLonZone) /
@@ -759,9 +770,9 @@ RPFGetCADRGFramesForEnvelope(int nZoneIn, int nReciprocalScale,
759770 RPFFrameDef sDef ;
760771 sDef .nZone = nZone;
761772 sDef .nReciprocalScale = nReciprocalScale;
762- sDef .dfResX = GetLonOrXInterval (nZone, nReciprocalScale);
773+ sDef .dfResX = GetXPixelSize (nZone, nReciprocalScale);
763774 // will lead to same value as dfResX
764- sDef .dfResY = GetLatOrYInterval (nZone, nReciprocalScale);
775+ sDef .dfResY = GetYPixelSize (nZone, nReciprocalScale);
765776 sDef .nFrameMinX =
766777 std::clamp (static_cast <int >((dfXMin / sDef .dfResX + R) /
767778 CADRG_FRAME_PIXEL_COUNT +
@@ -871,8 +882,8 @@ void RPFGetCADRGFrameExtent(int nZone, int nReciprocalScale, int nFrameX,
871882 double &dfXMax, double &dfYMax)
872883{
873884 CPLAssert (RPFCADRGIsValidZone (nZone));
874- const double dfXRes = GetLonOrXInterval (nZone, nReciprocalScale);
875- const double dfYRes = GetLatOrYInterval (nZone, nReciprocalScale);
885+ const double dfXRes = GetXPixelSize (nZone, nReciprocalScale);
886+ const double dfYRes = GetYPixelSize (nZone, nReciprocalScale);
876887
877888 double dfXMinLocal, dfYMinLocal;
878889 if (nZone == MAX_ZONE_NORTHERN_HEMISPHERE || nZone == MAX_ZONE)
@@ -973,7 +984,7 @@ int RPFGetCADRGClosestReciprocalScale(GDALDataset *poSrcDS,
973984 {
974985 // This is actually zone independent
975986 const double dfLatInterval =
976- GetLatOrYInterval (/* nZone = */ 1 , nReciprocalScale);
987+ GetYPixelSize (/* nZone = */ 1 , nReciprocalScale);
977988 if (nCandidateReciprocalScale == 0 &&
978989 dfLatInterval / dfYResAtNominalCADRGDPI > MAX_PROXIMITY_RATIO)
979990 {
@@ -1017,9 +1028,10 @@ int RPFGetCADRGClosestReciprocalScale(GDALDataset *poSrcDS,
10171028/* Create_CADRG_CoverageSection() */
10181029/* ***********************************************************************/
10191030
1020- static bool
1021- Create_CADRG_CoverageSection (GDALOffsetPatcher::OffsetPatcher *offsetPatcher,
1022- GDALDataset *poSrcDS, int nReciprocalScale)
1031+ static bool Create_CADRG_CoverageSection (
1032+ GDALOffsetPatcher::OffsetPatcher *offsetPatcher, GDALDataset *poSrcDS,
1033+ const std::string &osFilename, const CPLStringList &aosOptions,
1034+ int nReciprocalScale)
10231035{
10241036 auto poBuffer = offsetPatcher->CreateBuffer (
10251037 " CoverageSectionSubheader" , /* bEndiannessIsLittle = */ false );
@@ -1084,6 +1096,21 @@ Create_CADRG_CoverageSection(GDALOffsetPatcher::OffsetPatcher *offsetPatcher,
10841096 return dfLon;
10851097 };
10861098
1099+ int nZone = atoi (aosOptions.FetchNameValueDef (" ZONE" , " 0" ));
1100+ if (nZone < MIN_ZONE || nZone > MAX_ZONE)
1101+ {
1102+ const std::string osExt = CPLGetExtensionSafe (osFilename.c_str ());
1103+ if (osExt.size () == 3 )
1104+ nZone = RPFCADRGZoneCharToNum (osExt.back ());
1105+ if (nZone < MIN_ZONE || nZone > MAX_ZONE)
1106+ {
1107+ const double dfMeanLat = (dfULY + dfLLY) / 2 ;
1108+ nZone = GetARCZoneFromLat (dfMeanLat);
1109+ if (nZone == 0 )
1110+ return false ;
1111+ }
1112+ }
1113+
10871114 // Upper left corner lat, lon
10881115 poBuffer->AppendFloat64 (RoundIfCloseToInt (dfULY));
10891116 poBuffer->AppendFloat64 (RoundIfCloseToInt (NormalizeToMinusPlus180 (dfULX)));
@@ -1097,10 +1124,6 @@ Create_CADRG_CoverageSection(GDALOffsetPatcher::OffsetPatcher *offsetPatcher,
10971124 poBuffer->AppendFloat64 (RoundIfCloseToInt (dfLRY));
10981125 poBuffer->AppendFloat64 (RoundIfCloseToInt (NormalizeToMinusPlus180 (dfLRX)));
10991126
1100- const double dfMeanLat = (dfULY + dfLLY) / 2 ;
1101- const int nZone = GetARCZoneFromLat (dfMeanLat);
1102- if (nZone == 0 )
1103- return false ;
11041127 double latResolution = 0 ;
11051128 double lonResolution = 0 ;
11061129 double latInterval = 0 ;
@@ -1599,8 +1622,8 @@ RPFFrameCreateCADRG_TREs(GDALOffsetPatcher::OffsetPatcher *offsetPatcher,
15991622
16001623 // Create buffers that will be written into file by RPFFrameWriteCADRG_RPFIMG()s
16011624 Create_CADRG_LocationComponent (offsetPatcher);
1602- if (!Create_CADRG_CoverageSection (offsetPatcher, poSrcDS,
1603- copyContext.nReciprocalScale ))
1625+ if (!Create_CADRG_CoverageSection (offsetPatcher, poSrcDS, osFilename,
1626+ aosOptions, copyContext.nReciprocalScale ))
16041627 return nullptr ;
16051628 Create_CADRG_ColorGrayscaleSection (offsetPatcher);
16061629 Create_CADRG_ColormapSection (offsetPatcher, poSrcDS,
@@ -2981,10 +3004,8 @@ CADRGCreateCopy(const char *pszFilename, GDALDataset *poSrcDS, int bStrict,
29813004 frameDef.nFrameMinY = atoi (pszFrameY);
29823005 frameDef.nFrameMaxX = atoi (pszFrameX);
29833006 frameDef.nFrameMaxY = atoi (pszFrameY);
2984- frameDef.dfResX =
2985- GetLonOrXInterval (nZoneHint, nReciprocalScale);
2986- frameDef.dfResY =
2987- GetLatOrYInterval (nZoneHint, nReciprocalScale);
3007+ frameDef.dfResX = GetXPixelSize (nZoneHint, nReciprocalScale);
3008+ frameDef.dfResY = GetYPixelSize (nZoneHint, nReciprocalScale);
29883009
29893010 frameDefinitions.clear ();
29903011 frameDefinitions.push_back (std::move (frameDef));
0 commit comments