aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Evers <kristianevers@gmail.com>2021-09-27 09:38:29 +0200
committerGitHub <noreply@github.com>2021-09-27 09:38:29 +0200
commitd4c7584cf8345f43706279a2e6d416e705b38b9f (patch)
tree6194405ff994c1f5aaa3738042487b89601e59aa
parent15a619c4e56c53d36ab6c9ea458b603b215c87fa (diff)
parente33ddabcf8866731b5360a3db2c7552229a48a41 (diff)
downloadPROJ-d4c7584cf8345f43706279a2e6d416e705b38b9f.tar.gz
PROJ-d4c7584cf8345f43706279a2e6d416e705b38b9f.zip
Merge pull request #2870 from OSGeo/backport-2863-to-8.1
[Backport 8.1] DOC: Refresh Development/Quickstart and remove Development/Threads
-rw-r--r--docs/source/development/index.rst1
-rw-r--r--docs/source/development/quickstart.rst168
-rw-r--r--docs/source/development/threads.rst79
-rw-r--r--examples/pj_obs_api_mini_demo.c33
4 files changed, 122 insertions, 159 deletions
diff --git a/docs/source/development/index.rst b/docs/source/development/index.rst
index 2d544189..06e1d36a 100644
--- a/docs/source/development/index.rst
+++ b/docs/source/development/index.rst
@@ -14,7 +14,6 @@ PROJ project or using the library in their own software.
quickstart
transformations
errorhandling
- threads
reference/index
cmake
bindings
diff --git a/docs/source/development/quickstart.rst b/docs/source/development/quickstart.rst
index eefd5ac3..5be85641 100644
--- a/docs/source/development/quickstart.rst
+++ b/docs/source/development/quickstart.rst
@@ -28,10 +28,9 @@ See the :doc:`reference for more info on data types <reference/datatypes>`.
:lines: 43-46
:dedent: 4
-For use in multi-threaded programs the :c:type:`PJ_CONTEXT` threading-context is used.
-In this particular example it is not needed, but for the sake of completeness
-it created here. The section on :doc:`threads <threads>` discusses
-this in detail.
+For use in multi-threaded programs the :c:type:`PJ_CONTEXT` threading-context
+is used. In this particular example it is not needed, but for the sake of
+completeness we demonstrate its use here.
.. literalinclude:: ../../../examples/pj_obs_api_mini_demo.c
:language: c
@@ -39,13 +38,38 @@ this in detail.
:dedent: 4
Next we create the :c:type:`PJ` transformation object ``P`` with the function
-:c:func:`proj_create_crs_to_crs`. :c:func:`proj_create_crs_to_crs` takes the threading context ``C``
-created above, a string that describes the source coordinate reference system (CRS),
-a string that describes the target CRS and an optional description of the area of
-use.
-The strings for the source or target CRS may be PROJ strings (``+proj=longlat +datum=WGS84``),
-CRS identified by their code (``EPSG:4326`` or ``urn:ogc:def:crs:EPSG::4326``) or
-by a well-known text (WKT) string:
+:c:func:`proj_create_crs_to_crs`.
+
+.. literalinclude:: ../../../examples/pj_obs_api_mini_demo.c
+ :language: c
+ :lines: 52-60
+ :dedent: 4
+
+Here we have set up a transformation from geographic coordinates to UTM zone
+32N.
+
+:c:func:`proj_create_crs_to_crs` takes as its arguments:
+
+- the threading context ``C`` created above,
+- a string that describes the source coordinate reference system (CRS),
+- a string that describes the target CRS and
+- an optional description of the area of use.
+
+It is recommended to create one threading context per thread used by the
+program. This ensures that all :c:type:`PJ` objects created in the same
+context will be sharing resources such as error-numbers and loaded grids.
+
+If you are sure that ``P`` will only be used by a single program thread, you
+may pass ``NULL`` for the threading context. This will assign the default
+thread context to ``P``.
+
+The strings for the source and target CRS may be any of:
+
+- PROJ strings, e.g. ``+proj=longlat +datum=WGS84 +type=crs``,
+- CRS identified by their code, e.g. ``EPSG:4326`` or
+ ``urn:ogc:def:crs:EPSG::4326``, or
+- a well-known text (WKT) string, e.g.:
+
::
GEOGCRS["WGS 84",
@@ -67,89 +91,107 @@ by a well-known text (WKT) string:
BBOX[-90,-180,90,180]],
ID["EPSG",4326]]
-The use of PROJ strings to describe a CRS is considered as legacy (one of the
-main weakness of PROJ strings is their inability to describe a geodetic datum,
-other than the few ones hardcoded in the ``+datum`` parameter).
-Here we transform from geographic coordinates to UTM zone 32N.
-It is recommended to create one threading-context per thread used by the program.
-This ensures that all :c:type:`PJ` objects created in the same context will be
-sharing resources such as error-numbers and loaded grids.
-In case the creation of the :c:type:`PJ` object fails an error message is
-displayed and the program returns. See :doc:`errorhandling` for further
-details.
+.. warning::
-.. literalinclude:: ../../../examples/pj_obs_api_mini_demo.c
- :language: c
- :lines: 52-60
- :dedent: 4
+ The use of PROJ strings to describe a CRS is not recommended. One of the
+ main weaknesses of PROJ strings is their inability to describe a geodetic
+ datum, other than the few ones hardcoded in the ``+datum`` parameter.
+
+:c:func:`proj_create_crs_to_crs` will return a pointer to a :c:type:`PJ`
+object, or a null pointer in the case of an error. The details of the error
+can be retrieved using :c:func:`proj_context_errno`. See :doc:`errorhandling`
+for further details.
+
+Now that we have a normalized transformation object in ``P``, we can use it
+with :c:func:`proj_trans` to transform coordinates from the source CRS to the
+target CRS, but first we will discuss the interpretation of coordinates.
+
+By default, a :c:type:`PJ` transformation object accepts coordinates expressed
+in the units and axis order of the source CRS, and returns transformed
+coordinates in the units and axis order of the target CRS.
+
+For most geographic CRS, the units will be in degrees. In rare cases, such as
+EPSG:4807 / NTF (Paris), this can be grads. For geographic CRS defined by the
+EPSG authority, the order of coordinates is latitude first, longitude second.
+When using a PROJ string, the order is the reverse; longitude first, latitude
+second.
+
+For projected CRS, the units may vary (metre, us-foot, etc.). For projected CRS
+defined by the EPSG authority, and with EAST / NORTH directions, the order
+might be easting first, northing second, or the reverse. When using a PROJ
+string, the order will be easting first, northing second, except if the
+``+axis`` parameter modifies it.
+
+If you prefer to work with a uniform axis order, regardless of the axis orders
+mandated by the source and target CRS, you can use the
+:c:func:`proj_normalize_for_visualization` function.
-:c:func:`proj_create_crs_to_crs` creates a transformation object, which accepts
-coordinates expressed in the units and axis order of the definition of the
-source CRS, and return transformed coordinates in the units and axis order of
-the definition of the target CRS.
-For almost most geographic CRS, the units will be in most cases degrees (in
-rare cases, such as EPSG:4807 / NTF (Paris), this can be grads). For geographic
-CRS defined by the EPSG authority, the order of coordinates is latitude first,
-longitude second. When using a PROJ string, on contrary the order will be
-longitude first, latitude second.
-For projected CRS, the units may vary (metre, us-foot, etc..). For projected
-CRS defined by the EPSG authority, and with EAST / NORTH directions, the order
-might be easting first, northing second, or the reverse. When using a PROJ string,
-the order will be easting first, northing second, except if the ``+axis``
-parameter modifies it.
-
-If for the needs of your software, you want
-a uniform axis order (and thus do not care about axis order mandated by the
-authority defining the CRS), the :c:func:`proj_normalize_for_visualization`
-function can be used to modify the PJ* object returned by
-:c:func:`proj_create_crs_to_crs` so that it accepts as input and returns as
-output coordinates using the traditional GIS order, that is longitude, latitude
-(followed by elevation, time) for geographic CRS and easting, northing for most
-projected CRS.
+:c:func:`proj_normalize_for_visualization` takes a threading context and an
+existing :c:type:`PJ` object, and generates from it a new :c:type:`PJ` that
+accepts as input and returns as output coordinates using the traditional GIS
+order. That is, longitude followed by latitude, optionally followed by
+elevation and time for geographic CRS, and easting followed by northing for
+most projected CRS.
.. literalinclude:: ../../../examples/pj_obs_api_mini_demo.c
:language: c
:lines: 65-71
:dedent: 4
-PROJ uses its own data structures for handling coordinates. Here we use a
-:c:type:`PJ_COORD` which is easily assigned with the function :c:func:`proj_coord`.
-When using ``+proj=longlat``, the order of coordinates is longitude, latitude,
-and values are expressed in degrees. If you used instead a EPSG geographic CRS,
-like EPSG:4326 (WGS84), it would be latitude, longitude.
+Next we create a :c:type:`PJ_COORD` coordinate object, using the function
+:c:func:`proj_coord`.
+
+The following example creates a coordinate for 55°N 12°E (Copenhagen).
+
+Because we have normalized the transformation object with
+:c:func:`proj_normalize_for_visualization`, the order of coordinates is
+longitude followed by latitude, and the units are degrees.
.. literalinclude:: ../../../examples/pj_obs_api_mini_demo.c
:language: c
:lines: 76
:dedent: 4
-The coordinate defined above is transformed with :c:func:`proj_trans`. For this
-a :c:type:`PJ` object, a transformation direction (either forward or inverse)
-and the coordinate is needed. The transformed coordinate is returned in ``b``.
-Here the forward (:c:type:`PJ_FWD`) transformation from geographic to UTM is made.
+Now we are ready to transform the coordinate into UTM zone 32, using the
+function :c:func:`proj_trans`.
.. literalinclude:: ../../../examples/pj_obs_api_mini_demo.c
:language: c
:lines: 79-80
:dedent: 4
-The inverse transformation (UTM to geographic) is done similar to above,
-this time using :c:type:`PJ_INV` as the direction.
+:c:func:`proj_trans` takes as its arguments:
+
+- a :c:type:`PJ` transformation object,
+- a :c:type:`PJ_DIRECTION` direction, and
+- the :c:type:`PJ_COORD` coordinate to transform.
+
+The direction argument can be one of:
+
+- ``PJ_FWD`` -- "forward" transformation from source CRS to target CRS.
+- ``PJ_IDENT`` -- "identity", return the source coordinate unchanged.
+- ``PJ_INV`` -- "inverse" transformation from target CRS to source CRS.
+
+It returns the new transformed :c:type:`PJ_COORD` coordinate.
+
+We can perform the transformation in reverse (from UTM zone 32 back to
+geographic) as follows:
.. literalinclude:: ../../../examples/pj_obs_api_mini_demo.c
:language: c
- :lines: 81-82
+ :lines: 82-83
:dedent: 4
-Before ending the program the allocated memory needs to be released again:
+Before ending the program, we need to release the memory allocated to our
+objects:
.. literalinclude:: ../../../examples/pj_obs_api_mini_demo.c
:language: c
- :lines: 85-86
+ :lines: 86-87
:dedent: 4
-A complete compilable version of the above can be seen here:
+A complete compilable version of the example code can be seen below:
.. literalinclude:: ../../../examples/pj_obs_api_mini_demo.c
:language: c
diff --git a/docs/source/development/threads.rst b/docs/source/development/threads.rst
deleted file mode 100644
index 674f4bd1..00000000
--- a/docs/source/development/threads.rst
+++ /dev/null
@@ -1,79 +0,0 @@
-.. _threads:
-
-================================================================================
-Threads
-================================================================================
-
-This page is about efforts to make PROJ thread safe.
-
-Key Thread Safety Issues
---------------------------------------------------------------------------------
-
-* the global pj_errno variable is shared between threads and makes it
- essentially impossible to handle errors safely. Being addressed with the
- introduction of the projCtx execution context.
-* the datum shift using grid files uses globally shared lists of loaded grid
- information. Access to this has been made safe in 4.7.0 with the introduction
- of a PROJ mutex used to protect access to these memory structures (see
- pj_mutex.c).
-
-projCtx
---------------------------------------------------------------------------------
-
-Primarily in order to avoid having pj_errno as a global variable, a "thread
-context" structure has been introduced into a variation of the PROJ API for
-the 4.8.0 release. The pj_init() and pj_init_plus() functions now have context
-variations called pj_init_ctx() and pj_init_plus_ctx() which take a projections
-context.
-
-The projections context can be created with pj_ctx_alloc(), and there is a
-global default context used when one is not provided by the application. There
-is a pj_ctx\_ set of functions to create, manipulate, query, and destroy
-contexts. The contexts are also used now to handle setting debugging mode, and
-to hold an error reporting function for textual error and debug messages. The
-API looks like:
-
-::
-
- projPJ pj_init_ctx( projCtx, int, char ** );
- projPJ pj_init_plus_ctx( projCtx, const char * );
-
- projCtx pj_get_default_ctx(void);
- projCtx pj_get_ctx( projPJ );
- void pj_set_ctx( projPJ, projCtx );
- projCtx pj_ctx_alloc(void);
- void pj_ctx_free( projCtx );
- int pj_ctx_get_errno( projCtx );
- void pj_ctx_set_errno( projCtx, int );
- void pj_ctx_set_debug( projCtx, int );
- void pj_ctx_set_logger( projCtx, void (*)(void *, int, const char *) );
- void pj_ctx_set_app_data( projCtx, void * );
- void *pj_ctx_get_app_data( projCtx );
-
-Multithreaded applications are now expected to create a projCtx per thread
-using pj_ctx_alloc(). The context's error handlers, and app data may be
-modified if desired, but at the very least each context has an internal error
-value accessed with pj_ctx_get_errno() as opposed to looking at pj_errno.
-
-Note that pj_errno continues to exist, and it is set by pj_ctx_set_errno() (as
-well as setting the context specific error number), but pj_errno still suffers
-from the global shared problem between threads and should not be used by
-multithreaded applications.
-
-Note that pj_init_ctx(), and pj_init_plus_ctx() will assign the projCtx to the
-created projPJ object. Functions like pj_transform(), pj_fwd() and pj_inv()
-will use the context of the projPJ for error reporting.
-
-src/multistresstest.c
---------------------------------------------------------------------------------
-
-A small multi-threaded test program has been written (src/multistresstest.c)
-for testing multithreaded use of PROJ. It performs a series of reprojections
-to setup a table expected results, and then it does them many times in several
-threads to confirm that the results are consistent. At this time this program
-is not part of the builds but it can be built on linux like:
-
-::
-
- gcc -g multistresstest.c .libs/libproj.so -lpthread -o multistresstest
- ./multistresstest
diff --git a/examples/pj_obs_api_mini_demo.c b/examples/pj_obs_api_mini_demo.c
index 3df94e2d..5cd5efe4 100644
--- a/examples/pj_obs_api_mini_demo.c
+++ b/examples/pj_obs_api_mini_demo.c
@@ -1,6 +1,6 @@
/*******************************************************************************
- Tiny test of an evolving new API, demonstrating simple examples of
- 2D and 3D transformations.
+ Simple example code demonstrating use of the proj.h API for 2D coordinate
+ transformations.
The main transformation setup object is PJ, well known from the two
former proj APIs (projects.h and proj_api.h)
@@ -42,7 +42,7 @@
int main (void) {
PJ_CONTEXT *C;
PJ *P;
- PJ* P_for_GIS;
+ PJ *norm;
PJ_COORD a, b;
/* or you may set C=PJ_DEFAULT_CTX if you are sure you will */
@@ -54,35 +54,36 @@ int main (void) {
"+proj=utm +zone=32 +datum=WGS84", /* or EPSG:32632 */
NULL);
- if (0==P) {
- fprintf(stderr, "Oops\n");
+ if (0 == P) {
+ fprintf(stderr, "Failed to create transformation object.\n");
return 1;
}
/* This will ensure that the order of coordinates for the input CRS */
/* will be longitude, latitude, whereas EPSG:4326 mandates latitude, */
/* longitude */
- P_for_GIS = proj_normalize_for_visualization(C, P);
- if( 0 == P_for_GIS ) {
- fprintf(stderr, "Oops\n");
+ norm = proj_normalize_for_visualization(C, P);
+ if (0 == norm) {
+ fprintf(stderr, "Failed to normalize transformation object.\n");
return 1;
}
proj_destroy(P);
- P = P_for_GIS;
+ P = norm;
/* a coordinate union representing Copenhagen: 55d N, 12d E */
/* Given that we have used proj_normalize_for_visualization(), the order of
/* coordinates is longitude, latitude, and values are expressed in degrees. */
- a = proj_coord (12, 55, 0, 0);
+ a = proj_coord(12, 55, 0, 0);
/* transform to UTM zone 32, then back to geographical */
- b = proj_trans (P, PJ_FWD, a);
- printf ("easting: %.3f, northing: %.3f\n", b.enu.e, b.enu.n);
- b = proj_trans (P, PJ_INV, b);
- printf ("longitude: %g, latitude: %g\n", b.lp.lam, b.lp.phi);
+ b = proj_trans(P, PJ_FWD, a);
+ printf("easting: %.3f, northing: %.3f\n", b.enu.e, b.enu.n);
+
+ b = proj_trans(P, PJ_INV, b);
+ printf("longitude: %g, latitude: %g\n", b.lp.lam, b.lp.phi);
/* Clean up */
- proj_destroy (P);
- proj_context_destroy (C); /* may be omitted in the single threaded case */
+ proj_destroy(P);
+ proj_context_destroy(C); /* may be omitted in the single threaded case */
return 0;
}