Skip to content

Commit b1f4132

Browse files
author
Nathaniel McHugh
committed
Merge branch 'master' of git://github.com/php-geospatial/geospatial into vincenty
Conflicts: geospatial.c php_geospatial.h
2 parents c628cbe + 53918a0 commit b1f4132

File tree

5 files changed

+182
-54
lines changed

5 files changed

+182
-54
lines changed

config.m4

Lines changed: 1 addition & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,9 @@
11
dnl $Id$
22
dnl config.m4 for extension geospatial
33

4-
dnl Comments in this file start with the string 'dnl'.
5-
dnl Remove where necessary. This file will not work
6-
dnl without editing.
7-
8-
dnl If your extension references something external, use with:
9-
10-
dnl PHP_ARG_WITH(geospatial, for geospatial support,
11-
dnl Make sure that the comment is aligned:
12-
dnl [ --with-geospatial Include geospatial support])
13-
14-
dnl Otherwise use enable:
15-
164
PHP_ARG_ENABLE(geospatial, whether to enable geospatial support,
175
[ --enable-geospatial Enable geospatial support])
186

197
if test "$PHP_GEOSPATIAL" != "no"; then
20-
dnl Write more examples of tests here...
21-
22-
dnl # --with-geospatial -> check with-path
23-
dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
24-
dnl SEARCH_FOR="/include/geospatial.h" # you most likely want to change this
25-
dnl if test -r $PHP_GEOSPATIAL/$SEARCH_FOR; then # path given as parameter
26-
dnl GEOSPATIAL_DIR=$PHP_GEOSPATIAL
27-
dnl else # search default path list
28-
dnl AC_MSG_CHECKING([for geospatial files in default path])
29-
dnl for i in $SEARCH_PATH ; do
30-
dnl if test -r $i/$SEARCH_FOR; then
31-
dnl GEOSPATIAL_DIR=$i
32-
dnl AC_MSG_RESULT(found in $i)
33-
dnl fi
34-
dnl done
35-
dnl fi
36-
dnl
37-
dnl if test -z "$GEOSPATIAL_DIR"; then
38-
dnl AC_MSG_RESULT([not found])
39-
dnl AC_MSG_ERROR([Please reinstall the geospatial distribution])
40-
dnl fi
41-
42-
dnl # --with-geospatial -> add include path
43-
dnl PHP_ADD_INCLUDE($GEOSPATIAL_DIR/include)
44-
45-
dnl # --with-geospatial -> check for lib and symbol presence
46-
dnl LIBNAME=geospatial # you may want to change this
47-
dnl LIBSYMBOL=geospatial # you most likely want to change this
48-
49-
dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
50-
dnl [
51-
dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $GEOSPATIAL_DIR/lib, GEOSPATIAL_SHARED_LIBADD)
52-
dnl AC_DEFINE(HAVE_GEOSPATIALLIB,1,[ ])
53-
dnl ],[
54-
dnl AC_MSG_ERROR([wrong geospatial lib version or lib not found])
55-
dnl ],[
56-
dnl -L$GEOSPATIAL_DIR/lib -lm
57-
dnl ])
58-
dnl
59-
dnl PHP_SUBST(GEOSPATIAL_SHARED_LIBADD)
60-
61-
PHP_NEW_EXTENSION(geospatial, geospatial.c, $ext_shared)
8+
PHP_NEW_EXTENSION(geospatial, geospatial.c geo_array.c, $ext_shared)
629
fi

geo_array.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <stdlib.h>
2+
3+
#include "geo_array.h"
4+
5+
geo_array *geo_array_ctor(int element_count)
6+
{
7+
geo_array *tmp;
8+
9+
tmp = malloc(sizeof(geo_array));
10+
tmp->count = element_count;
11+
tmp->status = calloc(1, element_count);
12+
tmp->x = (double*) calloc(1, element_count * sizeof(double));
13+
tmp->y = (double*) calloc(1, element_count * sizeof(double));
14+
15+
return tmp;
16+
}
17+
18+
void geo_array_dtor(geo_array *points)
19+
{
20+
free(points->status);
21+
free(points->x);
22+
free(points->y);
23+
free(points);
24+
}

geo_array.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
typedef struct geo_array {
2+
double *x;
3+
double *y;
4+
char *status;
5+
int count;
6+
} geo_array;
7+
8+
geo_array *geo_array_ctor(int element_count);
9+
void geo_array_dtor(geo_array *points);

geospatial.c

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "php_ini.h"
2828
#include "ext/standard/info.h"
2929
#include "php_geospatial.h"
30+
#include "geo_array.h"
3031

3132
ZEND_BEGIN_ARG_INFO_EX(haversine_args, 0, 0, 4)
3233
ZEND_ARG_INFO(0, fromLatitude)
@@ -88,6 +89,11 @@ ZEND_BEGIN_ARG_INFO_EX(decimal_to_dms_args, 0, 0, 2)
8889
ZEND_ARG_INFO(0, coordinate)
8990
ZEND_END_ARG_INFO()
9091

92+
ZEND_BEGIN_ARG_INFO_EX(rdp_simplify_args, 0, 0, 2)
93+
ZEND_ARG_INFO(0, pointsArray)
94+
ZEND_ARG_INFO(0, epsilon)
95+
ZEND_END_ARG_INFO()
96+
9197
/* {{{ geospatial_functions[]
9298
*
9399
* Every user visible function must have an entry in geospatial_functions[].
@@ -102,6 +108,7 @@ const zend_function_entry geospatial_functions[] = {
102108
PHP_FE(dms_to_decimal, dms_to_decimal_args)
103109
PHP_FE(decimal_to_dms, decimal_to_dms_args)
104110
PHP_FE(vincenty, vincenty_args)
111+
PHP_FE(rdp_simplify, rdp_simplify_args)
105112
/* End of functions */
106113
{ NULL, NULL, NULL }
107114
};
@@ -498,6 +505,7 @@ PHP_FUNCTION(transform_datum)
498505
long from_reference_ellipsoid, to_reference_ellipsoid;
499506
geo_cartesian point, converted_point;
500507
geo_lat_long polar;
508+
501509
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ddll", &latitude, &longitude, &from_reference_ellipsoid, &to_reference_ellipsoid) == FAILURE) {
502510
return;
503511
}
@@ -591,6 +599,142 @@ PHP_FUNCTION(fraction_along_gc_line)
591599
}
592600
/* }}} */
593601

