aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorThomas Knudsen <busstoptaktik@users.noreply.github.com>2017-07-07 17:14:28 +0200
committerGitHub <noreply@github.com>2017-07-07 17:14:28 +0200
commite09e24eddbd49cd802ac1334f229f1698ea0b755 (patch)
tree5578b6a9356486b26354288d1f09f990d4fb4134 /examples
parentced55e88a7f50205d57ddf8ed77d601daa8c5bfd (diff)
downloadPROJ-e09e24eddbd49cd802ac1334f229f1698ea0b755.tar.gz
PROJ-e09e24eddbd49cd802ac1334f229f1698ea0b755.zip
obs_api revision and improvements: new namespace etc. (#530)
* obs_api revision and improvements: new namespace etc. * Minor corrections: use unused functions, add missing prototype, added fwd/invcoord to PJ * Minor correction: MSVC barfs on va_arg type specification. Trying once more with added parens * Reverting paren correction, which appears to be a non-solution * Significant improvements to the OBS_API, plus a number of corrections, mostly in test code, to reflect API changes * Added two missing prototypes * Adding the proj_transform function and some related checks * Improvements to proj_transform etc. based on suggestions from Even Rouault * Reducing the libc include footprint of proj.h - again based on suggestions from Even Rouault * A few minor corrections * Eliminate a MSVC warning about non-initialized usage. Not an actual issue, as another check has locked the path, but at least this should calm down MSVC * Improved support for the errno reset/restore paradigm * Introduced the internal header proj_internal.h; Moved most non-API stuff from pj_obs_api.c to pj_internal.c * Adding proj_internal.h to HEADERS_LIBPROJ to solve build problems * Correcting a few pj...proj blunders in PJ_pipeline.c * Correcting a few additional blunders in PJ_pipeline.c * Changed angle-brackets to quotation marks in includes of proj_internal.h * Some minor build system repairs * Some PJ_CONTEXT usage simplifications following suggestions by Kristian Evers @kbevers * Added version numbering to proj.h - Fixes #529 * remove proj_errno_restore macro, provide function implementation * Add proj_get_definition. Fixes #538 * Added library specific deallocator proj_buffer_free, eliminating a potential cross heap issues on Windows. Thx to Even Rouault for spotting this * Got rid of a meaningless cast in proj_buffer_free * Added some missing functions to proj.def (again spotted by @rouault); removed some not-yet-implemented material from proj.h * Renamed proj_get_definition/proj_buffer_free to proj_definition_create/proj_definition_destroy, for symmetry and clarity * Renaming the definition handlers to proj_definition_retrieve / proj_free * Renaming proj_free to proj_release
Diffstat (limited to 'examples')
-rw-r--r--examples/pj_obs_api_mini_demo.c66
-rw-r--r--examples/pj_obs_api_test.c243
2 files changed, 66 insertions, 243 deletions
diff --git a/examples/pj_obs_api_mini_demo.c b/examples/pj_obs_api_mini_demo.c
new file mode 100644
index 00000000..855c37f8
--- /dev/null
+++ b/examples/pj_obs_api_mini_demo.c
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ Tiny test of an evolving new API, demonstrating simple examples of
+ 2D and 3D transformations.
+
+ The main transformation setup object is PJ, well known from the two
+ former proj APIs (projects.h and proj_api.h)
+
+ The main data objects PJ_COORD and PJ_OBS are new, but encapsulate
+ the older LP, XY etc. objects in a framework for storing a 3D
+ observation taken at a 4D point in space-time, and including some
+ additional metadata (e.g. a serial number or an epsg code).
+
+ PJ_OBS and PJ_COORD use unions to enforce explicit statement of what
+ kind of coordinates are expected at a given spot in the code, where
+ the old API uses type punning, implicitly assuming that "you know what
+ you do". For backward compatibility, the new API is not really type
+ safe in the sense that you cannot use a cartesian coordinate where a
+ geographic is expected - but it makes it possible to explicitly state
+ in the code whet the programmer expected and intended.
+
+ The proj thread contexts have not seen widespread use, so one of the
+ intentions with this new API is to make them less visible on the API
+ surface.
+
+ A series of experiments have, however, shown that they, for (mostly)
+ historical reasons, are very hard to eliminate totally. But we have
+ reduced their API surface presence to a constructor and a destructor,
+ plus an extra argument to the PJ constructor, pj_create().
+
+ For single threaded programs, the calls to the context constructor
+ and destructor may be left out, and the default context selected
+ by passing a null-pointer to pj_create.
+
+ Thomas Knudsen, 2016-10-30/2017-07-06
+*******************************************************************************/
+#include <stdio.h>
+#include <proj.h>
+
+int main (void) {
+ PJ_CONTEXT *C;
+ PJ *P;
+ PJ_COORD a, b;
+
+ /* or you may set C=0 if you are sure you will use PJ objects from only one thread */
+ C = proj_context_create();
+
+ P = proj_create (C, "+proj=utm +zone=32 +ellps=GRS80");
+ if (0==P)
+ return puts ("Oops"), 0;
+
+ /* a coordinate union representing Copenhagen: 55d N, 12d E */
+ /* note: PROJ.4 works in radians, hence the proj_torad() calls */
+ a = proj_coord (proj_torad(12), proj_torad(55), 0, 0);
+
+ /* transform to UTM zone 32, then back to geographical */
+ /* note the use of union selectors to indicate what kind of coordinates are expected */
+ b = proj_trans_coord (P, PJ_FWD, a);
+ printf ("easting: %g, northing: %g\n", b.en.e, b.en.n);
+ b = proj_trans_coord (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 */
+ return 0;
+}
diff --git a/examples/pj_obs_api_test.c b/examples/pj_obs_api_test.c
deleted file mode 100644
index bb792c62..00000000
--- a/examples/pj_obs_api_test.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*******************************************************************************
- Tiny test of an evolving new API, demonstrating simple examples of
- 2D and 3D transformations.
-
- The main transformation setup object is PJ, well known from the two
- former proj APIs (projects.h and proj_api.h)
-
- The main data object PJ_OBS is new, but encapsulates the older
- LP, XY etc. objects in a framework for storing a 3D observation taken at
- a 4D point in space-time, and including some additional metadata (e.g.
- a serial number or an epsg code).
-
- PJ_OBS uses unions to enforce explicit statement of what kind of
- coordinates are expected at a given spot in the code.
-
- The primary elements of the API are:
-
- pj_create (char *desc):
- Create a new PJ object from a text description.
- pj_trans (PJ *P, int direction, PJ_OBS obs):
- Forward or inverse transformation of obs.
- pj_error (PJ *P):
- Check error status of P.
- pj_free (PJ *P):
- Clean up when done with the transformation object.
-
- These 4 functions should cover most of the common use cases. Additional
- functionality for handling thread contexts are provided by the functions
- pj_debug_set, pj_error_set, pj_log_set, pj_context_renew,
- pj_context_inherit, pj_context_free, pj_fileapi_set.
-
- The proj thread contexts have not seen widespread use, so one of the
- intentions with this new API is to make them less visible on the API
- surface: Contexts do not have a life by themselves, they are only
- visible through their associated PJs, and the number of functions
- supporting them is limited.
-
- Compilation example:
- gcc -pedantic -W -Wall -Wextra -I../src -o pj_proj_test pj_proj_test.c -L../../../build/proj.4/lib -lproj_4_9
-
- Thomas Knudsen, 2016-10-30/11-03
-*******************************************************************************/
-#include <proj.h>
-
-int pj_pipeline_selftest (void);
-
-int main (void) {
- PJ *P;
- PJ_OBS a, b;
- char *args[3] = {"proj=utm", "zone=32", "ellps=GRS80"};
- int err;
- double dist;
- XY cph_utm32;
-
- /* Log everything libproj offers to log for you */
- pj_log_level (0, PJ_LOG_TRACE);
-
- /* An utm projection on the GRS80 ellipsoid */
- P = pj_create ("+proj=utm +zone=32 +ellps=GRS80");
- if (0==P)
- return puts ("Oops"), 0;
-
- /* Clean up */
- pj_free (P);
-
- /* Same projection, now using argc/argv style initialization */
- P = pj_create_argv (3, args);
- if (0==P)
- return puts ("Oops"), 0;
-
- /* zero initialize everything, then set (longitude, latitude) to (12, 55) */
- a = pj_obs_null ();
- /* a.coo.lp: The coordinate part of a, interpreted as a classic LP pair */
- a.coo.lp.lam = TORAD(12);
- a.coo.lp.phi = TORAD(55);
-
- /* Forward projection */
- b = pj_trans (P, PJ_FWD, a);
- printf ("FWD: %15.9f %15.9f\n", b.coo.enh.e, b.coo.enh.n);
- cph_utm32 = b.coo.xy;
-
- /* Inverse projection */
- a = pj_trans (P, PJ_INV, b);
- printf ("INV: %15.9f %15.9f\n", TODEG(a.coo.lpz.lam), TODEG(a.coo.lpz.phi));
-
- /* Null projection */
- a = pj_trans (P, PJ_IDENT, a);
- printf ("IDENT: %15.9f %15.9f\n", TODEG(a.coo.lpz.lam), TODEG(a.coo.lpz.phi));
-
- /* Forward again, to get two linear items for comparison */
- a = pj_trans (P, PJ_FWD, a);
- printf ("FWD: %15.9f %15.9f\n", b.coo.enh.e, b.coo.enh.n);
-
- dist = pj_xy_dist (a.coo.xy, b.coo.xy);
- printf ("Roundtrip deviation, (nm): %15.9f\n", dist*1e9);
-
- /* should be identical - checking whether null-init is done */
- dist = pj_xyz_dist (a.coo.xyz, b.coo.xyz);
- printf ("Roundtrip deviation, (nm): %15.9f\n", dist*1e9);
-
- /* Invalid projection */
- a = pj_trans (P, 42, a);
- if (a.coo.lpz.lam!=DBL_MAX)
- printf ("%15.9f %15.9f\n", a.coo.lpz.lam, a.coo.lpz.phi);
- err = pj_err_level (P, PJ_ERR_TELL);
- printf ("pj_err_level: %d\n", err);
-
- /* Clean up */
- pj_free (P);
-
- /* Now do some 3D transformations */
- P = pj_create ("+proj=cart +ellps=GRS80");
- if (0==P)
- return puts ("Oops"), 0;
-
- /* zero initialize everything, then set (longitude, latitude, height) to (12, 55, 100) */
- a = b = pj_obs_null ();
- a.coo.lpz.lam = TORAD(12);
- a.coo.lpz.phi = TORAD(55);
- a.coo.lpz.z = 100;
-
- /* Forward projection: 3D-Cartesian-to-Ellipsoidal */
- b = pj_trans (P, PJ_FWD, a);
- printf ("FWD: %15.9f %15.9f %15.9f\n", b.coo.xyz.x, b.coo.xyz.y, b.coo.xyz.z);
-
- /* Check roundtrip precision for 10000 iterations each way */
- dist = pj_roundtrip (P, PJ_FWD, 10000, a);
- printf ("Roundtrip deviation, fwd (nm): %15.9f\n", dist*1e9*1e5);
- dist = pj_roundtrip (P, PJ_INV, 10000, b);
- printf ("Roundtrip deviation, inv (nm): %15.9f\n", dist*1e9);
-
- /* Inverse projection: Ellipsoidal-to-3D-Cartesian */
- b = pj_trans (P, PJ_INV, b);
- printf ("INV: %15.9f %15.9f %15.9f\n", TODEG(b.coo.lpz.lam), TODEG(b.coo.lpz.phi), b.coo.lpz.z);
-
- /* Move p to another context */
- pj_context_renew (P);
- b = pj_trans (P, PJ_FWD, b);
- printf ("CTX1: %15.9f %15.9f %15.9f\n", b.coo.xyz.x, b.coo.xyz.y, b.coo.xyz.z);
-
- /* Move it back to the default context */
- pj_context_free (P);
- b = pj_trans (P, PJ_INV, b);
- printf ("CTX0: %15.9f %15.9f %15.9f\n", TODEG(b.coo.lpz.lam), TODEG(b.coo.lpz.phi), b.coo.lpz.z);
-
- pj_free (P);
-
- /***************************************************************************
-
- P I P E L I N E T E S T S
-
- ***************************************************************************/
-
- /* forward-reverse geo->utm->geo */
- P = pj_create (
- "+proj=pipeline +ellps=GRS80 +zone=32 +step "
- "+proj=utm +step "
- "+proj=utm +inv"
- );
- if (0==P)
- return puts ("Oops"), 0;
- /* zero initialize everything, then set (longitude, latitude, height) to (12, 55, 100) */
- a = b = pj_obs_null ();
- a.coo.lpz.lam = TORAD(12);
- a.coo.lpz.phi = TORAD(55);
- a.coo.lpz.z = 100;
- printf ("PRE: %15.9f %15.9f\n", a.coo.lpz.lam, a.coo.lpz.phi);
-
- /* Forward projection */
- b = pj_trans (P, PJ_FWD, a);
- printf ("FWD: %15.9f %15.9f\n", TODEG(b.coo.lpz.lam), TODEG(b.coo.lpz.phi));
-
- /* Inverse projection */
- a = pj_trans (P, PJ_INV, b);
- printf ("INV: %15.9f %15.9f\n", TODEG(a.coo.lpz.lam), TODEG(a.coo.lpz.phi));
-
- pj_free (P);
-
-
- /* And now the back-to-back situation utm->geo->utm */
- P = pj_create (
- "+proj=pipeline +ellps=GRS80 +zone=32 +step "
- "+proj=utm +inv +step "
- "+proj=utm");
- if (0==P)
- return puts ("Oops"), 0;
-
- /* zero initialize everything, then set (easting, northing) to utm(12, 55) */
- a = b = pj_obs_null ();
- a.coo.xy = cph_utm32;
- printf ("PRE: %15.9f %15.9f\n", a.coo.xy.x, a.coo.xy.y);
-
- /* Forward projection */
- b = pj_trans (P, PJ_FWD, a);
- printf ("FWD: %15.9f %15.9f\n", b.coo.xy.x, b.coo.xy.y);
-
- /* Inverse projection */
- a = pj_trans (P, PJ_INV, b);
- printf ("INV: %15.9f %15.9f\n", a.coo.xy.x, a.coo.xy.y);
-
- pj_free (P);
-
-
-
- /* Finally testing a corner case: A rather pointless one-step pipeline geo->utm */
- P = pj_create ("+proj=pipeline +ellps=GRS80 +zone=32 +step +proj=utm");
- if (0==P)
- return puts ("Oops"), 0;
-
- /* zero initialize everything, then set (easting, northing) to utm(12, 55) */
- a = b = pj_obs_null ();
- a.coo.lpz.lam = TORAD(12);
- a.coo.lpz.phi = TORAD(55);
- printf ("PRE: %15.9f %15.9f\n", TODEG(a.coo.lp.lam), TODEG(a.coo.lp.phi));
- printf ("EXP: %15.9f %15.9f\n", cph_utm32.x, cph_utm32.y);
-
- /* Forward projection */
- b = pj_trans (P, PJ_FWD, a);
- printf ("FWD: %15.9f %15.9f\n", b.coo.xy.x, b.coo.xy.y);
-
- /* Inverse projection */
- a = pj_trans (P, PJ_INV, b);
- printf ("INV: %15.9f %15.9f\n", TODEG(a.coo.lp.lam), TODEG(a.coo.lp.phi));
-
- /* Geodesic distance between two points with angular 2D coordinates */
- a.coo.lp.lam = TORAD(12);
- a.coo.lp.phi = TORAD(60);
- b.coo.lp.lam = TORAD(12);
- b.coo.lp.phi = TORAD(61);
- dist = pj_lp_dist (P, a.coo.lp, b.coo.lp);
- printf ("1 deg at 60N: %15.9f\n", dist);
-
- a.coo.lp.lam = TORAD(12);
- a.coo.lp.phi = TORAD(0.);
- b.coo.lp.lam = TORAD(12);
- b.coo.lp.phi = TORAD(1.);
- dist = pj_lp_dist (P, a.coo.lp, b.coo.lp);
- printf ("1 deg at Equator: %15.9f\n", dist);
-
- pj_free (P);
- pj_pipeline_selftest ();
- return 0;
-}