/********************************************************************** * $Id: php_proj.c,v 1.10 2005/06/14 16:03:36 dan Exp $ * * Name: php_proj.c * Project: PHP wraper function to PROJ4 projection module * Language: ANSI C * Purpose: External interface functions * Author: Assefa Yewondwossen (assefa@dmsolutions.on.ca) * ********************************************************************** * Copyright (c) 2000-2005, DM Solutions Group inc. * * 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 above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * 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. ********************************************************************** * * $Log: php_proj.c,v $ * Revision 1.10 2005/06/14 16:03:36 dan * Updated copyright date to 2005 * * Revision 1.9 2005/01/04 22:55:27 assefa * Add PHP5 support for windows (Bug 1100). * * Revision 1.8 2002/03/08 23:16:41 assefa * Add PHP4.1 support. * * Revision 1.7 2002/01/22 19:18:54 dan * Fixed a typo in pj_transform() docs * * Revision 1.6 2002/01/22 19:18:17 dan * Took pj_datum_transform() out of docs to discourage its use. * * Revision 1.5 2001/09/25 14:52:54 assefa * Add pj_transform function. * * Revision 1.4 2001/02/23 20:35:57 assefa * Free function does not work for PHP4. Disable it for now. * * Revision 1.3 2001/01/09 05:24:41 dan * Fixes to build with PHP 4.0.4 * * Revision 1.2 2000/11/08 15:44:16 dan * Correct compilation errors with php4. * * Revision 1.1 2000/11/02 16:39:55 dan * PHP PROJ4 module. * * **********************************************************************/ /* * PHP PROJ4 Module * * This is a PHP module that gives acces to basic PROJ4 projection * functionalities. * * There following functions available in this module : * * 1) pj_init : create and initializes a projection structures * * PJ pj_init(array_of_parameters) * * Example : $projarray[0] = "proj=lcc"; * $projarray[1] = "ellps=GRS80"; * $projarray[2] = "lat_0=49"; * $projarray[3] = "lon_0=-95"; * $projarray[4] = "lat_1=49"; * $projarray[5] = "lat_2=77"; * * $pj = pj_init($projarray); * * 2) pj_fwd : Performs a projection from lat/long coordinates to * cartesian coordinates. * * retrun_array pj_fwd(double lat, double long, PJ pj) * * Example : $lat = 45.25; * $long = -75.42; * * $ret = pj_fwd($ingeox, $ingeoy, $pj); * printf("geo x = %f
\n", $ret["u"]); * printf("geo y = %f
\n",$ret["v"]); * * 3) pj_inv : Performs a projection from cartesian coordinates to * lat/long coordinates . * * retrun_array pj_fwd(double geox, double geoy, PJ pj) * * Example : $ingeox = 1537490.335842; * $ingeoy = -181633.471555; * * $ret = pj_inv($ingeox, $ingeoy, $pj); * printf("lat = %f
\n", $ret["u"]); * printf("lon = %f
\n",$ret["v"]); * * * 4) pj_transform : pj_transform(PJ pjsrc, PJ pjdst, double x, double y) * transforms coordinates from source projection to * destination projection. * * Example : $projarray[0] = "proj=lcc"; * $projarray[1] = "ellps=GRS80"; * $projarray[2] = "lat_0=49"; * $projarray[3] = "lon_0=-95"; * $projarray[4] = "lat_1=49"; * $projarray[5] = "lat_2=77"; * $projarray[6] = ""; * * $pjlcc = pj_init($projarray); * $projarray2[0] = "proj=latlong"; * $pjlat = pj_init($projarray2); * * $ingeox = 1537490.335842; * $ingeoy = -181633.471555; * * $ret = pj_transform($pjlcc, $pjlat, $ingeox, $ingeoy); * * 5) pj_free : frees PJ structure * * void pj_free(PJ pj); * **********************************************************************/ #ifdef USE_PROJ #include #include "php_mapscript_util.h" #if defined (PHP4) || defined (PHP5) #include "php.h" #include "php_globals.h" #else #include "phpdl.h" #include "php3_list.h" #include "functions/head.h" /* php3_header() */ #endif #include "maperror.h" #include #if defined(_WIN32) && !defined(__CYGWIN__) #include #else #include #endif #if defined (PHP4) || defined (PHP5) #define ZEND_DEBUG 0 #endif #ifndef DLEXPORT #define DLEXPORT ZEND_DLEXPORT #endif #define PHP_PROJ_VERSION "1.0.000 (Nov. 1, 2000)" /*===================================================================== * Prototypes *====================================================================*/ DLEXPORT void php_proj_pj_init(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_proj_pj_fwd(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_proj_pj_inv(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_proj_pj_transform(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_proj_pj_datum_transform(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_proj_pj_free(INTERNAL_FUNCTION_PARAMETERS); DLEXPORT void php_info_proj(void); DLEXPORT int php_init_proj(INIT_FUNC_ARGS); DLEXPORT int php_end_proj(SHUTDOWN_FUNC_ARGS); DLEXPORT void ttt(INTERNAL_FUNCTION_PARAMETERS); #ifdef ZEND_VERSION PHP_MINFO_FUNCTION(phpproj); #else DLEXPORT void php_info_proj(void); #endif #if defined (PHP4) || defined (PHP5) static zend_class_entry *proj_class_entry_ptr; #endif #define PHPMS_GLOBAL(a) a static int le_projobj; function_entry php_proj_functions[] = { {"pj_fwd", php_proj_pj_fwd, NULL}, {"pj_inv", php_proj_pj_inv, NULL}, {"pj_init", php_proj_pj_init, NULL}, {"pj_transform", php_proj_pj_transform, NULL}, {"pj_datum_transform", php_proj_pj_datum_transform, NULL}, {"pj_free", php_proj_pj_free, NULL}, {NULL, NULL, NULL} }; php3_module_entry php_proj_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "PHPPROJ", php_proj_functions, php_init_proj, php_end_proj, NULL, NULL, #ifdef ZEND_VERSION PHP_MINFO(phpproj), #else php_info_proj, #endif #if ZEND_MODULE_API_NO >= 20010901 "phpproj, php4.1version", /* extension version number (string) */ #endif STANDARD_MODULE_PROPERTIES }; #if COMPILE_DL DLEXPORT php3_module_entry *get_module(void) { return &php_proj_module_entry; } #endif function_entry php_proj_class_functions[] = { {"ttt", ttt, NULL}, {NULL, NULL, NULL} }; DLEXPORT void ttt(INTERNAL_FUNCTION_PARAMETERS) { } #ifdef ZEND_VERSION PHP_MINFO_FUNCTION(phpproj) #else DLEXPORT void php_info_proj(void) #endif { php3_printf(" Version %s
\n", PHP_PROJ_VERSION); php3_printf("
\n"); } DLEXPORT int php_init_proj(INIT_FUNC_ARGS) { #if defined (PHP4) || defined (PHP5) zend_class_entry tmp_class_entry; #endif PHPMS_GLOBAL(le_projobj) = register_list_destructors(php_proj_pj_free, NULL); #if defined (PHP4) || defined (PHP5) INIT_CLASS_ENTRY(tmp_class_entry, "proj", php_proj_class_functions); proj_class_entry_ptr = zend_register_internal_class(&tmp_class_entry TSRMLS_CC); #endif return SUCCESS; } DLEXPORT int php_end_proj(SHUTDOWN_FUNC_ARGS) { return SUCCESS; } #if !defined DEG_TO_RAD #define DEG_TO_RAD 0.0174532925199432958 #endif #if !defined RAD_TO_DEG #define RAD_TO_DEG 57.29577951308232 #endif /********************************************************************** * _php_proj_build_proj_object **********************************************************************/ static long _php_proj_build_proj_object(PJ *pj, HashTable *list, pval *return_value TSRMLS_DC) { int pj_id; if (pj == NULL) return 0; pj_id = php3_list_insert(pj, PHPMS_GLOBAL(le_projobj)); _phpms_object_init(return_value, pj_id, php_proj_class_functions, PHP4_CLASS_ENTRY(proj_class_entry_ptr) TSRMLS_CC); return pj_id; } /************************************************************************/ /* DLEXPORT void php_proj_pj_init(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Creates and initialize a PJ structure that can be used with */ /* proj_fwd and proj_inv function. */ /* */ /* Parameter : */ /* */ /* array : array of parameters */ /* */ /* Ex : */ /* */ /* $projarray[0] = "proj=lcc"; */ /* $projarray[1] = "ellps=GRS80"; */ /* $projarray[2] = "lat_0=49"; */ /* $projarray[3] = "lon_0=-95"; */ /* $projarray[4] = "lat_1=49"; */ /* $projarray[5] = "lat_2=77"; */ /* */ /* $pj = pj_init($projarray); */ /* */ /************************************************************************/ DLEXPORT void php_proj_pj_init(INTERNAL_FUNCTION_PARAMETERS) { pval *pArrayOfParams = NULL; #if defined (PHP4) || defined (PHP5) pval **pParam = NULL; HashTable *list=NULL; #else pval *pParam = NULL; #endif int nParamCount = 0; int i = 0; PJ *pj = NULL; char **papszBuf = NULL; // char *strttt = NULL; // int ttt; //ttt = strlen(strttt); /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 1, &pArrayOfParams) != SUCCESS) { WRONG_PARAM_COUNT; } if (pArrayOfParams->type == IS_ARRAY) nParamCount = _php3_hash_num_elements(pArrayOfParams->value.ht); else nParamCount = 0; if (nParamCount <= 0) RETURN_LONG(-1); papszBuf = (char **) malloc((nParamCount+2)*sizeof(char *)); for (i = 0; i < nParamCount; i++) { if (_php3_hash_index_find(pArrayOfParams->value.ht, i, (void **)&pParam) != FAILURE) { #if defined (PHP4) || defined (PHP5) convert_to_string((*pParam)); if ((*pParam)->value.str.val != NULL) papszBuf[i] = strdup((*pParam)->value.str.val); #else convert_to_string(pParam); if (pParam->value.str.val != NULL) papszBuf[i] = strdup(pParam->value.str.val); #endif } } papszBuf[i] = NULL; pj = pj_init(nParamCount, papszBuf); _php_proj_build_proj_object(pj, list, return_value TSRMLS_CC); } /************************************************************************/ /* DLEXPORT void php_proj_pj_fwd(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Performs a projection from lat/long coordinates to */ /* cartesian coordinates (projection defines in the pj parameter) */ /* Parameters : */ /* */ /* - double p1 : latitude (in decimal degree ) */ /* - double p2 : longitude (in decimal degree ) */ /* - PJ pj : valid projection structure (see pj_init) */ /* */ /* Ex : */ /* $lat = 45.25; */ /* $lon = -75.42; */ /* */ /* $ret = pj_fwd($lat, $lon, $pj); */ /* printf("geo x = %f
\n", $ret["u"]); */ /* printf("geo y = %f
\n",$ret["v"]); */ /* */ /************************************************************************/ DLEXPORT void php_proj_pj_fwd(INTERNAL_FUNCTION_PARAMETERS) { #if defined (PHP4) || defined (PHP5) HashTable *list=NULL; #endif pval *p1, *p2; pval *pj = NULL; PJ *popj = NULL; projUV pnt; projUV pntReturn = {0,0}; /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 3, &p1, &p2, &pj) != SUCCESS) { WRONG_PARAM_COUNT; } /* -------------------------------------------------------------------- */ /* initilize return array. */ /* -------------------------------------------------------------------- */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } convert_to_double(p1); convert_to_double(p2); popj = (PJ *)_phpms_fetch_handle(pj, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); if (popj) { pnt.u = p2->value.dval * DEG_TO_RAD; pnt.v = p1->value.dval * DEG_TO_RAD; pntReturn = pj_fwd(pnt, popj); } add_assoc_double(return_value, "u", pntReturn.u); add_assoc_double(return_value, "v", pntReturn.v); } /************************************************************************/ /* DLEXPORT void php_proj_pj_inv(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Performs a projection from cartesian coordinates */ /* (projection defines in the pj parameter) to lat/long */ /* coordinates. */ /* */ /* Return vales are in decimal degrees. */ /* */ /* Parameters : */ /* */ /* - double p1 : projected coordinates (x) */ /* - double p2 : projected coordinates (y) */ /* - PJ pj : valid projection structure (see pj_init) */ /* */ /* Ex : */ /* $ingeox = 1537490.335842; */ /* $ingeoy = -181633.471555; */ /* */ /* $ret = pj_inv($ingeox, $ingeoy, $pj); */ /* */ /* printf("latitude = %f
\n", $ret["u"]); */ /* printf("longitude = %f
\n",$ret["v"]); */ /************************************************************************/ DLEXPORT void php_proj_pj_inv(INTERNAL_FUNCTION_PARAMETERS) { #if defined (PHP4) || defined (PHP5) HashTable *list=NULL; #endif pval *p1, *p2; pval *pj = NULL; PJ *popj = NULL; projUV pnt; projUV pntReturn = {0,0}; /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 3, &p1, &p2, &pj) != SUCCESS) { WRONG_PARAM_COUNT; } /* -------------------------------------------------------------------- */ /* initilize return array. */ /* -------------------------------------------------------------------- */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } convert_to_double(p1); convert_to_double(p2); popj = (PJ *)_phpms_fetch_handle(pj, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); if (popj) { pnt.u = p1->value.dval; pnt.v = p2->value.dval; pntReturn = pj_inv(pnt, popj); pntReturn.u *= RAD_TO_DEG; pntReturn.v *= RAD_TO_DEG; } add_assoc_double(return_value, "u", pntReturn.v); add_assoc_double(return_value, "v", pntReturn.u); } /************************************************************************/ /* DLEXPORT void php_proj_pj_transform(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Transform coordinates from source projection to destination */ /* projection. */ /* */ /* Parameters : */ /* */ /* - PJ *srcdefn, */ /* - PJ *dstdefn, */ /* - double x */ /* - double y */ /* */ /************************************************************************/ DLEXPORT void php_proj_pj_transform(INTERNAL_FUNCTION_PARAMETERS) { #if defined (PHP4) || defined (PHP5) HashTable *list=NULL; #endif pval *p1, *p2; pval *pjin, *pjout = NULL; PJ *in = NULL; PJ *out = NULL; projUV pnt = {0, 0}; double z = 0; int error = -1; /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 4, &pjin , &pjout, &p1, &p2) != SUCCESS) { WRONG_PARAM_COUNT; } /* -------------------------------------------------------------------- */ /* initilize return array. */ /* -------------------------------------------------------------------- */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } convert_to_double(p1); convert_to_double(p2); in = (PJ *)_phpms_fetch_handle(pjin, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); out = (PJ *)_phpms_fetch_handle(pjout, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); if (in && out) { pnt.u = p1->value.dval; pnt.v = p2->value.dval; if( pj_is_latlong(in) ) { pnt.u *= DEG_TO_RAD; pnt.v *= DEG_TO_RAD; } error = pj_transform(in, out, 1, 0, &(pnt.u), &(pnt.v), &z ); if( pj_is_latlong(out) ) { pnt.u *= RAD_TO_DEG; pnt.v *= RAD_TO_DEG; } } if (error) { php_error(E_ERROR,"Error in pj_transform"); RETURN_LONG(-1); } else { add_assoc_double(return_value, "u", pnt.u); add_assoc_double(return_value, "v", pnt.v); } } /************************************************************************/ /* DLEXPORT */ /* void php_proj_pj_datum_transform(INTERNAL_FUNCTION_PARAMETERS) */ /* */ /* Datum from source projection to destination */ /* projection. */ /* */ /* Parameters : */ /* */ /* - PJ *srcdefn, */ /* - PJ *dstdefn, */ /* - double x */ /* - double y */ /* */ /************************************************************************/ DLEXPORT void php_proj_pj_datum_transform(INTERNAL_FUNCTION_PARAMETERS) { #if defined (PHP4) || defined (PHP5) HashTable *list=NULL; #endif pval *p1, *p2; pval *pjin, *pjout = NULL; PJ *in = NULL; PJ *out = NULL; projUV pnt = {0, 0}; double z = 0; int error = -1; /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 4, &pjin , &pjout, &p1, &p2) != SUCCESS) { WRONG_PARAM_COUNT; } /* -------------------------------------------------------------------- */ /* initilize return array. */ /* -------------------------------------------------------------------- */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } convert_to_double(p1); convert_to_double(p2); in = (PJ *)_phpms_fetch_handle(pjin, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); out = (PJ *)_phpms_fetch_handle(pjout, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); if (in && out) { pnt.u = p1->value.dval; pnt.v = p2->value.dval; if( pj_is_latlong(in) ) { pnt.u *= DEG_TO_RAD; pnt.v *= DEG_TO_RAD; } error = pj_transform(in, out, 1, 0, &(pnt.u), &(pnt.v), &z ); if (!error) { if( pj_is_latlong(out) ) { pnt.u *= RAD_TO_DEG; pnt.v *= RAD_TO_DEG; } } } if (error) { php_error(E_ERROR,"Error in pj_datum_transform"); RETURN_LONG(-1); } else { add_assoc_double(return_value, "u", pnt.u); add_assoc_double(return_value, "v", pnt.v); } } /************************************************************************/ /* DLEXPORT void php_proj_pj_free(INTERNAL_FUNCTION_PARAMETERS) */ /************************************************************************/ DLEXPORT void php_proj_pj_free(INTERNAL_FUNCTION_PARAMETERS) { /* ==================================================================== */ /* TODO : freeing does not work properly on PHP4. */ /* ==================================================================== */ #ifndef PHP4 #if defined (PHP4) || defined (PHP5) HashTable *list=NULL; #endif pval *pj = NULL; PJ *popj = NULL; /* -------------------------------------------------------------------- */ /* extract parameters. */ /* -------------------------------------------------------------------- */ if (getParameters(ht, 1, &pj) != SUCCESS) { WRONG_PARAM_COUNT; } popj = (PJ *)_phpms_fetch_handle(pj, PHPMS_GLOBAL(le_projobj), list TSRMLS_CC); if (popj) { pj_free(popj); } #endif } #endif /* USE_PROJ */