1
/**********************************************************************
2
* $Id: php_proj.c 9937 2010-03-11 15:17:39Z aboudreault $
5
* Purpose: PHP wraper function to PROJ4 projection module.
6
* Author: Yewondwossen Assefa, DM Solutions Group (assefa@dmsolutions.ca)
8
**********************************************************************
9
* Copyright (c) 2000-2005, Y. Assefa, DM Solutions Group inc.
11
* Permission is hereby granted, free of charge, to any person obtaining a
12
* copy of this software and associated documentation files (the "Software"),
13
* to deal in the Software without restriction, including without limitation
14
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
* and/or sell copies of the Software, and to permit persons to whom the
16
* Software is furnished to do so, subject to the following conditions:
18
* The above copyright notice and this permission notice shall be included in
19
* all copies of this Software or works derived from this Software.
21
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
* DEALINGS IN THE SOFTWARE.
28
**********************************************************************
31
* Revision 1.10 2005/06/14 16:03:36 dan
32
* Updated copyright date to 2005
34
* Revision 1.9 2005/01/04 22:55:27 assefa
35
* Add PHP5 support for windows (Bug 1100).
37
* Revision 1.8 2002/03/08 23:16:41 assefa
40
* Revision 1.7 2002/01/22 19:18:54 dan
41
* Fixed a typo in pj_transform() docs
43
* Revision 1.6 2002/01/22 19:18:17 dan
44
* Took pj_datum_transform() out of docs to discourage its use.
46
* Revision 1.5 2001/09/25 14:52:54 assefa
47
* Add pj_transform function.
49
* Revision 1.4 2001/02/23 20:35:57 assefa
50
* Free function does not work for PHP4. Disable it for now.
52
* Revision 1.3 2001/01/09 05:24:41 dan
53
* Fixes to build with PHP 4.0.4
55
* Revision 1.2 2000/11/08 15:44:16 dan
56
* Correct compilation errors with php4.
58
* Revision 1.1 2000/11/02 16:39:55 dan
62
**********************************************************************/
67
* This is a PHP module that gives acces to basic PROJ4 projection
70
* There following functions available in this module :
72
* 1) pj_init : create and initializes a projection structures
74
* PJ pj_init(array_of_parameters)
76
* Example : $projarray[0] = "proj=lcc";
77
* $projarray[1] = "ellps=GRS80";
78
* $projarray[2] = "lat_0=49";
79
* $projarray[3] = "lon_0=-95";
80
* $projarray[4] = "lat_1=49";
81
* $projarray[5] = "lat_2=77";
83
* $pj = pj_init($projarray);
85
* 2) pj_fwd : Performs a projection from lat/long coordinates to
86
* cartesian coordinates.
88
* retrun_array pj_fwd(double lat, double long, PJ pj)
90
* Example : $lat = 45.25;
93
* $ret = pj_fwd($ingeox, $ingeoy, $pj);
94
* printf("geo x = %f<br>\n", $ret["u"]);
95
* printf("geo y = %f<br>\n",$ret["v"]);
97
* 3) pj_inv : Performs a projection from cartesian coordinates to
98
* lat/long coordinates .
100
* retrun_array pj_fwd(double geox, double geoy, PJ pj)
102
* Example : $ingeox = 1537490.335842;
103
* $ingeoy = -181633.471555;
105
* $ret = pj_inv($ingeox, $ingeoy, $pj);
106
* printf("lat = %f<br>\n", $ret["u"]);
107
* printf("lon = %f<br>\n",$ret["v"]);
110
* 4) pj_transform : pj_transform(PJ pjsrc, PJ pjdst, double x, double y)
111
* transforms coordinates from source projection to
112
* destination projection.
114
* Example : $projarray[0] = "proj=lcc";
115
* $projarray[1] = "ellps=GRS80";
116
* $projarray[2] = "lat_0=49";
117
* $projarray[3] = "lon_0=-95";
118
* $projarray[4] = "lat_1=49";
119
* $projarray[5] = "lat_2=77";
120
* $projarray[6] = "";
122
* $pjlcc = pj_init($projarray);
123
* $projarray2[0] = "proj=latlong";
124
* $pjlat = pj_init($projarray2);
126
* $ingeox = 1537490.335842;
127
* $ingeoy = -181633.471555;
129
* $ret = pj_transform($pjlcc, $pjlat, $ingeox, $ingeoy);
131
* 5) pj_free : frees PJ structure
133
* void pj_free(PJ pj);
135
**********************************************************************/
138
#include <projects.h>
139
#include "php_mapscript_util.h"
142
#include "php_globals.h"
144
#include "maperror.h"
148
#if defined(_WIN32) && !defined(__CYGWIN__)
157
#define DLEXPORT ZEND_DLEXPORT
160
#define PHP_PROJ_VERSION "1.0.000 (Nov. 1, 2000)"
162
/*=====================================================================
164
*====================================================================*/
165
DLEXPORT void php_proj_pj_init(INTERNAL_FUNCTION_PARAMETERS);
166
DLEXPORT void php_proj_pj_fwd(INTERNAL_FUNCTION_PARAMETERS);
167
DLEXPORT void php_proj_pj_inv(INTERNAL_FUNCTION_PARAMETERS);
168
DLEXPORT void php_proj_pj_transform(INTERNAL_FUNCTION_PARAMETERS);
169
DLEXPORT void php_proj_pj_datum_transform(INTERNAL_FUNCTION_PARAMETERS);
170
DLEXPORT void php_proj_pj_free(INTERNAL_FUNCTION_PARAMETERS);
173
DLEXPORT void php_info_proj(void);
174
DLEXPORT int php_init_proj(INIT_FUNC_ARGS);
175
DLEXPORT int php_end_proj(SHUTDOWN_FUNC_ARGS);
177
DLEXPORT void ttt(INTERNAL_FUNCTION_PARAMETERS);
180
PHP_MINFO_FUNCTION(phpproj);
182
DLEXPORT void php_info_proj(void);
185
static zend_class_entry *proj_class_entry_ptr;
187
#define PHPMS_GLOBAL(a) a
188
static int le_projobj;
190
function_entry php_proj_functions[] = {
191
{"pj_fwd", php_proj_pj_fwd, NULL},
192
{"pj_inv", php_proj_pj_inv, NULL},
193
{"pj_init", php_proj_pj_init, NULL},
194
{"pj_transform", php_proj_pj_transform, NULL},
195
{"pj_datum_transform", php_proj_pj_datum_transform, NULL},
196
{"pj_free", php_proj_pj_free, NULL},
201
php3_module_entry php_proj_module_entry = {
202
#if ZEND_MODULE_API_NO >= 20010901
203
STANDARD_MODULE_HEADER,
205
"PHPPROJ", php_proj_functions, php_init_proj, php_end_proj,
212
#if ZEND_MODULE_API_NO >= 20010901
213
"phpproj, php4.1version", /* extension version number (string) */
215
STANDARD_MODULE_PROPERTIES
220
DLEXPORT php3_module_entry *get_module(void)
222
return &php_proj_module_entry;
227
function_entry php_proj_class_functions[] = {
232
DLEXPORT void ttt(INTERNAL_FUNCTION_PARAMETERS)
237
PHP_MINFO_FUNCTION(phpproj)
239
DLEXPORT void php_info_proj(void)
242
php3_printf(" Version %s<br>\n", PHP_PROJ_VERSION);
244
php3_printf("<BR>\n");
247
DLEXPORT int php_init_proj(INIT_FUNC_ARGS)
249
zend_class_entry tmp_class_entry;
251
PHPMS_GLOBAL(le_projobj) =
252
register_list_destructors(php_proj_pj_free,
255
INIT_CLASS_ENTRY(tmp_class_entry, "proj", php_proj_class_functions);
256
proj_class_entry_ptr = zend_register_internal_class(&tmp_class_entry TSRMLS_CC);
261
DLEXPORT int php_end_proj(SHUTDOWN_FUNC_ARGS)
267
#if !defined DEG_TO_RAD
268
#define DEG_TO_RAD 0.0174532925199432958
271
#if !defined RAD_TO_DEG
272
#define RAD_TO_DEG 57.29577951308232
275
/**********************************************************************
276
* _php_proj_build_proj_object
277
**********************************************************************/
278
static long _php_proj_build_proj_object(PJ *pj,
279
HashTable *list, pval *return_value TSRMLS_DC)
286
pj_id = php3_list_insert(pj, PHPMS_GLOBAL(le_projobj));
288
_phpms_object_init(return_value, pj_id, php_proj_class_functions,
289
PHP4_CLASS_ENTRY(proj_class_entry_ptr) TSRMLS_CC);
295
/************************************************************************/
296
/* DLEXPORT void php_proj_pj_init(INTERNAL_FUNCTION_PARAMETERS) */
298
/* Creates and initialize a PJ structure that can be used with */
299
/* proj_fwd and proj_inv function. */
303
/* array : array of parameters */
307
/* $projarray[0] = "proj=lcc"; */
308
/* $projarray[1] = "ellps=GRS80"; */
309
/* $projarray[2] = "lat_0=49"; */
310
/* $projarray[3] = "lon_0=-95"; */
311
/* $projarray[4] = "lat_1=49"; */
312
/* $projarray[5] = "lat_2=77"; */
314
/* $pj = pj_init($projarray); */
316
/************************************************************************/
317
DLEXPORT void php_proj_pj_init(INTERNAL_FUNCTION_PARAMETERS)
319
pval *pArrayOfParams = NULL;
321
pval **pParam = NULL;
322
HashTable *list=NULL;
328
char **papszBuf = NULL;
330
// char *strttt = NULL;
333
//ttt = strlen(strttt);
334
/* -------------------------------------------------------------------- */
335
/* extract parameters. */
336
/* -------------------------------------------------------------------- */
337
if (getParameters(ht, 1, &pArrayOfParams) != SUCCESS)
342
if (pArrayOfParams->type == IS_ARRAY)
343
nParamCount = _php3_hash_num_elements(pArrayOfParams->value.ht);
347
if (nParamCount <= 0)
350
papszBuf = (char **) malloc((nParamCount+2)*sizeof(char *));
352
for (i = 0; i < nParamCount; i++)
354
if (_php3_hash_index_find(pArrayOfParams->value.ht, i,
355
(void **)&pParam) != FAILURE)
357
convert_to_string((*pParam));
358
if ((*pParam)->value.str.val != NULL)
359
papszBuf[i] = strdup((*pParam)->value.str.val);
364
pj = pj_init(nParamCount, papszBuf);
366
_php_proj_build_proj_object(pj, list, return_value TSRMLS_CC);
370
/************************************************************************/
371
/* DLEXPORT void php_proj_pj_fwd(INTERNAL_FUNCTION_PARAMETERS) */
373
/* Performs a projection from lat/long coordinates to */
374
/* cartesian coordinates (projection defines in the pj parameter) */
377
/* - double p1 : latitude (in decimal degree ) */
378
/* - double p2 : longitude (in decimal degree ) */
379
/* - PJ pj : valid projection structure (see pj_init) */
385
/* $ret = pj_fwd($lat, $lon, $pj); */
386
/* printf("geo x = %f<br>\n", $ret["u"]); */
387
/* printf("geo y = %f<br>\n",$ret["v"]); */
389
/************************************************************************/
390
DLEXPORT void php_proj_pj_fwd(INTERNAL_FUNCTION_PARAMETERS)
392
HashTable *list=NULL;
397
projUV pntReturn = {0,0};
399
/* -------------------------------------------------------------------- */
400
/* extract parameters. */
401
/* -------------------------------------------------------------------- */
402
if (getParameters(ht, 3, &p1, &p2, &pj) != SUCCESS)
407
/* -------------------------------------------------------------------- */
408
/* initilize return array. */
409
/* -------------------------------------------------------------------- */
410
if (array_init(return_value) == FAILURE)
415
convert_to_double(p1);
416
convert_to_double(p2);
418
popj = (PJ *)_phpms_fetch_handle(pj,
419
PHPMS_GLOBAL(le_projobj), list TSRMLS_CC);
423
pnt.u = p2->value.dval * DEG_TO_RAD;
424
pnt.v = p1->value.dval * DEG_TO_RAD;
426
pntReturn = pj_fwd(pnt, popj);
429
add_assoc_double(return_value, "u", pntReturn.u);
430
add_assoc_double(return_value, "v", pntReturn.v);
434
/************************************************************************/
435
/* DLEXPORT void php_proj_pj_inv(INTERNAL_FUNCTION_PARAMETERS) */
437
/* Performs a projection from cartesian coordinates */
438
/* (projection defines in the pj parameter) to lat/long */
441
/* Return vales are in decimal degrees. */
445
/* - double p1 : projected coordinates (x) */
446
/* - double p2 : projected coordinates (y) */
447
/* - PJ pj : valid projection structure (see pj_init) */
450
/* $ingeox = 1537490.335842; */
451
/* $ingeoy = -181633.471555; */
453
/* $ret = pj_inv($ingeox, $ingeoy, $pj); */
455
/* printf("latitude = %f<br>\n", $ret["u"]); */
456
/* printf("longitude = %f<br>\n",$ret["v"]); */
457
/************************************************************************/
458
DLEXPORT void php_proj_pj_inv(INTERNAL_FUNCTION_PARAMETERS)
460
HashTable *list=NULL;
465
projUV pntReturn = {0,0};
466
/* -------------------------------------------------------------------- */
467
/* extract parameters. */
468
/* -------------------------------------------------------------------- */
469
if (getParameters(ht, 3, &p1, &p2, &pj) != SUCCESS)
474
/* -------------------------------------------------------------------- */
475
/* initilize return array. */
476
/* -------------------------------------------------------------------- */
477
if (array_init(return_value) == FAILURE)
482
convert_to_double(p1);
483
convert_to_double(p2);
485
popj = (PJ *)_phpms_fetch_handle(pj,
486
PHPMS_GLOBAL(le_projobj), list TSRMLS_CC);
490
pnt.u = p1->value.dval;
491
pnt.v = p2->value.dval;
493
pntReturn = pj_inv(pnt, popj);
494
pntReturn.u *= RAD_TO_DEG;
495
pntReturn.v *= RAD_TO_DEG;
498
add_assoc_double(return_value, "u", pntReturn.v);
499
add_assoc_double(return_value, "v", pntReturn.u);
502
/************************************************************************/
503
/* DLEXPORT void php_proj_pj_transform(INTERNAL_FUNCTION_PARAMETERS) */
505
/* Transform coordinates from source projection to destination */
515
/************************************************************************/
516
DLEXPORT void php_proj_pj_transform(INTERNAL_FUNCTION_PARAMETERS)
518
HashTable *list=NULL;
520
pval *pjin, *pjout = NULL;
526
/* -------------------------------------------------------------------- */
527
/* extract parameters. */
528
/* -------------------------------------------------------------------- */
529
if (getParameters(ht, 4, &pjin , &pjout, &p1, &p2) != SUCCESS)
534
/* -------------------------------------------------------------------- */
535
/* initilize return array. */
536
/* -------------------------------------------------------------------- */
537
if (array_init(return_value) == FAILURE)
542
convert_to_double(p1);
543
convert_to_double(p2);
545
in = (PJ *)_phpms_fetch_handle(pjin,
546
PHPMS_GLOBAL(le_projobj), list TSRMLS_CC);
548
out = (PJ *)_phpms_fetch_handle(pjout,
549
PHPMS_GLOBAL(le_projobj), list TSRMLS_CC);
553
pnt.u = p1->value.dval;
554
pnt.v = p2->value.dval;
556
if( pj_is_latlong(in) )
562
error = pj_transform(in, out, 1, 0,
563
&(pnt.u), &(pnt.v), &z );
565
if( pj_is_latlong(out) )
574
php_error(E_ERROR,"Error in pj_transform");
580
add_assoc_double(return_value, "u", pnt.u);
581
add_assoc_double(return_value, "v", pnt.v);
587
/************************************************************************/
589
/* void php_proj_pj_datum_transform(INTERNAL_FUNCTION_PARAMETERS) */
591
/* Datum from source projection to destination */
601
/************************************************************************/
602
DLEXPORT void php_proj_pj_datum_transform(INTERNAL_FUNCTION_PARAMETERS)
604
HashTable *list=NULL;
606
pval *pjin, *pjout = NULL;
612
/* -------------------------------------------------------------------- */
613
/* extract parameters. */
614
/* -------------------------------------------------------------------- */
615
if (getParameters(ht, 4, &pjin , &pjout, &p1, &p2) != SUCCESS)
620
/* -------------------------------------------------------------------- */
621
/* initilize return array. */
622
/* -------------------------------------------------------------------- */
623
if (array_init(return_value) == FAILURE)
628
convert_to_double(p1);
629
convert_to_double(p2);
631
in = (PJ *)_phpms_fetch_handle(pjin,
632
PHPMS_GLOBAL(le_projobj), list TSRMLS_CC);
634
out = (PJ *)_phpms_fetch_handle(pjout,
635
PHPMS_GLOBAL(le_projobj), list TSRMLS_CC);
639
pnt.u = p1->value.dval;
640
pnt.v = p2->value.dval;
642
if( pj_is_latlong(in) )
648
error = pj_transform(in, out, 1, 0,
649
&(pnt.u), &(pnt.v), &z );
653
if( pj_is_latlong(out) )
663
php_error(E_ERROR,"Error in pj_datum_transform");
669
add_assoc_double(return_value, "u", pnt.u);
670
add_assoc_double(return_value, "v", pnt.v);
674
/************************************************************************/
675
/* DLEXPORT void php_proj_pj_free(INTERNAL_FUNCTION_PARAMETERS) */
676
/************************************************************************/
677
DLEXPORT void php_proj_pj_free(INTERNAL_FUNCTION_PARAMETERS)
680
/* ==================================================================== */
681
/* TODO : freeing does not work properly on PHP4. */
682
/* ==================================================================== */
683
#ifdef PHP4_BAD_FREEING
685
HashTable *list=NULL;
688
/* -------------------------------------------------------------------- */
689
/* extract parameters. */
690
/* -------------------------------------------------------------------- */
691
if (getParameters(ht, 1, &pj) != SUCCESS)
696
popj = (PJ *)_phpms_fetch_handle(pj,
697
PHPMS_GLOBAL(le_projobj), list TSRMLS_CC);
706
#endif /* USE_PROJ */