/****************************************************************************** * $Id$ * * Project: LibCRS * Purpose: Primary LibCRS include file. * Author: Paul Ramsey * ****************************************************************************** * Copyright (c) 2009 Paul Ramsey * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * 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 * 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 * DEALINGS IN THE SOFTWARE. *****************************************************************************/ /****************************************************************************** * Theory of Operation: * * Every CRS shall be represented by a CRS* * If the CRS is a shell, behind which is either a PROJCS or GEOGCS, * just test CRS->type to see which one you have. * The interpretation of parameters is governed by the VENDOR flag * The default interpretation of parameters shall be VENDOR_STANDARD * *****************************************************************************/ /* ** We define a number of lists as arrays rather than trying to ** dynamically size them. Fortunately, these are pretty small structures ** with not many elements. We can affort to waste a few bytes here and there. */ #define CRS_MAX_PARAMS 16 /* ** Debug level. 0 = none. 5 = max. */ #define CRS_DEBUG_LEVEL 5 /* ** Rather than trusting FALSE and TRUE or over-riding them. */ enum { CRS_FALSE = 0, CRS_TRUE = 1 }; /* ** Return values for public API functions. */ enum { CRS_SUCCESS = 0, CRS_FAILURE }; /* ** Component types, so we can use an anonymous pointer type, ** PART, but still cast back into particular types ** when necessary. */ enum { CRS_AUTHORITY, CRS_UNIT, CRS_PRIMEM, CRS_SPHEROID, CRS_TOWGS84, CRS_DATUM, CRS_AXIS, CRS_GEOGCS, CRS_PROJECTION, CRS_PARAMETER, CRS_PROJCS, CRS_CRS, CRS_PARTLIST }; /* ** We may need more of these. VENDOR_STANDARD is considered ** the "internal standard" to which we transform all others. */ typedef enum { VENDOR_STANDARD = 0, VENDOR_ESRI, VENDOR_CADCORP, VENDOR_CSMAP, VENDOR_ORACLE } VENDOR; /****************************************************************************** * Structures of the CRS object. * The CRS object is (overly) complex and modelled on a slightly wide * interpretation of WKT. *****************************************************************************/ /* ** Anonymous component structure used in the WKT parser. */ typedef struct { int type; } PART; typedef struct { int type; char *name; char *id; char *description; } AUTHORITY; typedef struct { int type; char *name; double conversion; AUTHORITY *auth; } UNIT; typedef struct { int type; char *name; double origin; AUTHORITY *auth; } PRIMEM; typedef struct { int type; char *name; double semimajor; double invflattening; AUTHORITY *auth; } SPHEROID; typedef struct { int type; int num_params; double params[CRS_MAX_PARAMS]; } TOWGS84; typedef struct { int type; char *name; SPHEROID *spheroid; TOWGS84 *towgs84; AUTHORITY *auth; } DATUM; typedef struct { int type; char *name; char *orientation; } AXIS; typedef struct { int type; char *name; AUTHORITY *auth; } PROJECTION; typedef struct { int type; char *name; double value; } PARAMETER; /** * Geographic (lat/lon) coordinate system structure. * Modelled on the WKT geographic coordinate structure. * Two or zero axis definitions. Any of the sub-components may or may not be * present, always test for NULL before de-referencing. * * @see PROJCS */ typedef struct { int type; char *name; VENDOR vendor; DATUM *datum; PRIMEM *primem; UNIT *unit; AXIS *axis[2]; AUTHORITY *auth; } GEOGCS; /** * Projected coordinate system structure. * Modelled on the WKT projected coordinate structure. There are a variable number of * parameter. Two or zero axis definitions. Any of the sub-components may or may not be * present, always test for NULL before de-referencing. * * @see GEOGCS */ typedef struct { int type; char *name; VENDOR vendor; GEOGCS *geogcs; PROJECTION *projection; int num_parameters; PARAMETER *parameters[CRS_MAX_PARAMS]; UNIT *unit; AXIS *axis[2]; AUTHORITY *auth; } PROJCS; /** * Coordinate reference system struct wrapper. Can be a PROJCS or GEOGCS. * Test on the type to determine what it is, then cast. * * @see PROJCS * @see GEOGCS */ typedef PART CRS; /****************************************************************************** * CRSDEBUG() * * Debugging calls as macros. When debugging is set to 0, they get optimized * away. Otherwise, do the test and call a logging method. *****************************************************************************/ #if CRS_DEBUG_LEVEL > 0 #define CRSDEBUG(level, msg) \ do { \ if (CRS_DEBUG_LEVEL >= level) \ crsnotice("[%s:%s:%d] " msg, __FILE__, __func__, __LINE__); \ } while (0); #define CRSDEBUGF(level, msg, ...) \ do { \ if (CRS_DEBUG_LEVEL >= level) \ crsnotice("[%s:%s:%d] " msg, __FILE__, __func__, __LINE__, __VA_ARGS__); \ } while (0); #else /* Empty prototypes that can be optimised away by the compiler for non-debug builds */ #define CRSDEBUG(level, msg) ((void) 0) #define CRSDEBUGF(level, msg, ...) ((void) 0) #endif /* ** Prototypes for the actual error handling functions. */ /** * Write a notice to stderr. * * @param fmt Input format string. * @param ... Parameters to the format. */ extern void crsnotice(const char *fmt, ...); /** * Write a notice to stderr, and then exit. * * @param fmt Input format string. * @param ... Parameters to the format. */ extern void crserror(const char *fmt, ...); /****************************************************************************** * Public CRSlib functions *****************************************************************************/ /** * Create a CRS struct pointer from a well-known text string. * Reads the WKT string and create a CRS without validating the * contents of the CRS. If you are not sure of the provenance of the WKT, * use standardization functions before carrying out any further operations. * * @param str Input WKT string. * @param crs Output CRS pointer. Will be NULL on parse error. * @param errstr Output error string. Will be NULL on parse success. * @see CRS */ extern int crs_from_wkt_string(char *str, CRS **crs, char **errstr); /** * Deep free a CRS struct pointer. * Frees the CRS and all sub-components. Will automatically detect * whether the CRS is a PROJCS or GEOGCS and carry out the appropriate * freeing. * * @param crs Input CRS pointer. * @see crs_geogcs_free() * @see crs_projcs_free() * @see CRS */ extern void crs_free(CRS *crs); /** * Deep free a GEOGCS struct pointer. * Frees the GEOGCS and all sub-components. * * @param crs Input GEOGCS pointer. * @see GEOGCS */ extern void crs_geogcs_free(GEOGCS *geogcs); /** * Deep free a PROJCS struct pointer. * Frees the PROJCS and all sub-components. * * @param crs Input PROJCS pointer. * @see PROJCS */ extern void crs_projcs_free(PROJCS *projcs);