Skip to content

Commit

Permalink
Merge remote-tracking branch 'rouault/gdalbarn'
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Dec 9, 2018
2 parents 23127c0 + 9d60a52 commit 3945d99
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 25 deletions.
2 changes: 0 additions & 2 deletions include/proj/internal/coordinateoperation_internal.hpp
Expand Up @@ -66,8 +66,6 @@ const MethodMapping *getMapping(const char *wkt2_name) noexcept;
const MethodMapping *getMapping(const OperationMethod *method) noexcept;
std::vector<const MethodMapping *>
getMappingsFromPROJName(const std::string &projName);
const ParamMapping *getMapping(const MethodMapping *mapping,
const OperationParameterValue *param);
const ParamMapping *getMappingFromWKT1(const MethodMapping *mapping,
const std::string &wkt1_name);
bool areEquivalentParameters(const std::string &a, const std::string &b);
Expand Down
49 changes: 35 additions & 14 deletions src/coordinateoperation.cpp
Expand Up @@ -264,21 +264,37 @@ getMappingsFromPROJName(const std::string &projName) {

// ---------------------------------------------------------------------------

const ParamMapping *getMapping(const MethodMapping *mapping,
const OperationParameterValue *param) {
const auto &param_name = param->parameter()->name();
const std::string &name = *(param_name->description());
const std::string &code = param_name->code();
const int epsg_code = !code.empty() ? ::atoi(code.c_str()) : 0;
static const ParamMapping *getMapping(const MethodMapping *mapping,
const OperationParameterNNPtr &param) {
// First try with id
const int epsg_code = param->getEPSGCode();
if (epsg_code) {
for (int i = 0; mapping->params[i] != nullptr; ++i) {
const auto *paramMapping = mapping->params[i];
if (paramMapping->epsg_code == epsg_code) {
return paramMapping;
}
}
}

// then equivalent name
const std::string &name = param->nameStr();
for (int i = 0; mapping->params[i] != nullptr; ++i) {
const auto *paramMapping = mapping->params[i];
if (metadata::Identifier::isEquivalentName(paramMapping->wkt2_name,
name.c_str()) ||
(epsg_code != 0 && paramMapping->epsg_code == epsg_code) ||
areEquivalentParameters(paramMapping->wkt2_name, name)) {
name.c_str())) {
return paramMapping;
}
}

// and finally different name, but equivalent parameter
for (int i = 0; mapping->params[i] != nullptr; ++i) {
const auto *paramMapping = mapping->params[i];
if (areEquivalentParameters(paramMapping->wkt2_name, name)) {
return paramMapping;
}
}

return nullptr;
}

Expand Down Expand Up @@ -1002,7 +1018,7 @@ void OperationParameterValue::_exportToWKT(
void OperationParameterValue::_exportToWKT(io::WKTFormatter *formatter,
const MethodMapping *mapping) const {
const ParamMapping *paramMapping =
mapping ? getMapping(mapping, this) : nullptr;
mapping ? getMapping(mapping, d->parameter) : nullptr;
if (paramMapping && paramMapping->wkt1_name == nullptr) {
return;
}
Expand Down Expand Up @@ -9206,9 +9222,9 @@ static size_t getStepCount(const CoordinateOperationNNPtr &op) {

// ---------------------------------------------------------------------------

struct FilterAndSort {
struct FilterResults {

FilterAndSort(const std::vector<CoordinateOperationNNPtr> &sourceListIn,
FilterResults(const std::vector<CoordinateOperationNNPtr> &sourceListIn,
const CoordinateOperationContextNNPtr &contextIn,
const crs::CRSNNPtr &sourceCRSIn,
const crs::CRSNNPtr &targetCRSIn,
Expand All @@ -9223,6 +9239,9 @@ struct FilterAndSort {

computeAreaOfIntest();
filterOut(forceStrictContainmentTest);
}

FilterResults &andSort() {
sort();

// And now that we have a sorted list, we can remove uninteresting
Expand All @@ -9232,6 +9251,7 @@ struct FilterAndSort {
removeUninterestingOps();
removeDuplicateOps();
removeSyntheticNullTransforms();
return *this;
}

// ----------------------------------------------------------------------
Expand Down Expand Up @@ -9646,7 +9666,8 @@ static std::vector<CoordinateOperationNNPtr>
filterAndSort(const std::vector<CoordinateOperationNNPtr> &sourceList,
const CoordinateOperationContextNNPtr &context,
const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS) {
return FilterAndSort(sourceList, context, sourceCRS, targetCRS, false)
return FilterResults(sourceList, context, sourceCRS, targetCRS, false)
.andSort()
.getRes();
}
//! @endcond
Expand Down Expand Up @@ -10449,7 +10470,7 @@ createNullGeocentricTranslation(const crs::CRSNNPtr &sourceCRS,

bool CoordinateOperationFactory::Private::hasPerfectAccuracyResult(
const std::vector<CoordinateOperationNNPtr> &res, const Context &context) {
auto resTmp = FilterAndSort(res, context.context, context.sourceCRS,
auto resTmp = FilterResults(res, context.context, context.sourceCRS,
context.targetCRS, true)
.getRes();
for (const auto &op : resTmp) {
Expand Down
68 changes: 59 additions & 9 deletions src/factory.cpp
Expand Up @@ -202,6 +202,21 @@ struct DatabaseContext::Private {
void cache(const std::string &code,
const std::vector<operation::CoordinateOperationNNPtr> &list);

struct GridInfoCache {
std::string fullFilename{};
std::string packageName{};
std::string url{};
bool found = false;
bool directDownload = false;
bool openLicense = false;
bool gridAvailable = false;
};

// cppcheck-suppress functionStatic
bool getGridInfoFromCache(const std::string &code, GridInfoCache &info);
// cppcheck-suppress functionStatic
void cache(const std::string &code, const GridInfoCache &info);

private:
friend class DatabaseContext;

Expand All @@ -226,6 +241,7 @@ struct DatabaseContext::Private {
LRUCacheOfObjects cacheExtent_{CACHE_SIZE};
lru11::Cache<std::string, std::vector<operation::CoordinateOperationNNPtr>>
cacheCRSToCrsCoordOp_{CACHE_SIZE};
lru11::Cache<std::string, GridInfoCache> cacheGridInfo_{CACHE_SIZE};

static void insertIntoCache(LRUCacheOfObjects &cache,
const std::string &code,
Expand Down Expand Up @@ -428,6 +444,20 @@ void DatabaseContext::Private::cache(const std::string &code,

// ---------------------------------------------------------------------------

bool DatabaseContext::Private::getGridInfoFromCache(const std::string &code,
GridInfoCache &info) {
return cacheGridInfo_.tryGet(code, info);
}

// ---------------------------------------------------------------------------

void DatabaseContext::Private::cache(const std::string &code,
const GridInfoCache &info) {
cacheGridInfo_.insert(code, info);
}

// ---------------------------------------------------------------------------

#ifdef ENABLE_CUSTOM_LOCKLESS_VFS

typedef int (*ClosePtr)(sqlite3_file *);
Expand Down Expand Up @@ -965,6 +995,17 @@ bool DatabaseContext::lookForGridInfo(const std::string &projFilename,
std::string &url, bool &directDownload,
bool &openLicense,
bool &gridAvailable) const {
Private::GridInfoCache info;
if (d->getGridInfoFromCache(projFilename, info)) {
fullFilename = info.fullFilename;
packageName = info.packageName;
url = info.url;
directDownload = info.directDownload;
openLicense = info.openLicense;
gridAvailable = info.gridAvailable;
return info.found;
}

fullFilename.clear();
packageName.clear();
url.clear();
Expand Down Expand Up @@ -994,15 +1035,24 @@ bool DatabaseContext::lookForGridInfo(const std::string &projFilename,
"grid_alternatives.package_name = grid_packages.package_name "
"WHERE proj_grid_name = ?",
{projFilename});
if (res.empty()) {
return false;
}
const auto &row = res.front();
packageName = std::move(row[0]);
url = row[1].empty() ? std::move(row[2]) : std::move(row[1]);
openLicense = (row[3].empty() ? row[4] : row[3]) == "1";
directDownload = (row[5].empty() ? row[6] : row[5]) == "1";
return true;
bool ret = !res.empty();
if (ret) {
const auto &row = res.front();
packageName = std::move(row[0]);
url = row[1].empty() ? std::move(row[2]) : std::move(row[1]);
openLicense = (row[3].empty() ? row[4] : row[3]) == "1";
directDownload = (row[5].empty() ? row[6] : row[5]) == "1";

info.fullFilename = fullFilename;
info.packageName = packageName;
info.url = url;
info.directDownload = directDownload;
info.openLicense = openLicense;
info.gridAvailable = gridAvailable;
}
info.found = ret;
d->cache(projFilename, info);
return ret;
}

// ---------------------------------------------------------------------------
Expand Down
33 changes: 33 additions & 0 deletions src/internal.cpp
Expand Up @@ -45,6 +45,8 @@
#include <sstream> // std::istringstream and std::ostringstream
#include <string>

#include "sqlite3.h"

NS_PROJ_START

namespace internal {
Expand Down Expand Up @@ -296,6 +298,12 @@ std::vector<std::string> split(const std::string &str, char separator) {

// ---------------------------------------------------------------------------

#ifdef _WIN32

// For some reason, sqlite3_snprintf() in the sqlite3 builds used on AppVeyor
// doesn't round identically to the Unix builds, and thus breaks a number of
// unit test. So to avoid this, use the stdlib formatting

std::string toString(int val) {
std::ostringstream buffer;
buffer.imbue(std::locale::classic());
Expand All @@ -319,6 +327,31 @@ std::string toString(double val, int precision) {
return str;
}

#else

std::string toString(int val) {
// use sqlite3 API that is slighly faster than std::ostringstream
// with forcing the C locale. sqlite3_snprintf() emulates a C locale.
constexpr int BUF_SIZE = 16;
char szBuffer[BUF_SIZE];
sqlite3_snprintf(BUF_SIZE, szBuffer, "%d", val);
return szBuffer;
}

std::string toString(double val, int precision) {
// use sqlite3 API that is slighly faster than std::ostringstream
// with forcing the C locale. sqlite3_snprintf() emulates a C locale.
constexpr int BUF_SIZE = 32;
char szBuffer[BUF_SIZE];
sqlite3_snprintf(BUF_SIZE, szBuffer, "%.*g", precision, val);
if (precision == 15 && strstr(szBuffer, "9999999999")) {
sqlite3_snprintf(BUF_SIZE, szBuffer, "%.14g", val);
}
return szBuffer;
}

#endif

// ---------------------------------------------------------------------------

std::string concat(const char *a, const std::string &b) {
Expand Down

0 comments on commit 3945d99

Please sign in to comment.