602+
geo_array *geo_hashtable_to_array(zval *array)
603+
{
604+
geo_array *tmp;
605+
int element_count;
606+
HashPosition pos;
607+
zval **entry;
608+
zval **z_lon, **z_lat;
609+
int i = 0;
610+
611+
element_count = zend_hash_num_elements(Z_ARRVAL_P(array));
612+
tmp = geo_array_ctor(element_count);
613+
614+
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
615+
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {
616+
617+
if (Z_TYPE_PP(entry) != IS_ARRAY) {
618+
goto failure;
619+
}
620+
if (zend_hash_num_elements(Z_ARRVAL_PP(entry)) != 2)
621+
{
622+
goto failure;
623+
}
624+
if (zend_hash_index_find(HASH_OF(*entry), 0, (void**) &z_lon) != SUCCESS) {
625+
return 0;
626+
}
627+
if (zend_hash_index_find(HASH_OF(*entry), 1, (void**) &z_lat) != SUCCESS) {
628+
return 0;
629+
}
630+
convert_to_double_ex(z_lon);
631+
convert_to_double_ex(z_lat);
632+
633+
tmp->x[i] = Z_DVAL_PP(z_lon);
634+
tmp->y[i] = Z_DVAL_PP(z_lat);
635+
tmp->status[i] = 1;
636+
637+
zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos);
638+
i++;
639+
}
640+
641+
return tmp;
642+
643+
failure:
644+
geo_array_dtor(tmp);
645+
return NULL;
646+
}
647+
648+
double rdp_find_perpendicular_distable(double pX, double pY, double p1X, double p1Y, double p2X, double p2Y)
649+
{
650+
double slope, intercept, result;
651+
652+
if (p1X == p2X) {
653+
return fabs(pX - p1X);
654+
} else {
655+
slope = (p2Y - p1Y) / (p2X - p1X);
656+
intercept = p1Y - (slope * p1X);
657+
result = fabs(slope * pX - pY + intercept) / sqrt(pow(slope, 2) + 1);
658+
return result;
659+
}
660+
}
661+
662+
void rdp_simplify(geo_array *points, double epsilon, int start, int end)
663+
{
664+
double firstX = points->x[start];
665+
double firstY = points->y[start];
666+
double lastX = points->x[end];
667+
double lastY = points->y[end];
668+
int index = -1;
669+
double dist = 0.0, current_dist;
670+
int i;
671+
672+
if (end - start < 2) {
673+
return;
674+
}
675+
676+
for (i = start + 1; i < end; i++) {
677+
if (!points->status[i]) {
678+
continue;
679+
}
680+
681+
current_dist = rdp_find_perpendicular_distable(points->x[i], points->y[i], firstX, firstY, lastX, lastY);
682+
683+
if (current_dist > dist) {
684+
dist = current_dist;
685+
index = i;
686+
}
687+
}
688+
689+
if (dist > epsilon) {
690+
rdp_simplify(points, epsilon, start, index);
691+
rdp_simplify(points, epsilon, index, end);
692+
693+
return;
694+
} else {
695+
for (i = start + 1; i < end; i++) {
696+
points->status[i] = 0;
697+
}
698+
return;
699+
}
700+
}
701+
702+
/* {{{ proto array rdp_simplify(array points, float epsilon)
703+
Simplifies a 2D dimensional line according to the Ramer-Douglas-Peucker algorithm */
704+
PHP_FUNCTION(rdp_simplify)
705+
{
706+
zval *points_array;
707+
double epsilon;
708+
geo_array *points;
709+
int i;
710+
zval *pair;
711+
712+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zd", &points_array, &epsilon) == FAILURE) {
713+
return;
714+
}
715+
716+
if (!Z_TYPE_P(points_array) == IS_ARRAY) {
717+
return;
718+
}
719+
720+
array_init(return_value);
721+
722+
points = geo_hashtable_to_array(points_array);
723+
rdp_simplify(points, epsilon, 0, points->count - 1);
724+
for (i = 0; i < points->count; i++) {
725+
if (points->status[i]) {
726+
MAKE_STD_ZVAL(pair);
727+
array_init(pair);
728+
add_next_index_double(pair, points->x[i]);
729+
add_next_index_double(pair, points->y[i]);
730+
add_next_index_zval(return_value, pair);
731+
}
732+
}
733+
734+
geo_array_dtor(points);
735+
}
736+
/* }}} */
737+
594738
/*
595739
* Local variables:
596740
* tab-width: 4

php_geospatial.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,11 @@ PHP_FUNCTION(cartesian_to_polar);
133133
PHP_FUNCTION(transform_datum);
134134
PHP_FUNCTION(dms_to_decimal);
135135
PHP_FUNCTION(decimal_to_dms);
136+
<<<<<<< HEAD
136137
PHP_FUNCTION(vincenty);
138+
=======
139+
PHP_FUNCTION(rdp_simplify);
140+
>>>>>>> 53918a081d6392588cd4dae701af9b6f4ea78527
137141

138142
#endif /* PHP_GEOSPATIAL_H */
139143

0 commit comments

Comments
 (0)