diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2020-03-03 19:42:44 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-03 19:42:44 +0100 |
| commit | b2ca8e5f6b1879d88312188fc9de24e0f32daf73 (patch) | |
| tree | 38d12ed11eaa630c51c0f1d980ace727a90fece4 /src | |
| parent | 57c12c27d2318d8c74d85e1d35c01cbed28986d0 (diff) | |
| download | PROJ-b2ca8e5f6b1879d88312188fc9de24e0f32daf73.tar.gz PROJ-b2ca8e5f6b1879d88312188fc9de24e0f32daf73.zip | |
createUnitOfMeasure(): use full double resolution for the conversion factor (#2011)
Fixes https://github.com/OSGeo/gdal/issues/2290 where it was found that
PROJ returned value for conversion factor of US Survey Foot unit wasn't
at the maximum resolution, but only accurate to 15 significant digits.
Diffstat (limited to 'src')
| -rw-r--r-- | src/iso19111/factory.cpp | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index e7017ca3..a4529c9f 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -52,6 +52,7 @@ #include <cstring> #include <iomanip> #include <limits> +#include <locale> #include <map> #include <memory> #include <sstream> // std::ostringstream @@ -138,7 +139,8 @@ struct DatabaseContext::Private { void setPjCtxt(PJ_CONTEXT *ctxt) { pjCtxt_ = ctxt; } SQLResultSet run(const std::string &sql, - const ListOfParams ¶meters = ListOfParams()); + const ListOfParams ¶meters = ListOfParams(), + bool useMaxFloatPrecision = false); std::vector<std::string> getDatabaseStructure(); @@ -733,7 +735,8 @@ void DatabaseContext::Private::registerFunctions() { // --------------------------------------------------------------------------- SQLResultSet DatabaseContext::Private::run(const std::string &sql, - const ListOfParams ¶meters) { + const ListOfParams ¶meters, + bool useMaxFloatPrecision) { sqlite3_stmt *stmt = nullptr; auto iter = mapSqlToStatement_.find(sql); @@ -791,10 +794,20 @@ SQLResultSet DatabaseContext::Private::run(const std::string &sql, if (ret == SQLITE_ROW) { SQLRow row(column_count); for (int i = 0; i < column_count; i++) { - const char *txt = reinterpret_cast<const char *>( - sqlite3_column_text(stmt, i)); - if (txt) { - row[i] = txt; + if (useMaxFloatPrecision && + sqlite3_column_type(stmt, i) == SQLITE_FLOAT) { + // sqlite3_column_text() does not use maximum precision + std::ostringstream buffer; + buffer.imbue(std::locale::classic()); + buffer << std::setprecision(18); + buffer << sqlite3_column_double(stmt, i); + row[i] = buffer.str(); + } else { + const char *txt = reinterpret_cast<const char *>( + sqlite3_column_text(stmt, i)); + if (txt) { + row[i] = txt; + } } } result.emplace_back(std::move(row)); @@ -1646,10 +1659,10 @@ AuthorityFactory::createUnitOfMeasure(const std::string &code) const { return NN_NO_CHECK(uom); } } - auto res = d->runWithCodeParam( + auto res = d->context()->d->run( "SELECT name, conv_factor, type, deprecated FROM unit_of_measure WHERE " "auth_name = ? AND code = ?", - code); + {d->authority(), code}, true); if (res.empty()) { throw NoSuchAuthorityCodeException("unit of measure not found", d->authority(), code); |
