Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add proj_get_units_from_database() (fixes #2004) #2065

Merged
merged 2 commits into from
Mar 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions data/sql/customizations.sql
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,35 @@ INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6312','hermannskogel','
INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6299','ire65','PROJ');
INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6272','nzgd49','PROJ');
INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6277','OSGB36','PROJ');

---- PROJ unit short names -----

-- Linear units
UPDATE unit_of_measure SET proj_short_name = 'mm' WHERE auth_name = 'EPSG' AND code = '1025';
UPDATE unit_of_measure SET proj_short_name = 'cm' WHERE auth_name = 'EPSG' AND code = '1033';
UPDATE unit_of_measure SET proj_short_name = 'm' WHERE auth_name = 'EPSG' AND code = '9001';
UPDATE unit_of_measure SET proj_short_name = 'ft' WHERE auth_name = 'EPSG' AND code = '9002';
UPDATE unit_of_measure SET proj_short_name = 'us-ft' WHERE auth_name = 'EPSG' AND code = '9003';
UPDATE unit_of_measure SET proj_short_name = 'fath' WHERE auth_name = 'EPSG' AND code = '9014';
UPDATE unit_of_measure SET proj_short_name = 'kmi' WHERE auth_name = 'EPSG' AND code = '9030';
UPDATE unit_of_measure SET proj_short_name = 'us-ch' WHERE auth_name = 'EPSG' AND code = '9033';
UPDATE unit_of_measure SET proj_short_name = 'us-mi' WHERE auth_name = 'EPSG' AND code = '9035';
UPDATE unit_of_measure SET proj_short_name = 'km' WHERE auth_name = 'EPSG' AND code = '9036';
UPDATE unit_of_measure SET proj_short_name = 'ind-ft' WHERE auth_name = 'EPSG' AND code = '9081';
UPDATE unit_of_measure SET proj_short_name = 'ind-yd' WHERE auth_name = 'EPSG' AND code = '9085';
UPDATE unit_of_measure SET proj_short_name = 'mi' WHERE auth_name = 'EPSG' AND code = '9093';
UPDATE unit_of_measure SET proj_short_name = 'yd' WHERE auth_name = 'EPSG' AND code = '9096';
UPDATE unit_of_measure SET proj_short_name = 'ch' WHERE auth_name = 'EPSG' AND code = '9097';
UPDATE unit_of_measure SET proj_short_name = 'link' WHERE auth_name = 'EPSG' AND code = '9098';

-- Angular units
UPDATE unit_of_measure SET proj_short_name = 'rad' WHERE auth_name = 'EPSG' AND code = '9101';
UPDATE unit_of_measure SET proj_short_name = 'deg' WHERE auth_name = 'EPSG' AND code = '9102';
UPDATE unit_of_measure SET proj_short_name = 'grad' WHERE auth_name = 'EPSG' AND code = '9105';

-- PROJ specific units
INSERT INTO "unit_of_measure" VALUES('PROJ','DM','decimeter','length',0.01,'dm',0);
INSERT INTO "unit_of_measure" VALUES('PROJ','IN','inch','length',0.0254,'in',0);
INSERT INTO "unit_of_measure" VALUES('PROJ','US_IN','US survey inch','length',0.025400050800101,'us-in',0);
INSERT INTO "unit_of_measure" VALUES('PROJ','US_YD','US survey yard','length',0.914401828803658,'us-yd',0);
INSERT INTO "unit_of_measure" VALUES('PROJ','IND_CH','Indian chain','length',20.11669506,'ind-ch',0);
1 change: 1 addition & 0 deletions data/sql/proj_db_table_defs.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CREATE TABLE unit_of_measure(
name TEXT NOT NULL CHECK (length(name) >= 2),
type TEXT NOT NULL CHECK (type IN ('length', 'angle', 'scale', 'time')),
conv_factor FLOAT,
proj_short_name TEXT, -- PROJ string name, like 'm', 'ft'. Might be NULL
deprecated BOOLEAN NOT NULL CHECK (deprecated IN (0, 1)),
CONSTRAINT pk_unit_of_measure PRIMARY KEY (auth_name, code)
);
Expand Down
190 changes: 95 additions & 95 deletions data/sql/unit_of_measure.sql

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions docs/source/development/reference/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,9 @@ Lists
entry of the returned array is a NULL-entry. The array is statically
allocated and does not need to be freed after use.

Note: starting with PROJ 7.1, this function is deprecated by
rouault marked this conversation as resolved.
Show resolved Hide resolved
:cpp:func:`proj_get_units_from_database`

:returns: :c:type:`PJ_UNITS*`

.. c:function:: const PJ_PRIME_MERIDIANS* proj_list_prime_meridians(void)
Expand Down
30 changes: 29 additions & 1 deletion include/proj/io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,8 @@ class PROJ_GCC_DLL AuthorityFactory {

PROJ_DLL std::string getDescriptionText(const std::string &code) const;

// non-standard

/** CRS information */
struct CRSInfo {
/** Authority name */
Expand Down Expand Up @@ -1049,7 +1051,33 @@ class PROJ_GCC_DLL AuthorityFactory {

PROJ_DLL std::list<CRSInfo> getCRSInfoList() const;

// non-standard
/** Unit information */
struct UnitInfo {
/** Authority name */
std::string authName;
/** Code */
std::string code;
/** Name */
std::string name;
/** Category: one of "linear", "linear_per_time", "angular",
* "angular_per_time", "scale", "scale_per_time" or "time" */
std::string category;
/** Conversion factor to the SI unit.
* It might be 0 in some cases to indicate no known conversion factor.
*/
double convFactor;
/** PROJ short name (may be empty) */
std::string projShortName;
/** Whether the object is deprecated */
bool deprecated;

//! @cond Doxygen_Suppress
UnitInfo();
//! @endcond
};

PROJ_DLL std::list<UnitInfo> getUnitList() const;

PROJ_DLL static AuthorityFactoryNNPtr
create(const DatabaseContextNNPtr &context,
const std::string &authorityName);
Expand Down
2 changes: 1 addition & 1 deletion scripts/build_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def ingest_epsg():

def fill_unit_of_measure(proj_db_cursor):
proj_db_cursor.execute(
"INSERT INTO unit_of_measure SELECT ?, uom_code, unit_of_meas_name, unit_of_meas_type, factor_b / factor_c, deprecated FROM epsg.epsg_unitofmeasure", (EPSG_AUTHORITY,))
"INSERT INTO unit_of_measure SELECT ?, uom_code, unit_of_meas_name, unit_of_meas_type, factor_b / factor_c, NULL, deprecated FROM epsg.epsg_unitofmeasure", (EPSG_AUTHORITY,))


def fill_ellipsoid(proj_db_cursor):
Expand Down
17 changes: 12 additions & 5 deletions src/apps/cs2cs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,11 +425,18 @@ int main(int argc, char **argv) {
(void)printf("%9s %-16s %-16s %s\n", le->id,
le->major, le->ell, le->name);
} else if (arg[1] == 'u') { /* list units */
const struct PJ_UNITS *lu;

for (lu = proj_list_units(); lu->id; ++lu)
(void)printf("%12s %-20s %s\n", lu->id,
lu->to_meter, lu->name);
auto units = proj_get_units_from_database(nullptr, nullptr, "linear", false, nullptr);
for( int i = 0; units && units[i]; i++ )
{
if( units[i]->proj_short_name )
{
(void)printf("%12s %-20.15g %s\n",
units[i]->proj_short_name,
units[i]->conv_factor,
units[i]->name);
}
}
proj_unit_list_destroy(units);
} else if (arg[1] == 'm') { /* list prime meridians */
const struct PJ_PRIME_MERIDIANS *lpm;

Expand Down
17 changes: 12 additions & 5 deletions src/apps/geod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,18 @@ noargument: emess(1,"missing argument for -%c",*arg);
(void)printf("%9s %-16s %-16s %s\n",
le->id, le->major, le->ell, le->name);
} else if (arg[1] == 'u') { /* list of units */
const struct PJ_UNITS *lu;

for (lu = proj_list_units();lu->id ; ++lu)
(void)printf("%12s %-20s %s\n",
lu->id, lu->to_meter, lu->name);
auto units = proj_get_units_from_database(nullptr, nullptr, "linear", false, nullptr);
for( int i = 0; units && units[i]; i++ )
{
if( units[i]->proj_short_name )
{
(void)printf("%12s %-20.15g %s\n",
units[i]->proj_short_name,
units[i]->conv_factor,
units[i]->name);
}
}
proj_unit_list_destroy(units);
} else
emess(1,"invalid list option: l%c",arg[1]);
exit( 0 );
Expand Down
24 changes: 15 additions & 9 deletions src/apps/geod_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ geod_set(int argc, char **argv) {
paralist *start = nullptr, *curr;
double es;
char *name;
int i;

/* put arguments into internal linked list */
if (argc <= 0)
emess(1, "no arguments in initialization list");
start = curr = pj_mkparam(argv[0]);
if (!curr)
emess(1, "memory allocation failed");
for (i = 1; curr != nullptr && i < argc; ++i) {
for (int i = 1; curr != nullptr && i < argc; ++i) {
curr->next = pj_mkparam(argv[i]);
if (!curr->next)
emess(1, "memory allocation failed");
Expand All @@ -32,13 +31,20 @@ geod_set(int argc, char **argv) {
if (pj_ell_set(pj_get_default_ctx(),start, &geod_a, &es)) emess(1,"ellipse setup failure");
/* set units */
if ((name = pj_param(nullptr,start, "sunits").s) != nullptr) {
const char *s;
const struct PJ_UNITS *unit_list = proj_list_units();
for (i = 0; (s = unit_list[i].id) && strcmp(name, s) ; ++i) ;
if (!s)
emess(1,"%s unknown unit conversion id", name);
to_meter = unit_list[i].factor;
fr_meter = 1 / to_meter;
bool unit_found = false;
auto units = proj_get_units_from_database(nullptr, nullptr, "linear", false, nullptr);
for( int i = 0; units && units[i]; i++ )
{
if( units[i]->proj_short_name &&
strcmp(units[i]->proj_short_name, name) == 0 ) {
unit_found = true;
to_meter = units[i]->conv_factor;
fr_meter = 1 / to_meter;
}
}
proj_unit_list_destroy(units);
if( !unit_found )
emess(1,"%s unknown unit conversion id", name);
} else
to_meter = fr_meter = 1;
geod_f = es/(1 + sqrt(1 - es));
Expand Down
17 changes: 12 additions & 5 deletions src/apps/proj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,11 +380,18 @@ int main(int argc, char **argv) {
(void)printf("%9s %-16s %-16s %s\n",
le->id, le->major, le->ell, le->name);
} else if (arg[1] == 'u') { /* list units */
const struct PJ_UNITS *lu;

for (lu = proj_list_units(); lu->id ; ++lu)
(void)printf("%12s %-20s %s\n",
lu->id, lu->to_meter, lu->name);
auto units = proj_get_units_from_database(nullptr, nullptr, "linear", false, nullptr);
for( int i = 0; units && units[i]; i++ )
{
if( units[i]->proj_short_name )
{
(void)printf("%12s %-20.15g %s\n",
units[i]->proj_short_name,
units[i]->conv_factor,
units[i]->name);
}
}
proj_unit_list_destroy(units);
} else
emess(1,"invalid list option: l%c",arg[1]);
exit(0);
Expand Down
4 changes: 1 addition & 3 deletions src/conversions/unitconvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,7 @@ static double get_unit_conversion_factor(const char* name,
/***********************************************************************/
int i;
const char* s;
const PJ_UNITS *units;

units = proj_list_units();
const PJ_UNITS *units = pj_list_linear_units();

/* Try first with linear units */
for (i = 0; (s = units[i].id) ; ++i) {
Expand Down
2 changes: 1 addition & 1 deletion src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
return pj_default_destructor (PIN, PJD_ERR_K_LESS_THAN_ZERO);

/* Set units */
units = proj_list_units();
units = pj_list_linear_units();
s = nullptr;
if ((name = pj_param(ctx, start, "sunits").s) != nullptr) {
for (i = 0; (s = units[i].id) && strcmp(name, s) ; ++i) ;
Expand Down
Loading