aboutsummaryrefslogtreecommitdiff
path: root/src/proj.h
diff options
context:
space:
mode:
authorThomas Knudsen <busstoptaktik@users.noreply.github.com>2016-11-12 16:51:21 +0100
committerGitHub <noreply@github.com>2016-11-12 16:51:21 +0100
commit26e65892728d6bfb010677091b0a464d7c7ebc76 (patch)
tree7720fadfcd5f3ca416ca4ea26c94013b3b1801df /src/proj.h
parent7986e36875f729d7ef3767a97f732ba39fa1b57d (diff)
downloadPROJ-26e65892728d6bfb010677091b0a464d7c7ebc76.tar.gz
PROJ-26e65892728d6bfb010677091b0a464d7c7ebc76.zip
Pipeline plus api - in continuation of the Genereic Coordinates pull request (#445)
This commit reflects continued work on the new rationalized API with geodetic extensions (see rationale in proj.h). It also reflects the parallel work on the transformation pipeline reimplementation, by introducing the PJ_cart cartesian/ellipsoidal converter. See example/pj_obs_api_test.c for demo example code
Diffstat (limited to 'src/proj.h')
-rw-r--r--src/proj.h199
1 files changed, 145 insertions, 54 deletions
diff --git a/src/proj.h b/src/proj.h
index 3d8ba359..4b7cfc87 100644
--- a/src/proj.h
+++ b/src/proj.h
@@ -1,23 +1,88 @@
/******************************************************************************
* Project: PROJ.4
- * Purpose: Revised, experimental, "bare essentials" API for PROJ.4.
- * Intended as the foundation for added geodetic functionality.
+ * Purpose: Revised, experimental API for PROJ.4, intended as the foundation
+ * for added geodetic functionality.
*
- * Introduces the OBSERVATION data type, for generic coordinate
- * and ancillary data handling.
+ * The original proj API (defined in projects.h) has grown organically
+ * over the years, but it has also grown somewhat messy.
*
- * Also introduces the PJ_SPATIOTEMPORAL and PJ_TRIPLET unions
- * making it possible to make explicit the previously used
- * "implicit type punning", where a XY is turned into a LP by
- * re#defining both as UV, behind the back of the user.
+ * The same has happened with the newer high level API (defined in
+ * proj_api.h): To support various historical objectives, proj_api.h
+ * contains a rather complex combination of conditional defines and
+ * typedefs. Probably for good (historical) reasons, which are not
+ * always evident from today's perspective.
+ *
+ * This is an evolving attempt at creating a re-rationalized API
+ * with primary design goals focused on sanitizing the namespaces.
+ * Hence, all symbols exposed are being moved to the pj_ namespace,
+ * while all data types are being moved to the PJ_ namespace.
+ *
+ * Please note that this API is *orthogonal* to the previous APIs:
+ * Apart from some inclusion guards, projects.h and proj_api.h are not
+ * touched - if you do not include proj.h, the projects and proj_api
+ * APIs should work as they always have.
+ *
+ * A few implementation details:
+ *
+ * Apart from the namespacing efforts, I'm trying to eliminate three
+ * proj_api elements, which I have found especially confusing.
+ *
+ * FIRST and foremost, I try to avoid typedef'ing away pointer
+ * semantics. I agree that it can be occasionally useful, but I
+ * prefer having the pointer nature of function arguments being
+ * explicitly visible.
+ *
+ * Hence, projCtx has been replaced by PJ_CONTEXT *.
+ * and projPJ has been replaced by PJ *
+ *
+ * SECOND, I try to eliminate cases of information hiding implemented
+ * by redefining data types to void pointers.
+ *
+ * I prefer using a combination of forward declarations and typedefs.
+ * Hence:
+ * typedef void *projCtx;
+ * Has been replaced by:
+ * struct projCtx_t;
+ * typedef struct projCtx_t PJ_CONTEXT;
+ * This makes it possible for the calling program to know that the
+ * PJ_CONTEXT data type exists, and handle pointers to that data type
+ * without having any idea about its internals.
+ *
+ * (obviously, in this example, struct projCtx_t should also be
+ * renamed struct pj_ctx some day...)
+ *
+ * THIRD, I try to eliminate implicit type punning. Hence this API
+ * introduces the PJ_OBS ("observation") data type, for generic
+ * coordinate and handling of ancillary data.
+ *
+ * It includes the PJ_COORD and PJ_TRIPLET unions making it possible
+ * to make explicit the previously used "implicit type punning", where
+ * a XY is turned into a LP by re#defining both as UV, behind the back
+ * of the user.
+ *
+ * The PJ_COORD union is used for storing 1D, 2D, 3D and 4D coordinates.
+ * The PJ_TRIPLET union is used for storing any set of up to 3 related
+ * observations. At the application code level, the names of these
+ * unions will usually not be used - they will only be accessed via
+ * their tag names in the PJ_OBS data type.
*
* The bare essentials API presented here follows the PROJ.4
* convention of sailing the coordinate to be reprojected, up on
* the stack ("call by value"), and symmetrically returning the
- * result on the stack. Although the OBSERVATION object is 4 times
+ * result on the stack. Although the PJ_OBS object is 4 times
* as large as the traditional XY and LP objects, timing results
* have shown the overhead to be very reasonable.
*
+ * In its current incarnation, the API is focused on compactness:
+ * Currently it consists of only nine functions.
+ *
+ * Hence, due to the proj_ctx subsystem being little used, it has
+ * been replaced by a tiny set of 3 functions, making it possible,
+ * but not very convenient, to do almost everything possible with
+ * the original ctx API.
+ *
+ * See pj_proj_test.c for an example of how to use the API.
+ *
* Author: Thomas Knudsen, <thokn@sdfe.dk>
*
******************************************************************************
@@ -35,7 +100,7 @@
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO COORD SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
@@ -46,11 +111,21 @@
#endif
#include <math.h>
+#include <float.h>
+#include <limits.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#ifdef PROJECTS_H
+#error proj.h must be included before projects.h
+#endif
+#ifdef PROJ_API_H
+#error proj.h must be included before proj_api.h
+#endif
+
#ifndef PROJ_H
#define PROJ_H
#ifdef __cplusplus
@@ -58,33 +133,26 @@ extern "C" {
#endif
-/******************************************************************************
- proj.h is included by projects.h in order to determine the size of the
- PJ_OBSERVATION object.
+/* We need to access the PJ_VERSION symbol from proj_api.h */
+#define PROJ_API_INCLUDED_FOR_PJ_VERSION_ONLY
+#include <proj_api.h>
+#undef PROJ_API_INCLUDED_FOR_PJ_VERSION_ONLY
- In order to stomp as little as possible on the traditional proj.4 name
- space, proj.h is littered with inclusion guards, leaving only the minimum
- possible implementation when included from projects.h
- The PJ_OBSERVATION object is fully defined if proj.h is included alone or
- in connection with *but before* projects.h (the latter may be needed in
- some cases, where it is necessary to access this "bare essentials" API,
- while still having direct access to PJ object internals)
-******************************************************************************/
+/* first forward declare everything needed */
/* Data type for generic geodetic observations */
-struct PJ_OBSERVATION;
-typedef struct PJ_OBSERVATION PJ_OBSERVATION;
+struct PJ_OBS;
+typedef struct PJ_OBS PJ_OBS;
/* Data type for generic geodetic 3D data */
union PJ_TRIPLET;
typedef union PJ_TRIPLET PJ_TRIPLET;
/* Data type for generic geodetic 3D data plus epoch information */
-union PJ_SPATIOTEMPORAL;
-typedef union PJ_SPATIOTEMPORAL PJ_SPATIOTEMPORAL;
+union PJ_COORD;
+typedef union PJ_COORD PJ_COORD;
-#ifndef PROJECTS_H
/* Data type for projection/transformation information */
struct PJconsts;
typedef struct PJconsts PJ; /* the PJ object herself */
@@ -115,21 +183,18 @@ typedef struct { double lam, phi, z; } LPZ;
/* Degrees, minutes, and seconds */
typedef struct { double d, m, s; } PJ_DMS;
-/* Geoid undulation (N) and deflections of the vertical (z, e) */
-typedef struct { double N, z, e; } PJ_NZE;
+/* Geoid undulation (N) and deflections of the vertical (eta, zeta) */
+typedef struct { double e, z, N; } PJ_EZN;
/* Ellipsoidal parameters */
typedef struct { double a, f; } PJ_AF;
-#endif /* ndef PROJECTS_H */
-union PJ_SPATIOTEMPORAL {
-#ifndef PROJECTS_H
+union PJ_COORD {
PJ_XYZT xyzt;
PJ_UVWT uvwt;
PJ_ENHT enht;
PJ_LPZT lpzt;
PJ_ENH enh;
-#endif
double v[4]; /* Who cares - it's just a vector! */
XYZ xyz;
UVW uvw;
@@ -143,12 +208,10 @@ union PJ_SPATIOTEMPORAL {
/* Avoid preprocessor renaming and implicit type-punning: Use a union to make it explicit */
union PJ_TRIPLET {
-#ifndef PROJECTS_H
PJ_OPK opk;
PJ_ENH enh;
- PJ_NZE nze;
+ PJ_EZN ezn;
PJ_AF af;
-#endif
double v[3]; /* Who cares - it's just a vector! */
XYZ xyz;
LPZ lpz;
@@ -158,39 +221,68 @@ union PJ_TRIPLET {
UV uv;
};
-struct PJ_OBSERVATION {
- PJ_SPATIOTEMPORAL coo; /* coordinate data */
+struct PJ_OBS {
+ PJ_COORD coo; /* coordinate data */
PJ_TRIPLET anc; /* ancillary data */
int id; /* integer ancillary data - e.g. observation number, EPSG code... */
unsigned int flags; /* additional data, intended for flags */
};
+/* The context type - properly namespaced synonym for projCtx */
+struct projCtx_t;
+typedef struct projCtx_t PJ_CONTEXT;
+typedef int *PJ_FILE;
-#ifndef PROJECTS_H
+/* Manage the transformation definition object PJ */
+PJ *pj_create (const char *definition);
+PJ *pj_create_argv (int argc, char **argv);
+void pj_free (PJ *P);
+int pj_error (PJ *P);
-/* Direction: "+" forward, "-" reverse, 0: do nothing */
-enum pj_direction {
- PJ_FWD = -1,
- PJ_IDENT = 0,
- PJ_INV = 1
+/* High level functionality for handling thread contexts */
+enum pj_debug_level {
+ PJ_LOG_NONE = 0,
+ PJ_LOG_ERROR = 1,
+ PJ_LOG_DEBUG_MAJOR = 2,
+ PJ_LOG_DEBUG_MINOR = 3
};
+void pj_debug_set (PJ *P, enum pj_debug_level debuglevel);
+void pj_error_set (PJ *P, int err);
+void pj_log_set (PJ *P, void *app_data, void (*log)(void *, int, const char *));
+
+/* Lower level functionality for handling thread contexts */
+int pj_context_renew (PJ *P);
+void pj_context_inherit (PJ *mother, PJ *daughter);
+void pj_context_free (const PJ *P);
+
+/* Lowest level: Minimum support for fileapi */
+void pj_fileapi_set (PJ *P, void *fileapi);
/* Apply transformation to observation - in forward or inverse direction */
-PJ_OBSERVATION pj_apply (PJ *P, enum pj_direction direction, PJ_OBSERVATION obs);
+enum pj_direction {
+ PJ_FWD = 1, /* Forward */
+ PJ_IDENT = 0, /* Do nothing */
+ PJ_INV = -1 /* Inverse */
+};
+PJ_OBS pj_apply (PJ *P, enum pj_direction direction, PJ_OBS obs);
/* Measure internal consistency - in forward or inverse direction */
-double pj_roundtrip(PJ *P, enum pj_direction direction, int n, PJ_OBSERVATION obs);
+double pj_roundtrip (PJ *P, enum pj_direction direction, int n, PJ_OBS obs);
+
+/* Euclidean distance between two 2D coordinates stored in PJ_OBSs */
+double pj_obs_dist_2d (PJ_OBS a, PJ_OBS b);
+/* Euclidean distance between two 3D coordinates stored in PJ_OBSs */
+double pj_obs_dist_3d (PJ_OBS a, PJ_OBS b);
-int pj_show_triplet (FILE *stream, const char *banner, PJ_TRIPLET point);
-/* Constructor for the OBSERVATION object */
-PJ_OBSERVATION pj_observation (
- double x, double y, double z, double t,
- double o, double p, double k,
- int id, unsigned int flags
-);
+
+#ifndef PJ_OBS_C
+extern const PJ_OBS pj_obs_error;
+extern const PJ_OBS pj_obs_null;
+extern const PJ *pj_shutdown;
+#endif
#ifndef TODEG
#define TODEG(rad) ((rad)*180.0/M_PI)
@@ -199,10 +291,9 @@ PJ_OBSERVATION pj_observation (
#define TORAD(deg) ((deg)*M_PI/180.0)
#endif
-#endif /* ndef PROJECTS_H */
-
#ifdef __cplusplus
}
#endif
+
#endif /* ndef PROJ_H */