aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2018-12-03 18:13:05 +0100
committerEven Rouault <even.rouault@spatialys.com>2018-12-03 22:19:21 +0100
commit0ba9d249136ec7adf6e3a44c8148701818d0e63e (patch)
treedf8b68e9aa03c724a5cec632717f7b005217e961 /src
parentac24807d189e2deea969656a229aad7a8c1236c6 (diff)
downloadPROJ-0ba9d249136ec7adf6e3a44c8148701818d0e63e.tar.gz
PROJ-0ba9d249136ec7adf6e3a44c8148701818d0e63e.zip
projinfo: add a --area option (refs #1188)
Diffstat (limited to 'src')
-rw-r--r--src/factory.cpp35
-rw-r--r--src/projinfo.cpp76
2 files changed, 108 insertions, 3 deletions
diff --git a/src/factory.cpp b/src/factory.cpp
index 91d0c478..7bc9c4d2 100644
--- a/src/factory.cpp
+++ b/src/factory.cpp
@@ -3642,7 +3642,7 @@ std::list<common::IdentifiedObjectNNPtr>
AuthorityFactory::createObjectsFromName(
const std::string &searchedName,
const std::vector<ObjectType> &allowedObjectTypes, bool approximateMatch,
- size_t limitResultCount) {
+ size_t limitResultCount) const {
std::string searchedNameWithoutDeprecated(searchedName);
bool deprecated = false;
@@ -3885,6 +3885,39 @@ AuthorityFactory::createObjectsFromName(
// ---------------------------------------------------------------------------
+/** \brief Return a list of area of use from their name
+ *
+ * @param name Searched name.
+ * @param approximateMatch Whether approximate name identification is allowed.
+ * @return list of (auth_name, code) of matched objects.
+ * @throw FactoryException
+ */
+std::list<std::pair<std::string, std::string>>
+AuthorityFactory::listAreaOfUseFromName(const std::string &name,
+ bool approximateMatch) const {
+ std::string sql(
+ "SELECT auth_name, code FROM area WHERE deprecated = 0 AND ");
+ std::vector<SQLValues> params;
+ if (!getAuthority().empty()) {
+ sql += " auth_name = ? AND ";
+ params.emplace_back(getAuthority());
+ }
+ sql += "name LIKE ?";
+ if (!approximateMatch) {
+ params.push_back(name);
+ } else {
+ params.push_back('%' + name + '%');
+ }
+ auto sqlRes = d->run(sql, params);
+ std::list<std::pair<std::string, std::string>> res;
+ for (const auto &row : sqlRes) {
+ res.emplace_back(row[0], row[1]);
+ }
+ return res;
+}
+
+// ---------------------------------------------------------------------------
+
//! @cond Doxygen_Suppress
std::list<datum::EllipsoidNNPtr> AuthorityFactory::createEllipsoidFromExisting(
const datum::EllipsoidNNPtr &ellipsoid) const {
diff --git a/src/projinfo.cpp b/src/projinfo.cpp
index 5f580a6f..d13b5ee5 100644
--- a/src/projinfo.cpp
+++ b/src/projinfo.cpp
@@ -74,7 +74,8 @@ static void usage() {
std::cerr
<< "usage: projinfo [-o formats] [-k crs|operation] [--summary] [-q]"
<< std::endl
- << " [--bbox min_long,min_lat,max_long,max_lat] "
+ << " ([--area name_or_code] | "
+ "[--bbox min_long,min_lat,max_long,max_lat]) "
<< std::endl
<< " [--spatial-test contains|intersects]" << std::endl
<< " [--crs-extent-use none|both|intersection|smallest]"
@@ -565,6 +566,7 @@ int main(int argc, char **argv) {
bool kindIsCRS = true;
bool summary = false;
ExtentPtr bboxFilter = nullptr;
+ std::string area;
CoordinateOperationContext::SpatialCriterion spatialCriterion =
CoordinateOperationContext::SpatialCriterion::STRICT_CONTAINMENT;
CoordinateOperationContext::SourceTargetCRSExtentUse crsExtentUse =
@@ -686,6 +688,9 @@ int main(int argc, char **argv) {
<< ", " << e.what() << std::endl;
usage();
}
+ } else if (arg == "--area" && i + 1 < argc) {
+ i++;
+ area = argv[i];
} else if (arg == "-k" && i + 1 < argc) {
i++;
std::string kind(argv[i]);
@@ -818,12 +823,17 @@ int main(int argc, char **argv) {
}
}
+ if (bboxFilter && !area.empty()) {
+ std::cerr << "ERROR: --bbox and --area are exclusive" << std::endl;
+ std::exit(1);
+ }
+
DatabaseContextPtr dbContext;
try {
dbContext =
DatabaseContext::create(mainDBPath, auxDBPath).as_nullable();
} catch (const std::exception &e) {
- if (!mainDBPath.empty() || !auxDBPath.empty()) {
+ if (!mainDBPath.empty() || !auxDBPath.empty() || !area.empty()) {
std::cerr << "ERROR: Cannot create database connection: "
<< e.what() << std::endl;
std::exit(1);
@@ -928,6 +938,68 @@ int main(int argc, char **argv) {
}
}
} else {
+
+ if (!area.empty()) {
+ assert(dbContext);
+ try {
+ if (area.find(' ') == std::string::npos &&
+ area.find(':') != std::string::npos) {
+ auto tokens = split(area, ':');
+ if (tokens.size() == 2) {
+ const std::string &areaAuth = tokens[0];
+ const std::string &areaCode = tokens[1];
+ bboxFilter = AuthorityFactory::create(
+ NN_NO_CHECK(dbContext), areaAuth)
+ ->createExtent(areaCode)
+ .as_nullable();
+ }
+ }
+ if (!bboxFilter) {
+ auto authFactory = AuthorityFactory::create(
+ NN_NO_CHECK(dbContext), std::string());
+ auto res = authFactory->listAreaOfUseFromName(area, false);
+ if (res.size() == 1) {
+ bboxFilter =
+ AuthorityFactory::create(NN_NO_CHECK(dbContext),
+ res.front().first)
+ ->createExtent(res.front().second)
+ .as_nullable();
+ } else {
+ res = authFactory->listAreaOfUseFromName(area, true);
+ if (res.size() == 1) {
+ bboxFilter =
+ AuthorityFactory::create(NN_NO_CHECK(dbContext),
+ res.front().first)
+ ->createExtent(res.front().second)
+ .as_nullable();
+ } else if (res.empty()) {
+ std::cerr << "No area of use matching provided name"
+ << std::endl;
+ std::exit(1);
+ } else {
+ std::cerr << "Several candidates area of use "
+ "matching provided name :"
+ << std::endl;
+ for (const auto &candidate : res) {
+ auto obj =
+ AuthorityFactory::create(
+ NN_NO_CHECK(dbContext), candidate.first)
+ ->createExtent(candidate.second);
+ std::cerr << " " << candidate.first << ":"
+ << candidate.second << " : "
+ << *obj->description() << std::endl;
+ }
+ std::exit(1);
+ }
+ }
+ }
+ } catch (const std::exception &e) {
+ std::cerr << "Area of use retrieval failed: " << e.what()
+ << std::endl;
+ std::exit(1);
+ }
+ }
+
outputOperations(dbContext, sourceCRSStr, targetCRSStr, bboxFilter,
spatialCriterion, crsExtentUse, gridAvailabilityUse,
allowPivots, pivots, authority,