@@ -1278,6 +1278,109 @@ static void suggestCompletion(const std::vector<std::string> &args) {
12781278 break ;
12791279 }
12801280 }
1281+
1282+ // If the input was ``projinfo "NAD83(HARN) / California Albers +``,
1283+ // then check if "NAD83(HARN) / California Albers" is a known horizontal
1284+ // CRS, and if so, suggest relevant potential vertical CRS.
1285+ const auto posSpacePlus = lastArg.find (" +" );
1286+ if (first && posSpacePlus != std::string::npos) {
1287+ const std::string candidateHorizCRSName =
1288+ lastArg.substr (0 , posSpacePlus);
1289+ auto factory = AuthorityFactory::create (dbContext, std::string ());
1290+ #ifdef DEBUG_COMPLETION
1291+ fprintf (stderr, " candidateHorizCRSName='%s'\n " ,
1292+ candidateHorizCRSName.c_str ());
1293+ #endif
1294+ const auto candidateHorizCRS = factory->createObjectsFromName (
1295+ candidateHorizCRSName,
1296+ {AuthorityFactory::ObjectType::GEOGRAPHIC_2D_CRS,
1297+ AuthorityFactory::ObjectType::PROJECTED_CRS},
1298+ /* approximateMatch = */ true ,
1299+ /* limitResultCount = */ 2 );
1300+ if (!candidateHorizCRS.empty ()) {
1301+ const auto &domains = dynamic_cast <const ObjectUsage *>(
1302+ candidateHorizCRS.front ().get ())
1303+ ->domains ();
1304+ if (domains.size () == 1 ) {
1305+ const auto &domain = domains[0 ]->domainOfValidity ();
1306+ if (domain && domain->geographicElements ().size () == 1 ) {
1307+ const auto bbox =
1308+ dynamic_cast <const GeographicBoundingBox *>(
1309+ domain->geographicElements ()[0 ].get ());
1310+ if (bbox) {
1311+ std::string vertCRSAuthName;
1312+ const auto &codeSpace = candidateHorizCRS.front ()
1313+ ->identifiers ()
1314+ .front ()
1315+ ->codeSpace ();
1316+ if (codeSpace.has_value ())
1317+ vertCRSAuthName = *codeSpace;
1318+ auto factoryVertCRS = AuthorityFactory::create (
1319+ dbContext, vertCRSAuthName);
1320+ const auto list = factoryVertCRS->getCRSInfoList ();
1321+ std::string horizAreaOfUse;
1322+ if (domain->description ().has_value ()) {
1323+ horizAreaOfUse = *(domain->description ());
1324+ const auto posDash = horizAreaOfUse.find (" -" );
1325+ if (posDash != std::string::npos)
1326+ horizAreaOfUse.resize (posDash);
1327+ }
1328+ for (size_t attempt = 0 ; first && attempt < 2 ;
1329+ ++attempt) {
1330+ for (const auto &info : list) {
1331+ if (!info.deprecated && info.bbox_valid &&
1332+ info.type ==
1333+ AuthorityFactory::ObjectType::
1334+ VERTICAL_CRS &&
1335+ !starts_with (info.name ,
1336+ " EPSG example" )) {
1337+ std::string vertAreaOfUse =
1338+ info.areaName ;
1339+ const auto posDash =
1340+ vertAreaOfUse.find (" -" );
1341+ if (posDash != std::string::npos)
1342+ vertAreaOfUse.resize (posDash);
1343+ bool ok = false ;
1344+ if (attempt == 0 &&
1345+ !horizAreaOfUse.empty ()) {
1346+ ok =
1347+ horizAreaOfUse == vertAreaOfUse;
1348+ } else if (attempt == 1 &&
1349+ vertAreaOfUse == " World." ) {
1350+ // auto vertCrsBbox =
1351+ // GeographicBoundingBox::create(info.west_lon_degree,
1352+ // info.south_lat_degree,
1353+ // info.east_lon_degree,
1354+ // info.north_lat_degree); if(
1355+ // bbox->intersects(vertCrsBbox))
1356+ { ok = true ; }
1357+ }
1358+ if (ok) {
1359+ if (!first)
1360+ printf (" " );
1361+ first = false ;
1362+ #ifdef DEBUG_COMPLETION
1363+ fprintf (stderr, " '%s'\n " ,
1364+ replaceAll (info.name , " " ,
1365+ " \\ " )
1366+ .c_str ());
1367+ #endif
1368+ printf (" %s" , replaceAll (info.name ,
1369+ " " , " \\ " )
1370+ .c_str ());
1371+ }
1372+ }
1373+ }
1374+ if (!first) {
1375+ printf (" \n " );
1376+ }
1377+ }
1378+ }
1379+ }
1380+ }
1381+ }
1382+ }
1383+
12811384 } catch (const std::exception &) {
12821385 }
12831386}
0 commit comments